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

Go to the documentation of this file.
00001 /*
00002  *  FIPS-180-2 compliant SHA-256 implementation
00003  *
00004  *  Copyright (C) 2006-2007  Christophe Devine
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License, version 2.1 as published by the Free Software Foundation.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Lesser General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Lesser General Public
00016  *  License along with this library; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  *  MA  02110-1301  USA
00019  */
00020 /*
00021  *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
00022  *
00023  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
00024  */
00025 
00026 #ifndef _CRT_SECURE_NO_DEPRECATE
00027 #define _CRT_SECURE_NO_DEPRECATE 1
00028 #endif
00029 
00030 #include <string.h>
00031 #include <stdio.h>
00032 
00033 #include "xyssl/sha2.h"
00034 
00035 /*
00036  * 32-bit integer manipulation macros (big endian)
00037  */
00038 #ifndef GET_UINT32_BE
00039 #define GET_UINT32_BE(n,b,i)                            \
00040 {                                                       \
00041     (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
00042         | ( (unsigned long) (b)[(i) + 1] << 16 )        \
00043         | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
00044         | ( (unsigned long) (b)[(i) + 3]       );       \
00045 }
00046 #endif
00047 
00048 #ifndef PUT_UINT32_BE
00049 #define PUT_UINT32_BE(n,b,i)                            \
00050 {                                                       \
00051     (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
00052     (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
00053     (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
00054     (b)[(i) + 3] = (unsigned char) ( (n)       );       \
00055 }
00056 #endif
00057 
00058 /*
00059  * SHA-256 context setup
00060  */
00061 void sha2_starts( sha2_context *ctx, int is224 )
00062 {
00063     ctx->total[0] = 0;
00064     ctx->total[1] = 0;
00065 
00066     if( is224 == 0 )
00067     {
00068         /* SHA-256 */
00069         ctx->state[0] = 0x6A09E667;
00070         ctx->state[1] = 0xBB67AE85;
00071         ctx->state[2] = 0x3C6EF372;
00072         ctx->state[3] = 0xA54FF53A;
00073         ctx->state[4] = 0x510E527F;
00074         ctx->state[5] = 0x9B05688C;
00075         ctx->state[6] = 0x1F83D9AB;
00076         ctx->state[7] = 0x5BE0CD19;
00077     }
00078     else
00079     {
00080         /* SHA-224 */
00081         ctx->state[0] = 0xC1059ED8;
00082         ctx->state[1] = 0x367CD507;
00083         ctx->state[2] = 0x3070DD17;
00084         ctx->state[3] = 0xF70E5939;
00085         ctx->state[4] = 0xFFC00B31;
00086         ctx->state[5] = 0x68581511;
00087         ctx->state[6] = 0x64F98FA7;
00088         ctx->state[7] = 0xBEFA4FA4;
00089     }
00090 
00091     ctx->is224 = is224;
00092 }
00093 
00094 static void sha2_process( sha2_context *ctx, unsigned char data[64] )
00095 {
00096     unsigned long temp1, temp2, W[64];
00097     unsigned long A, B, C, D, E, F, G, H;
00098 
00099     GET_UINT32_BE( W[ 0], data,  0 );
00100     GET_UINT32_BE( W[ 1], data,  4 );
00101     GET_UINT32_BE( W[ 2], data,  8 );
00102     GET_UINT32_BE( W[ 3], data, 12 );
00103     GET_UINT32_BE( W[ 4], data, 16 );
00104     GET_UINT32_BE( W[ 5], data, 20 );
00105     GET_UINT32_BE( W[ 6], data, 24 );
00106     GET_UINT32_BE( W[ 7], data, 28 );
00107     GET_UINT32_BE( W[ 8], data, 32 );
00108     GET_UINT32_BE( W[ 9], data, 36 );
00109     GET_UINT32_BE( W[10], data, 40 );
00110     GET_UINT32_BE( W[11], data, 44 );
00111     GET_UINT32_BE( W[12], data, 48 );
00112     GET_UINT32_BE( W[13], data, 52 );
00113     GET_UINT32_BE( W[14], data, 56 );
00114     GET_UINT32_BE( W[15], data, 60 );
00115 
00116 #define  SHR(x,n) ((x & 0xFFFFFFFF) >> n)
00117 #define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
00118 
00119 #define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))
00120 #define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))
00121 
00122 #define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
00123 #define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
00124 
00125 #define F0(x,y,z) ((x & y) | (z & (x | y)))
00126 #define F1(x,y,z) (z ^ (x & (y ^ z)))
00127 
00128 #define R(t)                                    \
00129 (                                               \
00130     W[t] = S1(W[t -  2]) + W[t -  7] +          \
00131            S0(W[t - 15]) + W[t - 16]            \
00132 )
00133 
00134 #define P(a,b,c,d,e,f,g,h,x,K)                  \
00135 {                                               \
00136     temp1 = h + S3(e) + F1(e,f,g) + K + x;      \
00137     temp2 = S2(a) + F0(a,b,c);                  \
00138     d += temp1; h = temp1 + temp2;              \
00139 }
00140 
00141     A = ctx->state[0];
00142     B = ctx->state[1];
00143     C = ctx->state[2];
00144     D = ctx->state[3];
00145     E = ctx->state[4];
00146     F = ctx->state[5];
00147     G = ctx->state[6];
00148     H = ctx->state[7];
00149 
00150     P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
00151     P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
00152     P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
00153     P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
00154     P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
00155     P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
00156     P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
00157     P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
00158     P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
00159     P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
00160     P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
00161     P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
00162     P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
00163     P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
00164     P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
00165     P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
00166     P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
00167     P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
00168     P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
00169     P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
00170     P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
00171     P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
00172     P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
00173     P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
00174     P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
00175     P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
00176     P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
00177     P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
00178     P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
00179     P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
00180     P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
00181     P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
00182     P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
00183     P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
00184     P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
00185     P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
00186     P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
00187     P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
00188     P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
00189     P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
00190     P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
00191     P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
00192     P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
00193     P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
00194     P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
00195     P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
00196     P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
00197     P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
00198     P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
00199     P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
00200     P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
00201     P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
00202     P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
00203     P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
00204     P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
00205     P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
00206     P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
00207     P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
00208     P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
00209     P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
00210     P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
00211     P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
00212     P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
00213     P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
00214 
00215     ctx->state[0] += A;
00216     ctx->state[1] += B;
00217     ctx->state[2] += C;
00218     ctx->state[3] += D;
00219     ctx->state[4] += E;
00220     ctx->state[5] += F;
00221     ctx->state[6] += G;
00222     ctx->state[7] += H;
00223 }
00224 
00225 /*
00226  * SHA-256 process buffer
00227  */
00228 void sha2_update( sha2_context *ctx, unsigned char *input, int ilen )
00229 {
00230     int fill;
00231     unsigned long left;
00232 
00233     if( ilen <= 0 )
00234         return;
00235 
00236     left = ctx->total[0] & 0x3F;
00237     fill = 64 - left;
00238 
00239     ctx->total[0] += ilen;
00240     ctx->total[0] &= 0xFFFFFFFF;
00241 
00242     if( ctx->total[0] < (unsigned long) ilen )
00243         ctx->total[1]++;
00244 
00245     if( left && ilen >= fill )
00246     {
00247         memcpy( (void *) (ctx->buffer + left),
00248                 (void *) input, fill );
00249         sha2_process( ctx, ctx->buffer );
00250         input += fill;
00251         ilen  -= fill;
00252         left = 0;
00253     }
00254 
00255     while( ilen >= 64 )
00256     {
00257         sha2_process( ctx, input );
00258         input += 64;
00259         ilen  -= 64;
00260     }
00261 
00262     if( ilen > 0 )
00263     {
00264         memcpy( (void *) (ctx->buffer + left),
00265                 (void *) input, ilen );
00266     }
00267 }
00268 
00269 static const unsigned char sha2_padding[64] =
00270 {
00271  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00272     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00273     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00274     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00275 };
00276 
00277 /*
00278  * SHA-256 final digest
00279  */
00280 void sha2_finish( sha2_context *ctx, unsigned char *output )
00281 {
00282     unsigned long last, padn;
00283     unsigned long high, low;
00284     unsigned char msglen[8];
00285 
00286     high = ( ctx->total[0] >> 29 )
00287          | ( ctx->total[1] <<  3 );
00288     low  = ( ctx->total[0] <<  3 );
00289 
00290     PUT_UINT32_BE( high, msglen, 0 );
00291     PUT_UINT32_BE( low,  msglen, 4 );
00292 
00293     last = ctx->total[0] & 0x3F;
00294     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00295 
00296     sha2_update( ctx, (unsigned char *) sha2_padding, padn );
00297     sha2_update( ctx, msglen, 8 );
00298 
00299     PUT_UINT32_BE( ctx->state[0], output,  0 );
00300     PUT_UINT32_BE( ctx->state[1], output,  4 );
00301     PUT_UINT32_BE( ctx->state[2], output,  8 );
00302     PUT_UINT32_BE( ctx->state[3], output, 12 );
00303     PUT_UINT32_BE( ctx->state[4], output, 16 );
00304     PUT_UINT32_BE( ctx->state[5], output, 20 );
00305     PUT_UINT32_BE( ctx->state[6], output, 24 );
00306 
00307     if( ctx->is224 == 0 )
00308         PUT_UINT32_BE( ctx->state[7], output, 28 );
00309 }
00310 
00311 /*
00312  * Output = SHA-256( input buffer )
00313  */
00314 void sha2( unsigned char *input,  int ilen,
00315            unsigned char *output, int is224 )
00316 {
00317     sha2_context ctx;
00318 
00319     sha2_starts( &ctx, is224 );
00320     sha2_update( &ctx, input, ilen );
00321     sha2_finish( &ctx, output );
00322 
00323     memset( &ctx, 0, sizeof( sha2_context ) );
00324 }
00325 
00326 /*
00327  * Output = SHA-256( file contents )
00328  */
00329 int sha2_file( char *path, unsigned char *output, int is224 )
00330 {
00331     FILE *f;
00332     size_t n;
00333     sha2_context ctx;
00334     unsigned char buf[1024];
00335 
00336     if( ( f = fopen( path, "rb" ) ) == NULL )
00337         return( 1 );
00338 
00339     sha2_starts( &ctx, is224 );
00340 
00341     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00342         sha2_update( &ctx, buf, (int) n );
00343 
00344     sha2_finish( &ctx, output );
00345 
00346     memset( &ctx, 0, sizeof( sha2_context ) );
00347 
00348     if( ferror( f ) != 0 )
00349     {
00350         fclose( f );
00351         return( 2 );
00352     }
00353 
00354     fclose( f );
00355     return( 0 );
00356 }
00357 
00358 /*
00359  * SHA-256 HMAC context setup
00360  */
00361 void sha2_hmac_starts( sha2_context *ctx,  int is224,
00362                        unsigned char *key, int keylen )
00363 {
00364     int i;
00365 
00366     memset( ctx->ipad, 0x36, 64 );
00367     memset( ctx->opad, 0x5C, 64 );
00368 
00369     for( i = 0; i < keylen; i++ )
00370     {
00371         if( i >= 64 ) break;
00372 
00373         ctx->ipad[i] ^= key[i];
00374         ctx->opad[i] ^= key[i];
00375     }
00376 
00377     sha2_starts( ctx, is224 );
00378     sha2_update( ctx, ctx->ipad, 64 );
00379 }
00380 
00381 /*
00382  * SHA-256 HMAC process buffer
00383  */
00384 void sha2_hmac_update( sha2_context *ctx,
00385                        unsigned char *input, int ilen )
00386 {
00387     sha2_update( ctx, input, ilen );
00388 }
00389 
00390 /*
00391  * SHA-256 HMAC final digest
00392  */
00393 void sha2_hmac_finish( sha2_context *ctx, unsigned char *output )
00394 {
00395     int is224, hlen;
00396     unsigned char tmpbuf[32];
00397 
00398     is224 = ctx->is224;
00399     hlen = ( is224 == 0 ) ? 32 : 28;
00400 
00401     sha2_finish( ctx, tmpbuf );
00402     sha2_starts( ctx, is224 );
00403     sha2_update( ctx, ctx->opad, 64 );
00404     sha2_update( ctx, tmpbuf, hlen );
00405     sha2_finish( ctx, output );
00406 
00407     memset( tmpbuf, 0, sizeof( tmpbuf ) );
00408 }
00409 
00410 /*
00411  * Output = HMAC-SHA-256( hmac key, input buffer )
00412  */
00413 void sha2_hmac( unsigned char *key,  int keylen,
00414                 unsigned char *input,  int ilen,
00415                 unsigned char *output, int is224 )
00416 {
00417     sha2_context ctx;
00418 
00419     sha2_hmac_starts( &ctx, is224, key, keylen );
00420     sha2_hmac_update( &ctx, input, ilen );
00421     sha2_hmac_finish( &ctx, output );
00422 
00423     memset( &ctx, 0, sizeof( sha2_context ) );
00424 }
00425 
00426 static const char _sha2_src[] = "_sha2_src";
00427 
00428 #if defined(SELF_TEST)
00429 /*
00430  * FIPS-180-2 test vectors
00431  */
00432 static const char sha2_test_str[3][57] = 
00433 {
00434     { "abc" },
00435     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
00436     { "" }
00437 };
00438 
00439 static const unsigned char sha2_test_sum[6][32] =
00440 {
00441     /*
00442      * SHA-224 test vectors
00443      */
00444     { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
00445       0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
00446       0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
00447       0xE3, 0x6C, 0x9D, 0xA7 },
00448     { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
00449       0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
00450       0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
00451       0x52, 0x52, 0x25, 0x25 },
00452     { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
00453       0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
00454       0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
00455       0x4E, 0xE7, 0xAD, 0x67 },
00456 
00457     /*
00458      * SHA-256 test vectors
00459      */
00460     { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
00461       0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
00462       0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
00463       0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
00464     { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
00465       0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
00466       0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
00467       0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
00468     { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
00469       0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
00470       0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
00471       0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
00472 };
00473 
00474 /*
00475  * Checkup routine
00476  */
00477 int sha2_self_test( int verbose )
00478 {
00479     int i, j, k;
00480     unsigned char buf[1000];
00481     unsigned char sha2sum[32];
00482     sha2_context ctx;
00483 
00484     memset( buf, 'a', 1000 );
00485 
00486     for( i = 0; i < 6; i++ )
00487     {
00488         j = i % 3;
00489         k = i < 3;
00490 
00491         if( verbose != 0 )
00492             printf( "  SHA-%d test #%d: ", 256 - k * 32, j + 1 );
00493 
00494         sha2_starts( &ctx, k );
00495 
00496         if( j < 2 )
00497             sha2_update( &ctx,
00498                          (unsigned char *) sha2_test_str[j],
00499                          strlen( sha2_test_str[j] ) );
00500         else
00501         {
00502             for( j = 0; j < 1000; j++ )
00503                 sha2_update( &ctx, buf, 1000 );
00504         }
00505 
00506         sha2_finish( &ctx, sha2sum );
00507 
00508         if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 )
00509         {
00510             if( verbose != 0 )
00511                 printf( "failed\n" );
00512 
00513             return( 1 );
00514         }
00515 
00516         if( verbose != 0 )
00517             printf( "passed\n" );
00518     }
00519 
00520     if( verbose != 0 )
00521         printf( "\n" );
00522 
00523     return( 0 );
00524 }
00525 #else
00526 int sha2_self_test( int verbose )
00527 {
00528     return( 0 );
00529 }
00530 #endif

Generated on Fri May 16 14:49:55 2008 for Mobile-C by  doxygen 1.5.4