Hannes Tschofenig
/
aes-gcm-test-program
Example program to test AES-GCM functionality. Used for a workshop
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 19:40:15 by 1.7.2