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/* 8 * The NIST SP 800-90 DRBGs are described in the following publication. 9 * 10 * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf 11 */ 12 13#include "common.h" 14 15#if defined(MBEDTLS_CTR_DRBG_C) 16 17#include "ctr.h" 18#include "mbedtls/ctr_drbg.h" 19#include "mbedtls/platform_util.h" 20#include "mbedtls/error.h" 21 22#include <string.h> 23 24#if defined(MBEDTLS_FS_IO) 25#include <stdio.h> 26#endif 27 28/* Using error translation functions from PSA to MbedTLS */ 29#if !defined(MBEDTLS_AES_C) 30#include "psa_util_internal.h" 31#endif 32 33#include "mbedtls/platform.h" 34 35#if !defined(MBEDTLS_AES_C) 36static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx, 37 unsigned char *key, size_t key_len) 38{ 39 psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; 40 psa_status_t status; 41 42 psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); 43 psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); 44 psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES); 45 status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id); 46 if (status != PSA_SUCCESS) { 47 goto exit; 48 } 49 50 status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING); 51 if (status != PSA_SUCCESS) { 52 goto exit; 53 } 54 55exit: 56 psa_reset_key_attributes(&key_attr); 57 return status; 58} 59 60static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx) 61{ 62 psa_cipher_abort(&psa_ctx->operation); 63 psa_destroy_key(psa_ctx->key_id); 64 65 psa_ctx->operation = psa_cipher_operation_init(); 66 psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT; 67} 68#endif 69 70/* 71 * CTR_DRBG context initialization 72 */ 73void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx) 74{ 75 memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context)); 76#if defined(MBEDTLS_AES_C) 77 mbedtls_aes_init(&ctx->aes_ctx); 78#else 79 ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; 80 ctx->psa_ctx.operation = psa_cipher_operation_init(); 81#endif 82 /* Indicate that the entropy nonce length is not set explicitly. 83 * See mbedtls_ctr_drbg_set_nonce_len(). */ 84 ctx->reseed_counter = -1; 85 86 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 87} 88 89/* 90 * This function resets CTR_DRBG context to the state immediately 91 * after initial call of mbedtls_ctr_drbg_init(). 92 */ 93void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx) 94{ 95 if (ctx == NULL) { 96 return; 97 } 98 99#if defined(MBEDTLS_THREADING_C) 100 /* The mutex is initialized iff f_entropy is set. */ 101 if (ctx->f_entropy != NULL) { 102 mbedtls_mutex_free(&ctx->mutex); 103 } 104#endif 105#if defined(MBEDTLS_AES_C) 106 mbedtls_aes_free(&ctx->aes_ctx); 107#else 108 ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); 109#endif 110 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context)); 111 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 112 ctx->reseed_counter = -1; 113} 114 115void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx, 116 int resistance) 117{ 118 ctx->prediction_resistance = resistance; 119} 120 121void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, 122 size_t len) 123{ 124 ctx->entropy_len = len; 125} 126 127int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx, 128 size_t len) 129{ 130 /* If mbedtls_ctr_drbg_seed() has already been called, it's 131 * too late. Return the error code that's closest to making sense. */ 132 if (ctx->f_entropy != NULL) { 133 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 134 } 135 136 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { 137 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 138 } 139 140 /* This shouldn't be an issue because 141 * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible 142 * configuration, but make sure anyway. */ 143 if (len > INT_MAX) { 144 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 145 } 146 147 /* For backward compatibility with Mbed TLS <= 2.19, store the 148 * entropy nonce length in a field that already exists, but isn't 149 * used until after the initial seeding. */ 150 /* Due to the capping of len above, the value fits in an int. */ 151 ctx->reseed_counter = (int) len; 152 return 0; 153} 154 155void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, 156 int interval) 157{ 158 ctx->reseed_interval = interval; 159} 160 161static int block_cipher_df(unsigned char *output, 162 const unsigned char *data, size_t data_len) 163{ 164 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 165 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; 166 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 167 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 168 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 169 unsigned char *p, *iv; 170 int ret = 0; 171#if defined(MBEDTLS_AES_C) 172 mbedtls_aes_context aes_ctx; 173#else 174 psa_status_t status; 175 size_t tmp_len; 176 mbedtls_ctr_drbg_psa_context psa_ctx; 177 178 psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; 179 psa_ctx.operation = psa_cipher_operation_init(); 180#endif 181 182 int i, j; 183 size_t buf_len, use_len; 184 185 if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { 186 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 187 } 188 189 memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 190 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16); 191 192 /* 193 * Construct IV (16 bytes) and S in buffer 194 * IV = Counter (in 32-bits) padded to 16 with zeroes 195 * S = Length input string (in 32-bits) || Length of output (in 32-bits) || 196 * data || 0x80 197 * (Total is padded to a multiple of 16-bytes with zeroes) 198 */ 199 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; 200 MBEDTLS_PUT_UINT32_BE(data_len, p, 0); 201 p += 4 + 3; 202 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; 203 memcpy(p, data, data_len); 204 p[data_len] = 0x80; 205 206 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; 207 208 for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) { 209 key[i] = i; 210 } 211 212#if defined(MBEDTLS_AES_C) 213 mbedtls_aes_init(&aes_ctx); 214 215 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 216 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 217 goto exit; 218 } 219#else 220 status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key)); 221 if (status != PSA_SUCCESS) { 222 ret = psa_generic_status_to_mbedtls(status); 223 goto exit; 224 } 225#endif 226 227 /* 228 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data 229 */ 230 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { 231 p = buf; 232 memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE); 233 use_len = buf_len; 234 235 while (use_len > 0) { 236 mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE); 237 p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 238 use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ? 239 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; 240 241#if defined(MBEDTLS_AES_C) 242 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, 243 chain, chain)) != 0) { 244 goto exit; 245 } 246#else 247 status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, 248 chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); 249 if (status != PSA_SUCCESS) { 250 ret = psa_generic_status_to_mbedtls(status); 251 goto exit; 252 } 253#endif 254 } 255 256 memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE); 257 258 /* 259 * Update IV 260 */ 261 buf[3]++; 262 } 263 264 /* 265 * Do final encryption with reduced data 266 */ 267#if defined(MBEDTLS_AES_C) 268 if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp, 269 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 270 goto exit; 271 } 272#else 273 ctr_drbg_destroy_psa_contex(&psa_ctx); 274 275 status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); 276 if (status != PSA_SUCCESS) { 277 ret = psa_generic_status_to_mbedtls(status); 278 goto exit; 279 } 280#endif 281 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; 282 p = output; 283 284 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { 285#if defined(MBEDTLS_AES_C) 286 if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, 287 iv, iv)) != 0) { 288 goto exit; 289 } 290#else 291 status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, 292 iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); 293 if (status != PSA_SUCCESS) { 294 ret = psa_generic_status_to_mbedtls(status); 295 goto exit; 296 } 297#endif 298 memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE); 299 p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 300 } 301exit: 302#if defined(MBEDTLS_AES_C) 303 mbedtls_aes_free(&aes_ctx); 304#else 305 ctr_drbg_destroy_psa_contex(&psa_ctx); 306#endif 307 /* 308 * tidy up the stack 309 */ 310 mbedtls_platform_zeroize(buf, sizeof(buf)); 311 mbedtls_platform_zeroize(tmp, sizeof(tmp)); 312 mbedtls_platform_zeroize(key, sizeof(key)); 313 mbedtls_platform_zeroize(chain, sizeof(chain)); 314 if (0 != ret) { 315 /* 316 * wipe partial seed from memory 317 */ 318 mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN); 319 } 320 321 return ret; 322} 323 324/* CTR_DRBG_Update (SP 800-90A §10.2.1.2) 325 * ctr_drbg_update_internal(ctx, provided_data) 326 * implements 327 * CTR_DRBG_Update(provided_data, Key, V) 328 * with inputs and outputs 329 * ctx->aes_ctx = Key 330 * ctx->counter = V 331 */ 332static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx, 333 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN]) 334{ 335 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 336 unsigned char *p = tmp; 337 int j; 338 int ret = 0; 339#if !defined(MBEDTLS_AES_C) 340 psa_status_t status; 341 size_t tmp_len; 342#endif 343 344 memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN); 345 346 for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { 347 /* 348 * Increase counter 349 */ 350 mbedtls_ctr_increment_counter(ctx->counter); 351 352 /* 353 * Crypt counter block 354 */ 355#if defined(MBEDTLS_AES_C) 356 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 357 ctx->counter, p)) != 0) { 358 goto exit; 359 } 360#else 361 status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), 362 p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); 363 if (status != PSA_SUCCESS) { 364 ret = psa_generic_status_to_mbedtls(status); 365 goto exit; 366 } 367#endif 368 369 p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 370 } 371 372 mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN); 373 374 /* 375 * Update key and counter 376 */ 377#if defined(MBEDTLS_AES_C) 378 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp, 379 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 380 goto exit; 381 } 382#else 383 ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); 384 385 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); 386 if (status != PSA_SUCCESS) { 387 ret = psa_generic_status_to_mbedtls(status); 388 goto exit; 389 } 390#endif 391 memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, 392 MBEDTLS_CTR_DRBG_BLOCKSIZE); 393 394exit: 395 mbedtls_platform_zeroize(tmp, sizeof(tmp)); 396 return ret; 397} 398 399/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 400 * mbedtls_ctr_drbg_update(ctx, additional, add_len) 401 * implements 402 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 403 * security_strength) -> initial_working_state 404 * with inputs 405 * ctx->counter = all-bits-0 406 * ctx->aes_ctx = context from all-bits-0 key 407 * additional[:add_len] = entropy_input || nonce || personalization_string 408 * and with outputs 409 * ctx = initial_working_state 410 */ 411int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, 412 const unsigned char *additional, 413 size_t add_len) 414{ 415 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 416 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 417 418 if (add_len == 0) { 419 return 0; 420 } 421 422 if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) { 423 goto exit; 424 } 425 if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) { 426 goto exit; 427 } 428 429exit: 430 mbedtls_platform_zeroize(add_input, sizeof(add_input)); 431 return ret; 432} 433 434/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) 435 * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) 436 * implements 437 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) 438 * -> new_working_state 439 * with inputs 440 * ctx contains working_state 441 * additional[:len] = additional_input 442 * and entropy_input comes from calling ctx->f_entropy 443 * for (ctx->entropy_len + nonce_len) bytes 444 * and with output 445 * ctx contains new_working_state 446 */ 447static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx, 448 const unsigned char *additional, 449 size_t len, 450 size_t nonce_len) 451{ 452 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; 453 size_t seedlen = 0; 454 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 455 456 if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { 457 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 458 } 459 if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) { 460 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 461 } 462 if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) { 463 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 464 } 465 466 memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT); 467 468 /* Gather entropy_len bytes of entropy to seed state. */ 469 if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) { 470 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 471 } 472 seedlen += ctx->entropy_len; 473 474 /* Gather entropy for a nonce if requested. */ 475 if (nonce_len != 0) { 476 if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) { 477 return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 478 } 479 seedlen += nonce_len; 480 } 481 482 /* Add additional data if provided. */ 483 if (additional != NULL && len != 0) { 484 memcpy(seed + seedlen, additional, len); 485 seedlen += len; 486 } 487 488 /* Reduce to 384 bits. */ 489 if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) { 490 goto exit; 491 } 492 493 /* Update state. */ 494 if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) { 495 goto exit; 496 } 497 ctx->reseed_counter = 1; 498 499exit: 500 mbedtls_platform_zeroize(seed, sizeof(seed)); 501 return ret; 502} 503 504int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, 505 const unsigned char *additional, size_t len) 506{ 507 return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0); 508} 509 510/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length 511 * is sufficient to achieve the maximum security strength given the key 512 * size and entropy length. If there is enough entropy in the initial 513 * call to the entropy function to serve as both the entropy input and 514 * the nonce, don't make a second call to get a nonce. */ 515static size_t good_nonce_len(size_t entropy_len) 516{ 517 if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) { 518 return 0; 519 } else { 520 return (entropy_len + 1) / 2; 521 } 522} 523 524/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 525 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) 526 * implements 527 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 528 * security_strength) -> initial_working_state 529 * with inputs 530 * custom[:len] = nonce || personalization_string 531 * where entropy_input comes from f_entropy for ctx->entropy_len bytes 532 * and with outputs 533 * ctx = initial_working_state 534 */ 535int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, 536 int (*f_entropy)(void *, unsigned char *, size_t), 537 void *p_entropy, 538 const unsigned char *custom, 539 size_t len) 540{ 541 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 542 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 543 size_t nonce_len; 544 545 memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE); 546 547 /* The mutex is initialized iff f_entropy is set. */ 548#if defined(MBEDTLS_THREADING_C) 549 mbedtls_mutex_init(&ctx->mutex); 550#endif 551 552 ctx->f_entropy = f_entropy; 553 ctx->p_entropy = p_entropy; 554 555 if (ctx->entropy_len == 0) { 556 ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; 557 } 558 /* ctx->reseed_counter contains the desired amount of entropy to 559 * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). 560 * If it's -1, indicating that the entropy nonce length was not set 561 * explicitly, use a sufficiently large nonce for security. */ 562 nonce_len = (ctx->reseed_counter >= 0 ? 563 (size_t) ctx->reseed_counter : 564 good_nonce_len(ctx->entropy_len)); 565 566 /* Initialize with an empty key. */ 567#if defined(MBEDTLS_AES_C) 568 if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key, 569 MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 570 return ret; 571 } 572#else 573 psa_status_t status; 574 575 status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE); 576 if (status != PSA_SUCCESS) { 577 ret = psa_generic_status_to_mbedtls(status); 578 return status; 579 } 580#endif 581 582 /* Do the initial seeding. */ 583 if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len, 584 nonce_len)) != 0) { 585 return ret; 586 } 587 return 0; 588} 589 590/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) 591 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) 592 * implements 593 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) 594 * -> working_state_after_reseed 595 * if required, then 596 * CTR_DRBG_Generate(working_state_after_reseed, 597 * requested_number_of_bits, additional_input) 598 * -> status, returned_bits, new_working_state 599 * with inputs 600 * ctx contains working_state 601 * requested_number_of_bits = 8 * output_len 602 * additional[:add_len] = additional_input 603 * and entropy_input comes from calling ctx->f_entropy 604 * and with outputs 605 * status = SUCCESS (this function does the reseed internally) 606 * returned_bits = output[:output_len] 607 * ctx contains new_working_state 608 */ 609int mbedtls_ctr_drbg_random_with_add(void *p_rng, 610 unsigned char *output, size_t output_len, 611 const unsigned char *additional, size_t add_len) 612{ 613 int ret = 0; 614 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 615 unsigned char *p = output; 616 struct { 617 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 618 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 619 } locals; 620 size_t use_len; 621 622 if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) { 623 return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG; 624 } 625 626 if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) { 627 return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 628 } 629 630 memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN); 631 632 if (ctx->reseed_counter > ctx->reseed_interval || 633 ctx->prediction_resistance) { 634 if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) { 635 return ret; 636 } 637 add_len = 0; 638 } 639 640 if (add_len > 0) { 641 if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) { 642 goto exit; 643 } 644 if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { 645 goto exit; 646 } 647 } 648 649 while (output_len > 0) { 650 /* 651 * Increase counter (treat it as a 128-bit big-endian integer). 652 */ 653 mbedtls_ctr_increment_counter(ctx->counter); 654 655 /* 656 * Crypt counter block 657 */ 658#if defined(MBEDTLS_AES_C) 659 if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 660 ctx->counter, locals.tmp)) != 0) { 661 goto exit; 662 } 663#else 664 psa_status_t status; 665 size_t tmp_len; 666 667 status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), 668 locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); 669 if (status != PSA_SUCCESS) { 670 ret = psa_generic_status_to_mbedtls(status); 671 goto exit; 672 } 673#endif 674 675 use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE) 676 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; 677 /* 678 * Copy random block to destination 679 */ 680 memcpy(p, locals.tmp, use_len); 681 p += use_len; 682 output_len -= use_len; 683 } 684 685 if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { 686 goto exit; 687 } 688 689 ctx->reseed_counter++; 690 691exit: 692 mbedtls_platform_zeroize(&locals, sizeof(locals)); 693 return ret; 694} 695 696int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, 697 size_t output_len) 698{ 699 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 700 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 701 702#if defined(MBEDTLS_THREADING_C) 703 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { 704 return ret; 705 } 706#endif 707 708 ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0); 709 710#if defined(MBEDTLS_THREADING_C) 711 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { 712 return MBEDTLS_ERR_THREADING_MUTEX_ERROR; 713 } 714#endif 715 716 return ret; 717} 718 719#if defined(MBEDTLS_FS_IO) 720int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, 721 const char *path) 722{ 723 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 724 FILE *f; 725 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; 726 727 if ((f = fopen(path, "wb")) == NULL) { 728 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 729 } 730 731 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ 732 mbedtls_setbuf(f, NULL); 733 734 if ((ret = mbedtls_ctr_drbg_random(ctx, buf, 735 MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) { 736 goto exit; 737 } 738 739 if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) != 740 MBEDTLS_CTR_DRBG_MAX_INPUT) { 741 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 742 } else { 743 ret = 0; 744 } 745 746exit: 747 mbedtls_platform_zeroize(buf, sizeof(buf)); 748 749 fclose(f); 750 return ret; 751} 752 753int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, 754 const char *path) 755{ 756 int ret = 0; 757 FILE *f = NULL; 758 size_t n; 759 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; 760 unsigned char c; 761 762 if ((f = fopen(path, "rb")) == NULL) { 763 return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 764 } 765 766 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ 767 mbedtls_setbuf(f, NULL); 768 769 n = fread(buf, 1, sizeof(buf), f); 770 if (fread(&c, 1, 1, f) != 0) { 771 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 772 goto exit; 773 } 774 if (n == 0 || ferror(f)) { 775 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 776 goto exit; 777 } 778 fclose(f); 779 f = NULL; 780 781 ret = mbedtls_ctr_drbg_update(ctx, buf, n); 782 783exit: 784 mbedtls_platform_zeroize(buf, sizeof(buf)); 785 if (f != NULL) { 786 fclose(f); 787 } 788 if (ret != 0) { 789 return ret; 790 } 791 return mbedtls_ctr_drbg_write_seed_file(ctx, path); 792} 793#endif /* MBEDTLS_FS_IO */ 794 795#if defined(MBEDTLS_SELF_TEST) 796 797/* The CTR_DRBG NIST test vectors used here are available at 798 * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip 799 * 800 * The parameters used to derive the test data are: 801 * 802 * [AES-128 use df] 803 * [PredictionResistance = True/False] 804 * [EntropyInputLen = 128] 805 * [NonceLen = 64] 806 * [PersonalizationStringLen = 128] 807 * [AdditionalInputLen = 0] 808 * [ReturnedBitsLen = 512] 809 * 810 * [AES-256 use df] 811 * [PredictionResistance = True/False] 812 * [EntropyInputLen = 256] 813 * [NonceLen = 128] 814 * [PersonalizationStringLen = 256] 815 * [AdditionalInputLen = 0] 816 * [ReturnedBitsLen = 512] 817 * 818 */ 819 820#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) 821static const unsigned char entropy_source_pr[] = 822{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, 823 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92, 824 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8, 825 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, 826 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0, 827 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad, 828 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 }; 829 830static const unsigned char entropy_source_nopr[] = 831{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, 832 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, 833 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20, 834 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f, 835 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c }; 836 837static const unsigned char pers_pr[] = 838{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a, 839 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad }; 840 841static const unsigned char pers_nopr[] = 842{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c, 843 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f }; 844 845static const unsigned char result_pr[] = 846{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, 847 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff, 848 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10, 849 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, 850 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, 851 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc, 852 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06, 853 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf }; 854 855static const unsigned char result_nopr[] = 856{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, 857 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0, 858 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf, 859 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, 860 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, 861 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2, 862 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02, 863 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 }; 864#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 865 866static const unsigned char entropy_source_pr[] = 867{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, 868 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a, 869 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85, 870 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, 871 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15, 872 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45, 873 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, 874 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c, 875 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3, 876 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, 877 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e, 878 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76, 879 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, 880 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe }; 881 882static const unsigned char entropy_source_nopr[] = 883{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, 884 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0, 885 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73, 886 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, 887 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2, 888 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1, 889 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, 890 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb, 891 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a, 892 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 }; 893 894static const unsigned char pers_pr[] = 895{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, 896 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e, 897 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0, 898 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 }; 899 900static const unsigned char pers_nopr[] = 901{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, 902 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf, 903 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb, 904 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b }; 905 906static const unsigned char result_pr[] = 907{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, 908 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d, 909 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62, 910 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, 911 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, 912 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39, 913 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40, 914 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 }; 915 916static const unsigned char result_nopr[] = 917{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, 918 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3, 919 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b, 920 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, 921 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, 922 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30, 923 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a, 924 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 }; 925#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 926 927static size_t test_offset; 928static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf, 929 size_t len) 930{ 931 const unsigned char *p = data; 932 memcpy(buf, p + test_offset, len); 933 test_offset += len; 934 return 0; 935} 936 937#define CHK(c) if ((c) != 0) \ 938 { \ 939 if (verbose != 0) \ 940 mbedtls_printf("failed\n"); \ 941 return 1; \ 942 } 943 944#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64 945 946/* 947 * Checkup routine 948 */ 949int mbedtls_ctr_drbg_self_test(int verbose) 950{ 951 mbedtls_ctr_drbg_context ctx; 952 unsigned char buf[sizeof(result_pr)]; 953 954 mbedtls_ctr_drbg_init(&ctx); 955 956 /* 957 * Based on a NIST CTR_DRBG test vector (PR = True) 958 */ 959 if (verbose != 0) { 960 mbedtls_printf(" CTR_DRBG (PR = TRUE) : "); 961 } 962 963 test_offset = 0; 964 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); 965 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); 966 CHK(mbedtls_ctr_drbg_seed(&ctx, 967 ctr_drbg_self_test_entropy, 968 (void *) entropy_source_pr, 969 pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE)); 970 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON); 971 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); 972 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr))); 973 CHK(memcmp(buf, result_pr, sizeof(result_pr))); 974 975 mbedtls_ctr_drbg_free(&ctx); 976 977 if (verbose != 0) { 978 mbedtls_printf("passed\n"); 979 } 980 981 /* 982 * Based on a NIST CTR_DRBG test vector (PR = FALSE) 983 */ 984 if (verbose != 0) { 985 mbedtls_printf(" CTR_DRBG (PR = FALSE): "); 986 } 987 988 mbedtls_ctr_drbg_init(&ctx); 989 990 test_offset = 0; 991 mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); 992 mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); 993 CHK(mbedtls_ctr_drbg_seed(&ctx, 994 ctr_drbg_self_test_entropy, 995 (void *) entropy_source_nopr, 996 pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE)); 997 CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0)); 998 CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); 999 CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr))); 1000 CHK(memcmp(buf, result_nopr, sizeof(result_nopr))); 1001 1002 mbedtls_ctr_drbg_free(&ctx); 1003 1004 if (verbose != 0) { 1005 mbedtls_printf("passed\n"); 1006 } 1007 1008 if (verbose != 0) { 1009 mbedtls_printf("\n"); 1010 } 1011 1012 return 0; 1013} 1014#endif /* MBEDTLS_SELF_TEST */ 1015 1016#endif /* MBEDTLS_CTR_DRBG_C */ 1017