You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sha3_s390x.go 6.8KB

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