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