PolarSSL v1.1.4
sha4.c
Go to the documentation of this file.
00001 /*
00002  *  FIPS-180-2 compliant SHA-384/512 implementation
00003  *
00004  *  Copyright (C) 2006-2010, Brainspark B.V.
00005  *
00006  *  This file is part of PolarSSL (http://www.polarssl.org)
00007  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
00008  *
00009  *  All rights reserved.
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License along
00022  *  with this program; if not, write to the Free Software Foundation, Inc.,
00023  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00024  */
00025 /*
00026  *  The SHA-512 Secure Hash Standard was published by NIST in 2002.
00027  *
00028  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
00029  */
00030 
00031 #include "polarssl/config.h"
00032 
00033 #if defined(POLARSSL_SHA4_C)
00034 
00035 #include "polarssl/sha4.h"
00036 
00037 #if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
00038 #include <stdio.h>
00039 #endif
00040 
00041 /*
00042  * 64-bit integer manipulation macros (big endian)
00043  */
00044 #ifndef GET_UINT64_BE
00045 #define GET_UINT64_BE(n,b,i)                            \
00046 {                                                       \
00047     (n) = ( (unsigned long64) (b)[(i)    ] << 56 )       \
00048         | ( (unsigned long64) (b)[(i) + 1] << 48 )       \
00049         | ( (unsigned long64) (b)[(i) + 2] << 40 )       \
00050         | ( (unsigned long64) (b)[(i) + 3] << 32 )       \
00051         | ( (unsigned long64) (b)[(i) + 4] << 24 )       \
00052         | ( (unsigned long64) (b)[(i) + 5] << 16 )       \
00053         | ( (unsigned long64) (b)[(i) + 6] <<  8 )       \
00054         | ( (unsigned long64) (b)[(i) + 7]       );      \
00055 }
00056 #endif
00057 
00058 #ifndef PUT_UINT64_BE
00059 #define PUT_UINT64_BE(n,b,i)                            \
00060 {                                                       \
00061     (b)[(i)    ] = (unsigned char) ( (n) >> 56 );       \
00062     (b)[(i) + 1] = (unsigned char) ( (n) >> 48 );       \
00063     (b)[(i) + 2] = (unsigned char) ( (n) >> 40 );       \
00064     (b)[(i) + 3] = (unsigned char) ( (n) >> 32 );       \
00065     (b)[(i) + 4] = (unsigned char) ( (n) >> 24 );       \
00066     (b)[(i) + 5] = (unsigned char) ( (n) >> 16 );       \
00067     (b)[(i) + 6] = (unsigned char) ( (n) >>  8 );       \
00068     (b)[(i) + 7] = (unsigned char) ( (n)       );       \
00069 }
00070 #endif
00071 
00072 /*
00073  * Round constants
00074  */
00075 static const unsigned long64 K[80] =
00076 {
00077     UL64(0x428A2F98D728AE22),  UL64(0x7137449123EF65CD),
00078     UL64(0xB5C0FBCFEC4D3B2F),  UL64(0xE9B5DBA58189DBBC),
00079     UL64(0x3956C25BF348B538),  UL64(0x59F111F1B605D019),
00080     UL64(0x923F82A4AF194F9B),  UL64(0xAB1C5ED5DA6D8118),
00081     UL64(0xD807AA98A3030242),  UL64(0x12835B0145706FBE),
00082     UL64(0x243185BE4EE4B28C),  UL64(0x550C7DC3D5FFB4E2),
00083     UL64(0x72BE5D74F27B896F),  UL64(0x80DEB1FE3B1696B1),
00084     UL64(0x9BDC06A725C71235),  UL64(0xC19BF174CF692694),
00085     UL64(0xE49B69C19EF14AD2),  UL64(0xEFBE4786384F25E3),
00086     UL64(0x0FC19DC68B8CD5B5),  UL64(0x240CA1CC77AC9C65),
00087     UL64(0x2DE92C6F592B0275),  UL64(0x4A7484AA6EA6E483),
00088     UL64(0x5CB0A9DCBD41FBD4),  UL64(0x76F988DA831153B5),
00089     UL64(0x983E5152EE66DFAB),  UL64(0xA831C66D2DB43210),
00090     UL64(0xB00327C898FB213F),  UL64(0xBF597FC7BEEF0EE4),
00091     UL64(0xC6E00BF33DA88FC2),  UL64(0xD5A79147930AA725),
00092     UL64(0x06CA6351E003826F),  UL64(0x142929670A0E6E70),
00093     UL64(0x27B70A8546D22FFC),  UL64(0x2E1B21385C26C926),
00094     UL64(0x4D2C6DFC5AC42AED),  UL64(0x53380D139D95B3DF),
00095     UL64(0x650A73548BAF63DE),  UL64(0x766A0ABB3C77B2A8),
00096     UL64(0x81C2C92E47EDAEE6),  UL64(0x92722C851482353B),
00097     UL64(0xA2BFE8A14CF10364),  UL64(0xA81A664BBC423001),
00098     UL64(0xC24B8B70D0F89791),  UL64(0xC76C51A30654BE30),
00099     UL64(0xD192E819D6EF5218),  UL64(0xD69906245565A910),
00100     UL64(0xF40E35855771202A),  UL64(0x106AA07032BBD1B8),
00101     UL64(0x19A4C116B8D2D0C8),  UL64(0x1E376C085141AB53),
00102     UL64(0x2748774CDF8EEB99),  UL64(0x34B0BCB5E19B48A8),
00103     UL64(0x391C0CB3C5C95A63),  UL64(0x4ED8AA4AE3418ACB),
00104     UL64(0x5B9CCA4F7763E373),  UL64(0x682E6FF3D6B2B8A3),
00105     UL64(0x748F82EE5DEFB2FC),  UL64(0x78A5636F43172F60),
00106     UL64(0x84C87814A1F0AB72),  UL64(0x8CC702081A6439EC),
00107     UL64(0x90BEFFFA23631E28),  UL64(0xA4506CEBDE82BDE9),
00108     UL64(0xBEF9A3F7B2C67915),  UL64(0xC67178F2E372532B),
00109     UL64(0xCA273ECEEA26619C),  UL64(0xD186B8C721C0C207),
00110     UL64(0xEADA7DD6CDE0EB1E),  UL64(0xF57D4F7FEE6ED178),
00111     UL64(0x06F067AA72176FBA),  UL64(0x0A637DC5A2C898A6),
00112     UL64(0x113F9804BEF90DAE),  UL64(0x1B710B35131C471B),
00113     UL64(0x28DB77F523047D84),  UL64(0x32CAAB7B40C72493),
00114     UL64(0x3C9EBE0A15C9BEBC),  UL64(0x431D67C49C100D4C),
00115     UL64(0x4CC5D4BECB3E42B6),  UL64(0x597F299CFC657E2A),
00116     UL64(0x5FCB6FAB3AD6FAEC),  UL64(0x6C44198C4A475817)
00117 };
00118 
00119 /*
00120  * SHA-512 context setup
00121  */
00122 void sha4_starts( sha4_context *ctx, int is384 )
00123 {
00124     ctx->total[0] = 0;
00125     ctx->total[1] = 0;
00126 
00127     if( is384 == 0 )
00128     {
00129         /* SHA-512 */
00130         ctx->state[0] = UL64(0x6A09E667F3BCC908);
00131         ctx->state[1] = UL64(0xBB67AE8584CAA73B);
00132         ctx->state[2] = UL64(0x3C6EF372FE94F82B);
00133         ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
00134         ctx->state[4] = UL64(0x510E527FADE682D1);
00135         ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
00136         ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
00137         ctx->state[7] = UL64(0x5BE0CD19137E2179);
00138     }
00139     else
00140     {
00141         /* SHA-384 */
00142         ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
00143         ctx->state[1] = UL64(0x629A292A367CD507);
00144         ctx->state[2] = UL64(0x9159015A3070DD17);
00145         ctx->state[3] = UL64(0x152FECD8F70E5939);
00146         ctx->state[4] = UL64(0x67332667FFC00B31);
00147         ctx->state[5] = UL64(0x8EB44A8768581511);
00148         ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
00149         ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
00150     }
00151 
00152     ctx->is384 = is384;
00153 }
00154 
00155 static void sha4_process( sha4_context *ctx, const unsigned char data[128] )
00156 {
00157     int i;
00158     unsigned long64 temp1, temp2, W[80];
00159     unsigned long64 A, B, C, D, E, F, G, H;
00160 
00161 #define  SHR(x,n) (x >> n)
00162 #define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
00163 
00164 #define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^  SHR(x, 7))
00165 #define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^  SHR(x, 6))
00166 
00167 #define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
00168 #define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
00169 
00170 #define F0(x,y,z) ((x & y) | (z & (x | y)))
00171 #define F1(x,y,z) (z ^ (x & (y ^ z)))
00172 
00173 #define P(a,b,c,d,e,f,g,h,x,K)                  \
00174 {                                               \
00175     temp1 = h + S3(e) + F1(e,f,g) + K + x;      \
00176     temp2 = S2(a) + F0(a,b,c);                  \
00177     d += temp1; h = temp1 + temp2;              \
00178 }
00179 
00180     for( i = 0; i < 16; i++ )
00181     {
00182         GET_UINT64_BE( W[i], data, i << 3 );
00183     }
00184 
00185     for( ; i < 80; i++ )
00186     {
00187         W[i] = S1(W[i -  2]) + W[i -  7] +
00188                S0(W[i - 15]) + W[i - 16];
00189     }
00190 
00191     A = ctx->state[0];
00192     B = ctx->state[1];
00193     C = ctx->state[2];
00194     D = ctx->state[3];
00195     E = ctx->state[4];
00196     F = ctx->state[5];
00197     G = ctx->state[6];
00198     H = ctx->state[7];
00199     i = 0;
00200 
00201     do
00202     {
00203         P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
00204         P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
00205         P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
00206         P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
00207         P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
00208         P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
00209         P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
00210         P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
00211     }
00212     while( i < 80 );
00213 
00214     ctx->state[0] += A;
00215     ctx->state[1] += B;
00216     ctx->state[2] += C;
00217     ctx->state[3] += D;
00218     ctx->state[4] += E;
00219     ctx->state[5] += F;
00220     ctx->state[6] += G;
00221     ctx->state[7] += H;
00222 }
00223 
00224 /*
00225  * SHA-512 process buffer
00226  */
00227 void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen )
00228 {
00229     size_t fill;
00230     unsigned int left;
00231 
00232     if( ilen <= 0 )
00233         return;
00234 
00235     left = (unsigned int) (ctx->total[0] & 0x7F);
00236     fill = 128 - left;
00237 
00238     ctx->total[0] += (unsigned long64) ilen;
00239 
00240     if( ctx->total[0] < (unsigned long64) ilen )
00241         ctx->total[1]++;
00242 
00243     if( left && ilen >= fill )
00244     {
00245         memcpy( (void *) (ctx->buffer + left),
00246                 (void *) input, fill );
00247         sha4_process( ctx, ctx->buffer );
00248         input += fill;
00249         ilen  -= fill;
00250         left = 0;
00251     }
00252 
00253     while( ilen >= 128 )
00254     {
00255         sha4_process( ctx, input );
00256         input += 128;
00257         ilen  -= 128;
00258     }
00259 
00260     if( ilen > 0 )
00261     {
00262         memcpy( (void *) (ctx->buffer + left),
00263                 (void *) input, ilen );
00264     }
00265 }
00266 
00267 static const unsigned char sha4_padding[128] =
00268 {
00269  0x80, 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     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00275     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00276     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00277 };
00278 
00279 /*
00280  * SHA-512 final digest
00281  */
00282 void sha4_finish( sha4_context *ctx, unsigned char output[64] )
00283 {
00284     size_t last, padn;
00285     unsigned long64 high, low;
00286     unsigned char msglen[16];
00287 
00288     high = ( ctx->total[0] >> 61 )
00289          | ( ctx->total[1] <<  3 );
00290     low  = ( ctx->total[0] <<  3 );
00291 
00292     PUT_UINT64_BE( high, msglen, 0 );
00293     PUT_UINT64_BE( low,  msglen, 8 );
00294 
00295     last = (size_t)( ctx->total[0] & 0x7F );
00296     padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
00297 
00298     sha4_update( ctx, (unsigned char *) sha4_padding, padn );
00299     sha4_update( ctx, msglen, 16 );
00300 
00301     PUT_UINT64_BE( ctx->state[0], output,  0 );
00302     PUT_UINT64_BE( ctx->state[1], output,  8 );
00303     PUT_UINT64_BE( ctx->state[2], output, 16 );
00304     PUT_UINT64_BE( ctx->state[3], output, 24 );
00305     PUT_UINT64_BE( ctx->state[4], output, 32 );
00306     PUT_UINT64_BE( ctx->state[5], output, 40 );
00307 
00308     if( ctx->is384 == 0 )
00309     {
00310         PUT_UINT64_BE( ctx->state[6], output, 48 );
00311         PUT_UINT64_BE( ctx->state[7], output, 56 );
00312     }
00313 }
00314 
00315 /*
00316  * output = SHA-512( input buffer )
00317  */
00318 void sha4( const unsigned char *input, size_t ilen,
00319            unsigned char output[64], int is384 )
00320 {
00321     sha4_context ctx;
00322 
00323     sha4_starts( &ctx, is384 );
00324     sha4_update( &ctx, input, ilen );
00325     sha4_finish( &ctx, output );
00326 
00327     memset( &ctx, 0, sizeof( sha4_context ) );
00328 }
00329 
00330 #if defined(POLARSSL_FS_IO)
00331 /*
00332  * output = SHA-512( file contents )
00333  */
00334 int sha4_file( const char *path, unsigned char output[64], int is384 )
00335 {
00336     FILE *f;
00337     size_t n;
00338     sha4_context ctx;
00339     unsigned char buf[1024];
00340 
00341     if( ( f = fopen( path, "rb" ) ) == NULL )
00342         return( POLARSSL_ERR_SHA4_FILE_IO_ERROR );
00343 
00344     sha4_starts( &ctx, is384 );
00345 
00346     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00347         sha4_update( &ctx, buf, n );
00348 
00349     sha4_finish( &ctx, output );
00350 
00351     memset( &ctx, 0, sizeof( sha4_context ) );
00352 
00353     if( ferror( f ) != 0 )
00354     {
00355         fclose( f );
00356         return( POLARSSL_ERR_SHA4_FILE_IO_ERROR );
00357     }
00358 
00359     fclose( f );
00360     return( 0 );
00361 }
00362 #endif /* POLARSSL_FS_IO */
00363 
00364 /*
00365  * SHA-512 HMAC context setup
00366  */
00367 void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen,
00368                        int is384 )
00369 {
00370     size_t i;
00371     unsigned char sum[64];
00372 
00373     if( keylen > 128 )
00374     {
00375         sha4( key, keylen, sum, is384 );
00376         keylen = ( is384 ) ? 48 : 64;
00377         key = sum;
00378     }
00379 
00380     memset( ctx->ipad, 0x36, 128 );
00381     memset( ctx->opad, 0x5C, 128 );
00382 
00383     for( i = 0; i < keylen; i++ )
00384     {
00385         ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
00386         ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
00387     }
00388 
00389     sha4_starts( ctx, is384 );
00390     sha4_update( ctx, ctx->ipad, 128 );
00391 
00392     memset( sum, 0, sizeof( sum ) );
00393 }
00394 
00395 /*
00396  * SHA-512 HMAC process buffer
00397  */
00398 void sha4_hmac_update( sha4_context  *ctx,
00399                        const unsigned char *input, size_t ilen )
00400 {
00401     sha4_update( ctx, input, ilen );
00402 }
00403 
00404 /*
00405  * SHA-512 HMAC final digest
00406  */
00407 void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] )
00408 {
00409     int is384, hlen;
00410     unsigned char tmpbuf[64];
00411 
00412     is384 = ctx->is384;
00413     hlen = ( is384 == 0 ) ? 64 : 48;
00414 
00415     sha4_finish( ctx, tmpbuf );
00416     sha4_starts( ctx, is384 );
00417     sha4_update( ctx, ctx->opad, 128 );
00418     sha4_update( ctx, tmpbuf, hlen );
00419     sha4_finish( ctx, output );
00420 
00421     memset( tmpbuf, 0, sizeof( tmpbuf ) );
00422 }
00423 
00424 /*
00425  * SHA-512 HMAC context reset
00426  */
00427 void sha4_hmac_reset( sha4_context *ctx )
00428 {
00429     sha4_starts( ctx, ctx->is384 );
00430     sha4_update( ctx, ctx->ipad, 128 );
00431 }
00432 
00433 /*
00434  * output = HMAC-SHA-512( hmac key, input buffer )
00435  */
00436 void sha4_hmac( const unsigned char *key, size_t keylen,
00437                 const unsigned char *input, size_t ilen,
00438                 unsigned char output[64], int is384 )
00439 {
00440     sha4_context ctx;
00441 
00442     sha4_hmac_starts( &ctx, key, keylen, is384 );
00443     sha4_hmac_update( &ctx, input, ilen );
00444     sha4_hmac_finish( &ctx, output );
00445 
00446     memset( &ctx, 0, sizeof( sha4_context ) );
00447 }
00448 
00449 #if defined(POLARSSL_SELF_TEST)
00450 
00451 /*
00452  * FIPS-180-2 test vectors
00453  */
00454 static unsigned char sha4_test_buf[3][113] = 
00455 {
00456     { "abc" },
00457     { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
00458       "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
00459     { "" }
00460 };
00461 
00462 static const int sha4_test_buflen[3] =
00463 {
00464     3, 112, 1000
00465 };
00466 
00467 static const unsigned char sha4_test_sum[6][64] =
00468 {
00469     /*
00470      * SHA-384 test vectors
00471      */
00472     { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
00473       0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
00474       0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
00475       0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
00476       0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
00477       0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
00478     { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
00479       0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
00480       0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
00481       0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
00482       0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
00483       0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
00484     { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
00485       0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
00486       0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
00487       0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
00488       0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
00489       0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
00490 
00491     /*
00492      * SHA-512 test vectors
00493      */
00494     { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
00495       0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
00496       0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
00497       0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
00498       0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
00499       0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
00500       0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
00501       0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
00502     { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
00503       0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
00504       0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
00505       0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
00506       0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
00507       0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
00508       0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
00509       0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
00510     { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
00511       0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
00512       0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
00513       0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
00514       0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
00515       0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
00516       0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
00517       0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
00518 };
00519 
00520 /*
00521  * RFC 4231 test vectors
00522  */
00523 static unsigned char sha4_hmac_test_key[7][26] =
00524 {
00525     { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
00526       "\x0B\x0B\x0B\x0B" },
00527     { "Jefe" },
00528     { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
00529       "\xAA\xAA\xAA\xAA" },
00530     { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
00531       "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
00532     { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
00533       "\x0C\x0C\x0C\x0C" },
00534     { "" }, /* 0xAA 131 times */
00535     { "" }
00536 };
00537 
00538 static const int sha4_hmac_test_keylen[7] =
00539 {
00540     20, 4, 20, 25, 20, 131, 131
00541 };
00542 
00543 static unsigned char sha4_hmac_test_buf[7][153] =
00544 {
00545     { "Hi There" },
00546     { "what do ya want for nothing?" },
00547     { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00548       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00549       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00550       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
00551       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
00552     { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00553       "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00554       "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00555       "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
00556       "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
00557     { "Test With Truncation" },
00558     { "Test Using Larger Than Block-Size Key - Hash Key First" },
00559     { "This is a test using a larger than block-size key "
00560       "and a larger than block-size data. The key needs to "
00561       "be hashed before being used by the HMAC algorithm." }
00562 };
00563 
00564 static const int sha4_hmac_test_buflen[7] =
00565 {
00566     8, 28, 50, 50, 20, 54, 152
00567 };
00568 
00569 static const unsigned char sha4_hmac_test_sum[14][64] =
00570 {
00571     /*
00572      * HMAC-SHA-384 test vectors
00573      */
00574     { 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62,
00575       0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F,
00576       0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6,
00577       0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C,
00578       0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F,
00579       0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 },
00580     { 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31,
00581       0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B,
00582       0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47,
00583       0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E,
00584       0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7,
00585       0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 },
00586     { 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A,
00587       0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F,
00588       0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB,
00589       0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B,
00590       0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9,
00591       0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 },
00592     { 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85,
00593       0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7,
00594       0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C,
00595       0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E,
00596       0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79,
00597       0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB },
00598     { 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23,
00599       0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 },
00600     { 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90,
00601       0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4,
00602       0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F,
00603       0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6,
00604       0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82,
00605       0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 },
00606     { 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D,
00607       0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C,
00608       0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A,
00609       0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5,
00610       0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D,
00611       0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E },
00612 
00613     /*
00614      * HMAC-SHA-512 test vectors
00615      */
00616     { 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D,
00617       0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0,
00618       0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78,
00619       0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE,
00620       0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02,
00621       0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4,
00622       0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70,
00623       0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 },
00624     { 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2,
00625       0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3,
00626       0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6,
00627       0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54,
00628       0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A,
00629       0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD,
00630       0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B,
00631       0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 },
00632     { 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84,
00633       0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9,
00634       0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36,
00635       0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39,
00636       0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8,
00637       0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07,
00638       0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26,
00639       0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB },
00640     { 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69,
00641       0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7,
00642       0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D,
00643       0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB,
00644       0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4,
00645       0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63,
00646       0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D,
00647       0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD },
00648     { 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53,
00649       0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 },
00650     { 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB,
00651       0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4,
00652       0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1,
00653       0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52,
00654       0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98,
00655       0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52,
00656       0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC,
00657       0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 },
00658     { 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA,
00659       0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD,
00660       0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86,
00661       0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44,
00662       0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1,
00663       0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15,
00664       0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60,
00665       0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 }
00666 };
00667 
00668 /*
00669  * Checkup routine
00670  */
00671 int sha4_self_test( int verbose )
00672 {
00673     int i, j, k, buflen;
00674     unsigned char buf[1024];
00675     unsigned char sha4sum[64];
00676     sha4_context ctx;
00677 
00678     for( i = 0; i < 6; i++ )
00679     {
00680         j = i % 3;
00681         k = i < 3;
00682 
00683         if( verbose != 0 )
00684             printf( "  SHA-%d test #%d: ", 512 - k * 128, j + 1 );
00685 
00686         sha4_starts( &ctx, k );
00687 
00688         if( j == 2 )
00689         {
00690             memset( buf, 'a', buflen = 1000 );
00691 
00692             for( j = 0; j < 1000; j++ )
00693                 sha4_update( &ctx, buf, buflen );
00694         }
00695         else
00696             sha4_update( &ctx, sha4_test_buf[j],
00697                                sha4_test_buflen[j] );
00698 
00699         sha4_finish( &ctx, sha4sum );
00700 
00701         if( memcmp( sha4sum, sha4_test_sum[i], 64 - k * 16 ) != 0 )
00702         {
00703             if( verbose != 0 )
00704                 printf( "failed\n" );
00705 
00706             return( 1 );
00707         }
00708 
00709         if( verbose != 0 )
00710             printf( "passed\n" );
00711     }
00712 
00713     if( verbose != 0 )
00714         printf( "\n" );
00715 
00716     for( i = 0; i < 14; i++ )
00717     {
00718         j = i % 7;
00719         k = i < 7;
00720 
00721         if( verbose != 0 )
00722             printf( "  HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 );
00723 
00724         if( j == 5 || j == 6 )
00725         {
00726             memset( buf, '\xAA', buflen = 131 );
00727             sha4_hmac_starts( &ctx, buf, buflen, k );
00728         }
00729         else
00730             sha4_hmac_starts( &ctx, sha4_hmac_test_key[j],
00731                                     sha4_hmac_test_keylen[j], k );
00732 
00733         sha4_hmac_update( &ctx, sha4_hmac_test_buf[j],
00734                                 sha4_hmac_test_buflen[j] );
00735 
00736         sha4_hmac_finish( &ctx, sha4sum );
00737 
00738         buflen = ( j == 4 ) ? 16 : 64 - k * 16;
00739 
00740         if( memcmp( sha4sum, sha4_hmac_test_sum[i], buflen ) != 0 )
00741         {
00742             if( verbose != 0 )
00743                 printf( "failed\n" );
00744 
00745             return( 1 );
00746         }
00747 
00748         if( verbose != 0 )
00749             printf( "passed\n" );
00750     }
00751 
00752     if( verbose != 0 )
00753         printf( "\n" );
00754 
00755     return( 0 );
00756 }
00757 
00758 #endif
00759 
00760 #endif