Example program to test AES-GCM functionality. Used for a workshop

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hmac_drbg.c Source File

hmac_drbg.c

00001 /*
00002  *  HMAC_DRBG implementation (NIST SP 800-90)
00003  *
00004  *  Copyright (C) 2014, 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 /*
00027  *  The NIST SP 800-90A DRBGs are described in the following publication.
00028  *  http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
00029  *  References below are based on rev. 1 (January 2012).
00030  */
00031 
00032 #if !defined(POLARSSL_CONFIG_FILE)
00033 #include "polarssl/config.h"
00034 #else
00035 #include POLARSSL_CONFIG_FILE
00036 #endif
00037 
00038 #if defined(POLARSSL_HMAC_DRBG_C)
00039 
00040 #include "polarssl/hmac_drbg.h"
00041 
00042 #if defined(POLARSSL_FS_IO)
00043 #include <stdio.h>
00044 #endif
00045 
00046 #if defined(POLARSSL_PLATFORM_C)
00047 #include "polarssl/platform.h"
00048 #else
00049 #define polarssl_printf printf
00050 #endif
00051 
00052 /*
00053  * HMAC_DRBG update, using optional additional data (10.1.2.2)
00054  */
00055 void hmac_drbg_update( hmac_drbg_context *ctx,
00056                        const unsigned char *additional, size_t add_len )
00057 {
00058     size_t md_len = ctx->md_ctx .md_info->size;
00059     unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
00060     unsigned char sep[1];
00061     unsigned char K[POLARSSL_MD_MAX_SIZE];
00062 
00063     for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
00064     {
00065         /* Step 1 or 4 */
00066         md_hmac_reset( &ctx->md_ctx  );
00067         md_hmac_update( &ctx->md_ctx , ctx->V , md_len );
00068         md_hmac_update( &ctx->md_ctx , sep, 1 );
00069         if( rounds == 2 )
00070             md_hmac_update( &ctx->md_ctx , additional, add_len );
00071         md_hmac_finish( &ctx->md_ctx , K );
00072 
00073         /* Step 2 or 5 */
00074         md_hmac_starts( &ctx->md_ctx , K, md_len );
00075         md_hmac_update( &ctx->md_ctx , ctx->V , md_len );
00076         md_hmac_finish( &ctx->md_ctx , ctx->V  );
00077     }
00078 }
00079 
00080 /*
00081  * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
00082  */
00083 int hmac_drbg_init_buf( hmac_drbg_context *ctx,
00084                         const md_info_t * md_info,
00085                         const unsigned char *data, size_t data_len )
00086 {
00087     int ret;
00088 
00089     memset( ctx, 0, sizeof( hmac_drbg_context ) );
00090 
00091     if( ( ret = md_init_ctx( &ctx->md_ctx , md_info ) ) != 0 )
00092         return( ret );
00093 
00094     /*
00095      * Set initial working state.
00096      * Use the V memory location, which is currently all 0, to initialize the
00097      * MD context with an all-zero key. Then set V to its initial value.
00098      */
00099     md_hmac_starts( &ctx->md_ctx , ctx->V , md_info->size );
00100     memset( ctx->V , 0x01, md_info->size );
00101 
00102     hmac_drbg_update( ctx, data, data_len );
00103 
00104     return( 0 );
00105 }
00106 
00107 /*
00108  * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
00109  */
00110 int hmac_drbg_reseed( hmac_drbg_context *ctx,
00111                       const unsigned char *additional, size_t len )
00112 {
00113     unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
00114     size_t seedlen;
00115 
00116     /* III. Check input length */
00117     if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
00118         ctx->entropy_len  + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
00119     {
00120         return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
00121     }
00122 
00123     memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
00124 
00125     /* IV. Gather entropy_len bytes of entropy for the seed */
00126     if( ctx->f_entropy ( ctx->p_entropy , seed, ctx->entropy_len  ) != 0 )
00127         return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
00128 
00129     seedlen = ctx->entropy_len ;
00130 
00131     /* 1. Concatenate entropy and additional data if any */
00132     if( additional != NULL && len != 0 )
00133     {
00134         memcpy( seed + seedlen, additional, len );
00135         seedlen += len;
00136     }
00137 
00138     /* 2. Update state */
00139     hmac_drbg_update( ctx, seed, seedlen );
00140 
00141     /* 3. Reset reseed_counter */
00142     ctx->reseed_counter  = 1;
00143 
00144     /* 4. Done */
00145     return( 0 );
00146 }
00147 
00148 /*
00149  * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
00150  */
00151 int hmac_drbg_init( hmac_drbg_context *ctx,
00152                     const md_info_t * md_info,
00153                     int (*f_entropy)(void *, unsigned char *, size_t),
00154                     void *p_entropy,
00155                     const unsigned char *custom,
00156                     size_t len )
00157 {
00158     int ret;
00159     size_t entropy_len;
00160 
00161     memset( ctx, 0, sizeof( hmac_drbg_context ) );
00162 
00163     if( ( ret = md_init_ctx( &ctx->md_ctx , md_info ) ) != 0 )
00164         return( ret );
00165 
00166     /*
00167      * Set initial working state.
00168      * Use the V memory location, which is currently all 0, to initialize the
00169      * MD context with an all-zero key. Then set V to its initial value.
00170      */
00171     md_hmac_starts( &ctx->md_ctx , ctx->V , md_info->size );
00172     memset( ctx->V , 0x01, md_info->size );
00173 
00174     ctx->f_entropy  = f_entropy;
00175     ctx->p_entropy  = p_entropy;
00176 
00177     ctx->reseed_interval  = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
00178 
00179     /*
00180      * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
00181      * each hash function, then according to SP800-90A rev1 10.1 table 2,
00182      * min_entropy_len (in bits) is security_strength.
00183      *
00184      * (This also matches the sizes used in the NIST test vectors.)
00185      */
00186     entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
00187                   md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
00188                                         32;  /* better (256+) -> 256 bits */
00189 
00190     /*
00191      * For initialisation, use more entropy to emulate a nonce
00192      * (Again, matches test vectors.)
00193      */
00194     ctx->entropy_len  = entropy_len * 3 / 2;
00195 
00196     if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
00197         return( ret );
00198 
00199     ctx->entropy_len  = entropy_len;
00200 
00201     return( 0 );
00202 }
00203 
00204 /*
00205  * Set prediction resistance
00206  */
00207 void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
00208                                           int resistance )
00209 {
00210     ctx->prediction_resistance  = resistance;
00211 }
00212 
00213 /*
00214  * Set entropy length grabbed for reseeds
00215  */
00216 void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
00217 {
00218     ctx->entropy_len  = len;
00219 }
00220 
00221 /*
00222  * Set reseed interval
00223  */
00224 void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
00225 {
00226     ctx->reseed_interval  = interval;
00227 }
00228 
00229 /*
00230  * HMAC_DRBG random function with optional additional data:
00231  * 10.1.2.5 (arabic) + 9.3 (Roman)
00232  */
00233 int hmac_drbg_random_with_add( void *p_rng,
00234                                unsigned char *output, size_t out_len,
00235                                const unsigned char *additional, size_t add_len )
00236 {
00237     int ret;
00238     hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
00239     size_t md_len = md_get_size( ctx->md_ctx .md_info );
00240     size_t left = out_len;
00241     unsigned char *out = output;
00242 
00243     /* II. Check request length */
00244     if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
00245         return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
00246 
00247     /* III. Check input length */
00248     if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
00249         return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
00250 
00251     /* 1. (aka VII and IX) Check reseed counter and PR */
00252     if( ctx->f_entropy  != NULL && /* For no-reseeding instances */
00253         ( ctx->prediction_resistance  == POLARSSL_HMAC_DRBG_PR_ON ||
00254           ctx->reseed_counter  > ctx->reseed_interval  ) )
00255     {
00256         if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
00257             return( ret );
00258 
00259         add_len = 0; /* VII.4 */
00260     }
00261 
00262     /* 2. Use additional data if any */
00263     if( additional != NULL && add_len != 0 )
00264         hmac_drbg_update( ctx, additional, add_len );
00265 
00266     /* 3, 4, 5. Generate bytes */
00267     while( left != 0 )
00268     {
00269         size_t use_len = left > md_len ? md_len : left;
00270 
00271         md_hmac_reset( &ctx->md_ctx  );
00272         md_hmac_update( &ctx->md_ctx , ctx->V , md_len );
00273         md_hmac_finish( &ctx->md_ctx , ctx->V  );
00274 
00275         memcpy( out, ctx->V , use_len );
00276         out += use_len;
00277         left -= use_len;
00278     }
00279 
00280     /* 6. Update */
00281     hmac_drbg_update( ctx, additional, add_len );
00282 
00283     /* 7. Update reseed counter */
00284     ctx->reseed_counter ++;
00285 
00286     /* 8. Done */
00287     return( 0 );
00288 }
00289 
00290 /*
00291  * HMAC_DRBG random function
00292  */
00293 int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
00294 {
00295     return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
00296 }
00297 
00298 /*
00299  * Free an HMAC_DRBG context
00300  */
00301 void hmac_drbg_free( hmac_drbg_context *ctx )
00302 {
00303     if( ctx == NULL )
00304         return;
00305 
00306     md_free_ctx( &ctx->md_ctx  );
00307 
00308     memset( ctx, 0, sizeof( hmac_drbg_context ) );
00309 }
00310 
00311 #if defined(POLARSSL_FS_IO)
00312 int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
00313 {
00314     int ret;
00315     FILE *f;
00316     unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
00317 
00318     if( ( f = fopen( path, "wb" ) ) == NULL )
00319         return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
00320 
00321     if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
00322         goto exit;
00323 
00324     if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
00325     {
00326         ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
00327         goto exit;
00328     }
00329 
00330     ret = 0;
00331 
00332 exit:
00333     fclose( f );
00334     return( ret );
00335 }
00336 
00337 int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
00338 {
00339     FILE *f;
00340     size_t n;
00341     unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
00342 
00343     if( ( f = fopen( path, "rb" ) ) == NULL )
00344         return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
00345 
00346     fseek( f, 0, SEEK_END );
00347     n = (size_t) ftell( f );
00348     fseek( f, 0, SEEK_SET );
00349 
00350     if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
00351     {
00352         fclose( f );
00353         return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
00354     }
00355 
00356     if( fread( buf, 1, n, f ) != n )
00357     {
00358         fclose( f );
00359         return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
00360     }
00361 
00362     fclose( f );
00363 
00364     hmac_drbg_update( ctx, buf, n );
00365 
00366     return( hmac_drbg_write_seed_file( ctx, path ) );
00367 }
00368 #endif /* POLARSSL_FS_IO */
00369 
00370 
00371 #if defined(POLARSSL_SELF_TEST)
00372 
00373 #include <stdio.h>
00374 
00375 #if !defined(POLARSSL_SHA1_C)
00376 /* Dummy checkup routine */
00377 int hmac_drbg_self_test( int verbose )
00378 {
00379 
00380     if( verbose != 0 )
00381         polarssl_printf( "\n" );
00382 
00383     return( 0 );
00384 }
00385 #else
00386 
00387 #define OUTPUT_LEN  80
00388 
00389 /* From a NIST PR=true test vector */
00390 static unsigned char entropy_pr[] = {
00391     0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
00392     0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
00393     0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
00394     0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
00395     0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
00396 static const unsigned char result_pr[OUTPUT_LEN] = {
00397     0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
00398     0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
00399     0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
00400     0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
00401     0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
00402     0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
00403     0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
00404 
00405 /* From a NIST PR=false test vector */
00406 static unsigned char entropy_nopr[] = {
00407     0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
00408     0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
00409     0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
00410     0xe9, 0x9d, 0xfe, 0xdf };
00411 static const unsigned char result_nopr[OUTPUT_LEN] = {
00412     0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
00413     0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
00414     0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
00415     0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
00416     0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
00417     0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
00418     0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
00419 
00420 /* "Entropy" from buffer */
00421 static size_t test_offset;
00422 static int hmac_drbg_self_test_entropy( void *data,
00423                                         unsigned char *buf, size_t len )
00424 {
00425     const unsigned char *p = data;
00426     memcpy( buf, p + test_offset, len );
00427     test_offset += len;
00428     return( 0 );
00429 }
00430 
00431 #define CHK( c )    if( (c) != 0 )                          \
00432                     {                                       \
00433                         if( verbose != 0 )                  \
00434                             polarssl_printf( "failed\n" );  \
00435                         return( 1 );                        \
00436                     }
00437 
00438 /*
00439  * Checkup routine for HMAC_DRBG with SHA-1
00440  */
00441 int hmac_drbg_self_test( int verbose )
00442 {
00443     hmac_drbg_context ctx;
00444     unsigned char buf[OUTPUT_LEN];
00445     const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
00446 
00447     /*
00448      * PR = True
00449      */
00450     if( verbose != 0 )
00451         polarssl_printf( "  HMAC_DRBG (PR = True) : " );
00452 
00453     test_offset = 0;
00454     CHK( hmac_drbg_init( &ctx, md_info,
00455                          hmac_drbg_self_test_entropy, entropy_pr,
00456                          NULL, 0 ) );
00457     hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
00458     CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
00459     CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
00460     CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
00461     hmac_drbg_free( &ctx );
00462 
00463     if( verbose != 0 )
00464         polarssl_printf( "passed\n" );
00465 
00466     /*
00467      * PR = False
00468      */
00469     if( verbose != 0 )
00470         polarssl_printf( "  HMAC_DRBG (PR = False) : " );
00471 
00472     test_offset = 0;
00473     CHK( hmac_drbg_init( &ctx, md_info,
00474                          hmac_drbg_self_test_entropy, entropy_nopr,
00475                          NULL, 0 ) );
00476     CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
00477     CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
00478     CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
00479     CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
00480     hmac_drbg_free( &ctx );
00481 
00482     if( verbose != 0 )
00483         polarssl_printf( "passed\n" );
00484 
00485     if( verbose != 0 )
00486         polarssl_printf( "\n" );
00487 
00488     return( 0 );
00489 }
00490 #endif /* POLARSSL_SHA1_C */
00491 #endif /* POLARSSL_SELF_TEST */
00492 
00493 #endif /* POLARSSL_HMAC_DRBG_C */
00494 
00495