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 7package 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 13import ( 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. 21type code uint64 22 23const ( 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 38func 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 44func klmd(function code, chain *[200]byte, dst, src []byte) 45 46type 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 56func 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 87func (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. 95func (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. 103func (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. 110func (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. 145func (s *asmState) Read(out []byte) (n int, err error) { 146 // The 'compute last message digest' instruction only stores the digest 147 // at the first operand (dst) for SHAKE functions. 148 if s.function != shake_128 && s.function != shake_256 { 149 panic("sha3: can only call Read for SHAKE functions") 150 } 151 152 n = len(out) 153 154 // need to pad if we were absorbing 155 if s.state == spongeAbsorbing { 156 s.state = spongeSqueezing 157 158 // write hash directly into out if possible 159 if len(out)%s.rate == 0 { 160 klmd(s.function, &s.a, out, s.buf) // len(out) may be 0 161 s.buf = s.buf[:0] 162 return 163 } 164 165 // write hash into buffer 166 max := cap(s.buf) 167 if max > len(out) { 168 max = (len(out)/s.rate)*s.rate + s.rate 169 } 170 klmd(s.function, &s.a, s.buf[:max], s.buf) 171 s.buf = s.buf[:max] 172 } 173 174 for len(out) > 0 { 175 // flush the buffer 176 if len(s.buf) != 0 { 177 c := copy(out, s.buf) 178 out = out[c:] 179 s.buf = s.buf[c:] 180 continue 181 } 182 183 // write hash directly into out if possible 184 if len(out)%s.rate == 0 { 185 klmd(s.function|nopad, &s.a, out, nil) 186 return 187 } 188 189 // write hash into buffer 190 s.resetBuf() 191 if cap(s.buf) > len(out) { 192 s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate] 193 } 194 klmd(s.function|nopad, &s.a, s.buf, nil) 195 } 196 return 197} 198 199// Sum appends the current hash to b and returns the resulting slice. 200// It does not change the underlying hash state. 201func (s *asmState) Sum(b []byte) []byte { 202 if s.state != spongeAbsorbing { 203 panic("sha3: Sum after Read") 204 } 205 206 // Copy the state to preserve the original. 207 a := s.a 208 209 // Hash the buffer. Note that we don't clear it because we 210 // aren't updating the state. 211 switch s.function { 212 case sha3_224, sha3_256, sha3_384, sha3_512: 213 klmd(s.function, &a, nil, s.buf) 214 return append(b, a[:s.outputLen]...) 215 case shake_128, shake_256: 216 d := make([]byte, s.outputLen, 64) 217 klmd(s.function, &a, d, s.buf) 218 return append(b, d[:s.outputLen]...) 219 default: 220 panic("sha3: unknown function") 221 } 222} 223 224// Reset resets the Hash to its initial state. 225func (s *asmState) Reset() { 226 for i := range s.a { 227 s.a[i] = 0 228 } 229 s.resetBuf() 230 s.state = spongeAbsorbing 231} 232 233// Size returns the number of bytes Sum will return. 234func (s *asmState) Size() int { 235 return s.outputLen 236} 237 238// BlockSize returns the hash's underlying block size. 239// The Write method must be able to accept any amount 240// of data, but it may operate more efficiently if all writes 241// are a multiple of the block size. 242func (s *asmState) BlockSize() int { 243 return s.rate 244} 245 246// Clone returns a copy of the ShakeHash in its current state. 247func (s *asmState) Clone() ShakeHash { 248 return s.clone() 249} 250 251// new224 returns an assembly implementation of SHA3-224 if available, 252// otherwise it returns a generic implementation. 253func new224() hash.Hash { 254 if cpu.S390X.HasSHA3 { 255 return newAsmState(sha3_224) 256 } 257 return new224Generic() 258} 259 260// new256 returns an assembly implementation of SHA3-256 if available, 261// otherwise it returns a generic implementation. 262func new256() hash.Hash { 263 if cpu.S390X.HasSHA3 { 264 return newAsmState(sha3_256) 265 } 266 return new256Generic() 267} 268 269// new384 returns an assembly implementation of SHA3-384 if available, 270// otherwise it returns a generic implementation. 271func new384() hash.Hash { 272 if cpu.S390X.HasSHA3 { 273 return newAsmState(sha3_384) 274 } 275 return new384Generic() 276} 277 278// new512 returns an assembly implementation of SHA3-512 if available, 279// otherwise it returns a generic implementation. 280func new512() hash.Hash { 281 if cpu.S390X.HasSHA3 { 282 return newAsmState(sha3_512) 283 } 284 return new512Generic() 285} 286 287// newShake128 returns an assembly implementation of SHAKE-128 if available, 288// otherwise it returns a generic implementation. 289func newShake128() ShakeHash { 290 if cpu.S390X.HasSHA3 { 291 return newAsmState(shake_128) 292 } 293 return newShake128Generic() 294} 295 296// newShake256 returns an assembly implementation of SHAKE-256 if available, 297// otherwise it returns a generic implementation. 298func newShake256() ShakeHash { 299 if cpu.S390X.HasSHA3 { 300 return newAsmState(shake_256) 301 } 302 return newShake256Generic() 303} 304