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