mbed TLS library
Dependents: HTTPClient-SSL WS_SERVER
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
Generated on Tue Jul 12 2022 13:50:37 by 1.7.2