1 /* 2 * HMAC_DRBG implementation (NIST SP 800-90) 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may 8 * not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 /* 21 * The NIST SP 800-90A DRBGs are described in the following publication. 22 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf 23 * References below are based on rev. 1 (January 2012). 24 */ 25 26 #include "common.h" 27 28 #if defined(MBEDTLS_HMAC_DRBG_C) 29 30 #include "mbedtls/hmac_drbg.h" 31 #include "mbedtls/platform_util.h" 32 #include "mbedtls/error.h" 33 34 #include <string.h> 35 36 #if defined(MBEDTLS_FS_IO) 37 #include <stdio.h> 38 #endif 39 40 #if defined(MBEDTLS_SELF_TEST) 41 #if defined(MBEDTLS_PLATFORM_C) 42 #include "mbedtls/platform.h" 43 #else 44 #include <stdio.h> 45 #define mbedtls_printf printf 46 #endif /* MBEDTLS_SELF_TEST */ 47 #endif /* MBEDTLS_PLATFORM_C */ 48 49 /* 50 * HMAC_DRBG context initialization 51 */ 52 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) 53 { 54 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); 55 56 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; 57 } 58 59 /* 60 * HMAC_DRBG update, using optional additional data (10.1.2.2) 61 */ 62 int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, 63 const unsigned char *additional, 64 size_t add_len ) 65 { 66 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); 67 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; 68 unsigned char sep[1]; 69 unsigned char K[MBEDTLS_MD_MAX_SIZE]; 70 int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA; 71 72 for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) 73 { 74 /* Step 1 or 4 */ 75 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) 76 goto exit; 77 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, 78 ctx->V, md_len ) ) != 0 ) 79 goto exit; 80 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, 81 sep, 1 ) ) != 0 ) 82 goto exit; 83 if( rounds == 2 ) 84 { 85 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, 86 additional, add_len ) ) != 0 ) 87 goto exit; 88 } 89 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 ) 90 goto exit; 91 92 /* Step 2 or 5 */ 93 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 ) 94 goto exit; 95 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, 96 ctx->V, md_len ) ) != 0 ) 97 goto exit; 98 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) 99 goto exit; 100 } 101 102 exit: 103 mbedtls_platform_zeroize( K, sizeof( K ) ); 104 return( ret ); 105 } 106 107 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 108 void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, 109 const unsigned char *additional, 110 size_t add_len ) 111 { 112 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len ); 113 } 114 #endif /* MBEDTLS_DEPRECATED_REMOVED */ 115 116 /* 117 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) 118 */ 119 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, 120 const mbedtls_md_info_t * md_info, 121 const unsigned char *data, size_t data_len ) 122 { 123 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 124 125 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) 126 return( ret ); 127 128 #if defined(MBEDTLS_THREADING_C) 129 mbedtls_mutex_init( &ctx->mutex ); 130 #endif 131 132 /* 133 * Set initial working state. 134 * Use the V memory location, which is currently all 0, to initialize the 135 * MD context with an all-zero key. Then set V to its initial value. 136 */ 137 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, 138 mbedtls_md_get_size( md_info ) ) ) != 0 ) 139 return( ret ); 140 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); 141 142 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 ) 143 return( ret ); 144 145 return( 0 ); 146 } 147 148 /* 149 * Internal function used both for seeding and reseeding the DRBG. 150 * Comments starting with arabic numbers refer to section 10.1.2.4 151 * of SP800-90A, while roman numbers refer to section 9.2. 152 */ 153 static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx, 154 const unsigned char *additional, size_t len, 155 int use_nonce ) 156 { 157 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; 158 size_t seedlen = 0; 159 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 160 161 { 162 size_t total_entropy_len; 163 164 if( use_nonce == 0 ) 165 total_entropy_len = ctx->entropy_len; 166 else 167 total_entropy_len = ctx->entropy_len * 3 / 2; 168 169 /* III. Check input length */ 170 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || 171 total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) 172 { 173 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); 174 } 175 } 176 177 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); 178 179 /* IV. Gather entropy_len bytes of entropy for the seed */ 180 if( ( ret = ctx->f_entropy( ctx->p_entropy, 181 seed, ctx->entropy_len ) ) != 0 ) 182 { 183 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); 184 } 185 seedlen += ctx->entropy_len; 186 187 /* For initial seeding, allow adding of nonce generated 188 * from the entropy source. See Sect 8.6.7 in SP800-90A. */ 189 if( use_nonce ) 190 { 191 /* Note: We don't merge the two calls to f_entropy() in order 192 * to avoid requesting too much entropy from f_entropy() 193 * at once. Specifically, if the underlying digest is not 194 * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which 195 * is larger than the maximum of 32 Bytes that our own 196 * entropy source implementation can emit in a single 197 * call in configurations disabling SHA-512. */ 198 if( ( ret = ctx->f_entropy( ctx->p_entropy, 199 seed + seedlen, 200 ctx->entropy_len / 2 ) ) != 0 ) 201 { 202 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); 203 } 204 205 seedlen += ctx->entropy_len / 2; 206 } 207 208 209 /* 1. Concatenate entropy and additional data if any */ 210 if( additional != NULL && len != 0 ) 211 { 212 memcpy( seed + seedlen, additional, len ); 213 seedlen += len; 214 } 215 216 /* 2. Update state */ 217 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 ) 218 goto exit; 219 220 /* 3. Reset reseed_counter */ 221 ctx->reseed_counter = 1; 222 223 exit: 224 /* 4. Done */ 225 mbedtls_platform_zeroize( seed, seedlen ); 226 return( ret ); 227 } 228 229 /* 230 * HMAC_DRBG reseeding: 10.1.2.4 + 9.2 231 */ 232 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, 233 const unsigned char *additional, size_t len ) 234 { 235 return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) ); 236 } 237 238 /* 239 * HMAC_DRBG initialisation (10.1.2.3 + 9.1) 240 * 241 * The nonce is not passed as a separate parameter but extracted 242 * from the entropy source as suggested in 8.6.7. 243 */ 244 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, 245 const mbedtls_md_info_t * md_info, 246 int (*f_entropy)(void *, unsigned char *, size_t), 247 void *p_entropy, 248 const unsigned char *custom, 249 size_t len ) 250 { 251 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 252 size_t md_size; 253 254 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) 255 return( ret ); 256 257 /* The mutex is initialized iff the md context is set up. */ 258 #if defined(MBEDTLS_THREADING_C) 259 mbedtls_mutex_init( &ctx->mutex ); 260 #endif 261 262 md_size = mbedtls_md_get_size( md_info ); 263 264 /* 265 * Set initial working state. 266 * Use the V memory location, which is currently all 0, to initialize the 267 * MD context with an all-zero key. Then set V to its initial value. 268 */ 269 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 ) 270 return( ret ); 271 memset( ctx->V, 0x01, md_size ); 272 273 ctx->f_entropy = f_entropy; 274 ctx->p_entropy = p_entropy; 275 276 if( ctx->entropy_len == 0 ) 277 { 278 /* 279 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by 280 * each hash function, then according to SP800-90A rev1 10.1 table 2, 281 * min_entropy_len (in bits) is security_strength. 282 * 283 * (This also matches the sizes used in the NIST test vectors.) 284 */ 285 ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ 286 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ 287 32; /* better (256+) -> 256 bits */ 288 } 289 290 if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, 291 1 /* add nonce */ ) ) != 0 ) 292 { 293 return( ret ); 294 } 295 296 return( 0 ); 297 } 298 299 /* 300 * Set prediction resistance 301 */ 302 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, 303 int resistance ) 304 { 305 ctx->prediction_resistance = resistance; 306 } 307 308 /* 309 * Set entropy length grabbed for seeding 310 */ 311 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) 312 { 313 ctx->entropy_len = len; 314 } 315 316 /* 317 * Set reseed interval 318 */ 319 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) 320 { 321 ctx->reseed_interval = interval; 322 } 323 324 /* 325 * HMAC_DRBG random function with optional additional data: 326 * 10.1.2.5 (arabic) + 9.3 (Roman) 327 */ 328 int mbedtls_hmac_drbg_random_with_add( void *p_rng, 329 unsigned char *output, size_t out_len, 330 const unsigned char *additional, size_t add_len ) 331 { 332 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 333 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; 334 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); 335 size_t left = out_len; 336 unsigned char *out = output; 337 338 /* II. Check request length */ 339 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) 340 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); 341 342 /* III. Check input length */ 343 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) 344 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); 345 346 /* 1. (aka VII and IX) Check reseed counter and PR */ 347 if( ctx->f_entropy != NULL && /* For no-reseeding instances */ 348 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || 349 ctx->reseed_counter > ctx->reseed_interval ) ) 350 { 351 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) 352 return( ret ); 353 354 add_len = 0; /* VII.4 */ 355 } 356 357 /* 2. Use additional data if any */ 358 if( additional != NULL && add_len != 0 ) 359 { 360 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, 361 additional, add_len ) ) != 0 ) 362 goto exit; 363 } 364 365 /* 3, 4, 5. Generate bytes */ 366 while( left != 0 ) 367 { 368 size_t use_len = left > md_len ? md_len : left; 369 370 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) 371 goto exit; 372 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, 373 ctx->V, md_len ) ) != 0 ) 374 goto exit; 375 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) 376 goto exit; 377 378 memcpy( out, ctx->V, use_len ); 379 out += use_len; 380 left -= use_len; 381 } 382 383 /* 6. Update */ 384 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, 385 additional, add_len ) ) != 0 ) 386 goto exit; 387 388 /* 7. Update reseed counter */ 389 ctx->reseed_counter++; 390 391 exit: 392 /* 8. Done */ 393 return( ret ); 394 } 395 396 /* 397 * HMAC_DRBG random function 398 */ 399 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) 400 { 401 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 402 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; 403 404 #if defined(MBEDTLS_THREADING_C) 405 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 406 return( ret ); 407 #endif 408 409 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); 410 411 #if defined(MBEDTLS_THREADING_C) 412 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 413 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 414 #endif 415 416 return( ret ); 417 } 418 419 /* 420 * This function resets HMAC_DRBG context to the state immediately 421 * after initial call of mbedtls_hmac_drbg_init(). 422 */ 423 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) 424 { 425 if( ctx == NULL ) 426 return; 427 428 #if defined(MBEDTLS_THREADING_C) 429 /* The mutex is initialized iff the md context is set up. */ 430 if( ctx->md_ctx.md_info != NULL ) 431 mbedtls_mutex_free( &ctx->mutex ); 432 #endif 433 mbedtls_md_free( &ctx->md_ctx ); 434 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); 435 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; 436 } 437 438 #if defined(MBEDTLS_FS_IO) 439 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) 440 { 441 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 442 FILE *f; 443 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; 444 445 if( ( f = fopen( path, "wb" ) ) == NULL ) 446 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); 447 448 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) 449 goto exit; 450 451 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) 452 { 453 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; 454 goto exit; 455 } 456 457 ret = 0; 458 459 exit: 460 fclose( f ); 461 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 462 463 return( ret ); 464 } 465 466 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) 467 { 468 int ret = 0; 469 FILE *f = NULL; 470 size_t n; 471 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; 472 unsigned char c; 473 474 if( ( f = fopen( path, "rb" ) ) == NULL ) 475 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); 476 477 n = fread( buf, 1, sizeof( buf ), f ); 478 if( fread( &c, 1, 1, f ) != 0 ) 479 { 480 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; 481 goto exit; 482 } 483 if( n == 0 || ferror( f ) ) 484 { 485 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; 486 goto exit; 487 } 488 fclose( f ); 489 f = NULL; 490 491 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n ); 492 493 exit: 494 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 495 if( f != NULL ) 496 fclose( f ); 497 if( ret != 0 ) 498 return( ret ); 499 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); 500 } 501 #endif /* MBEDTLS_FS_IO */ 502 503 504 #if defined(MBEDTLS_SELF_TEST) 505 506 #if !defined(MBEDTLS_SHA1_C) 507 /* Dummy checkup routine */ 508 int mbedtls_hmac_drbg_self_test( int verbose ) 509 { 510 (void) verbose; 511 return( 0 ); 512 } 513 #else 514 515 #define OUTPUT_LEN 80 516 517 /* From a NIST PR=true test vector */ 518 static const unsigned char entropy_pr[] = { 519 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, 520 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, 521 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, 522 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, 523 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; 524 static const unsigned char result_pr[OUTPUT_LEN] = { 525 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, 526 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, 527 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, 528 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, 529 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, 530 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, 531 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; 532 533 /* From a NIST PR=false test vector */ 534 static const unsigned char entropy_nopr[] = { 535 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, 536 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, 537 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, 538 0xe9, 0x9d, 0xfe, 0xdf }; 539 static const unsigned char result_nopr[OUTPUT_LEN] = { 540 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, 541 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, 542 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, 543 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, 544 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, 545 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, 546 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; 547 548 /* "Entropy" from buffer */ 549 static size_t test_offset; 550 static int hmac_drbg_self_test_entropy( void *data, 551 unsigned char *buf, size_t len ) 552 { 553 const unsigned char *p = data; 554 memcpy( buf, p + test_offset, len ); 555 test_offset += len; 556 return( 0 ); 557 } 558 559 #define CHK( c ) if( (c) != 0 ) \ 560 { \ 561 if( verbose != 0 ) \ 562 mbedtls_printf( "failed\n" ); \ 563 return( 1 ); \ 564 } 565 566 /* 567 * Checkup routine for HMAC_DRBG with SHA-1 568 */ 569 int mbedtls_hmac_drbg_self_test( int verbose ) 570 { 571 mbedtls_hmac_drbg_context ctx; 572 unsigned char buf[OUTPUT_LEN]; 573 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); 574 575 mbedtls_hmac_drbg_init( &ctx ); 576 577 /* 578 * PR = True 579 */ 580 if( verbose != 0 ) 581 mbedtls_printf( " HMAC_DRBG (PR = True) : " ); 582 583 test_offset = 0; 584 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, 585 hmac_drbg_self_test_entropy, (void *) entropy_pr, 586 NULL, 0 ) ); 587 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); 588 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); 589 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); 590 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); 591 mbedtls_hmac_drbg_free( &ctx ); 592 593 mbedtls_hmac_drbg_free( &ctx ); 594 595 if( verbose != 0 ) 596 mbedtls_printf( "passed\n" ); 597 598 /* 599 * PR = False 600 */ 601 if( verbose != 0 ) 602 mbedtls_printf( " HMAC_DRBG (PR = False) : " ); 603 604 mbedtls_hmac_drbg_init( &ctx ); 605 606 test_offset = 0; 607 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, 608 hmac_drbg_self_test_entropy, (void *) entropy_nopr, 609 NULL, 0 ) ); 610 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); 611 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); 612 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); 613 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); 614 mbedtls_hmac_drbg_free( &ctx ); 615 616 mbedtls_hmac_drbg_free( &ctx ); 617 618 if( verbose != 0 ) 619 mbedtls_printf( "passed\n" ); 620 621 if( verbose != 0 ) 622 mbedtls_printf( "\n" ); 623 624 return( 0 ); 625 } 626 #endif /* MBEDTLS_SHA1_C */ 627 #endif /* MBEDTLS_SELF_TEST */ 628 629 #endif /* MBEDTLS_HMAC_DRBG_C */ 630