diff options
Diffstat (limited to 'tools/hmac-sha1.c')
-rw-r--r-- | tools/hmac-sha1.c | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/tools/hmac-sha1.c b/tools/hmac-sha1.c new file mode 100644 index 0000000000..1b4b3b5abd --- /dev/null +++ b/tools/hmac-sha1.c | |||
@@ -0,0 +1,463 @@ | |||
1 | /* | ||
2 | * sha1.c | ||
3 | * | ||
4 | * Description: | ||
5 | * This file implements the Secure Hashing Algorithm 1 as | ||
6 | * defined in FIPS PUB 180-1 published April 17, 1995. | ||
7 | * | ||
8 | * The SHA-1, produces a 160-bit message digest for a given | ||
9 | * data stream. It should take about 2**n steps to find a | ||
10 | * message with the same digest as a given message and | ||
11 | * 2**(n/2) to find any two messages with the same digest, | ||
12 | * when n is the digest size in bits. Therefore, this | ||
13 | * algorithm can serve as a means of providing a | ||
14 | * "fingerprint" for a message. | ||
15 | * | ||
16 | * Portability Issues: | ||
17 | * SHA-1 is defined in terms of 32-bit "words". This code | ||
18 | * uses <stdint.h> (included via "sha1.h" to define 32 and 8 | ||
19 | * bit unsigned integer types. If your C compiler does not | ||
20 | * support 32 bit unsigned integers, this code is not | ||
21 | * appropriate. | ||
22 | * | ||
23 | * Caveats: | ||
24 | * SHA-1 is designed to work with messages less than 2^64 bits | ||
25 | * long. Although SHA-1 allows a message digest to be generated | ||
26 | * for messages of any number of bits less than 2^64, this | ||
27 | * implementation only works with messages with a length that is | ||
28 | * a multiple of the size of an 8-bit character. | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #include "hmac-sha1.h" | ||
33 | |||
34 | /* | ||
35 | * Define the SHA1 circular left shift macro | ||
36 | */ | ||
37 | #define SHA1CircularShift(bits,word) \ | ||
38 | (((word) << (bits)) | ((word) >> (32-(bits)))) | ||
39 | |||
40 | /* Local Function Prototyptes */ | ||
41 | void SHA1PadMessage(SHA1Context *); | ||
42 | void SHA1ProcessMessageBlock(SHA1Context *); | ||
43 | |||
44 | /* | ||
45 | * SHA1Reset | ||
46 | * | ||
47 | * Description: | ||
48 | * This function will initialize the SHA1Context in preparation | ||
49 | * for computing a new SHA1 message digest. | ||
50 | * | ||
51 | * Parameters: | ||
52 | * context: [in/out] | ||
53 | * The context to reset. | ||
54 | * | ||
55 | * Returns: | ||
56 | * sha Error Code. | ||
57 | * | ||
58 | */ | ||
59 | int SHA1Reset(SHA1Context *context) | ||
60 | { | ||
61 | if (!context) | ||
62 | { | ||
63 | return shaNull; | ||
64 | } | ||
65 | |||
66 | context->Length_Low = 0; | ||
67 | context->Length_High = 0; | ||
68 | context->Message_Block_Index = 0; | ||
69 | |||
70 | context->Intermediate_Hash[0] = 0x67452301; | ||
71 | context->Intermediate_Hash[1] = 0xEFCDAB89; | ||
72 | context->Intermediate_Hash[2] = 0x98BADCFE; | ||
73 | context->Intermediate_Hash[3] = 0x10325476; | ||
74 | context->Intermediate_Hash[4] = 0xC3D2E1F0; | ||
75 | |||
76 | context->Computed = 0; | ||
77 | context->Corrupted = 0; | ||
78 | |||
79 | return shaSuccess; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * SHA1Result | ||
84 | * | ||
85 | * Description: | ||
86 | * This function will return the 160-bit message digest into the | ||
87 | * Message_Digest array provided by the caller. | ||
88 | * NOTE: The first octet of hash is stored in the 0th element, | ||
89 | * the last octet of hash in the 19th element. | ||
90 | * | ||
91 | * Parameters: | ||
92 | * context: [in/out] | ||
93 | * The context to use to calculate the SHA-1 hash. | ||
94 | * Message_Digest: [out] | ||
95 | * Where the digest is returned. | ||
96 | * | ||
97 | * Returns: | ||
98 | * sha Error Code. | ||
99 | * | ||
100 | */ | ||
101 | int SHA1Result( SHA1Context *context, | ||
102 | uint8_t Message_Digest[SHA1HashSize]) | ||
103 | { | ||
104 | int i; | ||
105 | |||
106 | if (!context || !Message_Digest) | ||
107 | { | ||
108 | return shaNull; | ||
109 | } | ||
110 | |||
111 | if (context->Corrupted) | ||
112 | { | ||
113 | return context->Corrupted; | ||
114 | } | ||
115 | |||
116 | if (!context->Computed) | ||
117 | { | ||
118 | SHA1PadMessage(context); | ||
119 | for(i=0; i<64; ++i) | ||
120 | { | ||
121 | /* message may be sensitive, clear it out */ | ||
122 | context->Message_Block[i] = 0; | ||
123 | } | ||
124 | context->Length_Low = 0; /* and clear length */ | ||
125 | context->Length_High = 0; | ||
126 | context->Computed = 1; | ||
127 | } | ||
128 | |||
129 | for(i = 0; i < SHA1HashSize; ++i) | ||
130 | { | ||
131 | Message_Digest[i] = context->Intermediate_Hash[i>>2] | ||
132 | >> 8 * ( 3 - ( i & 0x03 ) ); | ||
133 | } | ||
134 | |||
135 | return shaSuccess; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * SHA1Input | ||
140 | * | ||
141 | * Description: | ||
142 | * This function accepts an array of octets as the next portion | ||
143 | * of the message. | ||
144 | * | ||
145 | * Parameters: | ||
146 | * context: [in/out] | ||
147 | * The SHA context to update | ||
148 | * message_array: [in] | ||
149 | * An array of characters representing the next portion of | ||
150 | * the message. | ||
151 | * length: [in] | ||
152 | * The length of the message in message_array | ||
153 | * | ||
154 | * Returns: | ||
155 | * sha Error Code. | ||
156 | * | ||
157 | */ | ||
158 | int SHA1Input( SHA1Context *context, | ||
159 | const uint8_t *message_array, | ||
160 | unsigned length) | ||
161 | { | ||
162 | if (!length) | ||
163 | { | ||
164 | return shaSuccess; | ||
165 | } | ||
166 | |||
167 | if (!context || !message_array) | ||
168 | { | ||
169 | return shaNull; | ||
170 | } | ||
171 | |||
172 | if (context->Computed) | ||
173 | { | ||
174 | context->Corrupted = shaStateError; | ||
175 | return shaStateError; | ||
176 | } | ||
177 | |||
178 | if (context->Corrupted) | ||
179 | { | ||
180 | return context->Corrupted; | ||
181 | } | ||
182 | while(length-- && !context->Corrupted) | ||
183 | { | ||
184 | context->Message_Block[context->Message_Block_Index++] = | ||
185 | (*message_array & 0xFF); | ||
186 | |||
187 | context->Length_Low += 8; | ||
188 | if (context->Length_Low == 0) | ||
189 | { | ||
190 | context->Length_High++; | ||
191 | if (context->Length_High == 0) | ||
192 | { | ||
193 | /* Message is too long */ | ||
194 | context->Corrupted = 1; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | if (context->Message_Block_Index == 64) | ||
199 | { | ||
200 | SHA1ProcessMessageBlock(context); | ||
201 | } | ||
202 | |||
203 | message_array++; | ||
204 | } | ||
205 | |||
206 | return shaSuccess; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * SHA1ProcessMessageBlock | ||
211 | * | ||
212 | * Description: | ||
213 | * This function will process the next 512 bits of the message | ||
214 | * stored in the Message_Block array. | ||
215 | * | ||
216 | * Parameters: | ||
217 | * None. | ||
218 | * | ||
219 | * Returns: | ||
220 | * Nothing. | ||
221 | * | ||
222 | * Comments: | ||
223 | * Many of the variable names in this code, especially the | ||
224 | * single character names, were used because those were the | ||
225 | * names used in the publication. | ||
226 | * | ||
227 | * | ||
228 | */ | ||
229 | void SHA1ProcessMessageBlock(SHA1Context *context) | ||
230 | { | ||
231 | const uint32_t K[] = { /* Constants defined in SHA-1 */ | ||
232 | 0x5A827999, | ||
233 | 0x6ED9EBA1, | ||
234 | 0x8F1BBCDC, | ||
235 | 0xCA62C1D6 | ||
236 | }; | ||
237 | int t; /* Loop counter */ | ||
238 | uint32_t temp; /* Temporary word value */ | ||
239 | uint32_t W[80]; /* Word sequence */ | ||
240 | uint32_t A, B, C, D, E; /* Word buffers */ | ||
241 | |||
242 | /* | ||
243 | * Initialize the first 16 words in the array W | ||
244 | */ | ||
245 | for(t = 0; t < 16; t++) | ||
246 | { | ||
247 | W[t] = context->Message_Block[t * 4] << 24; | ||
248 | W[t] |= context->Message_Block[t * 4 + 1] << 16; | ||
249 | W[t] |= context->Message_Block[t * 4 + 2] << 8; | ||
250 | W[t] |= context->Message_Block[t * 4 + 3]; | ||
251 | } | ||
252 | |||
253 | for(t = 16; t < 80; t++) | ||
254 | { | ||
255 | W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); | ||
256 | } | ||
257 | |||
258 | A = context->Intermediate_Hash[0]; | ||
259 | B = context->Intermediate_Hash[1]; | ||
260 | C = context->Intermediate_Hash[2]; | ||
261 | D = context->Intermediate_Hash[3]; | ||
262 | E = context->Intermediate_Hash[4]; | ||
263 | |||
264 | for(t = 0; t < 20; t++) | ||
265 | { | ||
266 | temp = SHA1CircularShift(5,A) + | ||
267 | ((B & C) | ((~B) & D)) + E + W[t] + K[0]; | ||
268 | E = D; | ||
269 | D = C; | ||
270 | C = SHA1CircularShift(30,B); | ||
271 | B = A; | ||
272 | A = temp; | ||
273 | } | ||
274 | |||
275 | for(t = 20; t < 40; t++) | ||
276 | { | ||
277 | temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; | ||
278 | E = D; | ||
279 | D = C; | ||
280 | C = SHA1CircularShift(30,B); | ||
281 | B = A; | ||
282 | A = temp; | ||
283 | } | ||
284 | |||
285 | for(t = 40; t < 60; t++) | ||
286 | { | ||
287 | temp = SHA1CircularShift(5,A) + | ||
288 | ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; | ||
289 | E = D; | ||
290 | D = C; | ||
291 | C = SHA1CircularShift(30,B); | ||
292 | B = A; | ||
293 | A = temp; | ||
294 | } | ||
295 | |||
296 | for(t = 60; t < 80; t++) | ||
297 | { | ||
298 | temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; | ||
299 | E = D; | ||
300 | D = C; | ||
301 | C = SHA1CircularShift(30,B); | ||
302 | B = A; | ||
303 | A = temp; | ||
304 | } | ||
305 | |||
306 | context->Intermediate_Hash[0] += A; | ||
307 | context->Intermediate_Hash[1] += B; | ||
308 | context->Intermediate_Hash[2] += C; | ||
309 | context->Intermediate_Hash[3] += D; | ||
310 | context->Intermediate_Hash[4] += E; | ||
311 | |||
312 | context->Message_Block_Index = 0; | ||
313 | } | ||
314 | |||
315 | |||
316 | /* | ||
317 | * SHA1PadMessage | ||
318 | * | ||
319 | * Description: | ||
320 | * According to the standard, the message must be padded to an even | ||
321 | * 512 bits. The first padding bit must be a '1'. The last 64 | ||
322 | * bits represent the length of the original message. All bits in | ||
323 | * between should be 0. This function will pad the message | ||
324 | * according to those rules by filling the Message_Block array | ||
325 | * accordingly. It will also call the ProcessMessageBlock function | ||
326 | * provided appropriately. When it returns, it can be assumed that | ||
327 | * the message digest has been computed. | ||
328 | * | ||
329 | * Parameters: | ||
330 | * context: [in/out] | ||
331 | * The context to pad | ||
332 | * ProcessMessageBlock: [in] | ||
333 | * The appropriate SHA*ProcessMessageBlock function | ||
334 | * Returns: | ||
335 | * Nothing. | ||
336 | * | ||
337 | */ | ||
338 | |||
339 | void SHA1PadMessage(SHA1Context *context) | ||
340 | { | ||
341 | /* | ||
342 | * Check to see if the current message block is too small to hold | ||
343 | * the initial padding bits and length. If so, we will pad the | ||
344 | * block, process it, and then continue padding into a second | ||
345 | * block. | ||
346 | */ | ||
347 | if (context->Message_Block_Index > 55) | ||
348 | { | ||
349 | context->Message_Block[context->Message_Block_Index++] = 0x80; | ||
350 | while(context->Message_Block_Index < 64) | ||
351 | { | ||
352 | context->Message_Block[context->Message_Block_Index++] = 0; | ||
353 | } | ||
354 | |||
355 | SHA1ProcessMessageBlock(context); | ||
356 | |||
357 | while(context->Message_Block_Index < 56) | ||
358 | { | ||
359 | context->Message_Block[context->Message_Block_Index++] = 0; | ||
360 | } | ||
361 | } | ||
362 | else | ||
363 | { | ||
364 | context->Message_Block[context->Message_Block_Index++] = 0x80; | ||
365 | while(context->Message_Block_Index < 56) | ||
366 | { | ||
367 | context->Message_Block[context->Message_Block_Index++] = 0; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | /* | ||
372 | * Store the message length as the last 8 octets | ||
373 | */ | ||
374 | context->Message_Block[56] = context->Length_High >> 24; | ||
375 | context->Message_Block[57] = context->Length_High >> 16; | ||
376 | context->Message_Block[58] = context->Length_High >> 8; | ||
377 | context->Message_Block[59] = context->Length_High; | ||
378 | context->Message_Block[60] = context->Length_Low >> 24; | ||
379 | context->Message_Block[61] = context->Length_Low >> 16; | ||
380 | context->Message_Block[62] = context->Length_Low >> 8; | ||
381 | context->Message_Block[63] = context->Length_Low; | ||
382 | |||
383 | SHA1ProcessMessageBlock(context); | ||
384 | } | ||
385 | #define SHA_DIGESTSIZE 20 | ||
386 | |||
387 | #define SHA_BLOCKSIZE 64 | ||
388 | |||
389 | static void truncate | ||
390 | ( | ||
391 | char* d1, /* data to be truncated */ | ||
392 | char* d2, /* truncated data */ | ||
393 | int len /* length in bytes to keep */ | ||
394 | ) | ||
395 | { | ||
396 | int i ; | ||
397 | for (i = 0 ; i < len ; i++) d2[i] = d1[i]; | ||
398 | } | ||
399 | |||
400 | |||
401 | /* Function to compute the digest */ | ||
402 | void | ||
403 | hmac_sha | ||
404 | ( | ||
405 | char* k, /* secret key */ | ||
406 | int lk, /* length of the key in bytes */ | ||
407 | char* d, /* data */ | ||
408 | int ld, /* length of data in bytes */ | ||
409 | char* out, /* output buffer, at least "t" bytes */ | ||
410 | int t | ||
411 | ) | ||
412 | { | ||
413 | SHA1Context ictx, octx ; | ||
414 | char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE] ; | ||
415 | char key[SHA_DIGESTSIZE] ; | ||
416 | char buf[SHA_BLOCKSIZE] ; | ||
417 | int i ; | ||
418 | |||
419 | if (lk > SHA_BLOCKSIZE) { | ||
420 | |||
421 | SHA1Context tctx ; | ||
422 | |||
423 | SHA1Reset(&tctx) ; | ||
424 | SHA1Input(&tctx, k, lk) ; | ||
425 | SHA1Result(&tctx, key) ; | ||
426 | |||
427 | k = key ; | ||
428 | lk = SHA_DIGESTSIZE ; | ||
429 | } | ||
430 | |||
431 | /**** Inner Digest ****/ | ||
432 | |||
433 | SHA1Reset(&ictx) ; | ||
434 | |||
435 | /* Pad the key for inner digest */ | ||
436 | for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x36 ; | ||
437 | for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36 ; | ||
438 | |||
439 | SHA1Input(&ictx, buf, SHA_BLOCKSIZE) ; | ||
440 | SHA1Input(&ictx, d, ld) ; | ||
441 | |||
442 | SHA1Result(&ictx, isha) ; | ||
443 | |||
444 | /**** Outter Digest ****/ | ||
445 | |||
446 | SHA1Reset(&octx) ; | ||
447 | |||
448 | /* Pad the key for outter digest */ | ||
449 | |||
450 | |||
451 | for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x5C ; | ||
452 | for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x5C ; | ||
453 | |||
454 | SHA1Input(&octx, buf, SHA_BLOCKSIZE) ; | ||
455 | SHA1Input(&octx, isha, SHA_DIGESTSIZE) ; | ||
456 | |||
457 | SHA1Result(&octx, osha) ; | ||
458 | |||
459 | /* truncate and print the results */ | ||
460 | t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t ; | ||
461 | truncate(osha, out, t) ; | ||
462 | |||
463 | } | ||