K2.6 patches and update.
[tomato.git] / release / src-rt / bcmcrypto / sha1.c
blobfa36d3a11f5dfe8ec64986a304920c37e2bd87d9
1 /*
2 * Copyright (C) The Internet Society (2001). All Rights Reserved.
4 * This document and translations of it may be copied and furnished to
5 * others, and derivative works that comment on or otherwise explain it
6 * or assist in its implementation may be prepared, copied, published
7 * and distributed, in whole or in part, without restriction of any
8 * kind, provided that the above copyright notice and this paragraph are
9 * included on all such copies and derivative works. However, this
10 * document itself may not be modified in any way, such as by removing
11 * the copyright notice or references to the Internet Society or other
12 * Internet organizations, except as needed for the purpose of
13 * developing Internet standards in which case the procedures for
14 * copyrights defined in the Internet Standards process must be
15 * followed, or as required to translate it into languages other than
16 * English.
18 * The limited permissions granted above are perpetual and will not be
19 * revoked by the Internet Society or its successors or assigns.
21 * This document and the information contained herein is provided on an
22 * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
23 * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
24 * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
25 * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
26 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
28 * Copyright (C) 2010, Broadcom Corporation
29 * All Rights Reserved.
31 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
32 * the contents of this file may not be disclosed to third parties, copied
33 * or duplicated in any form, in whole or in part, without the prior
34 * written permission of Broadcom Corporation.
36 * $Id: sha1.c,v 1.14 2009-02-26 21:37:35 Exp $
38 * From rfc3174.txt
42 * sha1.c
44 * Description:
45 * This file implements the Secure Hashing Algorithm 1 as
46 * defined in FIPS PUB 180-1 published April 17, 1995.
48 * The SHA-1, produces a 160-bit message digest for a given
49 * data stream. It should take about 2**n steps to find a
50 * message with the same digest as a given message and
51 * 2**(n/2) to find any two messages with the same digest,
52 * when n is the digest size in bits. Therefore, this
53 * algorithm can serve as a means of providing a
54 * "fingerprint" for a message.
56 * Portability Issues:
57 * SHA-1 is defined in terms of 32-bit "words". This code
58 * uses <stdint.h> (included via "sha1.h" to define 32 and 8
59 * bit unsigned integer types. If your C compiler does not
60 * support 32 bit unsigned integers, this code is not
61 * appropriate.
63 * Caveats:
64 * SHA-1 is designed to work with messages less than 2^64 bits
65 * long. Although SHA-1 allows a message digest to be generated
66 * for messages of any number of bits less than 2^64, this
67 * implementation only works with messages with a length that is
68 * a multiple of the size of an 8-bit character.
72 #include <bcmcrypto/sha1.h>
74 #ifdef BCMDRIVER
75 #include <osl.h>
76 #else
77 #if defined(__GNUC__)
78 extern int bcmp(const void *b1, const void *b2, int len);
79 extern size_t strlen(const char *s);
80 #else
81 #define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
82 #endif /* __GNUC__ */
83 #endif /* BCMDRIVER */
86 * Define the SHA1 circular left shift macro
88 #define SHA1CircularShift(bits, word) \
89 (((word) << (bits)) | ((word) >> (32-(bits))))
91 /* Local Function Prototyptes */
92 static void SHA1PadMessage(SHA1Context *);
93 static void SHA1ProcessMessageBlock(SHA1Context *);
96 * SHA1Reset
98 * Description:
99 * This function will initialize the SHA1Context in preparation
100 * for computing a new SHA1 message digest.
102 * Parameters:
103 * context: [in/out]
104 * The context to reset.
106 * Returns:
107 * sha Error Code.
111 BCMROMFN(SHA1Reset)(SHA1Context *context)
113 if (!context) {
114 return shaNull;
117 context->Length_Low = 0;
118 context->Length_High = 0;
119 context->Message_Block_Index = 0;
121 context->Intermediate_Hash[0] = 0x67452301;
122 context->Intermediate_Hash[1] = 0xEFCDAB89;
123 context->Intermediate_Hash[2] = 0x98BADCFE;
124 context->Intermediate_Hash[3] = 0x10325476;
125 context->Intermediate_Hash[4] = 0xC3D2E1F0;
127 context->Computed = 0;
128 context->Corrupted = 0;
130 return shaSuccess;
134 * SHA1Result
136 * Description:
137 * This function will return the 160-bit message digest into the
138 * Message_Digest array provided by the caller.
139 * NOTE: The first octet of hash is stored in the 0th element,
140 * the last octet of hash in the 19th element.
142 * Parameters:
143 * context: [in/out]
144 * The context to use to calculate the SHA-1 hash.
145 * Message_Digest: [out]
146 * Where the digest is returned.
148 * Returns:
149 * sha Error Code.
153 BCMROMFN(SHA1Result)(SHA1Context *context, uint8 Message_Digest[SHA1HashSize])
155 int i;
157 if (!context || !Message_Digest) {
158 return shaNull;
161 if (context->Corrupted) {
162 return context->Corrupted;
165 if (!context->Computed) {
166 SHA1PadMessage(context);
167 for (i = 0; i < 64; ++i) {
168 /* message may be sensitive, clear it out */
169 context->Message_Block[i] = 0;
171 context->Length_Low = 0; /* and clear length */
172 context->Length_High = 0;
173 context->Computed = 1;
176 for (i = 0; i < SHA1HashSize; ++i) {
177 Message_Digest[i] = context->Intermediate_Hash[i >> 2] >>
178 8 * (3 - (i & 0x03));
181 return shaSuccess;
185 * SHA1Input
187 * Description:
188 * This function accepts an array of octets as the next portion
189 * of the message.
191 * Parameters:
192 * context: [in/out]
193 * The SHA context to update
194 * message_array: [in]
195 * An array of characters representing the next portion of
196 * the message.
197 * length: [in]
198 * The length of the message in message_array
200 * Returns:
201 * sha Error Code.
205 BCMROMFN(SHA1Input)(SHA1Context *context, const uint8 *message_array, unsigned length)
207 if (!length) {
208 return shaSuccess;
211 if (!context || !message_array) {
212 return shaNull;
215 if (context->Computed) {
216 context->Corrupted = shaStateError;
217 return shaStateError;
220 if (context->Corrupted) {
221 return context->Corrupted;
223 while (length-- && !context->Corrupted) {
224 context->Message_Block[context->Message_Block_Index++] =
225 (*message_array & 0xFF);
227 context->Length_Low += 8;
228 if (context->Length_Low == 0) {
229 context->Length_High++;
230 if (context->Length_High == 0) {
231 /* Message is too long */
232 context->Corrupted = 1;
236 if (context->Message_Block_Index == 64) {
237 SHA1ProcessMessageBlock(context);
240 message_array++;
243 return shaSuccess;
247 * SHA1ProcessMessageBlock
249 * Description:
250 * This function will process the next 512 bits of the message
251 * stored in the Message_Block array.
253 * Parameters:
254 * None.
256 * Returns:
257 * Nothing.
259 * Comments:
260 * Many of the variable names in this code, especially the
261 * single character names, were used because those were the
262 * names used in the publication.
266 static void
267 SHA1ProcessMessageBlock(SHA1Context *context)
269 const uint32 K[] = { /* Constants defined in SHA-1 */
270 0x5A827999,
271 0x6ED9EBA1,
272 0x8F1BBCDC,
273 0xCA62C1D6
275 int t; /* Loop counter */
276 uint32 temp; /* Temporary word value */
277 uint32 W[80]; /* Word sequence */
278 uint32 A, B, C, D, E; /* Word buffers */
281 * Initialize the first 16 words in the array W
283 for (t = 0; t < 16; t++) {
284 W[t] = context->Message_Block[t * 4] << 24;
285 W[t] |= context->Message_Block[t * 4 + 1] << 16;
286 W[t] |= context->Message_Block[t * 4 + 2] << 8;
287 W[t] |= context->Message_Block[t * 4 + 3];
290 for (t = 16; t < 80; t++) {
291 W[t] = SHA1CircularShift(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
294 A = context->Intermediate_Hash[0];
295 B = context->Intermediate_Hash[1];
296 C = context->Intermediate_Hash[2];
297 D = context->Intermediate_Hash[3];
298 E = context->Intermediate_Hash[4];
300 for (t = 0; t < 20; t++) {
301 temp = SHA1CircularShift(5, A) +
302 ((B & C) | ((~B) & D)) + E + W[t] + K[0];
303 E = D;
304 D = C;
305 C = SHA1CircularShift(30, B);
306 B = A;
307 A = temp;
310 for (t = 20; t < 40; t++) {
311 temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[1];
312 E = D;
313 D = C;
314 C = SHA1CircularShift(30, B);
315 B = A;
316 A = temp;
319 for (t = 40; t < 60; t++) {
320 temp = SHA1CircularShift(5, A) +
321 ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
322 E = D;
323 D = C;
324 C = SHA1CircularShift(30, B);
325 B = A;
326 A = temp;
329 for (t = 60; t < 80; t++) {
330 temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[3];
331 E = D;
332 D = C;
333 C = SHA1CircularShift(30, B);
334 B = A;
335 A = temp;
338 context->Intermediate_Hash[0] += A;
339 context->Intermediate_Hash[1] += B;
340 context->Intermediate_Hash[2] += C;
341 context->Intermediate_Hash[3] += D;
342 context->Intermediate_Hash[4] += E;
344 context->Message_Block_Index = 0;
349 * SHA1PadMessage
351 * Description:
352 * According to the standard, the message must be padded to an even
353 * 512 bits. The first padding bit must be a '1'. The last 64
354 * bits represent the length of the original message. All bits in
355 * between should be 0. This function will pad the message
356 * according to those rules by filling the Message_Block array
357 * accordingly. It will also call the ProcessMessageBlock function
358 * provided appropriately. When it returns, it can be assumed that
359 * the message digest has been computed.
361 * Parameters:
362 * context: [in/out]
363 * The context to pad
364 * ProcessMessageBlock: [in]
365 * The appropriate SHA*ProcessMessageBlock function
366 * Returns:
367 * Nothing.
371 static void SHA1PadMessage(SHA1Context *context)
374 * Check to see if the current message block is too small to hold
375 * the initial padding bits and length. If so, we will pad the
376 * block, process it, and then continue padding into a second
377 * block.
379 if (context->Message_Block_Index > 55) {
380 context->Message_Block[context->Message_Block_Index++] = 0x80;
381 while (context->Message_Block_Index < 64) {
382 context->Message_Block[context->Message_Block_Index++] = 0;
385 SHA1ProcessMessageBlock(context);
387 while (context->Message_Block_Index < 56) {
388 context->Message_Block[context->Message_Block_Index++] = 0;
390 } else {
391 context->Message_Block[context->Message_Block_Index++] = 0x80;
392 while (context->Message_Block_Index < 56) {
393 context->Message_Block[context->Message_Block_Index++] = 0;
398 * Store the message length as the last 8 octets
400 context->Message_Block[56] = (uint8) (context->Length_High >> 24);
401 context->Message_Block[57] = (uint8) (context->Length_High >> 16);
402 context->Message_Block[58] = (uint8) (context->Length_High >> 8);
403 context->Message_Block[59] = (uint8) (context->Length_High);
404 context->Message_Block[60] = (uint8) (context->Length_Low >> 24);
405 context->Message_Block[61] = (uint8) (context->Length_Low >> 16);
406 context->Message_Block[62] = (uint8) (context->Length_Low >> 8);
407 context->Message_Block[63] = (uint8) (context->Length_Low);
409 SHA1ProcessMessageBlock(context);
412 #ifdef BCMSHA1_TEST
414 * sha1test.c
416 * Description:
417 * This file will exercise the SHA-1 code performing the three
418 * tests documented in FIPS PUB 180-1 plus one which calls
419 * SHA1Input with an exact multiple of 512 bits, plus a few
420 * error test checks.
422 * Portability Issues:
423 * None.
427 #include <stdio.h>
430 * Define patterns for testing
432 #define TEST1 "abc"
433 #define TEST2a "abcdbcdecdefdefgefghfghighijhi"
434 #define TEST2b "jkijkljklmklmnlmnomnopnopq"
435 #define TEST2 TEST2a TEST2b
436 #define TEST3 "a"
437 #define TEST4a "01234567012345670123456701234567"
438 #define TEST4b "01234567012345670123456701234567"
439 /* an exact multiple of 512 bits */
440 #define TEST4 TEST4a TEST4b
441 char *testarray[4] =
443 TEST1,
444 TEST2,
445 TEST3,
446 TEST4
448 int repeatcount[4] = { 1, 1, 1000000, 10 };
449 uint8 resultarray[4][20] =
451 {0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
452 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D},
453 {0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
454 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1},
455 {0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
456 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F},
457 {0xDE, 0xA3, 0x56, 0xA2, 0xCD, 0xDD, 0x90, 0xC7, 0xA7, 0xEC,
458 0xED, 0xC5, 0xEB, 0xB5, 0x63, 0x93, 0x4F, 0x46, 0x04, 0x52}
461 int main()
463 SHA1Context sha;
464 int i, j, err, fail = 0;
465 uint8 Message_Digest[20];
468 * Perform SHA-1 tests
470 for (j = 0; j < 4; ++j) {
471 printf("\nTest %d: %d, '%s'\n", j + 1, repeatcount[j], testarray[j]);
473 err = SHA1Reset(&sha);
474 if (err) {
475 fprintf(stderr, "SHA1Reset Error %d.\n", err);
476 break; /* out of for j loop */
479 for (i = 0; i < repeatcount[j]; ++i) {
480 err = SHA1Input(&sha,
481 (const unsigned char *) testarray[j],
482 strlen(testarray[j]));
483 if (err) {
484 fprintf(stderr, "SHA1Input Error %d.\n", err);
485 break; /* out of for i loop */
489 err = SHA1Result(&sha, Message_Digest);
490 if (err) {
491 fprintf(stderr,
492 "SHA1Result Error %d, could not compute message digest.\n",
493 err);
494 } else {
495 printf("\t");
496 for (i = 0; i < 20; ++i) {
497 printf("%02X ", Message_Digest[i]);
499 printf("\n");
501 printf("Should match:\n");
502 printf("\t");
503 for (i = 0; i < 20; ++i) {
504 printf("%02X ", resultarray[j][i]);
506 printf("\n");
507 if (bcmp(Message_Digest, resultarray[j], 20)) fail++;
510 /* Test some error returns */
511 err = SHA1Input(&sha, (const unsigned char *) testarray[1], 1);
512 printf("\nError %d. Should be %d.\n", err, shaStateError);
513 if (err != shaStateError) fail++;
515 err = SHA1Reset(0);
516 printf("\nError %d. Should be %d.\n", err, shaNull);
517 if (err != shaNull) fail++;
519 printf("SHA1 test %s\n", fail? "FAILED" : "PASSED");
520 return fail;
522 #endif /* BCMSHA1_TEST */