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