]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/sha1.c
mtx-changer update, message fixes
[bacula/bacula] / bacula / src / lib / sha1.c
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  *  See sha1.h for copyright
31  */
32
33 #include "sha1.h"
34
35 /*
36  *  Define the SHA1 circular left shift macro
37  */
38 #define SHA1CircularShift(bits,word) \
39                 (((word) << (bits)) | ((word) >> (32-(bits))))
40
41 /* Local Function Prototyptes */
42 void SHA1PadMessage(SHA1Context *);
43 void SHA1ProcessMessageBlock(SHA1Context *);
44
45 /*
46  *  SHA1Reset
47  *
48  *  Description:
49  *      This function will initialize the SHA1Context in preparation
50  *      for computing a new SHA1 message digest.
51  *
52  *  Parameters:
53  *      context: [in/out]
54  *          The context to reset.
55  *
56  *  Returns:
57  *      sha Error Code.
58  *
59  */
60 int SHA1Reset(SHA1Context *context)
61 {
62     if (!context)
63     {
64         return shaNull;
65     }
66
67     context->Length_Low             = 0;
68     context->Length_High            = 0;
69     context->Message_Block_Index    = 0;
70
71     context->Intermediate_Hash[0]   = 0x67452301;
72     context->Intermediate_Hash[1]   = 0xEFCDAB89;
73     context->Intermediate_Hash[2]   = 0x98BADCFE;
74     context->Intermediate_Hash[3]   = 0x10325476;
75     context->Intermediate_Hash[4]   = 0xC3D2E1F0;
76
77     context->Computed   = 0;
78     context->Corrupted  = 0;
79
80     return shaSuccess;
81 }
82
83 /*
84  *  SHA1Result
85  *
86  *  Description:
87  *      This function will return the 160-bit message digest into the
88  *      Message_Digest array  provided by the caller.
89  *      NOTE: The first octet of hash is stored in the 0th element,
90  *            the last octet of hash in the 19th element.
91  *
92  *  Parameters:
93  *      context: [in/out]
94  *          The context to use to calculate the SHA-1 hash.
95  *      Message_Digest: [out]
96  *          Where the digest is returned.
97  *
98  *  Returns:
99  *      sha Error Code.
100  *
101  */
102 int SHA1Result( SHA1Context *context,
103                 uint8_t Message_Digest[SHA1HashSize])
104 {
105     int i;
106
107     if (!context || !Message_Digest)
108     {
109         return shaNull;
110     }
111
112     if (context->Corrupted)
113     {
114         return context->Corrupted;
115     }
116
117     if (!context->Computed)
118     {
119         SHA1PadMessage(context);
120         for(i=0; i<64; ++i)
121         {
122             /* message may be sensitive, clear it out */
123             context->Message_Block[i] = 0;
124         }
125         context->Length_Low = 0;    /* and clear length */
126         context->Length_High = 0;
127         context->Computed = 1;
128
129     }
130
131     for(i = 0; i < SHA1HashSize; ++i)
132     {
133         Message_Digest[i] = context->Intermediate_Hash[i>>2]
134                             >> 8 * ( 3 - ( i &amp; 0x03 ) );
135     }
136
137     return shaSuccess;
138 }
139
140 /*
141  *  SHA1Input
142  *
143  *  Description:
144  *      This function accepts an array of octets as the next portion
145  *      of the message.
146  *
147  *  Parameters:
148  *      context: [in/out]
149  *          The SHA context to update
150  *      message_array: [in]
151  *          An array of characters representing the next portion of
152  *          the message.
153  *      length: [in]
154  *          The length of the message in message_array
155  *
156  *  Returns:
157  *      sha Error Code.
158  *
159  */
160 int SHA1Input(    SHA1Context    *context,
161                   const uint8_t  *message_array,
162                   unsigned       length)
163 {
164     if (!length)
165     {
166         return shaSuccess;
167     }
168
169     if (!context || !message_array)
170     {
171         return shaNull;
172     }
173
174     if (context->Computed)
175     {
176         context->Corrupted = shaStateError;
177
178         return shaStateError;
179     }
180
181     if (context->Corrupted)
182     {
183          return context->Corrupted;
184     }
185     while(length-- &amp;&amp; !context->Corrupted)
186     {
187     context->Message_Block[context->Message_Block_Index++] =
188                     (*message_array &amp; 0xFF);
189
190     context->Length_Low += 8;
191     if (context->Length_Low == 0)
192     {
193         context->Length_High++;
194         if (context->Length_High == 0)
195         {
196             /* Message is too long */
197             context->Corrupted = 1;
198         }
199     }
200
201     if (context->Message_Block_Index == 64)
202     {
203         SHA1ProcessMessageBlock(context);
204     }
205
206     message_array++;
207     }
208
209     return shaSuccess;
210 }
211
212 /*
213  *  SHA1ProcessMessageBlock
214  *
215  *  Description:
216  *      This function will process the next 512 bits of the message
217  *      stored in the Message_Block array.
218  *
219  *  Parameters:
220  *      None.
221  *
222  *  Returns:
223  *      Nothing.
224  *
225  *  Comments:
226
227  *      Many of the variable names in this code, especially the
228  *      single character names, were used because those were the
229  *      names used in the publication.
230  *
231  *
232  */
233 void SHA1ProcessMessageBlock(SHA1Context *context)
234 {
235     const uint32_t K[] =    {       /* Constants defined in SHA-1   */
236                             0x5A827999,
237                             0x6ED9EBA1,
238                             0x8F1BBCDC,
239                             0xCA62C1D6
240                             };
241     int           t;                 /* Loop counter                */
242     uint32_t      temp;              /* Temporary word value        */
243     uint32_t      W[80];             /* Word sequence               */
244     uint32_t      A, B, C, D, E;     /* Word buffers                */
245
246     /*
247      *  Initialize the first 16 words in the array W
248      */
249     for(t = 0; t < 16; t++)
250     {
251         W[t] = context->Message_Block[t * 4] << 24;
252         W[t] |= context->Message_Block[t * 4 + 1] << 16;
253         W[t] |= context->Message_Block[t * 4 + 2] << 8;
254         W[t] |= context->Message_Block[t * 4 + 3];
255     }
256
257     for(t = 16; t < 80; t++)
258     {
259        W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
260     }
261
262     A = context->Intermediate_Hash[0];
263     B = context->Intermediate_Hash[1];
264     C = context->Intermediate_Hash[2];
265     D = context->Intermediate_Hash[3];
266     E = context->Intermediate_Hash[4];
267
268     for(t = 0; t < 20; t++)
269     {
270         temp =  SHA1CircularShift(5,A) +
271                 ((B &amp; C) | ((~B) &amp; D)) + E + W[t] + K[0];
272         E = D;
273         D = C;
274         C = SHA1CircularShift(30,B);
275
276         B = A;
277         A = temp;
278     }
279
280     for(t = 20; t < 40; t++)
281     {
282         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
283         E = D;
284         D = C;
285         C = SHA1CircularShift(30,B);
286         B = A;
287         A = temp;
288     }
289
290     for(t = 40; t < 60; t++)
291     {
292         temp = SHA1CircularShift(5,A) +
293                ((B &amp; C) | (B &amp; D) | (C &amp; D)) + E + W[t] + K[2];
294         E = D;
295         D = C;
296         C = SHA1CircularShift(30,B);
297         B = A;
298         A = temp;
299     }
300
301     for(t = 60; t < 80; t++)
302     {
303         temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
304         E = D;
305         D = C;
306         C = SHA1CircularShift(30,B);
307         B = A;
308         A = temp;
309     }
310
311     context->Intermediate_Hash[0] += A;
312     context->Intermediate_Hash[1] += B;
313     context->Intermediate_Hash[2] += C;
314     context->Intermediate_Hash[3] += D;
315     context->Intermediate_Hash[4] += E;
316
317     context->Message_Block_Index = 0;
318 }
319
320 /*
321  *  SHA1PadMessage
322  *
323
324  *  Description:
325  *      According to the standard, the message must be padded to an even
326  *      512 bits.  The first padding bit must be a '1'.  The last 64
327  *      bits represent the length of the original message.  All bits in
328  *      between should be 0.  This function will pad the message
329  *      according to those rules by filling the Message_Block array
330  *      accordingly.  It will also call the ProcessMessageBlock function
331  *      provided appropriately.  When it returns, it can be assumed that
332  *      the message digest has been computed.
333  *
334  *  Parameters:
335  *      context: [in/out]
336  *          The context to pad
337  *      ProcessMessageBlock: [in]
338  *          The appropriate SHA*ProcessMessageBlock function
339  *  Returns:
340  *      Nothing.
341  *
342  */
343
344 void SHA1PadMessage(SHA1Context *context)
345 {
346     /*
347      *  Check to see if the current message block is too small to hold
348      *  the initial padding bits and length.  If so, we will pad the
349      *  block, process it, and then continue padding into a second
350      *  block.
351      */
352     if (context->Message_Block_Index > 55)
353     {
354         context->Message_Block[context->Message_Block_Index++] = 0x80;
355         while(context->Message_Block_Index < 64)
356         {
357             context->Message_Block[context->Message_Block_Index++] = 0;
358         }
359
360         SHA1ProcessMessageBlock(context);
361
362         while(context->Message_Block_Index < 56)
363         {
364             context->Message_Block[context->Message_Block_Index++] = 0;
365         }
366     }
367     else
368     {
369         context->Message_Block[context->Message_Block_Index++] = 0x80;
370         while(context->Message_Block_Index < 56)
371         {
372
373             context->Message_Block[context->Message_Block_Index++] = 0;
374         }
375     }
376
377     /*
378      *  Store the message length as the last 8 octets
379      */
380     context->Message_Block[56] = context->Length_High >> 24;
381     context->Message_Block[57] = context->Length_High >> 16;
382     context->Message_Block[58] = context->Length_High >> 8;
383     context->Message_Block[59] = context->Length_High;
384     context->Message_Block[60] = context->Length_Low >> 24;
385     context->Message_Block[61] = context->Length_Low >> 16;
386     context->Message_Block[62] = context->Length_Low >> 8;
387     context->Message_Block[63] = context->Length_Low;
388
389     SHA1ProcessMessageBlock(context);
390 }
391
392 #ifdef TEST_DRIVER
393
394 /*
395  *  sha1test.c
396  *
397  *  Description:
398  *      This file will exercise the SHA-1 code performing the three
399  *      tests documented in FIPS PUB 180-1 plus one which calls
400  *      SHA1Input with an exact multiple of 512 bits, plus a few
401  *      error test checks.
402  *
403  *  Portability Issues:
404  *      None.
405  *
406  */
407
408 #include <stdint.h>
409 #include <stdio.h>
410 #include <string.h>
411 #include "sha1.h"
412
413 /*
414  *  Define patterns for testing
415  */
416 #define TEST1   "abc"
417 #define TEST2a  "abcdbcdecdefdefgefghfghighijhi"
418
419 #define TEST2b  "jkijkljklmklmnlmnomnopnopq"
420 #define TEST2   TEST2a TEST2b
421 #define TEST3   "a"
422 #define TEST4a  "01234567012345670123456701234567"
423 #define TEST4b  "01234567012345670123456701234567"
424     /* an exact multiple of 512 bits */
425 #define TEST4   TEST4a TEST4b
426 char *testarray[4] =
427 {
428     TEST1,
429     TEST2,
430     TEST3,
431     TEST4
432 };
433 long int repeatcount[4] = { 1, 1, 1000000, 10 };
434 char *resultarray[4] =
435 {
436     "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D",
437     "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1",
438     "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F",
439     "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52"
440 };
441
442 int main()
443 {
444     SHA1Context sha;
445     int i, j, err;
446     uint8_t Message_Digest[20];
447
448     /*
449      *  Perform SHA-1 tests
450      */
451     for(j = 0; j < 4; ++j)
452     {
453         printf( "\nTest %d: %d, '%s'\n",
454                 j+1,
455                 repeatcount[j],
456                 testarray[j]);
457
458         err = SHA1Reset(&amp;sha);
459         if (err)
460         {
461             fprintf(stderr, "SHA1Reset Error %d.\n", err );
462             break;    /* out of for j loop */
463         }
464
465         for(i = 0; i < repeatcount[j]; ++i)
466         {
467
468             err = SHA1Input(&amp;sha,
469                   (const unsigned char *) testarray[j],
470                   strlen(testarray[j]));
471             if (err)
472             {
473                 fprintf(stderr, "SHA1Input Error %d.\n", err );
474                 break;    /* out of for i loop */
475             }
476         }
477
478         err = SHA1Result(&amp;sha, Message_Digest);
479         if (err)
480         {
481             fprintf(stderr,
482             "SHA1Result Error %d, could not compute message digest.\n",
483             err );
484         }
485         else
486         {
487             printf("\t");
488             for(i = 0; i < 20 ; ++i)
489             {
490                 printf("%02X ", Message_Digest[i]);
491             }
492             printf("\n");
493         }
494         printf("Should match:\n");
495         printf("\t%s\n", resultarray[j]);
496     }
497
498     /* Test some error returns */
499     err = SHA1Input(&amp;sha,(const unsigned char *) testarray[1], 1);
500     printf ("\nError %d. Should be %d.\n", err, shaStateError );
501     err = SHA1Reset(0);
502     printf ("\nError %d. Should be %d.\n", err, shaNull );
503     return 0;
504 }
505
506 #endif /* TEST_DRIVER */