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