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

View as plain text