| // Copyright 2017 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| //go:build !purego |
| |
| package sha3 |
| |
| import ( |
| "crypto/internal/fips140/subtle" |
| "crypto/internal/fips140deps/cpu" |
| "crypto/internal/impl" |
| ) |
| |
| // This file contains code for using the 'compute intermediate |
| // message digest' (KIMD) and 'compute last message digest' (KLMD) |
| // instructions to compute SHA-3 and SHAKE hashes on IBM Z. See |
| // [z/Architecture Principles of Operation, Fourteen Edition]. |
| // |
| // [z/Architecture Principles of Operation, Fourteen Edition]: https://www.ibm.com/docs/en/module_1678991624569/pdf/SA22-7832-13.pdf |
| |
| var useSHA3 = cpu.S390XHasSHA3 |
| |
| func init() { |
| // CP Assist for Cryptographic Functions (CPACF) |
| impl.Register("sha3", "CPACF", &useSHA3) |
| } |
| |
| func keccakF1600(a *[200]byte) { |
| keccakF1600Generic(a) |
| } |
| |
| // codes represent 7-bit KIMD/KLMD function codes as defined in |
| // the Principles of Operation. |
| type code uint64 |
| |
| const ( |
| // Function codes for KIMD/KLMD, from Figure 7-207. |
| sha3_224 code = 32 |
| sha3_256 code = 33 |
| sha3_384 code = 34 |
| sha3_512 code = 35 |
| shake_128 code = 36 |
| shake_256 code = 37 |
| nopad = 0x100 |
| ) |
| |
| // kimd is a wrapper for the 'compute intermediate message digest' instruction. |
| // src is absorbed into the sponge state a. |
| // len(src) must be a multiple of the rate for the given function code. |
| // |
| //go:noescape |
| func kimd(function code, a *[200]byte, src []byte) |
| |
| // klmd is a wrapper for the 'compute last message digest' instruction. |
| // src is padded and absorbed into the sponge state a. |
| // |
| // If the function is a SHAKE XOF, the sponge is then optionally squeezed into |
| // dst by first applying the permutation and then copying the output until dst |
| // runs out. If len(dst) is a multiple of rate (including zero), the final |
| // permutation is not applied. If the nopad bit of function is set and len(src) |
| // is zero, only squeezing is performed. |
| // |
| //go:noescape |
| func klmd(function code, a *[200]byte, dst, src []byte) |
| |
| func (d *Digest) write(p []byte) (n int, err error) { |
| if d.state != spongeAbsorbing { |
| panic("sha3: Write after Read") |
| } |
| if !useSHA3 { |
| return d.writeGeneric(p) |
| } |
| |
| n = len(p) |
| |
| // If there is buffered input in the state, keep XOR'ing. |
| if d.n > 0 { |
| x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p) |
| d.n += x |
| p = p[x:] |
| } |
| |
| // If the sponge is full, apply the permutation. |
| if d.n == d.rate { |
| // Absorbing a "rate"ful of zeroes effectively XORs the state with |
| // zeroes (a no-op) and then runs the permutation. The actual function |
| // doesn't matter, they all run the same permutation. |
| kimd(shake_128, &d.a, make([]byte, rateK256)) |
| d.n = 0 |
| } |
| |
| // Absorb full blocks with KIMD. |
| if len(p) >= d.rate { |
| wholeBlocks := len(p) / d.rate * d.rate |
| kimd(d.function(), &d.a, p[:wholeBlocks]) |
| p = p[wholeBlocks:] |
| } |
| |
| // If there is any trailing input, XOR it into the state. |
| if len(p) > 0 { |
| d.n += subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p) |
| } |
| |
| return |
| } |
| |
| func (d *Digest) sum(b []byte) []byte { |
| if d.state != spongeAbsorbing { |
| panic("sha3: Sum after Read") |
| } |
| if !useSHA3 || d.dsbyte != dsbyteSHA3 && d.dsbyte != dsbyteShake { |
| return d.sumGeneric(b) |
| } |
| |
| // Copy the state to preserve the original. |
| a := d.a |
| |
| // We "absorb" a buffer of zeroes as long as the amount of input we already |
| // XOR'd into the sponge, to skip over it. The max cap is specified to avoid |
| // an allocation. |
| buf := make([]byte, d.n, rateK256) |
| function := d.function() |
| switch function { |
| case sha3_224, sha3_256, sha3_384, sha3_512: |
| klmd(function, &a, nil, buf) |
| return append(b, a[:d.outputLen]...) |
| case shake_128, shake_256: |
| h := make([]byte, d.outputLen, 64) |
| klmd(function, &a, h, buf) |
| return append(b, h...) |
| default: |
| panic("sha3: unknown function") |
| } |
| } |
| |
| func (d *Digest) read(out []byte) (n int, err error) { |
| if !useSHA3 || d.dsbyte != dsbyteShake { |
| return d.readGeneric(out) |
| } |
| |
| n = len(out) |
| |
| if d.state == spongeAbsorbing { |
| d.state = spongeSqueezing |
| |
| // We "absorb" a buffer of zeroes as long as the amount of input we |
| // already XOR'd into the sponge, to skip over it. The max cap is |
| // specified to avoid an allocation. |
| buf := make([]byte, d.n, rateK256) |
| klmd(d.function(), &d.a, out, buf) |
| } else { |
| // We have "buffered" output still to copy. |
| if d.n < d.rate { |
| x := copy(out, d.a[d.n:d.rate]) |
| d.n += x |
| out = out[x:] |
| } |
| if len(out) == 0 { |
| return |
| } |
| |
| klmd(d.function()|nopad, &d.a, out, nil) |
| } |
| |
| if len(out)%d.rate == 0 { |
| // The final permutation was not performed, |
| // so there is no "buffered" output. |
| d.n = d.rate |
| } else { |
| d.n = len(out) % d.rate |
| } |
| |
| return |
| } |
| |
| func (d *Digest) function() code { |
| switch d.rate { |
| case rateK256: |
| return shake_128 |
| case rateK448: |
| return sha3_224 |
| case rateK512: |
| if d.dsbyte == dsbyteSHA3 { |
| return sha3_256 |
| } else { |
| return shake_256 |
| } |
| case rateK768: |
| return sha3_384 |
| case rateK1024: |
| return sha3_512 |
| default: |
| panic("invalid rate") |
| } |
| } |