Source file src/crypto/internal/fips140/sha256/sha256.go

     1  // Copyright 2009 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 sha256 implements the SHA-224 and SHA-256 hash algorithms as defined
     6  // in FIPS 180-4.
     7  package sha256
     8  
     9  import (
    10  	"crypto/internal/fips140"
    11  	"crypto/internal/fips140deps/byteorder"
    12  	"errors"
    13  	"hash"
    14  )
    15  
    16  // The size of a SHA-256 checksum in bytes.
    17  const size = 32
    18  
    19  // The size of a SHA-224 checksum in bytes.
    20  const size224 = 28
    21  
    22  // The block size of SHA-256 and SHA-224 in bytes.
    23  const blockSize = 64
    24  
    25  // The maximum number of bytes that can be passed to block(). The limit exists
    26  // because implementations that rely on assembly routines are not preemptible.
    27  const maxAsmIters = 1024
    28  const maxAsmSize = blockSize * maxAsmIters // 64KiB
    29  
    30  const (
    31  	chunk     = 64
    32  	init0     = 0x6A09E667
    33  	init1     = 0xBB67AE85
    34  	init2     = 0x3C6EF372
    35  	init3     = 0xA54FF53A
    36  	init4     = 0x510E527F
    37  	init5     = 0x9B05688C
    38  	init6     = 0x1F83D9AB
    39  	init7     = 0x5BE0CD19
    40  	init0_224 = 0xC1059ED8
    41  	init1_224 = 0x367CD507
    42  	init2_224 = 0x3070DD17
    43  	init3_224 = 0xF70E5939
    44  	init4_224 = 0xFFC00B31
    45  	init5_224 = 0x68581511
    46  	init6_224 = 0x64F98FA7
    47  	init7_224 = 0xBEFA4FA4
    48  )
    49  
    50  // Digest is a SHA-224 or SHA-256 [hash.Hash] implementation.
    51  type Digest struct {
    52  	h     [8]uint32
    53  	x     [chunk]byte
    54  	nx    int
    55  	len   uint64
    56  	is224 bool // mark if this digest is SHA-224
    57  }
    58  
    59  const (
    60  	magic224      = "sha\x02"
    61  	magic256      = "sha\x03"
    62  	marshaledSize = len(magic256) + 8*4 + chunk + 8
    63  )
    64  
    65  func (d *Digest) MarshalBinary() ([]byte, error) {
    66  	return d.AppendBinary(make([]byte, 0, marshaledSize))
    67  }
    68  
    69  func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
    70  	if d.is224 {
    71  		b = append(b, magic224...)
    72  	} else {
    73  		b = append(b, magic256...)
    74  	}
    75  	b = byteorder.BEAppendUint32(b, d.h[0])
    76  	b = byteorder.BEAppendUint32(b, d.h[1])
    77  	b = byteorder.BEAppendUint32(b, d.h[2])
    78  	b = byteorder.BEAppendUint32(b, d.h[3])
    79  	b = byteorder.BEAppendUint32(b, d.h[4])
    80  	b = byteorder.BEAppendUint32(b, d.h[5])
    81  	b = byteorder.BEAppendUint32(b, d.h[6])
    82  	b = byteorder.BEAppendUint32(b, d.h[7])
    83  	b = append(b, d.x[:d.nx]...)
    84  	b = append(b, make([]byte, len(d.x)-d.nx)...)
    85  	b = byteorder.BEAppendUint64(b, d.len)
    86  	return b, nil
    87  }
    88  
    89  func (d *Digest) UnmarshalBinary(b []byte) error {
    90  	if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) {
    91  		return errors.New("crypto/sha256: invalid hash state identifier")
    92  	}
    93  	if len(b) != marshaledSize {
    94  		return errors.New("crypto/sha256: invalid hash state size")
    95  	}
    96  	b = b[len(magic224):]
    97  	b, d.h[0] = consumeUint32(b)
    98  	b, d.h[1] = consumeUint32(b)
    99  	b, d.h[2] = consumeUint32(b)
   100  	b, d.h[3] = consumeUint32(b)
   101  	b, d.h[4] = consumeUint32(b)
   102  	b, d.h[5] = consumeUint32(b)
   103  	b, d.h[6] = consumeUint32(b)
   104  	b, d.h[7] = consumeUint32(b)
   105  	b = b[copy(d.x[:], b):]
   106  	b, d.len = consumeUint64(b)
   107  	d.nx = int(d.len % chunk)
   108  	return nil
   109  }
   110  
   111  func consumeUint64(b []byte) ([]byte, uint64) {
   112  	return b[8:], byteorder.BEUint64(b)
   113  }
   114  
   115  func consumeUint32(b []byte) ([]byte, uint32) {
   116  	return b[4:], byteorder.BEUint32(b)
   117  }
   118  
   119  func (d *Digest) Clone() (hash.Cloner, error) {
   120  	r := *d
   121  	return &r, nil
   122  }
   123  
   124  func (d *Digest) Reset() {
   125  	if !d.is224 {
   126  		d.h[0] = init0
   127  		d.h[1] = init1
   128  		d.h[2] = init2
   129  		d.h[3] = init3
   130  		d.h[4] = init4
   131  		d.h[5] = init5
   132  		d.h[6] = init6
   133  		d.h[7] = init7
   134  	} else {
   135  		d.h[0] = init0_224
   136  		d.h[1] = init1_224
   137  		d.h[2] = init2_224
   138  		d.h[3] = init3_224
   139  		d.h[4] = init4_224
   140  		d.h[5] = init5_224
   141  		d.h[6] = init6_224
   142  		d.h[7] = init7_224
   143  	}
   144  	d.nx = 0
   145  	d.len = 0
   146  }
   147  
   148  // New returns a new Digest computing the SHA-256 hash.
   149  func New() *Digest {
   150  	d := new(Digest)
   151  	d.Reset()
   152  	return d
   153  }
   154  
   155  // New224 returns a new Digest computing the SHA-224 hash.
   156  func New224() *Digest {
   157  	d := new(Digest)
   158  	d.is224 = true
   159  	d.Reset()
   160  	return d
   161  }
   162  
   163  func (d *Digest) Size() int {
   164  	if !d.is224 {
   165  		return size
   166  	}
   167  	return size224
   168  }
   169  
   170  func (d *Digest) BlockSize() int { return blockSize }
   171  
   172  func (d *Digest) Write(p []byte) (nn int, err error) {
   173  	nn = len(p)
   174  	d.len += uint64(nn)
   175  	if d.nx > 0 {
   176  		n := copy(d.x[d.nx:], p)
   177  		d.nx += n
   178  		if d.nx == chunk {
   179  			block(d, d.x[:])
   180  			d.nx = 0
   181  		}
   182  		p = p[n:]
   183  	}
   184  	if len(p) >= chunk {
   185  		n := len(p) &^ (chunk - 1)
   186  		for n > maxAsmSize {
   187  			block(d, p[:maxAsmSize])
   188  			p = p[maxAsmSize:]
   189  			n -= maxAsmSize
   190  		}
   191  		block(d, p[:n])
   192  		p = p[n:]
   193  	}
   194  	if len(p) > 0 {
   195  		d.nx = copy(d.x[:], p)
   196  	}
   197  	return
   198  }
   199  
   200  func (d *Digest) Sum(in []byte) []byte {
   201  	fips140.RecordApproved()
   202  	// Make a copy of d so that caller can keep writing and summing.
   203  	d0 := *d
   204  	hash := d0.checkSum()
   205  	if d0.is224 {
   206  		return append(in, hash[:size224]...)
   207  	}
   208  	return append(in, hash[:]...)
   209  }
   210  
   211  func (d *Digest) checkSum() [size]byte {
   212  	len := d.len
   213  	// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
   214  	var tmp [64 + 8]byte // padding + length buffer
   215  	tmp[0] = 0x80
   216  	var t uint64
   217  	if len%64 < 56 {
   218  		t = 56 - len%64
   219  	} else {
   220  		t = 64 + 56 - len%64
   221  	}
   222  
   223  	// Length in bits.
   224  	len <<= 3
   225  	padlen := tmp[:t+8]
   226  	byteorder.BEPutUint64(padlen[t+0:], len)
   227  	d.Write(padlen)
   228  
   229  	if d.nx != 0 {
   230  		panic("d.nx != 0")
   231  	}
   232  
   233  	var digest [size]byte
   234  
   235  	byteorder.BEPutUint32(digest[0:], d.h[0])
   236  	byteorder.BEPutUint32(digest[4:], d.h[1])
   237  	byteorder.BEPutUint32(digest[8:], d.h[2])
   238  	byteorder.BEPutUint32(digest[12:], d.h[3])
   239  	byteorder.BEPutUint32(digest[16:], d.h[4])
   240  	byteorder.BEPutUint32(digest[20:], d.h[5])
   241  	byteorder.BEPutUint32(digest[24:], d.h[6])
   242  	if !d.is224 {
   243  		byteorder.BEPutUint32(digest[28:], d.h[7])
   244  	}
   245  
   246  	return digest
   247  }
   248  

View as plain text