Source file src/vendor/golang.org/x/crypto/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 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  	// 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.
   201  func (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.
   225  func (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.
   234  func (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.
   242  func (s *asmState) BlockSize() int {
   243  	return s.rate
   244  }
   245  
   246  // Clone returns a copy of the ShakeHash in its current state.
   247  func (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.
   253  func 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.
   262  func 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.
   271  func 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.
   280  func 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.
   289  func 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.
   298  func newShake256() ShakeHash {
   299  	if cpu.S390X.HasSHA3 {
   300  		return newAsmState(shake_256)
   301  	}
   302  	return newShake256Generic()
   303  }
   304  

View as plain text