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