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) Clone() (hash.Cloner, error) {
97 r := *d
98 return &r, nil
99 }
100
101 func (d *digest) Reset() {
102 d.h[0] = init0
103 d.h[1] = init1
104 d.h[2] = init2
105 d.h[3] = init3
106 d.h[4] = init4
107 d.nx = 0
108 d.len = 0
109 }
110
111
112
113
114
115 func New() hash.Hash {
116 if boring.Enabled {
117 return boring.NewSHA1()
118 }
119 d := new(digest)
120 d.Reset()
121 return d
122 }
123
124 func (d *digest) Size() int { return Size }
125
126 func (d *digest) BlockSize() int { return BlockSize }
127
128 func (d *digest) Write(p []byte) (nn int, err error) {
129 if fips140only.Enabled {
130 return 0, errors.New("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode")
131 }
132 boring.Unreachable()
133 nn = len(p)
134 d.len += uint64(nn)
135 if d.nx > 0 {
136 n := copy(d.x[d.nx:], p)
137 d.nx += n
138 if d.nx == chunk {
139 block(d, d.x[:])
140 d.nx = 0
141 }
142 p = p[n:]
143 }
144 if len(p) >= chunk {
145 n := len(p) &^ (chunk - 1)
146 block(d, p[:n])
147 p = p[n:]
148 }
149 if len(p) > 0 {
150 d.nx = copy(d.x[:], p)
151 }
152 return
153 }
154
155 func (d *digest) Sum(in []byte) []byte {
156 boring.Unreachable()
157
158 d0 := *d
159 hash := d0.checkSum()
160 return append(in, hash[:]...)
161 }
162
163 func (d *digest) checkSum() [Size]byte {
164 if fips140only.Enabled {
165 panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode")
166 }
167
168 len := d.len
169
170 var tmp [64 + 8]byte
171 tmp[0] = 0x80
172 var t uint64
173 if len%64 < 56 {
174 t = 56 - len%64
175 } else {
176 t = 64 + 56 - len%64
177 }
178
179
180 len <<= 3
181 padlen := tmp[:t+8]
182 byteorder.BEPutUint64(padlen[t:], len)
183 d.Write(padlen)
184
185 if d.nx != 0 {
186 panic("d.nx != 0")
187 }
188
189 var digest [Size]byte
190
191 byteorder.BEPutUint32(digest[0:], d.h[0])
192 byteorder.BEPutUint32(digest[4:], d.h[1])
193 byteorder.BEPutUint32(digest[8:], d.h[2])
194 byteorder.BEPutUint32(digest[12:], d.h[3])
195 byteorder.BEPutUint32(digest[16:], d.h[4])
196
197 return digest
198 }
199
200
201 func (d *digest) ConstantTimeSum(in []byte) []byte {
202 d0 := *d
203 hash := d0.constSum()
204 return append(in, hash[:]...)
205 }
206
207 func (d *digest) constSum() [Size]byte {
208 if fips140only.Enabled {
209 panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode")
210 }
211
212 var length [8]byte
213 l := d.len << 3
214 for i := uint(0); i < 8; i++ {
215 length[i] = byte(l >> (56 - 8*i))
216 }
217
218 nx := byte(d.nx)
219 t := nx - 56
220 mask1b := byte(int8(t) >> 7)
221
222 separator := byte(0x80)
223 for i := byte(0); i < chunk; i++ {
224 mask := byte(int8(i-nx) >> 7)
225
226
227 d.x[i] = (^mask & separator) | (mask & d.x[i])
228
229
230 separator &= mask
231
232 if i >= 56 {
233
234 d.x[i] |= mask1b & length[i-56]
235 }
236 }
237
238
239 block(d, d.x[:])
240
241 var digest [Size]byte
242 for i, s := range d.h {
243 digest[i*4] = mask1b & byte(s>>24)
244 digest[i*4+1] = mask1b & byte(s>>16)
245 digest[i*4+2] = mask1b & byte(s>>8)
246 digest[i*4+3] = mask1b & byte(s)
247 }
248
249 for i := byte(0); i < chunk; i++ {
250
251 if i < 56 {
252 d.x[i] = separator
253 separator = 0
254 } else {
255 d.x[i] = length[i-56]
256 }
257 }
258
259
260 block(d, d.x[:])
261
262 for i, s := range d.h {
263 digest[i*4] |= ^mask1b & byte(s>>24)
264 digest[i*4+1] |= ^mask1b & byte(s>>16)
265 digest[i*4+2] |= ^mask1b & byte(s>>8)
266 digest[i*4+3] |= ^mask1b & byte(s)
267 }
268
269 return digest
270 }
271
272
273 func Sum(data []byte) [Size]byte {
274 if boring.Enabled {
275 return boring.SHA1(data)
276 }
277 if fips140only.Enabled {
278 panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode")
279 }
280 var d digest
281 d.Reset()
282 d.Write(data)
283 return d.checkSum()
284 }
285
View as plain text