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