1 // SPDX-License-Identifier: Apache-2.0 2 /* 3 * CTR_DRBG implementation based on AES-256 (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 * The NIST SP 800-90 DRBGs are described in the following publication. 23 * 24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf 25 */ 26 27 #if !defined(MBEDTLS_CONFIG_FILE) 28 #include "mbedtls/config.h" 29 #else 30 #include MBEDTLS_CONFIG_FILE 31 #endif 32 33 #if defined(MBEDTLS_CTR_DRBG_C) 34 35 #include "mbedtls/ctr_drbg.h" 36 #include "mbedtls/platform_util.h" 37 38 #include <string.h> 39 40 #if defined(MBEDTLS_FS_IO) 41 #include <stdio.h> 42 #endif 43 44 #if defined(MBEDTLS_SELF_TEST) 45 #if defined(MBEDTLS_PLATFORM_C) 46 #include "mbedtls/platform.h" 47 #else 48 #include <stdio.h> 49 #define mbedtls_printf printf 50 #endif /* MBEDTLS_PLATFORM_C */ 51 #endif /* MBEDTLS_SELF_TEST */ 52 53 /* 54 * CTR_DRBG context initialization 55 */ 56 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) 57 { 58 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); 59 60 #if defined(MBEDTLS_THREADING_C) 61 mbedtls_mutex_init( &ctx->mutex ); 62 #endif 63 } 64 65 /* 66 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow 67 * NIST tests to succeed (which require known length fixed entropy) 68 */ 69 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 70 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy, 71 * custom, len, entropy_len) 72 * implements 73 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 74 * security_strength) -> initial_working_state 75 * with inputs 76 * custom[:len] = nonce || personalization_string 77 * where entropy_input comes from f_entropy for entropy_len bytes 78 * and with outputs 79 * ctx = initial_working_state 80 */ 81 int mbedtls_ctr_drbg_seed_entropy_len( 82 mbedtls_ctr_drbg_context *ctx, 83 int (*f_entropy)(void *, unsigned char *, size_t), 84 void *p_entropy, 85 const unsigned char *custom, 86 size_t len, 87 size_t entropy_len ) 88 { 89 int ret; 90 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 91 92 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); 93 94 mbedtls_aes_init( &ctx->aes_ctx ); 95 96 ctx->f_entropy = f_entropy; 97 ctx->p_entropy = p_entropy; 98 99 ctx->entropy_len = entropy_len; 100 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 101 102 /* 103 * Initialize with an empty key 104 */ 105 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 106 { 107 return( ret ); 108 } 109 110 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) 111 { 112 return( ret ); 113 } 114 return( 0 ); 115 } 116 117 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, 118 int (*f_entropy)(void *, unsigned char *, size_t), 119 void *p_entropy, 120 const unsigned char *custom, 121 size_t len ) 122 { 123 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, 124 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); 125 } 126 127 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) 128 { 129 if( ctx == NULL ) 130 return; 131 132 #if defined(MBEDTLS_THREADING_C) 133 mbedtls_mutex_free( &ctx->mutex ); 134 #endif 135 mbedtls_aes_free( &ctx->aes_ctx ); 136 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); 137 } 138 139 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) 140 { 141 ctx->prediction_resistance = resistance; 142 } 143 144 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ) 145 { 146 ctx->entropy_len = len; 147 } 148 149 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ) 150 { 151 ctx->reseed_interval = interval; 152 } 153 154 static int block_cipher_df( unsigned char *output, 155 const unsigned char *data, size_t data_len ) 156 { 157 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; 158 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 159 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 160 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 161 unsigned char *p, *iv; 162 mbedtls_aes_context aes_ctx; 163 int ret = 0; 164 165 int i, j; 166 size_t buf_len, use_len; 167 168 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 169 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 170 171 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); 172 mbedtls_aes_init( &aes_ctx ); 173 174 /* 175 * Construct IV (16 bytes) and S in buffer 176 * IV = Counter (in 32-bits) padded to 16 with zeroes 177 * S = Length input string (in 32-bits) || Length of output (in 32-bits) || 178 * data || 0x80 179 * (Total is padded to a multiple of 16-bytes with zeroes) 180 */ 181 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; 182 *p++ = ( data_len >> 24 ) & 0xff; 183 *p++ = ( data_len >> 16 ) & 0xff; 184 *p++ = ( data_len >> 8 ) & 0xff; 185 *p++ = ( data_len ) & 0xff; 186 p += 3; 187 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; 188 memcpy( p, data, data_len ); 189 p[data_len] = 0x80; 190 191 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; 192 193 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) 194 key[i] = i; 195 196 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 197 { 198 goto exit; 199 } 200 201 /* 202 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data 203 */ 204 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 205 { 206 p = buf; 207 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 208 use_len = buf_len; 209 210 while( use_len > 0 ) 211 { 212 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) 213 chain[i] ^= p[i]; 214 p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 215 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? 216 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; 217 218 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 ) 219 { 220 goto exit; 221 } 222 } 223 224 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 225 226 /* 227 * Update IV 228 */ 229 buf[3]++; 230 } 231 232 /* 233 * Do final encryption with reduced data 234 */ 235 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 236 { 237 goto exit; 238 } 239 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; 240 p = output; 241 242 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 243 { 244 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 ) 245 { 246 goto exit; 247 } 248 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 249 p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 250 } 251 exit: 252 mbedtls_aes_free( &aes_ctx ); 253 /* 254 * tidy up the stack 255 */ 256 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 257 mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 258 mbedtls_platform_zeroize( key, sizeof( key ) ); 259 mbedtls_platform_zeroize( chain, sizeof( chain ) ); 260 if( 0 != ret ) 261 { 262 /* 263 * wipe partial seed from memory 264 */ 265 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); 266 } 267 268 return( ret ); 269 } 270 271 /* CTR_DRBG_Update (SP 800-90A §10.2.1.2) 272 * ctr_drbg_update_internal(ctx, provided_data) 273 * implements 274 * CTR_DRBG_Update(provided_data, Key, V) 275 * with inputs and outputs 276 * ctx->aes_ctx = Key 277 * ctx->counter = V 278 */ 279 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, 280 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) 281 { 282 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 283 unsigned char *p = tmp; 284 int i, j; 285 int ret = 0; 286 287 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 288 289 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 290 { 291 /* 292 * Increase counter 293 */ 294 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 295 if( ++ctx->counter[i - 1] != 0 ) 296 break; 297 298 /* 299 * Crypt counter block 300 */ 301 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) 302 goto exit; 303 304 p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 305 } 306 307 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) 308 tmp[i] ^= data[i]; 309 310 /* 311 * Update key and counter 312 */ 313 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 314 goto exit; 315 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 316 317 exit: 318 mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 319 return( ret ); 320 } 321 322 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 323 * mbedtls_ctr_drbg_update(ctx, additional, add_len) 324 * implements 325 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 326 * security_strength) -> initial_working_state 327 * with inputs 328 * ctx->counter = all-bits-0 329 * ctx->aes_ctx = context from all-bits-0 key 330 * additional[:add_len] = entropy_input || nonce || personalization_string 331 * and with outputs 332 * ctx = initial_working_state 333 */ 334 int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, 335 const unsigned char *additional, 336 size_t add_len ) 337 { 338 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 339 int ret; 340 341 if( add_len == 0 ) 342 return( 0 ); 343 344 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 345 goto exit; 346 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 347 goto exit; 348 349 exit: 350 mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 351 return( ret ); 352 } 353 354 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 355 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, 356 const unsigned char *additional, 357 size_t add_len ) 358 { 359 /* MAX_INPUT would be more logical here, but we have to match 360 * block_cipher_df()'s limits since we can't propagate errors */ 361 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 362 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; 363 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); 364 } 365 #endif /* MBEDTLS_DEPRECATED_REMOVED */ 366 367 /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) 368 * mbedtls_ctr_drbg_reseed(ctx, additional, len) 369 * implements 370 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) 371 * -> new_working_state 372 * with inputs 373 * ctx contains working_state 374 * additional[:len] = additional_input 375 * and entropy_input comes from calling ctx->f_entropy 376 * and with output 377 * ctx contains new_working_state 378 */ 379 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, 380 const unsigned char *additional, size_t len ) 381 { 382 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; 383 size_t seedlen = 0; 384 int ret; 385 386 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || 387 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) 388 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 389 390 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); 391 392 /* 393 * Gather entropy_len bytes of entropy to seed state 394 */ 395 if( 0 != ctx->f_entropy( ctx->p_entropy, seed, 396 ctx->entropy_len ) ) 397 { 398 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 399 } 400 401 seedlen += ctx->entropy_len; 402 403 /* 404 * Add additional data 405 */ 406 if( additional && len ) 407 { 408 memcpy( seed + seedlen, additional, len ); 409 seedlen += len; 410 } 411 412 /* 413 * Reduce to 384 bits 414 */ 415 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) 416 goto exit; 417 418 /* 419 * Update state 420 */ 421 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) 422 goto exit; 423 ctx->reseed_counter = 1; 424 425 exit: 426 mbedtls_platform_zeroize( seed, sizeof( seed ) ); 427 return( ret ); 428 } 429 430 /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) 431 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) 432 * implements 433 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) 434 * -> working_state_after_reseed 435 * if required, then 436 * CTR_DRBG_Generate(working_state_after_reseed, 437 * requested_number_of_bits, additional_input) 438 * -> status, returned_bits, new_working_state 439 * with inputs 440 * ctx contains working_state 441 * requested_number_of_bits = 8 * output_len 442 * additional[:add_len] = additional_input 443 * and entropy_input comes from calling ctx->f_entropy 444 * and with outputs 445 * status = SUCCESS (this function does the reseed internally) 446 * returned_bits = output[:output_len] 447 * ctx contains new_working_state 448 */ 449 int mbedtls_ctr_drbg_random_with_add( void *p_rng, 450 unsigned char *output, size_t output_len, 451 const unsigned char *additional, size_t add_len ) 452 { 453 int ret = 0; 454 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 455 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 456 unsigned char *p = output; 457 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 458 int i; 459 size_t use_len; 460 461 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) 462 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); 463 464 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) 465 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 466 467 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 468 469 if( ctx->reseed_counter > ctx->reseed_interval || 470 ctx->prediction_resistance ) 471 { 472 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) 473 { 474 return( ret ); 475 } 476 add_len = 0; 477 } 478 479 if( add_len > 0 ) 480 { 481 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 482 goto exit; 483 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 484 goto exit; 485 } 486 487 while( output_len > 0 ) 488 { 489 /* 490 * Increase counter 491 */ 492 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 493 if( ++ctx->counter[i - 1] != 0 ) 494 break; 495 496 /* 497 * Crypt counter block 498 */ 499 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) 500 goto exit; 501 502 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : 503 output_len; 504 /* 505 * Copy random block to destination 506 */ 507 memcpy( p, tmp, use_len ); 508 p += use_len; 509 output_len -= use_len; 510 } 511 512 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 513 goto exit; 514 515 ctx->reseed_counter++; 516 517 exit: 518 mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 519 mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 520 return( 0 ); 521 } 522 523 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) 524 { 525 int ret; 526 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 527 528 #if defined(MBEDTLS_THREADING_C) 529 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 530 return( ret ); 531 #endif 532 533 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); 534 535 #if defined(MBEDTLS_THREADING_C) 536 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 537 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 538 #endif 539 540 return( ret ); 541 } 542 543 #if defined(MBEDTLS_FS_IO) 544 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) 545 { 546 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 547 FILE *f; 548 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 549 550 if( ( f = fopen( path, "wb" ) ) == NULL ) 551 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 552 553 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) 554 goto exit; 555 556 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT ) 557 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 558 else 559 ret = 0; 560 561 exit: 562 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 563 564 fclose( f ); 565 return( ret ); 566 } 567 568 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) 569 { 570 int ret = 0; 571 FILE *f = NULL; 572 size_t n; 573 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 574 unsigned char c; 575 576 if( ( f = fopen( path, "rb" ) ) == NULL ) 577 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 578 579 n = fread( buf, 1, sizeof( buf ), f ); 580 if( fread( &c, 1, 1, f ) != 0 ) 581 { 582 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 583 goto exit; 584 } 585 if( n == 0 || ferror( f ) ) 586 { 587 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 588 goto exit; 589 } 590 fclose( f ); 591 f = NULL; 592 593 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); 594 595 exit: 596 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 597 if( f != NULL ) 598 fclose( f ); 599 if( ret != 0 ) 600 return( ret ); 601 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); 602 } 603 #endif /* MBEDTLS_FS_IO */ 604 605 #if defined(MBEDTLS_SELF_TEST) 606 607 static const unsigned char entropy_source_pr[96] = 608 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, 609 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, 610 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, 611 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, 612 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, 613 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, 614 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, 615 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, 616 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, 617 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, 618 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, 619 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; 620 621 static const unsigned char entropy_source_nopr[64] = 622 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, 623 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, 624 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, 625 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, 626 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, 627 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, 628 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, 629 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; 630 631 static const unsigned char nonce_pers_pr[16] = 632 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, 633 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; 634 635 static const unsigned char nonce_pers_nopr[16] = 636 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, 637 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; 638 639 static const unsigned char result_pr[16] = 640 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, 641 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; 642 643 static const unsigned char result_nopr[16] = 644 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, 645 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; 646 647 static size_t test_offset; 648 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, 649 size_t len ) 650 { 651 const unsigned char *p = data; 652 memcpy( buf, p + test_offset, len ); 653 test_offset += len; 654 return( 0 ); 655 } 656 657 #define CHK( c ) if( (c) != 0 ) \ 658 { \ 659 if( verbose != 0 ) \ 660 mbedtls_printf( "failed\n" ); \ 661 return( 1 ); \ 662 } 663 664 /* 665 * Checkup routine 666 */ 667 int mbedtls_ctr_drbg_self_test( int verbose ) 668 { 669 mbedtls_ctr_drbg_context ctx; 670 unsigned char buf[16]; 671 672 mbedtls_ctr_drbg_init( &ctx ); 673 674 /* 675 * Based on a NIST CTR_DRBG test vector (PR = True) 676 */ 677 if( verbose != 0 ) 678 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); 679 680 test_offset = 0; 681 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, 682 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); 683 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); 684 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); 685 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); 686 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); 687 688 mbedtls_ctr_drbg_free( &ctx ); 689 690 if( verbose != 0 ) 691 mbedtls_printf( "passed\n" ); 692 693 /* 694 * Based on a NIST CTR_DRBG test vector (PR = FALSE) 695 */ 696 if( verbose != 0 ) 697 mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); 698 699 mbedtls_ctr_drbg_init( &ctx ); 700 701 test_offset = 0; 702 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, 703 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); 704 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); 705 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); 706 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); 707 CHK( memcmp( buf, result_nopr, 16 ) ); 708 709 mbedtls_ctr_drbg_free( &ctx ); 710 711 if( verbose != 0 ) 712 mbedtls_printf( "passed\n" ); 713 714 if( verbose != 0 ) 715 mbedtls_printf( "\n" ); 716 717 return( 0 ); 718 } 719 #endif /* MBEDTLS_SELF_TEST */ 720 721 #endif /* MBEDTLS_CTR_DRBG_C */ 722