/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/library/sha1.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 174 $ : Last Committed Revision
00003  * $Date: 2008-06-24 10:50:29 -0700 (Tue, 24 Jun 2008) $ : Last Committed Date */
00004 /*
00005  *  FIPS-180-1 compliant SHA-1 implementation
00006  *
00007  *  Copyright (C) 2006-2007  Christophe Devine
00008  *
00009  *  This library is free software; you can redistribute it and/or
00010  *  modify it under the terms of the GNU Lesser General Public
00011  *  License, version 2.1 as published by the Free Software Foundation.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Lesser General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Lesser General Public
00019  *  License along with this library; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00021  *  MA  02110-1301  USA
00022  */
00023 /*
00024  *  The SHA-1 standard was published by NIST in 1993.
00025  *
00026  *  http://www.itl.nist.gov/fipspubs/fip180-1.htm
00027  */
00028 
00029 #ifndef _CRT_SECURE_NO_DEPRECATE
00030 #define _CRT_SECURE_NO_DEPRECATE 1
00031 #endif
00032 
00033 #include <string.h>
00034 #include <stdio.h>
00035 
00036 #include "xyssl/sha1.h"
00037 
00038 /*
00039  * 32-bit integer manipulation macros (big endian)
00040  */
00041 #ifndef GET_UINT32_BE
00042 #define GET_UINT32_BE(n,b,i)                            \
00043 {                                                       \
00044     (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
00045         | ( (unsigned long) (b)[(i) + 1] << 16 )        \
00046         | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
00047         | ( (unsigned long) (b)[(i) + 3]       );       \
00048 }
00049 #endif
00050 
00051 #ifndef PUT_UINT32_BE
00052 #define PUT_UINT32_BE(n,b,i)                            \
00053 {                                                       \
00054     (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
00055     (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
00056     (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
00057     (b)[(i) + 3] = (unsigned char) ( (n)       );       \
00058 }
00059 #endif
00060 
00061 /*
00062  * SHA-1 context setup
00063  */
00064 void sha1_starts( sha1_context *ctx )
00065 {
00066     ctx->total[0] = 0;
00067     ctx->total[1] = 0;
00068 
00069     ctx->state[0] = 0x67452301;
00070     ctx->state[1] = 0xEFCDAB89;
00071     ctx->state[2] = 0x98BADCFE;
00072     ctx->state[3] = 0x10325476;
00073     ctx->state[4] = 0xC3D2E1F0;
00074 }
00075 
00076 static void sha1_process( sha1_context *ctx, unsigned char data[64] )
00077 {
00078     unsigned long temp, W[16], A, B, C, D, E;
00079 
00080     GET_UINT32_BE( W[ 0], data,  0 );
00081     GET_UINT32_BE( W[ 1], data,  4 );
00082     GET_UINT32_BE( W[ 2], data,  8 );
00083     GET_UINT32_BE( W[ 3], data, 12 );
00084     GET_UINT32_BE( W[ 4], data, 16 );
00085     GET_UINT32_BE( W[ 5], data, 20 );
00086     GET_UINT32_BE( W[ 6], data, 24 );
00087     GET_UINT32_BE( W[ 7], data, 28 );
00088     GET_UINT32_BE( W[ 8], data, 32 );
00089     GET_UINT32_BE( W[ 9], data, 36 );
00090     GET_UINT32_BE( W[10], data, 40 );
00091     GET_UINT32_BE( W[11], data, 44 );
00092     GET_UINT32_BE( W[12], data, 48 );
00093     GET_UINT32_BE( W[13], data, 52 );
00094     GET_UINT32_BE( W[14], data, 56 );
00095     GET_UINT32_BE( W[15], data, 60 );
00096 
00097 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00098 
00099 #define R(t)                                            \
00100 (                                                       \
00101     temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \
00102            W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],      \
00103     ( W[t & 0x0F] = S(temp,1) )                         \
00104 )
00105 
00106 #define P(a,b,c,d,e,x)                                  \
00107 {                                                       \
00108     e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);        \
00109 }
00110 
00111     A = ctx->state[0];
00112     B = ctx->state[1];
00113     C = ctx->state[2];
00114     D = ctx->state[3];
00115     E = ctx->state[4];
00116 
00117 #define F(x,y,z) (z ^ (x & (y ^ z)))
00118 #define K 0x5A827999
00119 
00120     P( A, B, C, D, E, W[0]  );
00121     P( E, A, B, C, D, W[1]  );
00122     P( D, E, A, B, C, W[2]  );
00123     P( C, D, E, A, B, W[3]  );
00124     P( B, C, D, E, A, W[4]  );
00125     P( A, B, C, D, E, W[5]  );
00126     P( E, A, B, C, D, W[6]  );
00127     P( D, E, A, B, C, W[7]  );
00128     P( C, D, E, A, B, W[8]  );
00129     P( B, C, D, E, A, W[9]  );
00130     P( A, B, C, D, E, W[10] );
00131     P( E, A, B, C, D, W[11] );
00132     P( D, E, A, B, C, W[12] );
00133     P( C, D, E, A, B, W[13] );
00134     P( B, C, D, E, A, W[14] );
00135     P( A, B, C, D, E, W[15] );
00136     P( E, A, B, C, D, R(16) );
00137     P( D, E, A, B, C, R(17) );
00138     P( C, D, E, A, B, R(18) );
00139     P( B, C, D, E, A, R(19) );
00140 
00141 #undef K
00142 #undef F
00143 
00144 #define F(x,y,z) (x ^ y ^ z)
00145 #define K 0x6ED9EBA1
00146 
00147     P( A, B, C, D, E, R(20) );
00148     P( E, A, B, C, D, R(21) );
00149     P( D, E, A, B, C, R(22) );
00150     P( C, D, E, A, B, R(23) );
00151     P( B, C, D, E, A, R(24) );
00152     P( A, B, C, D, E, R(25) );
00153     P( E, A, B, C, D, R(26) );
00154     P( D, E, A, B, C, R(27) );
00155     P( C, D, E, A, B, R(28) );
00156     P( B, C, D, E, A, R(29) );
00157     P( A, B, C, D, E, R(30) );
00158     P( E, A, B, C, D, R(31) );
00159     P( D, E, A, B, C, R(32) );
00160     P( C, D, E, A, B, R(33) );
00161     P( B, C, D, E, A, R(34) );
00162     P( A, B, C, D, E, R(35) );
00163     P( E, A, B, C, D, R(36) );
00164     P( D, E, A, B, C, R(37) );
00165     P( C, D, E, A, B, R(38) );
00166     P( B, C, D, E, A, R(39) );
00167 
00168 #undef K
00169 #undef F
00170 
00171 #define F(x,y,z) ((x & y) | (z & (x | y)))
00172 #define K 0x8F1BBCDC
00173 
00174     P( A, B, C, D, E, R(40) );
00175     P( E, A, B, C, D, R(41) );
00176     P( D, E, A, B, C, R(42) );
00177     P( C, D, E, A, B, R(43) );
00178     P( B, C, D, E, A, R(44) );
00179     P( A, B, C, D, E, R(45) );
00180     P( E, A, B, C, D, R(46) );
00181     P( D, E, A, B, C, R(47) );
00182     P( C, D, E, A, B, R(48) );
00183     P( B, C, D, E, A, R(49) );
00184     P( A, B, C, D, E, R(50) );
00185     P( E, A, B, C, D, R(51) );
00186     P( D, E, A, B, C, R(52) );
00187     P( C, D, E, A, B, R(53) );
00188     P( B, C, D, E, A, R(54) );
00189     P( A, B, C, D, E, R(55) );
00190     P( E, A, B, C, D, R(56) );
00191     P( D, E, A, B, C, R(57) );
00192     P( C, D, E, A, B, R(58) );
00193     P( B, C, D, E, A, R(59) );
00194 
00195 #undef K
00196 #undef F
00197 
00198 #define F(x,y,z) (x ^ y ^ z)
00199 #define K 0xCA62C1D6
00200 
00201     P( A, B, C, D, E, R(60) );
00202     P( E, A, B, C, D, R(61) );
00203     P( D, E, A, B, C, R(62) );
00204     P( C, D, E, A, B, R(63) );
00205     P( B, C, D, E, A, R(64) );
00206     P( A, B, C, D, E, R(65) );
00207     P( E, A, B, C, D, R(66) );
00208     P( D, E, A, B, C, R(67) );
00209     P( C, D, E, A, B, R(68) );
00210     P( B, C, D, E, A, R(69) );
00211     P( A, B, C, D, E, R(70) );
00212     P( E, A, B, C, D, R(71) );
00213     P( D, E, A, B, C, R(72) );
00214     P( C, D, E, A, B, R(73) );
00215     P( B, C, D, E, A, R(74) );
00216     P( A, B, C, D, E, R(75) );
00217     P( E, A, B, C, D, R(76) );
00218     P( D, E, A, B, C, R(77) );
00219     P( C, D, E, A, B, R(78) );
00220     P( B, C, D, E, A, R(79) );
00221 
00222 #undef K
00223 #undef F
00224 
00225     ctx->state[0] += A;
00226     ctx->state[1] += B;
00227     ctx->state[2] += C;
00228     ctx->state[3] += D;
00229     ctx->state[4] += E;
00230 }
00231 
00232 /*
00233  * SHA-1 process buffer
00234  */
00235 void sha1_update( sha1_context *ctx, unsigned char *input, int ilen )
00236 {
00237     int fill;
00238     unsigned long left;
00239 
00240     if( ilen <= 0 )
00241         return;
00242 
00243     left = ctx->total[0] & 0x3F;
00244     fill = 64 - left;
00245 
00246     ctx->total[0] += ilen;
00247     ctx->total[0] &= 0xFFFFFFFF;
00248 
00249     if( ctx->total[0] < (unsigned long) ilen )
00250         ctx->total[1]++;
00251 
00252     if( left && ilen >= fill )
00253     {
00254         memcpy( (void *) (ctx->buffer + left),
00255                 (void *) input, fill );
00256         sha1_process( ctx, ctx->buffer );
00257         input += fill;
00258         ilen  -= fill;
00259         left = 0;
00260     }
00261 
00262     while( ilen >= 64 )
00263     {
00264         sha1_process( ctx, input );
00265         input += 64;
00266         ilen  -= 64;
00267     }
00268 
00269     if( ilen > 0 )
00270     {
00271         memcpy( (void *) (ctx->buffer + left),
00272                 (void *) input, ilen );
00273     }
00274 }
00275 
00276 static const unsigned char sha1_padding[64] =
00277 {
00278  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00279     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00280     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00281     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00282 };
00283 
00284 /*
00285  * SHA-1 final digest
00286  */
00287 void sha1_finish( sha1_context *ctx, unsigned char *output )
00288 {
00289     unsigned long last, padn;
00290     unsigned long high, low;
00291     unsigned char msglen[8];
00292 
00293     high = ( ctx->total[0] >> 29 )
00294          | ( ctx->total[1] <<  3 );
00295     low  = ( ctx->total[0] <<  3 );
00296 
00297     PUT_UINT32_BE( high, msglen, 0 );
00298     PUT_UINT32_BE( low,  msglen, 4 );
00299 
00300     last = ctx->total[0] & 0x3F;
00301     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00302 
00303     sha1_update( ctx, (unsigned char *) sha1_padding, padn );
00304     sha1_update( ctx, msglen, 8 );
00305 
00306     PUT_UINT32_BE( ctx->state[0], output,  0 );
00307     PUT_UINT32_BE( ctx->state[1], output,  4 );
00308     PUT_UINT32_BE( ctx->state[2], output,  8 );
00309     PUT_UINT32_BE( ctx->state[3], output, 12 );
00310     PUT_UINT32_BE( ctx->state[4], output, 16 );
00311 }
00312 
00313 /*
00314  * Output = SHA-1( input buffer )
00315  */
00316 void sha1( unsigned char *input, int ilen,
00317            unsigned char *output )
00318 {
00319     sha1_context ctx;
00320 
00321     sha1_starts( &ctx );
00322     sha1_update( &ctx, input, ilen );
00323     sha1_finish( &ctx, output );
00324 
00325     memset( &ctx, 0, sizeof( sha1_context ) );
00326 }
00327 
00328 /*
00329  * Output = SHA-1( file contents )
00330  */
00331 int sha1_file( char *path, unsigned char *output )
00332 {
00333     FILE *f;
00334     size_t n;
00335     sha1_context ctx;
00336     unsigned char buf[1024];
00337 
00338     if( ( f = fopen( path, "rb" ) ) == NULL )
00339         return( 1 );
00340 
00341     sha1_starts( &ctx );
00342 
00343     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00344         sha1_update( &ctx, buf, (int) n );
00345 
00346     sha1_finish( &ctx, output );
00347 
00348     memset( &ctx, 0, sizeof( sha1_context ) );
00349 
00350     if( ferror( f ) != 0 )
00351     {
00352         fclose( f );
00353         return( 2 );
00354     }
00355 
00356     fclose( f );
00357     return( 0 );
00358 }
00359 
00360 /*
00361  * SHA-1 HMAC context setup
00362  */
00363 void sha1_hmac_starts( sha1_context *ctx,
00364                        unsigned char *key, int keylen )
00365 {
00366     int i;
00367 
00368     memset( ctx->ipad, 0x36, 64 );
00369     memset( ctx->opad, 0x5C, 64 );
00370 
00371     for( i = 0; i < keylen; i++ )
00372     {
00373         if( i >= 64 ) break;
00374 
00375         ctx->ipad[i] ^= key[i];
00376         ctx->opad[i] ^= key[i];
00377     }
00378 
00379     sha1_starts( ctx );
00380     sha1_update( ctx, ctx->ipad, 64 );
00381 }
00382 
00383 /*
00384  * SHA-1 HMAC process buffer
00385  */
00386 void sha1_hmac_update( sha1_context *ctx,
00387                        unsigned char *input, int ilen )
00388 {
00389     sha1_update( ctx, input, ilen );
00390 }
00391 
00392 /*
00393  * SHA-1 HMAC final digest
00394  */
00395 void sha1_hmac_finish( sha1_context *ctx, unsigned char *output )
00396 {
00397     unsigned char tmpbuf[20];
00398 
00399     sha1_finish( ctx, tmpbuf );
00400     sha1_starts( ctx );
00401     sha1_update( ctx, ctx->opad, 64 );
00402     sha1_update( ctx, tmpbuf, 20 );
00403     sha1_finish( ctx, output );
00404 
00405     memset( tmpbuf, 0, sizeof( tmpbuf ) );
00406 }
00407 
00408 /*
00409  * Output = HMAC-SHA-1( hmac key, input buffer )
00410  */
00411 void sha1_hmac( unsigned char *key, int keylen,
00412                 unsigned char *input, int ilen,
00413                 unsigned char *output )
00414 {
00415     sha1_context ctx;
00416 
00417     sha1_hmac_starts( &ctx, key, keylen );
00418     sha1_hmac_update( &ctx, input, ilen );
00419     sha1_hmac_finish( &ctx, output );
00420 
00421     memset( &ctx, 0, sizeof( sha1_context ) );
00422 }
00423 
00424 static const char _sha1_src[] = "_sha1_src";
00425 
00426 #if defined(SELF_TEST)
00427 /*
00428  * FIPS-180-1 test vectors
00429  */
00430 static const char sha1_test_str[3][57] = 
00431 {
00432     { "abc" },
00433     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
00434     { "" }
00435 };
00436 
00437 static const unsigned char sha1_test_sum[3][20] =
00438 {
00439     { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
00440       0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
00441     { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
00442       0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
00443     { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
00444       0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
00445 };
00446 
00447 /*
00448  * Checkup routine
00449  */
00450 int sha1_self_test( int verbose )
00451 {
00452     int i, j;
00453     unsigned char buf[1000];
00454     unsigned char sha1sum[20];
00455     sha1_context ctx;
00456 
00457     for( i = 0; i < 3; i++ )
00458     {
00459         if( verbose != 0 )
00460             printf( "  SHA-1 test #%d: ", i + 1 );
00461 
00462         sha1_starts( &ctx );
00463 
00464         if( i < 2 )
00465             sha1_update( &ctx, (unsigned char *) sha1_test_str[i],
00466                          strlen( sha1_test_str[i] ) );
00467         else
00468         {
00469             memset( buf, 'a', 1000 );
00470             for( j = 0; j < 1000; j++ )
00471                 sha1_update( &ctx, buf, 1000 );
00472         }
00473 
00474         sha1_finish( &ctx, sha1sum );
00475 
00476         if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
00477         {
00478             if( verbose != 0 )
00479                 printf( "failed\n" );
00480 
00481             return( 1 );
00482         }
00483 
00484         if( verbose != 0 )
00485             printf( "passed\n" );
00486     }
00487 
00488     if( verbose != 0 )
00489         printf( "\n" );
00490 
00491     return( 0 );
00492 }
00493 #else
00494 int sha1_self_test( int verbose )
00495 {
00496     return( 0 );
00497 }
00498 #endif

Generated on Tue Jul 1 15:29:59 2008 for Mobile-C by  doxygen 1.5.4