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

     1  // Copyright 2014 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  // Package sha3 implements the SHA-3 fixed-output-length hash functions and
     6  // the SHAKE variable-output-length functions defined by [FIPS 202], as well as
     7  // the cSHAKE extendable-output-length functions defined by [SP 800-185].
     8  //
     9  // [FIPS 202]: https://doi.org/10.6028/NIST.FIPS.202
    10  // [SP 800-185]: https://doi.org/10.6028/NIST.SP.800-185
    11  package sha3
    12  
    13  import (
    14  	"crypto/internal/fips"
    15  	"crypto/internal/fips/subtle"
    16  	"errors"
    17  )
    18  
    19  // spongeDirection indicates the direction bytes are flowing through the sponge.
    20  type spongeDirection int
    21  
    22  const (
    23  	// spongeAbsorbing indicates that the sponge is absorbing input.
    24  	spongeAbsorbing spongeDirection = iota
    25  	// spongeSqueezing indicates that the sponge is being squeezed.
    26  	spongeSqueezing
    27  )
    28  
    29  type Digest struct {
    30  	a [1600 / 8]byte // main state of the hash
    31  
    32  	// a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR
    33  	// into before running the permutation. If squeezing, it's the remaining
    34  	// output to produce before running the permutation.
    35  	n, rate int
    36  
    37  	// dsbyte contains the "domain separation" bits and the first bit of
    38  	// the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
    39  	// SHA-3 and SHAKE functions by appending bitstrings to the message.
    40  	// Using a little-endian bit-ordering convention, these are "01" for SHA-3
    41  	// and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
    42  	// padding rule from section 5.1 is applied to pad the message to a multiple
    43  	// of the rate, which involves adding a "1" bit, zero or more "0" bits, and
    44  	// a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
    45  	// giving 00000110b (0x06) and 00011111b (0x1f).
    46  	// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
    47  	//     "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
    48  	//      Extendable-Output Functions (May 2014)"
    49  	dsbyte byte
    50  
    51  	outputLen int             // the default output size in bytes
    52  	state     spongeDirection // whether the sponge is absorbing or squeezing
    53  }
    54  
    55  // BlockSize returns the rate of sponge underlying this hash function.
    56  func (d *Digest) BlockSize() int { return d.rate }
    57  
    58  // Size returns the output size of the hash function in bytes.
    59  func (d *Digest) Size() int { return d.outputLen }
    60  
    61  // Reset resets the Digest to its initial state.
    62  func (d *Digest) Reset() {
    63  	// Zero the permutation's state.
    64  	for i := range d.a {
    65  		d.a[i] = 0
    66  	}
    67  	d.state = spongeAbsorbing
    68  	d.n = 0
    69  }
    70  
    71  func (d *Digest) Clone() *Digest {
    72  	ret := *d
    73  	return &ret
    74  }
    75  
    76  // permute applies the KeccakF-1600 permutation.
    77  func (d *Digest) permute() {
    78  	keccakF1600(&d.a)
    79  	d.n = 0
    80  }
    81  
    82  // padAndPermute appends the domain separation bits in dsbyte, applies
    83  // the multi-bitrate 10..1 padding rule, and permutes the state.
    84  func (d *Digest) padAndPermute() {
    85  	// Pad with this instance's domain-separator bits. We know that there's
    86  	// at least one byte of space in the sponge because, if it were full,
    87  	// permute would have been called to empty it. dsbyte also contains the
    88  	// first one bit for the padding. See the comment in the state struct.
    89  	d.a[d.n] ^= d.dsbyte
    90  	// This adds the final one bit for the padding. Because of the way that
    91  	// bits are numbered from the LSB upwards, the final bit is the MSB of
    92  	// the last byte.
    93  	d.a[d.rate-1] ^= 0x80
    94  	// Apply the permutation
    95  	d.permute()
    96  	d.state = spongeSqueezing
    97  }
    98  
    99  // Write absorbs more data into the hash's state.
   100  func (d *Digest) Write(p []byte) (n int, err error) { return d.write(p) }
   101  func (d *Digest) writeGeneric(p []byte) (n int, err error) {
   102  	if d.state != spongeAbsorbing {
   103  		panic("sha3: Write after Read")
   104  	}
   105  
   106  	n = len(p)
   107  
   108  	for len(p) > 0 {
   109  		x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
   110  		d.n += x
   111  		p = p[x:]
   112  
   113  		// If the sponge is full, apply the permutation.
   114  		if d.n == d.rate {
   115  			d.permute()
   116  		}
   117  	}
   118  
   119  	return
   120  }
   121  
   122  // read squeezes an arbitrary number of bytes from the sponge.
   123  func (d *Digest) readGeneric(out []byte) (n int, err error) {
   124  	// If we're still absorbing, pad and apply the permutation.
   125  	if d.state == spongeAbsorbing {
   126  		d.padAndPermute()
   127  	}
   128  
   129  	n = len(out)
   130  
   131  	// Now, do the squeezing.
   132  	for len(out) > 0 {
   133  		// Apply the permutation if we've squeezed the sponge dry.
   134  		if d.n == d.rate {
   135  			d.permute()
   136  		}
   137  
   138  		x := copy(out, d.a[d.n:d.rate])
   139  		d.n += x
   140  		out = out[x:]
   141  	}
   142  
   143  	return
   144  }
   145  
   146  // Sum appends the current hash to b and returns the resulting slice.
   147  // It does not change the underlying hash state.
   148  func (d *Digest) Sum(b []byte) []byte {
   149  	fips.RecordApproved()
   150  	return d.sum(b)
   151  }
   152  
   153  func (d *Digest) sumGeneric(b []byte) []byte {
   154  	if d.state != spongeAbsorbing {
   155  		panic("sha3: Sum after Read")
   156  	}
   157  
   158  	// Make a copy of the original hash so that caller can keep writing
   159  	// and summing.
   160  	dup := d.Clone()
   161  	hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation
   162  	dup.read(hash)
   163  	return append(b, hash...)
   164  }
   165  
   166  const (
   167  	magicSHA3   = "sha\x08"
   168  	magicShake  = "sha\x09"
   169  	magicCShake = "sha\x0a"
   170  	magicKeccak = "sha\x0b"
   171  	// magic || rate || main state || n || sponge direction
   172  	marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1
   173  )
   174  
   175  func (d *Digest) MarshalBinary() ([]byte, error) {
   176  	return d.AppendBinary(make([]byte, 0, marshaledSize))
   177  }
   178  
   179  func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
   180  	switch d.dsbyte {
   181  	case dsbyteSHA3:
   182  		b = append(b, magicSHA3...)
   183  	case dsbyteShake:
   184  		b = append(b, magicShake...)
   185  	case dsbyteCShake:
   186  		b = append(b, magicCShake...)
   187  	case dsbyteKeccak:
   188  		b = append(b, magicKeccak...)
   189  	default:
   190  		panic("unknown dsbyte")
   191  	}
   192  	// rate is at most 168, and n is at most rate.
   193  	b = append(b, byte(d.rate))
   194  	b = append(b, d.a[:]...)
   195  	b = append(b, byte(d.n), byte(d.state))
   196  	return b, nil
   197  }
   198  
   199  func (d *Digest) UnmarshalBinary(b []byte) error {
   200  	if len(b) != marshaledSize {
   201  		return errors.New("sha3: invalid hash state")
   202  	}
   203  
   204  	magic := string(b[:len(magicSHA3)])
   205  	b = b[len(magicSHA3):]
   206  	switch {
   207  	case magic == magicSHA3 && d.dsbyte == dsbyteSHA3:
   208  	case magic == magicShake && d.dsbyte == dsbyteShake:
   209  	case magic == magicCShake && d.dsbyte == dsbyteCShake:
   210  	case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
   211  	default:
   212  		return errors.New("sha3: invalid hash state identifier")
   213  	}
   214  
   215  	rate := int(b[0])
   216  	b = b[1:]
   217  	if rate != d.rate {
   218  		return errors.New("sha3: invalid hash state function")
   219  	}
   220  
   221  	copy(d.a[:], b)
   222  	b = b[len(d.a):]
   223  
   224  	n, state := int(b[0]), spongeDirection(b[1])
   225  	if n > d.rate {
   226  		return errors.New("sha3: invalid hash state")
   227  	}
   228  	d.n = n
   229  	if state != spongeAbsorbing && state != spongeSqueezing {
   230  		return errors.New("sha3: invalid hash state")
   231  	}
   232  	d.state = state
   233  
   234  	return nil
   235  }
   236  

View as plain text