version 0.0.1
[fms.git] / src / xyssl / sha1.c
1 /*\r
2  *  FIPS-180-1 compliant SHA-1 implementation\r
3  *\r
4  *  Copyright (C) 2006-2007  Christophe Devine\r
5  *\r
6  *  This library is free software; you can redistribute it and/or\r
7  *  modify it under the terms of the GNU Lesser General Public\r
8  *  License, version 2.1 as published by the Free Software Foundation.\r
9  *\r
10  *  This library is distributed in the hope that it will be useful,\r
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
13  *  Lesser General Public License for more details.\r
14  *\r
15  *  You should have received a copy of the GNU Lesser General Public\r
16  *  License along with this library; if not, write to the Free Software\r
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,\r
18  *  MA  02110-1301  USA\r
19  */\r
20 /*\r
21  *  The SHA-1 standard was published by NIST in 1993.\r
22  *\r
23  *  http://www.itl.nist.gov/fipspubs/fip180-1.htm\r
24  */\r
25 \r
26 #include "../../include/xyssl/config.h"\r
27 \r
28 #if defined(XYSSL_SHA1_C)\r
29 \r
30 #include "../../include/xyssl/sha1.h"\r
31 \r
32 #include <string.h>\r
33 #include <stdio.h>\r
34 \r
35 /*\r
36  * 32-bit integer manipulation macros (big endian)\r
37  */\r
38 #ifndef GET_ULONG_BE\r
39 #define GET_ULONG_BE(n,b,i)                             \\r
40 {                                                       \\r
41     (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \\r
42         | ( (unsigned long) (b)[(i) + 1] << 16 )        \\r
43         | ( (unsigned long) (b)[(i) + 2] <<  8 )        \\r
44         | ( (unsigned long) (b)[(i) + 3]       );       \\r
45 }\r
46 #endif\r
47 \r
48 #ifndef PUT_ULONG_BE\r
49 #define PUT_ULONG_BE(n,b,i)                             \\r
50 {                                                       \\r
51     (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \\r
52     (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \\r
53     (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \\r
54     (b)[(i) + 3] = (unsigned char) ( (n)       );       \\r
55 }\r
56 #endif\r
57 \r
58 /*\r
59  * SHA-1 context setup\r
60  */\r
61 void sha1_starts( sha1_context *ctx )\r
62 {\r
63     ctx->total[0] = 0;\r
64     ctx->total[1] = 0;\r
65 \r
66     ctx->state[0] = 0x67452301;\r
67     ctx->state[1] = 0xEFCDAB89;\r
68     ctx->state[2] = 0x98BADCFE;\r
69     ctx->state[3] = 0x10325476;\r
70     ctx->state[4] = 0xC3D2E1F0;\r
71 }\r
72 \r
73 static void sha1_process( sha1_context *ctx, unsigned char data[64] )\r
74 {\r
75     unsigned long temp, W[16], A, B, C, D, E;\r
76 \r
77     GET_ULONG_BE( W[ 0], data,  0 );\r
78     GET_ULONG_BE( W[ 1], data,  4 );\r
79     GET_ULONG_BE( W[ 2], data,  8 );\r
80     GET_ULONG_BE( W[ 3], data, 12 );\r
81     GET_ULONG_BE( W[ 4], data, 16 );\r
82     GET_ULONG_BE( W[ 5], data, 20 );\r
83     GET_ULONG_BE( W[ 6], data, 24 );\r
84     GET_ULONG_BE( W[ 7], data, 28 );\r
85     GET_ULONG_BE( W[ 8], data, 32 );\r
86     GET_ULONG_BE( W[ 9], data, 36 );\r
87     GET_ULONG_BE( W[10], data, 40 );\r
88     GET_ULONG_BE( W[11], data, 44 );\r
89     GET_ULONG_BE( W[12], data, 48 );\r
90     GET_ULONG_BE( W[13], data, 52 );\r
91     GET_ULONG_BE( W[14], data, 56 );\r
92     GET_ULONG_BE( W[15], data, 60 );\r
93 \r
94 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))\r
95 \r
96 #define R(t)                                            \\r
97 (                                                       \\r
98     temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \\r
99            W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],      \\r
100     ( W[t & 0x0F] = S(temp,1) )                         \\r
101 )\r
102 \r
103 #define P(a,b,c,d,e,x)                                  \\r
104 {                                                       \\r
105     e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);        \\r
106 }\r
107 \r
108     A = ctx->state[0];\r
109     B = ctx->state[1];\r
110     C = ctx->state[2];\r
111     D = ctx->state[3];\r
112     E = ctx->state[4];\r
113 \r
114 #define F(x,y,z) (z ^ (x & (y ^ z)))\r
115 #define K 0x5A827999\r
116 \r
117     P( A, B, C, D, E, W[0]  );\r
118     P( E, A, B, C, D, W[1]  );\r
119     P( D, E, A, B, C, W[2]  );\r
120     P( C, D, E, A, B, W[3]  );\r
121     P( B, C, D, E, A, W[4]  );\r
122     P( A, B, C, D, E, W[5]  );\r
123     P( E, A, B, C, D, W[6]  );\r
124     P( D, E, A, B, C, W[7]  );\r
125     P( C, D, E, A, B, W[8]  );\r
126     P( B, C, D, E, A, W[9]  );\r
127     P( A, B, C, D, E, W[10] );\r
128     P( E, A, B, C, D, W[11] );\r
129     P( D, E, A, B, C, W[12] );\r
130     P( C, D, E, A, B, W[13] );\r
131     P( B, C, D, E, A, W[14] );\r
132     P( A, B, C, D, E, W[15] );\r
133     P( E, A, B, C, D, R(16) );\r
134     P( D, E, A, B, C, R(17) );\r
135     P( C, D, E, A, B, R(18) );\r
136     P( B, C, D, E, A, R(19) );\r
137 \r
138 #undef K\r
139 #undef F\r
140 \r
141 #define F(x,y,z) (x ^ y ^ z)\r
142 #define K 0x6ED9EBA1\r
143 \r
144     P( A, B, C, D, E, R(20) );\r
145     P( E, A, B, C, D, R(21) );\r
146     P( D, E, A, B, C, R(22) );\r
147     P( C, D, E, A, B, R(23) );\r
148     P( B, C, D, E, A, R(24) );\r
149     P( A, B, C, D, E, R(25) );\r
150     P( E, A, B, C, D, R(26) );\r
151     P( D, E, A, B, C, R(27) );\r
152     P( C, D, E, A, B, R(28) );\r
153     P( B, C, D, E, A, R(29) );\r
154     P( A, B, C, D, E, R(30) );\r
155     P( E, A, B, C, D, R(31) );\r
156     P( D, E, A, B, C, R(32) );\r
157     P( C, D, E, A, B, R(33) );\r
158     P( B, C, D, E, A, R(34) );\r
159     P( A, B, C, D, E, R(35) );\r
160     P( E, A, B, C, D, R(36) );\r
161     P( D, E, A, B, C, R(37) );\r
162     P( C, D, E, A, B, R(38) );\r
163     P( B, C, D, E, A, R(39) );\r
164 \r
165 #undef K\r
166 #undef F\r
167 \r
168 #define F(x,y,z) ((x & y) | (z & (x | y)))\r
169 #define K 0x8F1BBCDC\r
170 \r
171     P( A, B, C, D, E, R(40) );\r
172     P( E, A, B, C, D, R(41) );\r
173     P( D, E, A, B, C, R(42) );\r
174     P( C, D, E, A, B, R(43) );\r
175     P( B, C, D, E, A, R(44) );\r
176     P( A, B, C, D, E, R(45) );\r
177     P( E, A, B, C, D, R(46) );\r
178     P( D, E, A, B, C, R(47) );\r
179     P( C, D, E, A, B, R(48) );\r
180     P( B, C, D, E, A, R(49) );\r
181     P( A, B, C, D, E, R(50) );\r
182     P( E, A, B, C, D, R(51) );\r
183     P( D, E, A, B, C, R(52) );\r
184     P( C, D, E, A, B, R(53) );\r
185     P( B, C, D, E, A, R(54) );\r
186     P( A, B, C, D, E, R(55) );\r
187     P( E, A, B, C, D, R(56) );\r
188     P( D, E, A, B, C, R(57) );\r
189     P( C, D, E, A, B, R(58) );\r
190     P( B, C, D, E, A, R(59) );\r
191 \r
192 #undef K\r
193 #undef F\r
194 \r
195 #define F(x,y,z) (x ^ y ^ z)\r
196 #define K 0xCA62C1D6\r
197 \r
198     P( A, B, C, D, E, R(60) );\r
199     P( E, A, B, C, D, R(61) );\r
200     P( D, E, A, B, C, R(62) );\r
201     P( C, D, E, A, B, R(63) );\r
202     P( B, C, D, E, A, R(64) );\r
203     P( A, B, C, D, E, R(65) );\r
204     P( E, A, B, C, D, R(66) );\r
205     P( D, E, A, B, C, R(67) );\r
206     P( C, D, E, A, B, R(68) );\r
207     P( B, C, D, E, A, R(69) );\r
208     P( A, B, C, D, E, R(70) );\r
209     P( E, A, B, C, D, R(71) );\r
210     P( D, E, A, B, C, R(72) );\r
211     P( C, D, E, A, B, R(73) );\r
212     P( B, C, D, E, A, R(74) );\r
213     P( A, B, C, D, E, R(75) );\r
214     P( E, A, B, C, D, R(76) );\r
215     P( D, E, A, B, C, R(77) );\r
216     P( C, D, E, A, B, R(78) );\r
217     P( B, C, D, E, A, R(79) );\r
218 \r
219 #undef K\r
220 #undef F\r
221 \r
222     ctx->state[0] += A;\r
223     ctx->state[1] += B;\r
224     ctx->state[2] += C;\r
225     ctx->state[3] += D;\r
226     ctx->state[4] += E;\r
227 }\r
228 \r
229 /*\r
230  * SHA-1 process buffer\r
231  */\r
232 void sha1_update( sha1_context *ctx, unsigned char *input, int ilen )\r
233 {\r
234     int fill;\r
235     unsigned long left;\r
236 \r
237     if( ilen <= 0 )\r
238         return;\r
239 \r
240     left = ctx->total[0] & 0x3F;\r
241     fill = 64 - left;\r
242 \r
243     ctx->total[0] += ilen;\r
244     ctx->total[0] &= 0xFFFFFFFF;\r
245 \r
246     if( ctx->total[0] < (unsigned long) ilen )\r
247         ctx->total[1]++;\r
248 \r
249     if( left && ilen >= fill )\r
250     {\r
251         memcpy( (void *) (ctx->buffer + left),\r
252                 (void *) input, fill );\r
253         sha1_process( ctx, ctx->buffer );\r
254         input += fill;\r
255         ilen  -= fill;\r
256         left = 0;\r
257     }\r
258 \r
259     while( ilen >= 64 )\r
260     {\r
261         sha1_process( ctx, input );\r
262         input += 64;\r
263         ilen  -= 64;\r
264     }\r
265 \r
266     if( ilen > 0 )\r
267     {\r
268         memcpy( (void *) (ctx->buffer + left),\r
269                 (void *) input, ilen );\r
270     }\r
271 }\r
272 \r
273 static const unsigned char sha1_padding[64] =\r
274 {\r
275  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
276     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
277     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
278     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
279 };\r
280 \r
281 /*\r
282  * SHA-1 final digest\r
283  */\r
284 void sha1_finish( sha1_context *ctx, unsigned char output[20] )\r
285 {\r
286     unsigned long last, padn;\r
287     unsigned long high, low;\r
288     unsigned char msglen[8];\r
289 \r
290     high = ( ctx->total[0] >> 29 )\r
291          | ( ctx->total[1] <<  3 );\r
292     low  = ( ctx->total[0] <<  3 );\r
293 \r
294     PUT_ULONG_BE( high, msglen, 0 );\r
295     PUT_ULONG_BE( low,  msglen, 4 );\r
296 \r
297     last = ctx->total[0] & 0x3F;\r
298     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );\r
299 \r
300     sha1_update( ctx, (unsigned char *) sha1_padding, padn );\r
301     sha1_update( ctx, msglen, 8 );\r
302 \r
303     PUT_ULONG_BE( ctx->state[0], output,  0 );\r
304     PUT_ULONG_BE( ctx->state[1], output,  4 );\r
305     PUT_ULONG_BE( ctx->state[2], output,  8 );\r
306     PUT_ULONG_BE( ctx->state[3], output, 12 );\r
307     PUT_ULONG_BE( ctx->state[4], output, 16 );\r
308 }\r
309 \r
310 /*\r
311  * output = SHA-1( input buffer )\r
312  */\r
313 void sha1( unsigned char *input, int ilen, unsigned char output[20] )\r
314 {\r
315     sha1_context ctx;\r
316 \r
317     sha1_starts( &ctx );\r
318     sha1_update( &ctx, input, ilen );\r
319     sha1_finish( &ctx, output );\r
320 \r
321     memset( &ctx, 0, sizeof( sha1_context ) );\r
322 }\r
323 \r
324 /*\r
325  * output = SHA-1( file contents )\r
326  */\r
327 int sha1_file( char *path, unsigned char output[20] )\r
328 {\r
329     FILE *f;\r
330     size_t n;\r
331     sha1_context ctx;\r
332     unsigned char buf[1024];\r
333 \r
334     if( ( f = fopen( path, "rb" ) ) == NULL )\r
335         return( 1 );\r
336 \r
337     sha1_starts( &ctx );\r
338 \r
339     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )\r
340         sha1_update( &ctx, buf, (int) n );\r
341 \r
342     sha1_finish( &ctx, output );\r
343 \r
344     memset( &ctx, 0, sizeof( sha1_context ) );\r
345 \r
346     if( ferror( f ) != 0 )\r
347     {\r
348         fclose( f );\r
349         return( 2 );\r
350     }\r
351 \r
352     fclose( f );\r
353     return( 0 );\r
354 }\r
355 \r
356 /*\r
357  * SHA-1 HMAC context setup\r
358  */\r
359 void sha1_hmac_starts( sha1_context *ctx, unsigned char *key, int keylen )\r
360 {\r
361     int i;\r
362     unsigned char sum[20];\r
363 \r
364     if( keylen > 64 )\r
365     {\r
366         sha1( key, keylen, sum );\r
367         keylen = 20;\r
368         key = sum;\r
369     }\r
370 \r
371     memset( ctx->ipad, 0x36, 64 );\r
372     memset( ctx->opad, 0x5C, 64 );\r
373 \r
374     for( i = 0; i < keylen; i++ )\r
375     {\r
376         ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );\r
377         ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );\r
378     }\r
379 \r
380     sha1_starts( ctx );\r
381     sha1_update( ctx, ctx->ipad, 64 );\r
382 \r
383     memset( sum, 0, sizeof( sum ) );\r
384 }\r
385 \r
386 /*\r
387  * SHA-1 HMAC process buffer\r
388  */\r
389 void sha1_hmac_update( sha1_context *ctx, unsigned char *input, int ilen )\r
390 {\r
391     sha1_update( ctx, input, ilen );\r
392 }\r
393 \r
394 /*\r
395  * SHA-1 HMAC final digest\r
396  */\r
397 void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )\r
398 {\r
399     unsigned char tmpbuf[20];\r
400 \r
401     sha1_finish( ctx, tmpbuf );\r
402     sha1_starts( ctx );\r
403     sha1_update( ctx, ctx->opad, 64 );\r
404     sha1_update( ctx, tmpbuf, 20 );\r
405     sha1_finish( ctx, output );\r
406 \r
407     memset( tmpbuf, 0, sizeof( tmpbuf ) );\r
408 }\r
409 \r
410 /*\r
411  * output = HMAC-SHA-1( hmac key, input buffer )\r
412  */\r
413 void sha1_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,\r
414                 unsigned char output[20] )\r
415 {\r
416     sha1_context ctx;\r
417 \r
418     sha1_hmac_starts( &ctx, key, keylen );\r
419     sha1_hmac_update( &ctx, input, ilen );\r
420     sha1_hmac_finish( &ctx, output );\r
421 \r
422     memset( &ctx, 0, sizeof( sha1_context ) );\r
423 }\r
424 \r
425 #if defined(XYSSL_SELF_TEST)\r
426 \r
427 /*\r
428  * FIPS-180-1 test vectors\r
429  */\r
430 static const char sha1_test_str[3][57] = \r
431 {\r
432     { "abc" },\r
433     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },\r
434     { "" }\r
435 };\r
436 \r
437 static const unsigned char sha1_test_sum[3][20] =\r
438 {\r
439     { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,\r
440       0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },\r
441     { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,\r
442       0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },\r
443     { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,\r
444       0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }\r
445 };\r
446 \r
447 /*\r
448  * Checkup routine\r
449  */\r
450 int sha1_self_test( int verbose )\r
451 {\r
452     int i, j;\r
453     unsigned char buf[1000];\r
454     unsigned char sha1sum[20];\r
455     sha1_context ctx;\r
456 \r
457     for( i = 0; i < 3; i++ )\r
458     {\r
459         if( verbose != 0 )\r
460             printf( "  SHA-1 test #%d: ", i + 1 );\r
461 \r
462         sha1_starts( &ctx );\r
463 \r
464         if( i < 2 )\r
465             sha1_update( &ctx, (unsigned char *) sha1_test_str[i],\r
466                          strlen( sha1_test_str[i] ) );\r
467         else\r
468         {\r
469             memset( buf, 'a', 1000 );\r
470             for( j = 0; j < 1000; j++ )\r
471                 sha1_update( &ctx, buf, 1000 );\r
472         }\r
473 \r
474         sha1_finish( &ctx, sha1sum );\r
475 \r
476         if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )\r
477         {\r
478             if( verbose != 0 )\r
479                 printf( "failed\n" );\r
480 \r
481             return( 1 );\r
482         }\r
483 \r
484         if( verbose != 0 )\r
485             printf( "passed\n" );\r
486     }\r
487 \r
488     if( verbose != 0 )\r
489         printf( "\n" );\r
490 \r
491     return( 0 );\r
492 }\r
493 \r
494 #endif\r
495 \r
496 #endif