Source file src/crypto/internal/fips/sha3/sha3_s390x.go

     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 !purego
     6  
     7  package sha3
     8  
     9  import (
    10  	"crypto/internal/fips/subtle"
    11  	"crypto/internal/impl"
    12  	"internal/cpu"
    13  )
    14  
    15  // This file contains code for using the 'compute intermediate
    16  // message digest' (KIMD) and 'compute last message digest' (KLMD)
    17  // instructions to compute SHA-3 and SHAKE hashes on IBM Z. See
    18  // [z/Architecture Principles of Operation, Fourteen Edition].
    19  //
    20  // [z/Architecture Principles of Operation, Fourteen Edition]: https://www.ibm.com/docs/en/module_1678991624569/pdf/SA22-7832-13.pdf
    21  
    22  var useSHA3 = cpu.S390X.HasSHA3
    23  
    24  func init() {
    25  	// CP Assist for Cryptographic Functions (CPACF)
    26  	impl.Register("crypto/sha3", "CPACF", &useSHA3)
    27  }
    28  
    29  func keccakF1600(a *[200]byte) {
    30  	keccakF1600Generic(a)
    31  }
    32  
    33  // codes represent 7-bit KIMD/KLMD function codes as defined in
    34  // the Principles of Operation.
    35  type code uint64
    36  
    37  const (
    38  	// Function codes for KIMD/KLMD, from Figure 7-207.
    39  	sha3_224  code = 32
    40  	sha3_256  code = 33
    41  	sha3_384  code = 34
    42  	sha3_512  code = 35
    43  	shake_128 code = 36
    44  	shake_256 code = 37
    45  	nopad          = 0x100
    46  )
    47  
    48  // kimd is a wrapper for the 'compute intermediate message digest' instruction.
    49  // src is absorbed into the sponge state a.
    50  // len(src) must be a multiple of the rate for the given function code.
    51  //
    52  //go:noescape
    53  func kimd(function code, a *[200]byte, src []byte)
    54  
    55  // klmd is a wrapper for the 'compute last message digest' instruction.
    56  // src is padded and absorbed into the sponge state a.
    57  //
    58  // If the function is a SHAKE XOF, the sponge is then optionally squeezed into
    59  // dst by first applying the permutation and then copying the output until dst
    60  // runs out. If len(dst) is a multiple of rate (including zero), the final
    61  // permutation is not applied. If the nopad bit of function is set and len(src)
    62  // is zero, only squeezing is performed.
    63  //
    64  //go:noescape
    65  func klmd(function code, a *[200]byte, dst, src []byte)
    66  
    67  func (d *Digest) write(p []byte) (n int, err error) {
    68  	if d.state != spongeAbsorbing {
    69  		panic("sha3: Write after Read")
    70  	}
    71  	if !useSHA3 {
    72  		return d.writeGeneric(p)
    73  	}
    74  
    75  	n = len(p)
    76  
    77  	// If there is buffered input in the state, keep XOR'ing.
    78  	if d.n > 0 {
    79  		x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
    80  		d.n += x
    81  		p = p[x:]
    82  	}
    83  
    84  	// If the sponge is full, apply the permutation.
    85  	if d.n == d.rate {
    86  		// Absorbing a "rate"ful of zeroes effectively XORs the state with
    87  		// zeroes (a no-op) and then runs the permutation. The actual function
    88  		// doesn't matter, they all run the same permutation.
    89  		kimd(shake_128, &d.a, make([]byte, rateK256))
    90  		d.n = 0
    91  	}
    92  
    93  	// Absorb full blocks with KIMD.
    94  	if len(p) >= d.rate {
    95  		wholeBlocks := len(p) / d.rate * d.rate
    96  		kimd(d.function(), &d.a, p[:wholeBlocks])
    97  		p = p[wholeBlocks:]
    98  	}
    99  
   100  	// If there is any trailing input, XOR it into the state.
   101  	if len(p) > 0 {
   102  		d.n += subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
   103  	}
   104  
   105  	return
   106  }
   107  
   108  func (d *Digest) sum(b []byte) []byte {
   109  	if d.state != spongeAbsorbing {
   110  		panic("sha3: Sum after Read")
   111  	}
   112  	if !useSHA3 || d.dsbyte != dsbyteSHA3 && d.dsbyte != dsbyteShake {
   113  		return d.sumGeneric(b)
   114  	}
   115  
   116  	// Copy the state to preserve the original.
   117  	a := d.a
   118  
   119  	// We "absorb" a buffer of zeroes as long as the amount of input we already
   120  	// XOR'd into the sponge, to skip over it. The max cap is specified to avoid
   121  	// an allocation.
   122  	buf := make([]byte, d.n, rateK256)
   123  	function := d.function()
   124  	switch function {
   125  	case sha3_224, sha3_256, sha3_384, sha3_512:
   126  		klmd(function, &a, nil, buf)
   127  		return append(b, a[:d.outputLen]...)
   128  	case shake_128, shake_256:
   129  		h := make([]byte, d.outputLen, 64)
   130  		klmd(function, &a, h, buf)
   131  		return append(b, h...)
   132  	default:
   133  		panic("sha3: unknown function")
   134  	}
   135  }
   136  
   137  func (d *Digest) read(out []byte) (n int, err error) {
   138  	if !useSHA3 || d.dsbyte != dsbyteShake {
   139  		return d.readGeneric(out)
   140  	}
   141  
   142  	n = len(out)
   143  
   144  	if d.state == spongeAbsorbing {
   145  		d.state = spongeSqueezing
   146  
   147  		// We "absorb" a buffer of zeroes as long as the amount of input we
   148  		// already XOR'd into the sponge, to skip over it. The max cap is
   149  		// specified to avoid an allocation.
   150  		buf := make([]byte, d.n, rateK256)
   151  		klmd(d.function(), &d.a, out, buf)
   152  	} else {
   153  		// We have "buffered" output still to copy.
   154  		if d.n < d.rate {
   155  			x := copy(out, d.a[d.n:d.rate])
   156  			d.n += x
   157  			out = out[x:]
   158  		}
   159  		if len(out) == 0 {
   160  			return
   161  		}
   162  
   163  		klmd(d.function()|nopad, &d.a, out, nil)
   164  	}
   165  
   166  	if len(out)%d.rate == 0 {
   167  		// The final permutation was not performed,
   168  		// so there is no "buffered" output.
   169  		d.n = d.rate
   170  	} else {
   171  		d.n = len(out) % d.rate
   172  	}
   173  
   174  	return
   175  }
   176  
   177  func (d *Digest) function() code {
   178  	switch d.rate {
   179  	case rateK256:
   180  		return shake_128
   181  	case rateK448:
   182  		return sha3_224
   183  	case rateK512:
   184  		if d.dsbyte == dsbyteSHA3 {
   185  			return sha3_256
   186  		} else {
   187  			return shake_256
   188  		}
   189  	case rateK768:
   190  		return sha3_384
   191  	case rateK1024:
   192  		return sha3_512
   193  	default:
   194  		panic("invalid rate")
   195  	}
   196  }
   197  

View as plain text