Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // Copyright 2017 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build gc && !purego
  5. // +build gc,!purego
  6. package sha3
  7. // This file contains code for using the 'compute intermediate
  8. // message digest' (KIMD) and 'compute last message digest' (KLMD)
  9. // instructions to compute SHA-3 and SHAKE hashes on IBM Z.
  10. import (
  11. "hash"
  12. "golang.org/x/sys/cpu"
  13. )
  14. // codes represent 7-bit KIMD/KLMD function codes as defined in
  15. // the Principles of Operation.
  16. type code uint64
  17. const (
  18. // function codes for KIMD/KLMD
  19. sha3_224 code = 32
  20. sha3_256 = 33
  21. sha3_384 = 34
  22. sha3_512 = 35
  23. shake_128 = 36
  24. shake_256 = 37
  25. nopad = 0x100
  26. )
  27. // kimd is a wrapper for the 'compute intermediate message digest' instruction.
  28. // src must be a multiple of the rate for the given function code.
  29. //go:noescape
  30. func kimd(function code, chain *[200]byte, src []byte)
  31. // klmd is a wrapper for the 'compute last message digest' instruction.
  32. // src padding is handled by the instruction.
  33. //go:noescape
  34. func klmd(function code, chain *[200]byte, dst, src []byte)
  35. type asmState struct {
  36. a [200]byte // 1600 bit state
  37. buf []byte // care must be taken to ensure cap(buf) is a multiple of rate
  38. rate int // equivalent to block size
  39. storage [3072]byte // underlying storage for buf
  40. outputLen int // output length if fixed, 0 if not
  41. function code // KIMD/KLMD function code
  42. state spongeDirection // whether the sponge is absorbing or squeezing
  43. }
  44. func newAsmState(function code) *asmState {
  45. var s asmState
  46. s.function = function
  47. switch function {
  48. case sha3_224:
  49. s.rate = 144
  50. s.outputLen = 28
  51. case sha3_256:
  52. s.rate = 136
  53. s.outputLen = 32
  54. case sha3_384:
  55. s.rate = 104
  56. s.outputLen = 48
  57. case sha3_512:
  58. s.rate = 72
  59. s.outputLen = 64
  60. case shake_128:
  61. s.rate = 168
  62. case shake_256:
  63. s.rate = 136
  64. default:
  65. panic("sha3: unrecognized function code")
  66. }
  67. // limit s.buf size to a multiple of s.rate
  68. s.resetBuf()
  69. return &s
  70. }
  71. func (s *asmState) clone() *asmState {
  72. c := *s
  73. c.buf = c.storage[:len(s.buf):cap(s.buf)]
  74. return &c
  75. }
  76. // copyIntoBuf copies b into buf. It will panic if there is not enough space to
  77. // store all of b.
  78. func (s *asmState) copyIntoBuf(b []byte) {
  79. bufLen := len(s.buf)
  80. s.buf = s.buf[:len(s.buf)+len(b)]
  81. copy(s.buf[bufLen:], b)
  82. }
  83. // resetBuf points buf at storage, sets the length to 0 and sets cap to be a
  84. // multiple of the rate.
  85. func (s *asmState) resetBuf() {
  86. max := (cap(s.storage) / s.rate) * s.rate
  87. s.buf = s.storage[:0:max]
  88. }
  89. // Write (via the embedded io.Writer interface) adds more data to the running hash.
  90. // It never returns an error.
  91. func (s *asmState) Write(b []byte) (int, error) {
  92. if s.state != spongeAbsorbing {
  93. panic("sha3: write to sponge after read")
  94. }
  95. length := len(b)
  96. for len(b) > 0 {
  97. if len(s.buf) == 0 && len(b) >= cap(s.buf) {
  98. // Hash the data directly and push any remaining bytes
  99. // into the buffer.
  100. remainder := len(b) % s.rate
  101. kimd(s.function, &s.a, b[:len(b)-remainder])
  102. if remainder != 0 {
  103. s.copyIntoBuf(b[len(b)-remainder:])
  104. }
  105. return length, nil
  106. }
  107. if len(s.buf) == cap(s.buf) {
  108. // flush the buffer
  109. kimd(s.function, &s.a, s.buf)
  110. s.buf = s.buf[:0]
  111. }
  112. // copy as much as we can into the buffer
  113. n := len(b)
  114. if len(b) > cap(s.buf)-len(s.buf) {
  115. n = cap(s.buf) - len(s.buf)
  116. }
  117. s.copyIntoBuf(b[:n])
  118. b = b[n:]
  119. }
  120. return length, nil
  121. }
  122. // Read squeezes an arbitrary number of bytes from the sponge.
  123. func (s *asmState) Read(out []byte) (n int, err error) {
  124. n = len(out)
  125. // need to pad if we were absorbing
  126. if s.state == spongeAbsorbing {
  127. s.state = spongeSqueezing
  128. // write hash directly into out if possible
  129. if len(out)%s.rate == 0 {
  130. klmd(s.function, &s.a, out, s.buf) // len(out) may be 0
  131. s.buf = s.buf[:0]
  132. return
  133. }
  134. // write hash into buffer
  135. max := cap(s.buf)
  136. if max > len(out) {
  137. max = (len(out)/s.rate)*s.rate + s.rate
  138. }
  139. klmd(s.function, &s.a, s.buf[:max], s.buf)
  140. s.buf = s.buf[:max]
  141. }
  142. for len(out) > 0 {
  143. // flush the buffer
  144. if len(s.buf) != 0 {
  145. c := copy(out, s.buf)
  146. out = out[c:]
  147. s.buf = s.buf[c:]
  148. continue
  149. }
  150. // write hash directly into out if possible
  151. if len(out)%s.rate == 0 {
  152. klmd(s.function|nopad, &s.a, out, nil)
  153. return
  154. }
  155. // write hash into buffer
  156. s.resetBuf()
  157. if cap(s.buf) > len(out) {
  158. s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate]
  159. }
  160. klmd(s.function|nopad, &s.a, s.buf, nil)
  161. }
  162. return
  163. }
  164. // Sum appends the current hash to b and returns the resulting slice.
  165. // It does not change the underlying hash state.
  166. func (s *asmState) Sum(b []byte) []byte {
  167. if s.outputLen == 0 {
  168. panic("sha3: cannot call Sum on SHAKE functions")
  169. }
  170. // Copy the state to preserve the original.
  171. a := s.a
  172. // Hash the buffer. Note that we don't clear it because we
  173. // aren't updating the state.
  174. klmd(s.function, &a, nil, s.buf)
  175. return append(b, a[:s.outputLen]...)
  176. }
  177. // Reset resets the Hash to its initial state.
  178. func (s *asmState) Reset() {
  179. for i := range s.a {
  180. s.a[i] = 0
  181. }
  182. s.resetBuf()
  183. s.state = spongeAbsorbing
  184. }
  185. // Size returns the number of bytes Sum will return.
  186. func (s *asmState) Size() int {
  187. return s.outputLen
  188. }
  189. // BlockSize returns the hash's underlying block size.
  190. // The Write method must be able to accept any amount
  191. // of data, but it may operate more efficiently if all writes
  192. // are a multiple of the block size.
  193. func (s *asmState) BlockSize() int {
  194. return s.rate
  195. }
  196. // Clone returns a copy of the ShakeHash in its current state.
  197. func (s *asmState) Clone() ShakeHash {
  198. return s.clone()
  199. }
  200. // new224Asm returns an assembly implementation of SHA3-224 if available,
  201. // otherwise it returns nil.
  202. func new224Asm() hash.Hash {
  203. if cpu.S390X.HasSHA3 {
  204. return newAsmState(sha3_224)
  205. }
  206. return nil
  207. }
  208. // new256Asm returns an assembly implementation of SHA3-256 if available,
  209. // otherwise it returns nil.
  210. func new256Asm() hash.Hash {
  211. if cpu.S390X.HasSHA3 {
  212. return newAsmState(sha3_256)
  213. }
  214. return nil
  215. }
  216. // new384Asm returns an assembly implementation of SHA3-384 if available,
  217. // otherwise it returns nil.
  218. func new384Asm() hash.Hash {
  219. if cpu.S390X.HasSHA3 {
  220. return newAsmState(sha3_384)
  221. }
  222. return nil
  223. }
  224. // new512Asm returns an assembly implementation of SHA3-512 if available,
  225. // otherwise it returns nil.
  226. func new512Asm() hash.Hash {
  227. if cpu.S390X.HasSHA3 {
  228. return newAsmState(sha3_512)
  229. }
  230. return nil
  231. }
  232. // newShake128Asm returns an assembly implementation of SHAKE-128 if available,
  233. // otherwise it returns nil.
  234. func newShake128Asm() ShakeHash {
  235. if cpu.S390X.HasSHA3 {
  236. return newAsmState(shake_128)
  237. }
  238. return nil
  239. }
  240. // newShake256Asm returns an assembly implementation of SHAKE-256 if available,
  241. // otherwise it returns nil.
  242. func newShake256Asm() ShakeHash {
  243. if cpu.S390X.HasSHA3 {
  244. return newAsmState(shake_256)
  245. }
  246. return nil
  247. }