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  }