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