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