Source file src/crypto/internal/fips140/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/fips140"
    15  	"crypto/internal/fips140/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  	clear(d.a[:])
    65  	d.state = spongeAbsorbing
    66  	d.n = 0
    67  }
    68  
    69  func (d *Digest) Clone() *Digest {
    70  	ret := *d
    71  	return &ret
    72  }
    73  
    74  // permute applies the KeccakF-1600 permutation.
    75  func (d *Digest) permute() {
    76  	keccakF1600(&d.a)
    77  	d.n = 0
    78  }
    79  
    80  // padAndPermute appends the domain separation bits in dsbyte, applies
    81  // the multi-bitrate 10..1 padding rule, and permutes the state.
    82  func (d *Digest) padAndPermute() {
    83  	// Pad with this instance's domain-separator bits. We know that there's
    84  	// at least one byte of space in the sponge because, if it were full,
    85  	// permute would have been called to empty it. dsbyte also contains the
    86  	// first one bit for the padding. See the comment in the state struct.
    87  	d.a[d.n] ^= d.dsbyte
    88  	// This adds the final one bit for the padding. Because of the way that
    89  	// bits are numbered from the LSB upwards, the final bit is the MSB of
    90  	// the last byte.
    91  	d.a[d.rate-1] ^= 0x80
    92  	// Apply the permutation
    93  	d.permute()
    94  	d.state = spongeSqueezing
    95  }
    96  
    97  // Write absorbs more data into the hash's state.
    98  func (d *Digest) Write(p []byte) (n int, err error) { return d.write(p) }
    99  func (d *Digest) writeGeneric(p []byte) (n int, err error) {
   100  	if d.state != spongeAbsorbing {
   101  		panic("sha3: Write after Read")
   102  	}
   103  
   104  	n = len(p)
   105  
   106  	for len(p) > 0 {
   107  		x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
   108  		d.n += x
   109  		p = p[x:]
   110  
   111  		// If the sponge is full, apply the permutation.
   112  		if d.n == d.rate {
   113  			d.permute()
   114  		}
   115  	}
   116  
   117  	return
   118  }
   119  
   120  // read squeezes an arbitrary number of bytes from the sponge.
   121  func (d *Digest) readGeneric(out []byte) (n int, err error) {
   122  	// If we're still absorbing, pad and apply the permutation.
   123  	if d.state == spongeAbsorbing {
   124  		d.padAndPermute()
   125  	}
   126  
   127  	n = len(out)
   128  
   129  	// Now, do the squeezing.
   130  	for len(out) > 0 {
   131  		// Apply the permutation if we've squeezed the sponge dry.
   132  		if d.n == d.rate {
   133  			d.permute()
   134  		}
   135  
   136  		x := copy(out, d.a[d.n:d.rate])
   137  		d.n += x
   138  		out = out[x:]
   139  	}
   140  
   141  	return
   142  }
   143  
   144  // Sum appends the current hash to b and returns the resulting slice.
   145  // It does not change the underlying hash state.
   146  func (d *Digest) Sum(b []byte) []byte {
   147  	fips140.RecordApproved()
   148  	return d.sum(b)
   149  }
   150  
   151  func (d *Digest) sumGeneric(b []byte) []byte {
   152  	if d.state != spongeAbsorbing {
   153  		panic("sha3: Sum after Read")
   154  	}
   155  
   156  	// Make a copy of the original hash so that caller can keep writing
   157  	// and summing.
   158  	dup := d.Clone()
   159  	hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation
   160  	dup.read(hash)
   161  	return append(b, hash...)
   162  }
   163  
   164  const (
   165  	magicSHA3   = "sha\x08"
   166  	magicShake  = "sha\x09"
   167  	magicCShake = "sha\x0a"
   168  	magicKeccak = "sha\x0b"
   169  	// magic || rate || main state || n || sponge direction
   170  	marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1
   171  )
   172  
   173  func (d *Digest) MarshalBinary() ([]byte, error) {
   174  	return d.AppendBinary(make([]byte, 0, marshaledSize))
   175  }
   176  
   177  func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
   178  	switch d.dsbyte {
   179  	case dsbyteSHA3:
   180  		b = append(b, magicSHA3...)
   181  	case dsbyteShake:
   182  		b = append(b, magicShake...)
   183  	case dsbyteCShake:
   184  		b = append(b, magicCShake...)
   185  	case dsbyteKeccak:
   186  		b = append(b, magicKeccak...)
   187  	default:
   188  		panic("unknown dsbyte")
   189  	}
   190  	// rate is at most 168, and n is at most rate.
   191  	b = append(b, byte(d.rate))
   192  	b = append(b, d.a[:]...)
   193  	b = append(b, byte(d.n), byte(d.state))
   194  	return b, nil
   195  }
   196  
   197  func (d *Digest) UnmarshalBinary(b []byte) error {
   198  	if len(b) != marshaledSize {
   199  		return errors.New("sha3: invalid hash state")
   200  	}
   201  
   202  	magic := string(b[:len(magicSHA3)])
   203  	b = b[len(magicSHA3):]
   204  	switch {
   205  	case magic == magicSHA3 && d.dsbyte == dsbyteSHA3:
   206  	case magic == magicShake && d.dsbyte == dsbyteShake:
   207  	case magic == magicCShake && d.dsbyte == dsbyteCShake:
   208  	case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
   209  	default:
   210  		return errors.New("sha3: invalid hash state identifier")
   211  	}
   212  
   213  	rate := int(b[0])
   214  	b = b[1:]
   215  	if rate != d.rate {
   216  		return errors.New("sha3: invalid hash state function")
   217  	}
   218  
   219  	copy(d.a[:], b)
   220  	b = b[len(d.a):]
   221  
   222  	n, state := int(b[0]), spongeDirection(b[1])
   223  	if n > d.rate {
   224  		return errors.New("sha3: invalid hash state")
   225  	}
   226  	d.n = n
   227  	if state != spongeAbsorbing && state != spongeSqueezing {
   228  		return errors.New("sha3: invalid hash state")
   229  	}
   230  	d.state = state
   231  
   232  	return nil
   233  }
   234  

View as plain text