mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

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