1
2
3
4
5
6
7
8
9 package sha1
10
11 import (
12 "crypto"
13 "crypto/internal/boring"
14 "crypto/internal/fips140only"
15 "errors"
16 "hash"
17 "internal/byteorder"
18 )
19
20 func init() {
21 crypto.RegisterHash(crypto.SHA1, New)
22 }
23
24
25 const Size = 20
26
27
28 const BlockSize = 64
29
30 const (
31 chunk = 64
32 init0 = 0x67452301
33 init1 = 0xEFCDAB89
34 init2 = 0x98BADCFE
35 init3 = 0x10325476
36 init4 = 0xC3D2E1F0
37 )
38
39
40 type digest struct {
41 h [5]uint32
42 x [chunk]byte
43 nx int
44 len uint64
45 }
46
47 const (
48 magic = "sha\x01"
49 marshaledSize = len(magic) + 5*4 + chunk + 8
50 )
51
52 func (d *digest) MarshalBinary() ([]byte, error) {
53 return d.AppendBinary(make([]byte, 0, marshaledSize))
54 }
55
56 func (d *digest) AppendBinary(b []byte) ([]byte, error) {
57 b = append(b, magic...)
58 b = byteorder.BEAppendUint32(b, d.h[0])
59 b = byteorder.BEAppendUint32(b, d.h[1])
60 b = byteorder.BEAppendUint32(b, d.h[2])
61 b = byteorder.BEAppendUint32(b, d.h[3])
62 b = byteorder.BEAppendUint32(b, d.h[4])
63 b = append(b, d.x[:d.nx]...)
64 b = append(b, make([]byte, len(d.x)-d.nx)...)
65 b = byteorder.BEAppendUint64(b, d.len)
66 return b, nil
67 }
68
69 func (d *digest) UnmarshalBinary(b []byte) error {
70 if len(b) < len(magic) || string(b[:len(magic)]) != magic {
71 return errors.New("crypto/sha1: invalid hash state identifier")
72 }
73 if len(b) != marshaledSize {
74 return errors.New("crypto/sha1: invalid hash state size")
75 }
76 b = b[len(magic):]
77 b, d.h[0] = consumeUint32(b)
78 b, d.h[1] = consumeUint32(b)
79 b, d.h[2] = consumeUint32(b)
80 b, d.h[3] = consumeUint32(b)
81 b, d.h[4] = consumeUint32(b)
82 b = b[copy(d.x[:], b):]
83 b, d.len = consumeUint64(b)
84 d.nx = int(d.len % chunk)
85 return nil
86 }
87
88 func consumeUint64(b []byte) ([]byte, uint64) {
89 return b[8:], byteorder.BEUint64(b)
90 }
91
92 func consumeUint32(b []byte) ([]byte, uint32) {
93 return b[4:], byteorder.BEUint32(b)
94 }
95
96 func (d *digest) Reset() {
97 d.h[0] = init0
98 d.h[1] = init1
99 d.h[2] = init2
100 d.h[3] = init3
101 d.h[4] = init4
102 d.nx = 0
103 d.len = 0
104 }
105
106
107
108
109
110 func New() hash.Hash {
111 if boring.Enabled {
112 return boring.NewSHA1()
113 }
114 d := new(digest)
115 d.Reset()
116 return d
117 }
118
119 func (d *digest) Size() int { return Size }
120
121 func (d *digest) BlockSize() int { return BlockSize }
122
123 func (d *digest) Write(p []byte) (nn int, err error) {
124 if fips140only.Enabled {
125 return 0, errors.New("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode")
126 }
127 boring.Unreachable()
128 nn = len(p)
129 d.len += uint64(nn)
130 if d.nx > 0 {
131 n := copy(d.x[d.nx:], p)
132 d.nx += n
133 if d.nx == chunk {
134 block(d, d.x[:])
135 d.nx = 0
136 }
137 p = p[n:]
138 }
139 if len(p) >= chunk {
140 n := len(p) &^ (chunk - 1)
141 block(d, p[:n])
142 p = p[n:]
143 }
144 if len(p) > 0 {
145 d.nx = copy(d.x[:], p)
146 }
147 return
148 }
149
150 func (d *digest) Sum(in []byte) []byte {
151 boring.Unreachable()
152
153 d0 := *d
154 hash := d0.checkSum()
155 return append(in, hash[:]...)
156 }
157
158 func (d *digest) checkSum() [Size]byte {
159 if fips140only.Enabled {
160 panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode")
161 }
162
163 len := d.len
164
165 var tmp [64 + 8]byte
166 tmp[0] = 0x80
167 var t uint64
168 if len%64 < 56 {
169 t = 56 - len%64
170 } else {
171 t = 64 + 56 - len%64
172 }
173
174
175 len <<= 3
176 padlen := tmp[:t+8]
177 byteorder.BEPutUint64(padlen[t:], len)
178 d.Write(padlen)
179
180 if d.nx != 0 {
181 panic("d.nx != 0")
182 }
183
184 var digest [Size]byte
185
186 byteorder.BEPutUint32(digest[0:], d.h[0])
187 byteorder.BEPutUint32(digest[4:], d.h[1])
188 byteorder.BEPutUint32(digest[8:], d.h[2])
189 byteorder.BEPutUint32(digest[12:], d.h[3])
190 byteorder.BEPutUint32(digest[16:], d.h[4])
191
192 return digest
193 }
194
195
196 func (d *digest) ConstantTimeSum(in []byte) []byte {
197 d0 := *d
198 hash := d0.constSum()
199 return append(in, hash[:]...)
200 }
201
202 func (d *digest) constSum() [Size]byte {
203 if fips140only.Enabled {
204 panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode")
205 }
206
207 var length [8]byte
208 l := d.len << 3
209 for i := uint(0); i < 8; i++ {
210 length[i] = byte(l >> (56 - 8*i))
211 }
212
213 nx := byte(d.nx)
214 t := nx - 56
215 mask1b := byte(int8(t) >> 7)
216
217 separator := byte(0x80)
218 for i := byte(0); i < chunk; i++ {
219 mask := byte(int8(i-nx) >> 7)
220
221
222 d.x[i] = (^mask & separator) | (mask & d.x[i])
223
224
225 separator &= mask
226
227 if i >= 56 {
228
229 d.x[i] |= mask1b & length[i-56]
230 }
231 }
232
233
234 block(d, d.x[:])
235
236 var digest [Size]byte
237 for i, s := range d.h {
238 digest[i*4] = mask1b & byte(s>>24)
239 digest[i*4+1] = mask1b & byte(s>>16)
240 digest[i*4+2] = mask1b & byte(s>>8)
241 digest[i*4+3] = mask1b & byte(s)
242 }
243
244 for i := byte(0); i < chunk; i++ {
245
246 if i < 56 {
247 d.x[i] = separator
248 separator = 0
249 } else {
250 d.x[i] = length[i-56]
251 }
252 }
253
254
255 block(d, d.x[:])
256
257 for i, s := range d.h {
258 digest[i*4] |= ^mask1b & byte(s>>24)
259 digest[i*4+1] |= ^mask1b & byte(s>>16)
260 digest[i*4+2] |= ^mask1b & byte(s>>8)
261 digest[i*4+3] |= ^mask1b & byte(s)
262 }
263
264 return digest
265 }
266
267
268 func Sum(data []byte) [Size]byte {
269 if boring.Enabled {
270 return boring.SHA1(data)
271 }
272 if fips140only.Enabled {
273 panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode")
274 }
275 var d digest
276 d.Reset()
277 d.Write(data)
278 return d.checkSum()
279 }
280
View as plain text