1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1996-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
19 ***********************************************************************/
24 * By Steve Reid <steve@edmweb.com>
27 * Test Vectors (from FIPS PUB 180-1)
29 * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
30 * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
31 * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
32 * A million repetitions of "a"
33 * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
36 #define sha1_description "FIPS 180-1 SHA-1 secure hash algorithm 1."
37 #define sha1_options "[+(version)?sha1 (FIPS 180-1) 1996-09-26]\
38 [+(author)?Steve Reid <steve@edmweb.com>]"
39 #define sha1_match "sha1|SHA1|sha-1|SHA-1"
42 #define sha1_padding md5_pad
52 uint8_t digest_sum
[20];
55 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
58 * blk0() and blk() perform the initial expand.
59 * I got the idea of expanding during the round function from SSLeay
63 (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \
64 | (rol(block->l[i], 8) & 0x00FF00FF))
66 # define blk0(i) block->l[i]
69 (block->l[i & 15] = rol(block->l[(i + 13) & 15] \
70 ^ block->l[(i + 8) & 15] \
71 ^ block->l[(i + 2) & 15] \
72 ^ block->l[i & 15], 1))
75 * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
77 #define R0(v,w,x,y,z,i) \
78 z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
80 #define R1(v,w,x,y,z,i) \
81 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
83 #define R2(v,w,x,y,z,i) \
84 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
86 #define R3(v,w,x,y,z,i) \
87 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
89 #define R4(v,w,x,y,z,i) \
90 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
99 static void do_R01(uint32_t *a
, uint32_t *b
, uint32_t *c
,
100 uint32_t *d
, uint32_t *e
, CHAR64LONG16
*);
101 static void do_R2(uint32_t *a
, uint32_t *b
, uint32_t *c
,
102 uint32_t *d
, uint32_t *e
, CHAR64LONG16
*);
103 static void do_R3(uint32_t *a
, uint32_t *b
, uint32_t *c
,
104 uint32_t *d
, uint32_t *e
, CHAR64LONG16
*);
105 static void do_R4(uint32_t *a
, uint32_t *b
, uint32_t *c
,
106 uint32_t *d
, uint32_t *e
, CHAR64LONG16
*);
108 #define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i)
109 #define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i)
110 #define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i)
111 #define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i)
112 #define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i)
115 do_R01(uint32_t *a
, uint32_t *b
, uint32_t *c
, uint32_t *d
,
116 uint32_t *e
, CHAR64LONG16
*block
)
118 nR0(a
,b
,c
,d
,e
, 0); nR0(e
,a
,b
,c
,d
, 1); nR0(d
,e
,a
,b
,c
, 2);
119 nR0(c
,d
,e
,a
,b
, 3); nR0(b
,c
,d
,e
,a
, 4); nR0(a
,b
,c
,d
,e
, 5);
120 nR0(e
,a
,b
,c
,d
, 6); nR0(d
,e
,a
,b
,c
, 7); nR0(c
,d
,e
,a
,b
, 8);
121 nR0(b
,c
,d
,e
,a
, 9); nR0(a
,b
,c
,d
,e
,10); nR0(e
,a
,b
,c
,d
,11);
122 nR0(d
,e
,a
,b
,c
,12); nR0(c
,d
,e
,a
,b
,13); nR0(b
,c
,d
,e
,a
,14);
123 nR0(a
,b
,c
,d
,e
,15); nR1(e
,a
,b
,c
,d
,16); nR1(d
,e
,a
,b
,c
,17);
124 nR1(c
,d
,e
,a
,b
,18); nR1(b
,c
,d
,e
,a
,19);
128 do_R2(uint32_t *a
, uint32_t *b
, uint32_t *c
, uint32_t *d
,
129 uint32_t *e
, CHAR64LONG16
*block
)
131 nR2(a
,b
,c
,d
,e
,20); nR2(e
,a
,b
,c
,d
,21); nR2(d
,e
,a
,b
,c
,22);
132 nR2(c
,d
,e
,a
,b
,23); nR2(b
,c
,d
,e
,a
,24); nR2(a
,b
,c
,d
,e
,25);
133 nR2(e
,a
,b
,c
,d
,26); nR2(d
,e
,a
,b
,c
,27); nR2(c
,d
,e
,a
,b
,28);
134 nR2(b
,c
,d
,e
,a
,29); nR2(a
,b
,c
,d
,e
,30); nR2(e
,a
,b
,c
,d
,31);
135 nR2(d
,e
,a
,b
,c
,32); nR2(c
,d
,e
,a
,b
,33); nR2(b
,c
,d
,e
,a
,34);
136 nR2(a
,b
,c
,d
,e
,35); nR2(e
,a
,b
,c
,d
,36); nR2(d
,e
,a
,b
,c
,37);
137 nR2(c
,d
,e
,a
,b
,38); nR2(b
,c
,d
,e
,a
,39);
141 do_R3(uint32_t *a
, uint32_t *b
, uint32_t *c
, uint32_t *d
,
142 uint32_t *e
, CHAR64LONG16
*block
)
144 nR3(a
,b
,c
,d
,e
,40); nR3(e
,a
,b
,c
,d
,41); nR3(d
,e
,a
,b
,c
,42);
145 nR3(c
,d
,e
,a
,b
,43); nR3(b
,c
,d
,e
,a
,44); nR3(a
,b
,c
,d
,e
,45);
146 nR3(e
,a
,b
,c
,d
,46); nR3(d
,e
,a
,b
,c
,47); nR3(c
,d
,e
,a
,b
,48);
147 nR3(b
,c
,d
,e
,a
,49); nR3(a
,b
,c
,d
,e
,50); nR3(e
,a
,b
,c
,d
,51);
148 nR3(d
,e
,a
,b
,c
,52); nR3(c
,d
,e
,a
,b
,53); nR3(b
,c
,d
,e
,a
,54);
149 nR3(a
,b
,c
,d
,e
,55); nR3(e
,a
,b
,c
,d
,56); nR3(d
,e
,a
,b
,c
,57);
150 nR3(c
,d
,e
,a
,b
,58); nR3(b
,c
,d
,e
,a
,59);
154 do_R4(uint32_t *a
, uint32_t *b
, uint32_t *c
, uint32_t *d
,
155 uint32_t *e
, CHAR64LONG16
*block
)
157 nR4(a
,b
,c
,d
,e
,60); nR4(e
,a
,b
,c
,d
,61); nR4(d
,e
,a
,b
,c
,62);
158 nR4(c
,d
,e
,a
,b
,63); nR4(b
,c
,d
,e
,a
,64); nR4(a
,b
,c
,d
,e
,65);
159 nR4(e
,a
,b
,c
,d
,66); nR4(d
,e
,a
,b
,c
,67); nR4(c
,d
,e
,a
,b
,68);
160 nR4(b
,c
,d
,e
,a
,69); nR4(a
,b
,c
,d
,e
,70); nR4(e
,a
,b
,c
,d
,71);
161 nR4(d
,e
,a
,b
,c
,72); nR4(c
,d
,e
,a
,b
,73); nR4(b
,c
,d
,e
,a
,74);
162 nR4(a
,b
,c
,d
,e
,75); nR4(e
,a
,b
,c
,d
,76); nR4(d
,e
,a
,b
,c
,77);
163 nR4(c
,d
,e
,a
,b
,78); nR4(b
,c
,d
,e
,a
,79);
168 * Hash a single 512-bit block. This is the core of the algorithm.
171 sha1_transform(uint32_t state
[5], const unsigned char buffer
[64]) {
172 uint32_t a
, b
, c
, d
, e
;
174 CHAR64LONG16 workspace
;
177 (void)memcpy(block
, buffer
, 64);
179 /* Copy sha->state[] to working vars */
187 do_R01(&a
, &b
, &c
, &d
, &e
, block
);
188 do_R2(&a
, &b
, &c
, &d
, &e
, block
);
189 do_R3(&a
, &b
, &c
, &d
, &e
, block
);
190 do_R4(&a
, &b
, &c
, &d
, &e
, block
);
192 /* 4 rounds of 20 operations each. Loop unrolled. */
193 R0(a
,b
,c
,d
,e
, 0); R0(e
,a
,b
,c
,d
, 1); R0(d
,e
,a
,b
,c
, 2); R0(c
,d
,e
,a
,b
, 3);
194 R0(b
,c
,d
,e
,a
, 4); R0(a
,b
,c
,d
,e
, 5); R0(e
,a
,b
,c
,d
, 6); R0(d
,e
,a
,b
,c
, 7);
195 R0(c
,d
,e
,a
,b
, 8); R0(b
,c
,d
,e
,a
, 9); R0(a
,b
,c
,d
,e
,10); R0(e
,a
,b
,c
,d
,11);
196 R0(d
,e
,a
,b
,c
,12); R0(c
,d
,e
,a
,b
,13); R0(b
,c
,d
,e
,a
,14); R0(a
,b
,c
,d
,e
,15);
197 R1(e
,a
,b
,c
,d
,16); R1(d
,e
,a
,b
,c
,17); R1(c
,d
,e
,a
,b
,18); R1(b
,c
,d
,e
,a
,19);
198 R2(a
,b
,c
,d
,e
,20); R2(e
,a
,b
,c
,d
,21); R2(d
,e
,a
,b
,c
,22); R2(c
,d
,e
,a
,b
,23);
199 R2(b
,c
,d
,e
,a
,24); R2(a
,b
,c
,d
,e
,25); R2(e
,a
,b
,c
,d
,26); R2(d
,e
,a
,b
,c
,27);
200 R2(c
,d
,e
,a
,b
,28); R2(b
,c
,d
,e
,a
,29); R2(a
,b
,c
,d
,e
,30); R2(e
,a
,b
,c
,d
,31);
201 R2(d
,e
,a
,b
,c
,32); R2(c
,d
,e
,a
,b
,33); R2(b
,c
,d
,e
,a
,34); R2(a
,b
,c
,d
,e
,35);
202 R2(e
,a
,b
,c
,d
,36); R2(d
,e
,a
,b
,c
,37); R2(c
,d
,e
,a
,b
,38); R2(b
,c
,d
,e
,a
,39);
203 R3(a
,b
,c
,d
,e
,40); R3(e
,a
,b
,c
,d
,41); R3(d
,e
,a
,b
,c
,42); R3(c
,d
,e
,a
,b
,43);
204 R3(b
,c
,d
,e
,a
,44); R3(a
,b
,c
,d
,e
,45); R3(e
,a
,b
,c
,d
,46); R3(d
,e
,a
,b
,c
,47);
205 R3(c
,d
,e
,a
,b
,48); R3(b
,c
,d
,e
,a
,49); R3(a
,b
,c
,d
,e
,50); R3(e
,a
,b
,c
,d
,51);
206 R3(d
,e
,a
,b
,c
,52); R3(c
,d
,e
,a
,b
,53); R3(b
,c
,d
,e
,a
,54); R3(a
,b
,c
,d
,e
,55);
207 R3(e
,a
,b
,c
,d
,56); R3(d
,e
,a
,b
,c
,57); R3(c
,d
,e
,a
,b
,58); R3(b
,c
,d
,e
,a
,59);
208 R4(a
,b
,c
,d
,e
,60); R4(e
,a
,b
,c
,d
,61); R4(d
,e
,a
,b
,c
,62); R4(c
,d
,e
,a
,b
,63);
209 R4(b
,c
,d
,e
,a
,64); R4(a
,b
,c
,d
,e
,65); R4(e
,a
,b
,c
,d
,66); R4(d
,e
,a
,b
,c
,67);
210 R4(c
,d
,e
,a
,b
,68); R4(b
,c
,d
,e
,a
,69); R4(a
,b
,c
,d
,e
,70); R4(e
,a
,b
,c
,d
,71);
211 R4(d
,e
,a
,b
,c
,72); R4(c
,d
,e
,a
,b
,73); R4(b
,c
,d
,e
,a
,74); R4(a
,b
,c
,d
,e
,75);
212 R4(e
,a
,b
,c
,d
,76); R4(d
,e
,a
,b
,c
,77); R4(c
,d
,e
,a
,b
,78); R4(b
,c
,d
,e
,a
,79);
215 /* Add the working vars back into context.state[] */
223 a
= b
= c
= d
= e
= 0;
227 sha1_block(register Sum_t
* p
, const void* s
, size_t len
)
229 Sha1_t
* sha
= (Sha1_t
*)p
;
230 uint8_t* data
= (uint8_t*)s
;
235 if ((sha
->count
[0] += len
<< 3) < j
)
236 sha
->count
[1] += (len
>> 29) + 1;
238 if ((j
+ len
) > 63) {
239 (void)memcpy(&sha
->buffer
[j
], data
, (i
= 64 - j
));
240 sha1_transform(sha
->state
, sha
->buffer
);
241 for ( ; i
+ 63 < len
; i
+= 64)
242 sha1_transform(sha
->state
, &data
[i
]);
248 (void)memcpy(&sha
->buffer
[j
], &data
[i
], len
- i
);
256 register Sha1_t
* sha
= (Sha1_t
*)p
;
258 sha
->count
[0] = sha
->count
[1] = 0;
259 sha
->state
[0] = 0x67452301;
260 sha
->state
[1] = 0xEFCDAB89;
261 sha
->state
[2] = 0x98BADCFE;
262 sha
->state
[3] = 0x10325476;
263 sha
->state
[4] = 0xC3D2E1F0;
269 sha1_open(const Method_t
* method
, const char* name
)
273 if (sha
= newof(0, Sha1_t
, 1, 0))
275 sha
->method
= (Method_t
*)method
;
277 sha1_init((Sum_t
*)sha
);
283 * Add padding and return the message digest.
286 static const unsigned char final_200
= 128;
287 static const unsigned char final_0
= 0;
292 Sha1_t
* sha
= (Sha1_t
*)p
;
294 unsigned char finalcount
[8];
296 for (i
= 0; i
< 8; i
++) {
297 /* Endian independent */
298 finalcount
[i
] = (unsigned char)
299 ((sha
->count
[(i
>= 4 ? 0 : 1)]
300 >> ((3 - (i
& 3)) * 8)) & 255);
303 sha1_block(p
, &final_200
, 1);
304 while ((sha
->count
[0] & 504) != 448)
305 sha1_block(p
, &final_0
, 1);
306 /* The next Update should cause a sha1_transform() */
307 sha1_block(p
, finalcount
, 8);
309 for (i
= 0; i
< elementsof(sha
->digest
); i
++)
311 sha
->digest
[i
] = (unsigned char)((sha
->state
[i
>> 2] >> ((3 - (i
& 3)) * 8)) & 255);
312 sha
->digest_sum
[i
] ^= sha
->digest
[i
];
314 memset(sha
->count
, 0, sizeof(sha
->count
));
315 memset(sha
->state
, 0, sizeof(sha
->state
));
316 memset(sha
->buffer
, 0, sizeof(sha
->buffer
));
321 sha1_print(Sum_t
* p
, Sfio_t
* sp
, register int flags
, size_t scale
)
323 register Sha1_t
* sha
= (Sha1_t
*)p
;
324 register unsigned char* d
;
327 d
= (flags
& SUM_TOTAL
) ? sha
->digest_sum
: sha
->digest
;
328 for (n
= 0; n
< elementsof(sha
->digest
); n
++)
329 sfprintf(sp
, "%02x", d
[n
]);
334 sha1_data(Sum_t
* p
, Sumdata_t
* data
)
336 register Sha1_t
* sha
= (Sha1_t
*)p
;
338 data
->size
= elementsof(sha
->digest
);
340 data
->buf
= sha
->digest
;