00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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/sha4.h"
00037
00038
00039
00040
00041 #ifndef GET_UINT64_BE
00042 #define GET_UINT64_BE(n,b,i) \
00043 { \
00044 (n) = ( (uint64) (b)[(i) ] << 56 ) \
00045 | ( (uint64) (b)[(i) + 1] << 48 ) \
00046 | ( (uint64) (b)[(i) + 2] << 40 ) \
00047 | ( (uint64) (b)[(i) + 3] << 32 ) \
00048 | ( (uint64) (b)[(i) + 4] << 24 ) \
00049 | ( (uint64) (b)[(i) + 5] << 16 ) \
00050 | ( (uint64) (b)[(i) + 6] << 8 ) \
00051 | ( (uint64) (b)[(i) + 7] ); \
00052 }
00053 #endif
00054
00055 #ifndef PUT_UINT64_BE
00056 #define PUT_UINT64_BE(n,b,i) \
00057 { \
00058 (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
00059 (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
00060 (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
00061 (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
00062 (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
00063 (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
00064 (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
00065 (b)[(i) + 7] = (unsigned char) ( (n) ); \
00066 }
00067 #endif
00068
00069
00070
00071
00072 static const uint64 K[80] =
00073 {
00074 UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
00075 UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
00076 UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
00077 UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
00078 UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
00079 UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
00080 UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
00081 UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
00082 UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
00083 UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
00084 UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
00085 UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
00086 UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
00087 UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
00088 UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
00089 UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
00090 UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
00091 UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
00092 UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
00093 UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
00094 UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
00095 UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
00096 UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
00097 UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
00098 UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
00099 UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
00100 UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
00101 UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
00102 UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
00103 UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
00104 UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
00105 UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
00106 UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
00107 UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
00108 UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
00109 UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
00110 UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
00111 UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
00112 UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
00113 UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
00114 };
00115
00116
00117
00118
00119 void sha4_starts( sha4_context *ctx, int is384 )
00120 {
00121 ctx->total[0] = 0;
00122 ctx->total[1] = 0;
00123
00124 if( is384 == 0 )
00125 {
00126
00127 ctx->state[0] = UL64(0x6A09E667F3BCC908);
00128 ctx->state[1] = UL64(0xBB67AE8584CAA73B);
00129 ctx->state[2] = UL64(0x3C6EF372FE94F82B);
00130 ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
00131 ctx->state[4] = UL64(0x510E527FADE682D1);
00132 ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
00133 ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
00134 ctx->state[7] = UL64(0x5BE0CD19137E2179);
00135 }
00136 else
00137 {
00138
00139 ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
00140 ctx->state[1] = UL64(0x629A292A367CD507);
00141 ctx->state[2] = UL64(0x9159015A3070DD17);
00142 ctx->state[3] = UL64(0x152FECD8F70E5939);
00143 ctx->state[4] = UL64(0x67332667FFC00B31);
00144 ctx->state[5] = UL64(0x8EB44A8768581511);
00145 ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
00146 ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
00147 }
00148
00149 ctx->is384 = is384;
00150 }
00151
00152 static void sha4_process( sha4_context *ctx, unsigned char data[128] )
00153 {
00154 int i;
00155 uint64 temp1, temp2, W[80];
00156 uint64 A, B, C, D, E, F, G, H;
00157
00158 #define SHR(x,n) (x >> n)
00159 #define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
00160
00161 #define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
00162 #define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
00163
00164 #define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
00165 #define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
00166
00167 #define F0(x,y,z) ((x & y) | (z & (x | y)))
00168 #define F1(x,y,z) (z ^ (x & (y ^ z)))
00169
00170 #define P(a,b,c,d,e,f,g,h,x,K) \
00171 { \
00172 temp1 = h + S3(e) + F1(e,f,g) + K + x; \
00173 temp2 = S2(a) + F0(a,b,c); \
00174 d += temp1; h = temp1 + temp2; \
00175 }
00176
00177 for( i = 0; i < 16; i++ )
00178 {
00179 GET_UINT64_BE( W[i], data, i << 3 );
00180 }
00181
00182 for( ; i < 80; i++ )
00183 {
00184 W[i] = S1(W[i - 2]) + W[i - 7] +
00185 S0(W[i - 15]) + W[i - 16];
00186 }
00187
00188 A = ctx->state[0];
00189 B = ctx->state[1];
00190 C = ctx->state[2];
00191 D = ctx->state[3];
00192 E = ctx->state[4];
00193 F = ctx->state[5];
00194 G = ctx->state[6];
00195 H = ctx->state[7];
00196 i = 0;
00197
00198 do
00199 {
00200 P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
00201 P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
00202 P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
00203 P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
00204 P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
00205 P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
00206 P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
00207 P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
00208 }
00209 while( i < 80 );
00210
00211 ctx->state[0] += A;
00212 ctx->state[1] += B;
00213 ctx->state[2] += C;
00214 ctx->state[3] += D;
00215 ctx->state[4] += E;
00216 ctx->state[5] += F;
00217 ctx->state[6] += G;
00218 ctx->state[7] += H;
00219 }
00220
00221
00222
00223
00224 void sha4_update( sha4_context *ctx, unsigned char *input, int ilen )
00225 {
00226 int fill;
00227 uint64 left;
00228
00229 if( ilen <= 0 )
00230 return;
00231
00232 left = ctx->total[0] & 0x7F;
00233 fill = (int)( 128 - left );
00234
00235 ctx->total[0] += ilen;
00236
00237 if( ctx->total[0] < (uint64) ilen )
00238 ctx->total[1]++;
00239
00240 if( left && ilen >= fill )
00241 {
00242 memcpy( (void *) (ctx->buffer + left),
00243 (void *) input, fill );
00244 sha4_process( ctx, ctx->buffer );
00245 input += fill;
00246 ilen -= fill;
00247 left = 0;
00248 }
00249
00250 while( ilen >= 128 )
00251 {
00252 sha4_process( ctx, input );
00253 input += 128;
00254 ilen -= 128;
00255 }
00256
00257 if( ilen > 0 )
00258 {
00259 memcpy( (void *) (ctx->buffer + left),
00260 (void *) input, ilen );
00261 }
00262 }
00263
00264 static const unsigned char sha4_padding[128] =
00265 {
00266 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00267 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00268 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00269 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00270 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00271 0, 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 };
00275
00276
00277
00278
00279 void sha4_finish( sha4_context *ctx, unsigned char *output )
00280 {
00281 int last, padn;
00282 uint64 high, low;
00283 unsigned char msglen[16];
00284
00285 high = ( ctx->total[0] >> 61 )
00286 | ( ctx->total[1] << 3 );
00287 low = ( ctx->total[0] << 3 );
00288
00289 PUT_UINT64_BE( high, msglen, 0 );
00290 PUT_UINT64_BE( low, msglen, 8 );
00291
00292 last = (int)( ctx->total[0] & 0x7F );
00293 padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
00294
00295 sha4_update( ctx, (unsigned char *) sha4_padding, padn );
00296 sha4_update( ctx, msglen, 16 );
00297
00298 PUT_UINT64_BE( ctx->state[0], output, 0 );
00299 PUT_UINT64_BE( ctx->state[1], output, 8 );
00300 PUT_UINT64_BE( ctx->state[2], output, 16 );
00301 PUT_UINT64_BE( ctx->state[3], output, 24 );
00302 PUT_UINT64_BE( ctx->state[4], output, 32 );
00303 PUT_UINT64_BE( ctx->state[5], output, 40 );
00304
00305 if( ctx->is384 == 0 )
00306 {
00307 PUT_UINT64_BE( ctx->state[6], output, 48 );
00308 PUT_UINT64_BE( ctx->state[7], output, 56 );
00309 }
00310 }
00311
00312
00313
00314
00315 void sha4( unsigned char *input, int ilen,
00316 unsigned char *output, int is384 )
00317 {
00318 sha4_context ctx;
00319
00320 sha4_starts( &ctx, is384 );
00321 sha4_update( &ctx, input, ilen );
00322 sha4_finish( &ctx, output );
00323
00324 memset( &ctx, 0, sizeof( sha4_context ) );
00325 }
00326
00327
00328
00329
00330 int sha4_file( char *path, unsigned char *output, int is384 )
00331 {
00332 FILE *f;
00333 size_t n;
00334 sha4_context ctx;
00335 unsigned char buf[1024];
00336
00337 if( ( f = fopen( path, "rb" ) ) == NULL )
00338 return( 1 );
00339
00340 sha4_starts( &ctx, is384 );
00341
00342 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00343 sha4_update( &ctx, buf, (int) n );
00344
00345 sha4_finish( &ctx, output );
00346
00347 memset( &ctx, 0, sizeof( sha4_context ) );
00348
00349 if( ferror( f ) != 0 )
00350 {
00351 fclose( f );
00352 return( 2 );
00353 }
00354
00355 fclose( f );
00356 return( 0 );
00357 }
00358
00359
00360
00361
00362 void sha4_hmac_starts( sha4_context *ctx, int is384,
00363 unsigned char *key, int keylen )
00364 {
00365 int i;
00366
00367 memset( ctx->ipad, 0x36, 64 );
00368 memset( ctx->opad, 0x5C, 64 );
00369
00370 for( i = 0; i < keylen; i++ )
00371 {
00372 if( i >= 64 ) break;
00373
00374 ctx->ipad[i] ^= key[i];
00375 ctx->opad[i] ^= key[i];
00376 }
00377
00378 sha4_starts( ctx, is384 );
00379 sha4_update( ctx, ctx->ipad, 64 );
00380 }
00381
00382
00383
00384
00385 void sha4_hmac_update( sha4_context *ctx,
00386 unsigned char *input, int ilen )
00387 {
00388 sha4_update( ctx, input, ilen );
00389 }
00390
00391
00392
00393
00394 void sha4_hmac_finish( sha4_context *ctx, unsigned char *output )
00395 {
00396 int is384, hlen;
00397 unsigned char tmpbuf[64];
00398
00399 is384 = ctx->is384;
00400 hlen = ( is384 == 0 ) ? 64 : 48;
00401
00402 sha4_finish( ctx, tmpbuf );
00403 sha4_starts( ctx, is384 );
00404 sha4_update( ctx, ctx->opad, 64 );
00405 sha4_update( ctx, tmpbuf, hlen );
00406 sha4_finish( ctx, output );
00407
00408 memset( tmpbuf, 0, sizeof( tmpbuf ) );
00409 }
00410
00411
00412
00413
00414 void sha4_hmac( unsigned char *key, int keylen,
00415 unsigned char *input, int ilen,
00416 unsigned char *output, int is384 )
00417 {
00418 sha4_context ctx;
00419
00420 sha4_hmac_starts( &ctx, is384, key, keylen );
00421 sha4_hmac_update( &ctx, input, ilen );
00422 sha4_hmac_finish( &ctx, output );
00423
00424 memset( &ctx, 0, sizeof( sha4_context ) );
00425 }
00426
00427 static const char _sha4_src[] = "_sha4_src";
00428
00429 #if defined(SELF_TEST)
00430
00431
00432
00433 static const char sha4_test_str[3][112] =
00434 {
00435 { "abc" },
00436 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
00437 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
00438 { "" }
00439 };
00440
00441 static const unsigned char sha4_test_sum[6][64] =
00442 {
00443
00444
00445
00446 { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
00447 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
00448 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
00449 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
00450 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
00451 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
00452 { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
00453 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
00454 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
00455 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
00456 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
00457 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
00458 { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
00459 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
00460 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
00461 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
00462 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
00463 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
00464
00465
00466
00467
00468 { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
00469 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
00470 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
00471 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
00472 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
00473 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
00474 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
00475 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
00476 { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
00477 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
00478 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
00479 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
00480 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
00481 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
00482 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
00483 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
00484 { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
00485 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
00486 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
00487 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
00488 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
00489 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
00490 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
00491 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
00492 };
00493
00494
00495
00496
00497 int sha4_self_test( int verbose )
00498 {
00499 int i, j, k;
00500 unsigned char buf[1000];
00501 unsigned char sha4sum[64];
00502 sha4_context ctx;
00503
00504 memset( buf, 'a', 1000 );
00505
00506 for( i = 0; i < 6; i++ )
00507 {
00508 j = i % 3;
00509 k = i < 3;
00510
00511 if( verbose != 0 )
00512 printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
00513
00514 sha4_starts( &ctx, k );
00515
00516 if( j < 2 )
00517 sha4_update( &ctx,
00518 (unsigned char *) sha4_test_str[j],
00519 strlen( sha4_test_str[j] ) );
00520 else
00521 {
00522 for( j = 0; j < 1000; j++ )
00523 sha4_update( &ctx, buf, 1000 );
00524 }
00525
00526 sha4_finish( &ctx, sha4sum );
00527
00528 if( memcmp( sha4sum, sha4_test_sum[i], 64 - k * 16 ) != 0 )
00529 {
00530 if( verbose != 0 )
00531 printf( "failed\n" );
00532
00533 return( 1 );
00534 }
00535
00536 if( verbose != 0 )
00537 printf( "passed\n" );
00538 }
00539
00540 if( verbose != 0 )
00541 printf( "\n" );
00542
00543 return( 0 );
00544 }
00545 #else
00546 int sha4_self_test( int verbose )
00547 {
00548 return( 0 );
00549 }
00550 #endif