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