1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 5*b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6817466cbSJens Wiklander */ 7817466cbSJens Wiklander /* 83d3b0591SJens Wiklander * The NIST SP 800-90 DRBGs are described in the following publication. 9817466cbSJens Wiklander * 10*b0563631STom Van Eyck * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf 11817466cbSJens Wiklander */ 12817466cbSJens Wiklander 137901324dSJerome Forissier #include "common.h" 14817466cbSJens Wiklander 15817466cbSJens Wiklander #if defined(MBEDTLS_CTR_DRBG_C) 16817466cbSJens Wiklander 17*b0563631STom Van Eyck #include "ctr.h" 18817466cbSJens Wiklander #include "mbedtls/ctr_drbg.h" 193d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 2011fa71b9SJerome Forissier #include "mbedtls/error.h" 21817466cbSJens Wiklander 22817466cbSJens Wiklander #include <string.h> 23817466cbSJens Wiklander 24817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 25817466cbSJens Wiklander #include <stdio.h> 26817466cbSJens Wiklander #endif 27817466cbSJens Wiklander 28*b0563631STom Van Eyck /* Using error translation functions from PSA to MbedTLS */ 29*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_C) 30*b0563631STom Van Eyck #include "psa_util_internal.h" 31*b0563631STom Van Eyck #endif 32*b0563631STom Van Eyck 33817466cbSJens Wiklander #include "mbedtls/platform.h" 34817466cbSJens Wiklander 35*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_C) 36*b0563631STom Van Eyck static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx, 37*b0563631STom Van Eyck unsigned char *key, size_t key_len) 38*b0563631STom Van Eyck { 39*b0563631STom Van Eyck psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; 40*b0563631STom Van Eyck psa_status_t status; 41*b0563631STom Van Eyck 42*b0563631STom Van Eyck psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); 43*b0563631STom Van Eyck psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); 44*b0563631STom Van Eyck psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES); 45*b0563631STom Van Eyck status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id); 46*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 47*b0563631STom Van Eyck goto exit; 48*b0563631STom Van Eyck } 49*b0563631STom Van Eyck 50*b0563631STom Van Eyck status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING); 51*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 52*b0563631STom Van Eyck goto exit; 53*b0563631STom Van Eyck } 54*b0563631STom Van Eyck 55*b0563631STom Van Eyck exit: 56*b0563631STom Van Eyck psa_reset_key_attributes(&key_attr); 57*b0563631STom Van Eyck return status; 58*b0563631STom Van Eyck } 59*b0563631STom Van Eyck 60*b0563631STom Van Eyck static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx) 61*b0563631STom Van Eyck { 62*b0563631STom Van Eyck psa_cipher_abort(&psa_ctx->operation); 63*b0563631STom Van Eyck psa_destroy_key(psa_ctx->key_id); 64*b0563631STom Van Eyck 65*b0563631STom Van Eyck psa_ctx->operation = psa_cipher_operation_init(); 66*b0563631STom Van Eyck psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT; 67*b0563631STom Van Eyck } 68*b0563631STom Van Eyck #endif 69*b0563631STom Van Eyck 70817466cbSJens Wiklander /* 71817466cbSJens Wiklander * CTR_DRBG context initialization 72817466cbSJens Wiklander */ 73817466cbSJens Wiklander void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx) 74817466cbSJens Wiklander { 75817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context)); 76*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 7732b31808SJens Wiklander mbedtls_aes_init(&ctx->aes_ctx); 78*b0563631STom Van Eyck #else 79*b0563631STom Van Eyck ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; 80*b0563631STom Van Eyck ctx->psa_ctx.operation = psa_cipher_operation_init(); 81*b0563631STom Van Eyck #endif 8211fa71b9SJerome Forissier /* Indicate that the entropy nonce length is not set explicitly. 8311fa71b9SJerome Forissier * See mbedtls_ctr_drbg_set_nonce_len(). */ 8411fa71b9SJerome Forissier ctx->reseed_counter = -1; 85817466cbSJens Wiklander 867901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 87817466cbSJens Wiklander } 88817466cbSJens Wiklander 897901324dSJerome Forissier /* 907901324dSJerome Forissier * This function resets CTR_DRBG context to the state immediately 917901324dSJerome Forissier * after initial call of mbedtls_ctr_drbg_init(). 927901324dSJerome Forissier */ 93817466cbSJens Wiklander void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx) 94817466cbSJens Wiklander { 9532b31808SJens Wiklander if (ctx == NULL) { 96817466cbSJens Wiklander return; 9732b31808SJens Wiklander } 98817466cbSJens Wiklander 99817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 1007901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */ 10132b31808SJens Wiklander if (ctx->f_entropy != NULL) { 102817466cbSJens Wiklander mbedtls_mutex_free(&ctx->mutex); 10332b31808SJens Wiklander } 104817466cbSJens Wiklander #endif 105*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 106817466cbSJens Wiklander mbedtls_aes_free(&ctx->aes_ctx); 107*b0563631STom Van Eyck #else 108*b0563631STom Van Eyck ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); 109*b0563631STom Van Eyck #endif 1103d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context)); 1117901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 1127901324dSJerome Forissier ctx->reseed_counter = -1; 113817466cbSJens Wiklander } 114817466cbSJens Wiklander 11511fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx, 11611fa71b9SJerome Forissier int resistance) 117817466cbSJens Wiklander { 118817466cbSJens Wiklander ctx->prediction_resistance = resistance; 119817466cbSJens Wiklander } 120817466cbSJens Wiklander 12111fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, 12211fa71b9SJerome Forissier size_t len) 123817466cbSJens Wiklander { 124817466cbSJens Wiklander ctx->entropy_len = len; 125817466cbSJens Wiklander } 126817466cbSJens Wiklander 12711fa71b9SJerome Forissier int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx, 12811fa71b9SJerome Forissier size_t len) 12911fa71b9SJerome Forissier { 13011fa71b9SJerome Forissier /* If mbedtls_ctr_drbg_seed() has already been called, it's 13111fa71b9SJerome Forissier * too late. Return the error code that's closest to making sense. */ 13232b31808SJens Wiklander if (ctx->f_entropy != NULL) { 13332b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 13432b31808SJens Wiklander } 13511fa71b9SJerome Forissier 13632b31808SJens Wiklander if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { 13732b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 13832b31808SJens Wiklander } 13932b31808SJens Wiklander 14011fa71b9SJerome Forissier /* This shouldn't be an issue because 14111fa71b9SJerome Forissier * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible 14211fa71b9SJerome Forissier * configuration, but make sure anyway. */ 14332b31808SJens Wiklander if (len > INT_MAX) { 14432b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 14532b31808SJens Wiklander } 14611fa71b9SJerome Forissier 14711fa71b9SJerome Forissier /* For backward compatibility with Mbed TLS <= 2.19, store the 14811fa71b9SJerome Forissier * entropy nonce length in a field that already exists, but isn't 14911fa71b9SJerome Forissier * used until after the initial seeding. */ 15011fa71b9SJerome Forissier /* Due to the capping of len above, the value fits in an int. */ 15111fa71b9SJerome Forissier ctx->reseed_counter = (int) len; 15232b31808SJens Wiklander return 0; 15311fa71b9SJerome Forissier } 15411fa71b9SJerome Forissier 15511fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, 15611fa71b9SJerome Forissier int interval) 157817466cbSJens Wiklander { 158817466cbSJens Wiklander ctx->reseed_interval = interval; 159817466cbSJens Wiklander } 160817466cbSJens Wiklander 161817466cbSJens Wiklander static int block_cipher_df(unsigned char *output, 162817466cbSJens Wiklander const unsigned char *data, size_t data_len) 163817466cbSJens Wiklander { 16411fa71b9SJerome Forissier unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 16511fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; 166817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 167817466cbSJens Wiklander unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 168817466cbSJens Wiklander unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 169817466cbSJens Wiklander unsigned char *p, *iv; 1703d3b0591SJens Wiklander int ret = 0; 171*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 172*b0563631STom Van Eyck mbedtls_aes_context aes_ctx; 173*b0563631STom Van Eyck #else 174*b0563631STom Van Eyck psa_status_t status; 175*b0563631STom Van Eyck size_t tmp_len; 176*b0563631STom Van Eyck mbedtls_ctr_drbg_psa_context psa_ctx; 177*b0563631STom Van Eyck 178*b0563631STom Van Eyck psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; 179*b0563631STom Van Eyck psa_ctx.operation = psa_cipher_operation_init(); 180*b0563631STom Van Eyck #endif 181817466cbSJens Wiklander 182817466cbSJens Wiklander int i, j; 183817466cbSJens Wiklander size_t buf_len, use_len; 184817466cbSJens Wiklander 18532b31808SJens Wiklander if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { 18632b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 18732b31808SJens Wiklander } 188817466cbSJens Wiklander 18911fa71b9SJerome Forissier memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 19011fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16); 191817466cbSJens Wiklander 192817466cbSJens Wiklander /* 193817466cbSJens Wiklander * Construct IV (16 bytes) and S in buffer 194817466cbSJens Wiklander * IV = Counter (in 32-bits) padded to 16 with zeroes 195817466cbSJens Wiklander * S = Length input string (in 32-bits) || Length of output (in 32-bits) || 196817466cbSJens Wiklander * data || 0x80 197817466cbSJens Wiklander * (Total is padded to a multiple of 16-bytes with zeroes) 198817466cbSJens Wiklander */ 199817466cbSJens Wiklander p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; 200039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(data_len, p, 0); 201039e02dfSJerome Forissier p += 4 + 3; 202817466cbSJens Wiklander *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; 203817466cbSJens Wiklander memcpy(p, data, data_len); 204817466cbSJens Wiklander p[data_len] = 0x80; 205817466cbSJens Wiklander 206817466cbSJens Wiklander buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; 207817466cbSJens Wiklander 20832b31808SJens Wiklander for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) { 209817466cbSJens Wiklander key[i] = i; 21032b31808SJens Wiklander } 211817466cbSJens Wiklander 212*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 213*b0563631STom Van Eyck mbedtls_aes_init(&aes_ctx); 214*b0563631STom Van Eyck 21511fa71b9SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 21632b31808SJens Wiklander MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 2173d3b0591SJens Wiklander goto exit; 2183d3b0591SJens Wiklander } 219*b0563631STom Van Eyck #else 220*b0563631STom Van Eyck status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key)); 221*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 222*b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status); 223*b0563631STom Van Eyck goto exit; 224*b0563631STom Van Eyck } 225*b0563631STom Van Eyck #endif 226817466cbSJens Wiklander 227817466cbSJens Wiklander /* 228817466cbSJens Wiklander * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data 229817466cbSJens Wiklander */ 23032b31808SJens Wiklander for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { 231817466cbSJens Wiklander p = buf; 232817466cbSJens Wiklander memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE); 233817466cbSJens Wiklander use_len = buf_len; 234817466cbSJens Wiklander 23532b31808SJens Wiklander while (use_len > 0) { 23632b31808SJens Wiklander mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE); 237817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 238817466cbSJens Wiklander use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ? 239817466cbSJens Wiklander MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; 240817466cbSJens Wiklander 241*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 24211fa71b9SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, 24332b31808SJens Wiklander chain, chain)) != 0) { 2443d3b0591SJens Wiklander goto exit; 2453d3b0591SJens Wiklander } 246*b0563631STom Van Eyck #else 247*b0563631STom Van Eyck status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, 248*b0563631STom Van Eyck chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); 249*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 250*b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status); 251*b0563631STom Van Eyck goto exit; 252*b0563631STom Van Eyck } 253*b0563631STom Van Eyck #endif 254817466cbSJens Wiklander } 255817466cbSJens Wiklander 256817466cbSJens Wiklander memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE); 257817466cbSJens Wiklander 258817466cbSJens Wiklander /* 259817466cbSJens Wiklander * Update IV 260817466cbSJens Wiklander */ 261817466cbSJens Wiklander buf[3]++; 262817466cbSJens Wiklander } 263817466cbSJens Wiklander 264817466cbSJens Wiklander /* 265817466cbSJens Wiklander * Do final encryption with reduced data 266817466cbSJens Wiklander */ 267*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 26811fa71b9SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp, 26932b31808SJens Wiklander MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 2703d3b0591SJens Wiklander goto exit; 2713d3b0591SJens Wiklander } 272*b0563631STom Van Eyck #else 273*b0563631STom Van Eyck ctr_drbg_destroy_psa_contex(&psa_ctx); 274*b0563631STom Van Eyck 275*b0563631STom Van Eyck status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); 276*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 277*b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status); 278*b0563631STom Van Eyck goto exit; 279*b0563631STom Van Eyck } 280*b0563631STom Van Eyck #endif 281817466cbSJens Wiklander iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; 282817466cbSJens Wiklander p = output; 283817466cbSJens Wiklander 28432b31808SJens Wiklander for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { 285*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 28611fa71b9SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, 28732b31808SJens Wiklander iv, iv)) != 0) { 2883d3b0591SJens Wiklander goto exit; 2893d3b0591SJens Wiklander } 290*b0563631STom Van Eyck #else 291*b0563631STom Van Eyck status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, 292*b0563631STom Van Eyck iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); 293*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 294*b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status); 295*b0563631STom Van Eyck goto exit; 296*b0563631STom Van Eyck } 297*b0563631STom Van Eyck #endif 298817466cbSJens Wiklander memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE); 299817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 300817466cbSJens Wiklander } 3013d3b0591SJens Wiklander exit: 302*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 303817466cbSJens Wiklander mbedtls_aes_free(&aes_ctx); 304*b0563631STom Van Eyck #else 305*b0563631STom Van Eyck ctr_drbg_destroy_psa_contex(&psa_ctx); 306*b0563631STom Van Eyck #endif 3073d3b0591SJens Wiklander /* 3083d3b0591SJens Wiklander * tidy up the stack 3093d3b0591SJens Wiklander */ 3103d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, sizeof(buf)); 3113d3b0591SJens Wiklander mbedtls_platform_zeroize(tmp, sizeof(tmp)); 3123d3b0591SJens Wiklander mbedtls_platform_zeroize(key, sizeof(key)); 3133d3b0591SJens Wiklander mbedtls_platform_zeroize(chain, sizeof(chain)); 31432b31808SJens Wiklander if (0 != ret) { 3153d3b0591SJens Wiklander /* 3163d3b0591SJens Wiklander * wipe partial seed from memory 3173d3b0591SJens Wiklander */ 3183d3b0591SJens Wiklander mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN); 319817466cbSJens Wiklander } 320817466cbSJens Wiklander 32132b31808SJens Wiklander return ret; 3223d3b0591SJens Wiklander } 3233d3b0591SJens Wiklander 3243d3b0591SJens Wiklander /* CTR_DRBG_Update (SP 800-90A §10.2.1.2) 3253d3b0591SJens Wiklander * ctr_drbg_update_internal(ctx, provided_data) 3263d3b0591SJens Wiklander * implements 3273d3b0591SJens Wiklander * CTR_DRBG_Update(provided_data, Key, V) 3283d3b0591SJens Wiklander * with inputs and outputs 3293d3b0591SJens Wiklander * ctx->aes_ctx = Key 3303d3b0591SJens Wiklander * ctx->counter = V 3313d3b0591SJens Wiklander */ 332817466cbSJens Wiklander static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx, 333817466cbSJens Wiklander const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN]) 334817466cbSJens Wiklander { 335817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 336817466cbSJens Wiklander unsigned char *p = tmp; 337*b0563631STom Van Eyck int j; 3383d3b0591SJens Wiklander int ret = 0; 339*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_C) 340*b0563631STom Van Eyck psa_status_t status; 341*b0563631STom Van Eyck size_t tmp_len; 342*b0563631STom Van Eyck #endif 343817466cbSJens Wiklander 344817466cbSJens Wiklander memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN); 345817466cbSJens Wiklander 34632b31808SJens Wiklander for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { 347817466cbSJens Wiklander /* 348817466cbSJens Wiklander * Increase counter 349817466cbSJens Wiklander */ 350*b0563631STom Van Eyck mbedtls_ctr_increment_counter(ctx->counter); 351817466cbSJens Wiklander 352817466cbSJens Wiklander /* 353817466cbSJens Wiklander * Crypt counter block 354817466cbSJens Wiklander */ 355*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 35611fa71b9SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 35732b31808SJens Wiklander ctx->counter, p)) != 0) { 3583d3b0591SJens Wiklander goto exit; 35911fa71b9SJerome Forissier } 360*b0563631STom Van Eyck #else 361*b0563631STom Van Eyck status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), 362*b0563631STom Van Eyck p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); 363*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 364*b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status); 365*b0563631STom Van Eyck goto exit; 366*b0563631STom Van Eyck } 367*b0563631STom Van Eyck #endif 368817466cbSJens Wiklander 369817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 370817466cbSJens Wiklander } 371817466cbSJens Wiklander 372*b0563631STom Van Eyck mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN); 373817466cbSJens Wiklander 374817466cbSJens Wiklander /* 375817466cbSJens Wiklander * Update key and counter 376817466cbSJens Wiklander */ 377*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 37811fa71b9SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp, 37932b31808SJens Wiklander MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 3803d3b0591SJens Wiklander goto exit; 38111fa71b9SJerome Forissier } 382*b0563631STom Van Eyck #else 383*b0563631STom Van Eyck ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); 384*b0563631STom Van Eyck 385*b0563631STom Van Eyck status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); 386*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 387*b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status); 388*b0563631STom Van Eyck goto exit; 389*b0563631STom Van Eyck } 390*b0563631STom Van Eyck #endif 39111fa71b9SJerome Forissier memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, 39211fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE); 393817466cbSJens Wiklander 3943d3b0591SJens Wiklander exit: 3953d3b0591SJens Wiklander mbedtls_platform_zeroize(tmp, sizeof(tmp)); 39632b31808SJens Wiklander return ret; 397817466cbSJens Wiklander } 398817466cbSJens Wiklander 3993d3b0591SJens Wiklander /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 4003d3b0591SJens Wiklander * mbedtls_ctr_drbg_update(ctx, additional, add_len) 4013d3b0591SJens Wiklander * implements 4023d3b0591SJens Wiklander * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 4033d3b0591SJens Wiklander * security_strength) -> initial_working_state 4043d3b0591SJens Wiklander * with inputs 4053d3b0591SJens Wiklander * ctx->counter = all-bits-0 4063d3b0591SJens Wiklander * ctx->aes_ctx = context from all-bits-0 key 4073d3b0591SJens Wiklander * additional[:add_len] = entropy_input || nonce || personalization_string 4083d3b0591SJens Wiklander * and with outputs 4093d3b0591SJens Wiklander * ctx = initial_working_state 4103d3b0591SJens Wiklander */ 41132b31808SJens Wiklander int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, 4123d3b0591SJens Wiklander const unsigned char *additional, 4133d3b0591SJens Wiklander size_t add_len) 414817466cbSJens Wiklander { 415817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 41611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 417817466cbSJens Wiklander 41832b31808SJens Wiklander if (add_len == 0) { 41932b31808SJens Wiklander return 0; 42032b31808SJens Wiklander } 4213d3b0591SJens Wiklander 42232b31808SJens Wiklander if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) { 4233d3b0591SJens Wiklander goto exit; 42432b31808SJens Wiklander } 42532b31808SJens Wiklander if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) { 4263d3b0591SJens Wiklander goto exit; 42732b31808SJens Wiklander } 4283d3b0591SJens Wiklander 4293d3b0591SJens Wiklander exit: 4303d3b0591SJens Wiklander mbedtls_platform_zeroize(add_input, sizeof(add_input)); 43132b31808SJens Wiklander return ret; 4323d3b0591SJens Wiklander } 4333d3b0591SJens Wiklander 4343d3b0591SJens Wiklander /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) 43511fa71b9SJerome Forissier * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) 4363d3b0591SJens Wiklander * implements 4373d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) 4383d3b0591SJens Wiklander * -> new_working_state 4393d3b0591SJens Wiklander * with inputs 4403d3b0591SJens Wiklander * ctx contains working_state 4413d3b0591SJens Wiklander * additional[:len] = additional_input 4423d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 44311fa71b9SJerome Forissier * for (ctx->entropy_len + nonce_len) bytes 4443d3b0591SJens Wiklander * and with output 4453d3b0591SJens Wiklander * ctx contains new_working_state 4463d3b0591SJens Wiklander */ 44711fa71b9SJerome Forissier static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx, 44811fa71b9SJerome Forissier const unsigned char *additional, 44911fa71b9SJerome Forissier size_t len, 45011fa71b9SJerome Forissier size_t nonce_len) 451817466cbSJens Wiklander { 452817466cbSJens Wiklander unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; 453817466cbSJens Wiklander size_t seedlen = 0; 45411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 455817466cbSJens Wiklander 45632b31808SJens Wiklander if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { 45732b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 45832b31808SJens Wiklander } 45932b31808SJens Wiklander if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) { 46032b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 46132b31808SJens Wiklander } 46232b31808SJens Wiklander if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) { 46332b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 46432b31808SJens Wiklander } 465817466cbSJens Wiklander 466817466cbSJens Wiklander memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT); 467817466cbSJens Wiklander 46811fa71b9SJerome Forissier /* Gather entropy_len bytes of entropy to seed state. */ 46932b31808SJens Wiklander if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) { 47032b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 471817466cbSJens Wiklander } 472817466cbSJens Wiklander seedlen += ctx->entropy_len; 473817466cbSJens Wiklander 47411fa71b9SJerome Forissier /* Gather entropy for a nonce if requested. */ 47532b31808SJens Wiklander if (nonce_len != 0) { 47632b31808SJens Wiklander if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) { 47732b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 47811fa71b9SJerome Forissier } 47911fa71b9SJerome Forissier seedlen += nonce_len; 48011fa71b9SJerome Forissier } 48111fa71b9SJerome Forissier 48211fa71b9SJerome Forissier /* Add additional data if provided. */ 48332b31808SJens Wiklander if (additional != NULL && len != 0) { 484817466cbSJens Wiklander memcpy(seed + seedlen, additional, len); 485817466cbSJens Wiklander seedlen += len; 486817466cbSJens Wiklander } 487817466cbSJens Wiklander 48811fa71b9SJerome Forissier /* Reduce to 384 bits. */ 48932b31808SJens Wiklander if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) { 4903d3b0591SJens Wiklander goto exit; 49132b31808SJens Wiklander } 492817466cbSJens Wiklander 49311fa71b9SJerome Forissier /* Update state. */ 49432b31808SJens Wiklander if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) { 4953d3b0591SJens Wiklander goto exit; 49632b31808SJens Wiklander } 497817466cbSJens Wiklander ctx->reseed_counter = 1; 498817466cbSJens Wiklander 4993d3b0591SJens Wiklander exit: 5003d3b0591SJens Wiklander mbedtls_platform_zeroize(seed, sizeof(seed)); 50132b31808SJens Wiklander return ret; 502817466cbSJens Wiklander } 503817466cbSJens Wiklander 50411fa71b9SJerome Forissier int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, 50511fa71b9SJerome Forissier const unsigned char *additional, size_t len) 50611fa71b9SJerome Forissier { 50732b31808SJens Wiklander return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0); 50811fa71b9SJerome Forissier } 50911fa71b9SJerome Forissier 51011fa71b9SJerome Forissier /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length 51111fa71b9SJerome Forissier * is sufficient to achieve the maximum security strength given the key 51211fa71b9SJerome Forissier * size and entropy length. If there is enough entropy in the initial 51311fa71b9SJerome Forissier * call to the entropy function to serve as both the entropy input and 51411fa71b9SJerome Forissier * the nonce, don't make a second call to get a nonce. */ 51511fa71b9SJerome Forissier static size_t good_nonce_len(size_t entropy_len) 51611fa71b9SJerome Forissier { 51732b31808SJens Wiklander if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) { 51832b31808SJens Wiklander return 0; 51932b31808SJens Wiklander } else { 52032b31808SJens Wiklander return (entropy_len + 1) / 2; 52132b31808SJens Wiklander } 52211fa71b9SJerome Forissier } 52311fa71b9SJerome Forissier 5245b25c76aSJerome Forissier /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 5255b25c76aSJerome Forissier * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) 5265b25c76aSJerome Forissier * implements 5275b25c76aSJerome Forissier * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 5285b25c76aSJerome Forissier * security_strength) -> initial_working_state 5295b25c76aSJerome Forissier * with inputs 5305b25c76aSJerome Forissier * custom[:len] = nonce || personalization_string 5315b25c76aSJerome Forissier * where entropy_input comes from f_entropy for ctx->entropy_len bytes 5325b25c76aSJerome Forissier * and with outputs 5335b25c76aSJerome Forissier * ctx = initial_working_state 5345b25c76aSJerome Forissier */ 5355b25c76aSJerome Forissier int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, 5365b25c76aSJerome Forissier int (*f_entropy)(void *, unsigned char *, size_t), 5375b25c76aSJerome Forissier void *p_entropy, 5385b25c76aSJerome Forissier const unsigned char *custom, 5395b25c76aSJerome Forissier size_t len) 5405b25c76aSJerome Forissier { 54111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 5425b25c76aSJerome Forissier unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 54311fa71b9SJerome Forissier size_t nonce_len; 5445b25c76aSJerome Forissier 5455b25c76aSJerome Forissier memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE); 5465b25c76aSJerome Forissier 5477901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */ 5487901324dSJerome Forissier #if defined(MBEDTLS_THREADING_C) 5497901324dSJerome Forissier mbedtls_mutex_init(&ctx->mutex); 5507901324dSJerome Forissier #endif 5517901324dSJerome Forissier 5525b25c76aSJerome Forissier ctx->f_entropy = f_entropy; 5535b25c76aSJerome Forissier ctx->p_entropy = p_entropy; 5545b25c76aSJerome Forissier 55532b31808SJens Wiklander if (ctx->entropy_len == 0) { 5565b25c76aSJerome Forissier ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; 55732b31808SJens Wiklander } 55811fa71b9SJerome Forissier /* ctx->reseed_counter contains the desired amount of entropy to 55911fa71b9SJerome Forissier * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). 56011fa71b9SJerome Forissier * If it's -1, indicating that the entropy nonce length was not set 56111fa71b9SJerome Forissier * explicitly, use a sufficiently large nonce for security. */ 56211fa71b9SJerome Forissier nonce_len = (ctx->reseed_counter >= 0 ? 56311fa71b9SJerome Forissier (size_t) ctx->reseed_counter : 56411fa71b9SJerome Forissier good_nonce_len(ctx->entropy_len)); 56511fa71b9SJerome Forissier 56611fa71b9SJerome Forissier /* Initialize with an empty key. */ 567*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 56811fa71b9SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key, 56932b31808SJens Wiklander MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 57032b31808SJens Wiklander return ret; 5715b25c76aSJerome Forissier } 572*b0563631STom Van Eyck #else 573*b0563631STom Van Eyck psa_status_t status; 574*b0563631STom Van Eyck 575*b0563631STom Van Eyck status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE); 576*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 577*b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status); 578*b0563631STom Van Eyck return status; 579*b0563631STom Van Eyck } 580*b0563631STom Van Eyck #endif 5815b25c76aSJerome Forissier 58211fa71b9SJerome Forissier /* Do the initial seeding. */ 58311fa71b9SJerome Forissier if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len, 58432b31808SJens Wiklander nonce_len)) != 0) { 58532b31808SJens Wiklander return ret; 5865b25c76aSJerome Forissier } 58732b31808SJens Wiklander return 0; 5885b25c76aSJerome Forissier } 5895b25c76aSJerome Forissier 5903d3b0591SJens Wiklander /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) 5913d3b0591SJens Wiklander * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) 5923d3b0591SJens Wiklander * implements 5933d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) 5943d3b0591SJens Wiklander * -> working_state_after_reseed 5953d3b0591SJens Wiklander * if required, then 5963d3b0591SJens Wiklander * CTR_DRBG_Generate(working_state_after_reseed, 5973d3b0591SJens Wiklander * requested_number_of_bits, additional_input) 5983d3b0591SJens Wiklander * -> status, returned_bits, new_working_state 5993d3b0591SJens Wiklander * with inputs 6003d3b0591SJens Wiklander * ctx contains working_state 6013d3b0591SJens Wiklander * requested_number_of_bits = 8 * output_len 6023d3b0591SJens Wiklander * additional[:add_len] = additional_input 6033d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 6043d3b0591SJens Wiklander * and with outputs 6053d3b0591SJens Wiklander * status = SUCCESS (this function does the reseed internally) 6063d3b0591SJens Wiklander * returned_bits = output[:output_len] 6073d3b0591SJens Wiklander * ctx contains new_working_state 6083d3b0591SJens Wiklander */ 609817466cbSJens Wiklander int mbedtls_ctr_drbg_random_with_add(void *p_rng, 610817466cbSJens Wiklander unsigned char *output, size_t output_len, 611817466cbSJens Wiklander const unsigned char *additional, size_t add_len) 612817466cbSJens Wiklander { 613817466cbSJens Wiklander int ret = 0; 614817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 615817466cbSJens Wiklander unsigned char *p = output; 616*b0563631STom Van Eyck struct { 617*b0563631STom Van Eyck unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 618817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 619*b0563631STom Van Eyck } locals; 620817466cbSJens Wiklander size_t use_len; 621817466cbSJens Wiklander 62232b31808SJens Wiklander if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) { 62332b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG; 62432b31808SJens Wiklander } 625817466cbSJens Wiklander 62632b31808SJens Wiklander if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) { 62732b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 62832b31808SJens Wiklander } 629817466cbSJens Wiklander 630*b0563631STom Van Eyck memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN); 631817466cbSJens Wiklander 632817466cbSJens Wiklander if (ctx->reseed_counter > ctx->reseed_interval || 63332b31808SJens Wiklander ctx->prediction_resistance) { 63432b31808SJens Wiklander if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) { 63532b31808SJens Wiklander return ret; 6363d3b0591SJens Wiklander } 637817466cbSJens Wiklander add_len = 0; 638817466cbSJens Wiklander } 639817466cbSJens Wiklander 64032b31808SJens Wiklander if (add_len > 0) { 641*b0563631STom Van Eyck if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) { 6423d3b0591SJens Wiklander goto exit; 643817466cbSJens Wiklander } 644*b0563631STom Van Eyck if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { 64532b31808SJens Wiklander goto exit; 64632b31808SJens Wiklander } 64732b31808SJens Wiklander } 648817466cbSJens Wiklander 64932b31808SJens Wiklander while (output_len > 0) { 650817466cbSJens Wiklander /* 651*b0563631STom Van Eyck * Increase counter (treat it as a 128-bit big-endian integer). 652817466cbSJens Wiklander */ 653*b0563631STom Van Eyck mbedtls_ctr_increment_counter(ctx->counter); 654817466cbSJens Wiklander 655817466cbSJens Wiklander /* 656817466cbSJens Wiklander * Crypt counter block 657817466cbSJens Wiklander */ 658*b0563631STom Van Eyck #if defined(MBEDTLS_AES_C) 65911fa71b9SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 660*b0563631STom Van Eyck ctx->counter, locals.tmp)) != 0) { 6613d3b0591SJens Wiklander goto exit; 66211fa71b9SJerome Forissier } 663*b0563631STom Van Eyck #else 664*b0563631STom Van Eyck psa_status_t status; 665*b0563631STom Van Eyck size_t tmp_len; 666*b0563631STom Van Eyck 667*b0563631STom Van Eyck status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), 668*b0563631STom Van Eyck locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); 669*b0563631STom Van Eyck if (status != PSA_SUCCESS) { 670*b0563631STom Van Eyck ret = psa_generic_status_to_mbedtls(status); 671*b0563631STom Van Eyck goto exit; 672*b0563631STom Van Eyck } 673*b0563631STom Van Eyck #endif 674817466cbSJens Wiklander 67511fa71b9SJerome Forissier use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE) 67611fa71b9SJerome Forissier ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; 677817466cbSJens Wiklander /* 678817466cbSJens Wiklander * Copy random block to destination 679817466cbSJens Wiklander */ 680*b0563631STom Van Eyck memcpy(p, locals.tmp, use_len); 681817466cbSJens Wiklander p += use_len; 682817466cbSJens Wiklander output_len -= use_len; 683817466cbSJens Wiklander } 684817466cbSJens Wiklander 685*b0563631STom Van Eyck if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { 6863d3b0591SJens Wiklander goto exit; 68732b31808SJens Wiklander } 688817466cbSJens Wiklander 689817466cbSJens Wiklander ctx->reseed_counter++; 690817466cbSJens Wiklander 6913d3b0591SJens Wiklander exit: 692*b0563631STom Van Eyck mbedtls_platform_zeroize(&locals, sizeof(locals)); 69332b31808SJens Wiklander return ret; 694817466cbSJens Wiklander } 695817466cbSJens Wiklander 69611fa71b9SJerome Forissier int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, 69711fa71b9SJerome Forissier size_t output_len) 698817466cbSJens Wiklander { 69911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 700817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 701817466cbSJens Wiklander 702817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 70332b31808SJens Wiklander if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { 70432b31808SJens Wiklander return ret; 70532b31808SJens Wiklander } 706817466cbSJens Wiklander #endif 707817466cbSJens Wiklander 708817466cbSJens Wiklander ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0); 709817466cbSJens Wiklander 710817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 71132b31808SJens Wiklander if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { 71232b31808SJens Wiklander return MBEDTLS_ERR_THREADING_MUTEX_ERROR; 71332b31808SJens Wiklander } 714817466cbSJens Wiklander #endif 715817466cbSJens Wiklander 71632b31808SJens Wiklander return ret; 717817466cbSJens Wiklander } 718817466cbSJens Wiklander 719817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 72011fa71b9SJerome Forissier int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, 72111fa71b9SJerome Forissier const char *path) 722817466cbSJens Wiklander { 723817466cbSJens Wiklander int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 724817466cbSJens Wiklander FILE *f; 725817466cbSJens Wiklander unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; 726817466cbSJens Wiklander 72732b31808SJens Wiklander if ((f = fopen(path, "wb")) == NULL) { 72832b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 72932b31808SJens Wiklander } 73032b31808SJens Wiklander 73132b31808SJens Wiklander /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ 73232b31808SJens Wiklander mbedtls_setbuf(f, NULL); 733817466cbSJens Wiklander 73411fa71b9SJerome Forissier if ((ret = mbedtls_ctr_drbg_random(ctx, buf, 73532b31808SJens Wiklander MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) { 736817466cbSJens Wiklander goto exit; 73732b31808SJens Wiklander } 738817466cbSJens Wiklander 73911fa71b9SJerome Forissier if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) != 74032b31808SJens Wiklander MBEDTLS_CTR_DRBG_MAX_INPUT) { 741817466cbSJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 74232b31808SJens Wiklander } else { 743817466cbSJens Wiklander ret = 0; 74411fa71b9SJerome Forissier } 745817466cbSJens Wiklander 746817466cbSJens Wiklander exit: 7473d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, sizeof(buf)); 7483d3b0591SJens Wiklander 749817466cbSJens Wiklander fclose(f); 75032b31808SJens Wiklander return ret; 751817466cbSJens Wiklander } 752817466cbSJens Wiklander 75311fa71b9SJerome Forissier int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, 75411fa71b9SJerome Forissier const char *path) 755817466cbSJens Wiklander { 7563d3b0591SJens Wiklander int ret = 0; 7573d3b0591SJens Wiklander FILE *f = NULL; 758817466cbSJens Wiklander size_t n; 759817466cbSJens Wiklander unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; 7603d3b0591SJens Wiklander unsigned char c; 761817466cbSJens Wiklander 76232b31808SJens Wiklander if ((f = fopen(path, "rb")) == NULL) { 76332b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 76432b31808SJens Wiklander } 76532b31808SJens Wiklander 76632b31808SJens Wiklander /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ 76732b31808SJens Wiklander mbedtls_setbuf(f, NULL); 768817466cbSJens Wiklander 7693d3b0591SJens Wiklander n = fread(buf, 1, sizeof(buf), f); 77032b31808SJens Wiklander if (fread(&c, 1, 1, f) != 0) { 7713d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 7723d3b0591SJens Wiklander goto exit; 773817466cbSJens Wiklander } 77432b31808SJens Wiklander if (n == 0 || ferror(f)) { 7753d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 7763d3b0591SJens Wiklander goto exit; 777817466cbSJens Wiklander } 778817466cbSJens Wiklander fclose(f); 7793d3b0591SJens Wiklander f = NULL; 780817466cbSJens Wiklander 78132b31808SJens Wiklander ret = mbedtls_ctr_drbg_update(ctx, buf, n); 782817466cbSJens Wiklander 7833d3b0591SJens Wiklander exit: 7843d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, sizeof(buf)); 78532b31808SJens Wiklander if (f != NULL) { 7863d3b0591SJens Wiklander fclose(f); 78732b31808SJens Wiklander } 78832b31808SJens Wiklander if (ret != 0) { 78932b31808SJens Wiklander return ret; 79032b31808SJens Wiklander } 79132b31808SJens Wiklander return mbedtls_ctr_drbg_write_seed_file(ctx, path); 792817466cbSJens Wiklander } 793817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */ 794817466cbSJens Wiklander 795817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 796817466cbSJens Wiklander 7977901324dSJerome Forissier /* The CTR_DRBG NIST test vectors used here are available at 7987901324dSJerome Forissier * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip 7997901324dSJerome Forissier * 8007901324dSJerome Forissier * The parameters used to derive the test data are: 8017901324dSJerome Forissier * 8027901324dSJerome Forissier * [AES-128 use df] 8037901324dSJerome Forissier * [PredictionResistance = True/False] 8047901324dSJerome Forissier * [EntropyInputLen = 128] 8057901324dSJerome Forissier * [NonceLen = 64] 8067901324dSJerome Forissier * [PersonalizationStringLen = 128] 8077901324dSJerome Forissier * [AdditionalInputLen = 0] 8087901324dSJerome Forissier * [ReturnedBitsLen = 512] 8097901324dSJerome Forissier * 8107901324dSJerome Forissier * [AES-256 use df] 8117901324dSJerome Forissier * [PredictionResistance = True/False] 8127901324dSJerome Forissier * [EntropyInputLen = 256] 8137901324dSJerome Forissier * [NonceLen = 128] 8147901324dSJerome Forissier * [PersonalizationStringLen = 256] 8157901324dSJerome Forissier * [AdditionalInputLen = 0] 8167901324dSJerome Forissier * [ReturnedBitsLen = 512] 8177901324dSJerome Forissier * 8187901324dSJerome Forissier */ 819817466cbSJens Wiklander 82011fa71b9SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) 8217901324dSJerome Forissier static const unsigned char entropy_source_pr[] = 8227901324dSJerome Forissier { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, 8237901324dSJerome Forissier 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92, 8247901324dSJerome Forissier 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8, 8257901324dSJerome Forissier 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, 8267901324dSJerome Forissier 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0, 8277901324dSJerome Forissier 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad, 8287901324dSJerome Forissier 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 }; 82911fa71b9SJerome Forissier 8307901324dSJerome Forissier static const unsigned char entropy_source_nopr[] = 8317901324dSJerome Forissier { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, 8327901324dSJerome Forissier 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, 8337901324dSJerome Forissier 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20, 8347901324dSJerome Forissier 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f, 8357901324dSJerome Forissier 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c }; 8367901324dSJerome Forissier 8377901324dSJerome Forissier static const unsigned char pers_pr[] = 8387901324dSJerome Forissier { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a, 8397901324dSJerome Forissier 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad }; 8407901324dSJerome Forissier 8417901324dSJerome Forissier static const unsigned char pers_nopr[] = 8427901324dSJerome Forissier { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c, 8437901324dSJerome Forissier 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f }; 8447901324dSJerome Forissier 8457901324dSJerome Forissier static const unsigned char result_pr[] = 8467901324dSJerome Forissier { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, 8477901324dSJerome Forissier 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff, 8487901324dSJerome Forissier 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10, 8497901324dSJerome Forissier 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, 8507901324dSJerome Forissier 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, 8517901324dSJerome Forissier 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc, 8527901324dSJerome Forissier 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06, 8537901324dSJerome Forissier 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf }; 8547901324dSJerome Forissier 8557901324dSJerome Forissier static const unsigned char result_nopr[] = 8567901324dSJerome Forissier { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, 8577901324dSJerome Forissier 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0, 8587901324dSJerome Forissier 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf, 8597901324dSJerome Forissier 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, 8607901324dSJerome Forissier 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, 8617901324dSJerome Forissier 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2, 8627901324dSJerome Forissier 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02, 8637901324dSJerome Forissier 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 }; 86411fa71b9SJerome Forissier #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 865817466cbSJens Wiklander 8667901324dSJerome Forissier static const unsigned char entropy_source_pr[] = 8677901324dSJerome Forissier { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, 8687901324dSJerome Forissier 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a, 8697901324dSJerome Forissier 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85, 8707901324dSJerome Forissier 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, 8717901324dSJerome Forissier 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15, 8727901324dSJerome Forissier 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45, 8737901324dSJerome Forissier 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, 8747901324dSJerome Forissier 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c, 8757901324dSJerome Forissier 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3, 8767901324dSJerome Forissier 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, 8777901324dSJerome Forissier 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e, 8787901324dSJerome Forissier 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76, 8797901324dSJerome Forissier 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, 8807901324dSJerome Forissier 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe }; 8817901324dSJerome Forissier 8827901324dSJerome Forissier static const unsigned char entropy_source_nopr[] = 8837901324dSJerome Forissier { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, 8847901324dSJerome Forissier 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0, 8857901324dSJerome Forissier 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73, 8867901324dSJerome Forissier 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, 8877901324dSJerome Forissier 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2, 8887901324dSJerome Forissier 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1, 8897901324dSJerome Forissier 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, 8907901324dSJerome Forissier 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb, 8917901324dSJerome Forissier 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a, 8927901324dSJerome Forissier 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 }; 8937901324dSJerome Forissier 8947901324dSJerome Forissier static const unsigned char pers_pr[] = 8957901324dSJerome Forissier { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, 8967901324dSJerome Forissier 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e, 8977901324dSJerome Forissier 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0, 8987901324dSJerome Forissier 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 }; 8997901324dSJerome Forissier 9007901324dSJerome Forissier static const unsigned char pers_nopr[] = 9017901324dSJerome Forissier { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, 9027901324dSJerome Forissier 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf, 9037901324dSJerome Forissier 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb, 9047901324dSJerome Forissier 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b }; 9057901324dSJerome Forissier 9067901324dSJerome Forissier static const unsigned char result_pr[] = 9077901324dSJerome Forissier { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, 9087901324dSJerome Forissier 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d, 9097901324dSJerome Forissier 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62, 9107901324dSJerome Forissier 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, 9117901324dSJerome Forissier 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, 9127901324dSJerome Forissier 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39, 9137901324dSJerome Forissier 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40, 9147901324dSJerome Forissier 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 }; 9157901324dSJerome Forissier 9167901324dSJerome Forissier static const unsigned char result_nopr[] = 9177901324dSJerome Forissier { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, 9187901324dSJerome Forissier 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3, 9197901324dSJerome Forissier 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b, 9207901324dSJerome Forissier 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, 9217901324dSJerome Forissier 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, 9227901324dSJerome Forissier 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30, 9237901324dSJerome Forissier 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a, 9247901324dSJerome Forissier 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 }; 92511fa71b9SJerome Forissier #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 926817466cbSJens Wiklander 927817466cbSJens Wiklander static size_t test_offset; 928817466cbSJens Wiklander static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf, 929817466cbSJens Wiklander size_t len) 930817466cbSJens Wiklander { 931817466cbSJens Wiklander const unsigned char *p = data; 932817466cbSJens Wiklander memcpy(buf, p + test_offset, len); 933817466cbSJens Wiklander test_offset += len; 93432b31808SJens Wiklander return 0; 935817466cbSJens Wiklander } 936817466cbSJens Wiklander 937817466cbSJens Wiklander #define CHK(c) if ((c) != 0) \ 938817466cbSJens Wiklander { \ 939817466cbSJens Wiklander if (verbose != 0) \ 940817466cbSJens Wiklander mbedtls_printf("failed\n"); \ 94132b31808SJens Wiklander return 1; \ 942817466cbSJens Wiklander } 943817466cbSJens Wiklander 944039e02dfSJerome Forissier #define SELF_TEST_OUTPUT_DISCARD_LENGTH 64 9457901324dSJerome Forissier 946817466cbSJens Wiklander /* 947817466cbSJens Wiklander * Checkup routine 948817466cbSJens Wiklander */ 949817466cbSJens Wiklander int mbedtls_ctr_drbg_self_test(int verbose) 950817466cbSJens Wiklander { 951817466cbSJens Wiklander mbedtls_ctr_drbg_context ctx; 9527901324dSJerome Forissier unsigned char buf[sizeof(result_pr)]; 953817466cbSJens Wiklander 954817466cbSJens Wiklander mbedtls_ctr_drbg_init(&ctx); 955817466cbSJens Wiklander 956817466cbSJens Wiklander /* 957817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = True) 958817466cbSJens Wiklander */ 95932b31808SJens Wiklander if (verbose != 0) { 960817466cbSJens Wiklander mbedtls_printf(" CTR_DRBG (PR = TRUE) : "); 96132b31808SJens Wiklander } 962817466cbSJens Wiklander 963817466cbSJens Wiklander test_offset = 0; 9647901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); 9657901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); 9665b25c76aSJerome Forissier CHK(mbedtls_ctr_drbg_seed(&ctx, 9675b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 9685b25c76aSJerome Forissier (void *) entropy_source_pr, 9697901324dSJerome Forissier pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE)); 970817466cbSJens Wiklander mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON); 971039e02dfSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); 9727901324dSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr))); 9737901324dSJerome Forissier CHK(memcmp(buf, result_pr, sizeof(result_pr))); 974817466cbSJens Wiklander 975817466cbSJens Wiklander mbedtls_ctr_drbg_free(&ctx); 976817466cbSJens Wiklander 97732b31808SJens Wiklander if (verbose != 0) { 978817466cbSJens Wiklander mbedtls_printf("passed\n"); 97932b31808SJens Wiklander } 980817466cbSJens Wiklander 981817466cbSJens Wiklander /* 982817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = FALSE) 983817466cbSJens Wiklander */ 98432b31808SJens Wiklander if (verbose != 0) { 985817466cbSJens Wiklander mbedtls_printf(" CTR_DRBG (PR = FALSE): "); 98632b31808SJens Wiklander } 987817466cbSJens Wiklander 988817466cbSJens Wiklander mbedtls_ctr_drbg_init(&ctx); 989817466cbSJens Wiklander 990817466cbSJens Wiklander test_offset = 0; 9917901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); 9927901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); 9935b25c76aSJerome Forissier CHK(mbedtls_ctr_drbg_seed(&ctx, 9945b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 9955b25c76aSJerome Forissier (void *) entropy_source_nopr, 9967901324dSJerome Forissier pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE)); 997817466cbSJens Wiklander CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0)); 998039e02dfSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); 9997901324dSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr))); 10007901324dSJerome Forissier CHK(memcmp(buf, result_nopr, sizeof(result_nopr))); 1001817466cbSJens Wiklander 1002817466cbSJens Wiklander mbedtls_ctr_drbg_free(&ctx); 1003817466cbSJens Wiklander 100432b31808SJens Wiklander if (verbose != 0) { 1005817466cbSJens Wiklander mbedtls_printf("passed\n"); 100632b31808SJens Wiklander } 1007817466cbSJens Wiklander 100832b31808SJens Wiklander if (verbose != 0) { 1009817466cbSJens Wiklander mbedtls_printf("\n"); 101032b31808SJens Wiklander } 1011817466cbSJens Wiklander 101232b31808SJens Wiklander return 0; 1013817466cbSJens Wiklander } 1014817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 1015817466cbSJens Wiklander 1016817466cbSJens Wiklander #endif /* MBEDTLS_CTR_DRBG_C */ 1017