Path: blob/master/thirdparty/mbedtls/library/ctr_drbg.c
9903 views
/*1* CTR_DRBG implementation based on AES-256 (NIST SP 800-90)2*3* Copyright The Mbed TLS Contributors4* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later5*/6/*7* The NIST SP 800-90 DRBGs are described in the following publication.8*9* https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf10*/1112#include "common.h"1314#if defined(MBEDTLS_CTR_DRBG_C)1516#include "ctr.h"17#include "mbedtls/ctr_drbg.h"18#include "mbedtls/platform_util.h"19#include "mbedtls/error.h"2021#include <string.h>2223#if defined(MBEDTLS_FS_IO)24#include <stdio.h>25#endif2627/* Using error translation functions from PSA to MbedTLS */28#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)29#include "psa_util_internal.h"30#endif3132#include "mbedtls/platform.h"3334#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)35static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx,36unsigned char *key, size_t key_len)37{38psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;39psa_status_t status;4041psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);42psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);43psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);44status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id);45if (status != PSA_SUCCESS) {46goto exit;47}4849status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING);50if (status != PSA_SUCCESS) {51goto exit;52}5354exit:55psa_reset_key_attributes(&key_attr);56return status;57}5859static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx)60{61psa_cipher_abort(&psa_ctx->operation);62psa_destroy_key(psa_ctx->key_id);6364psa_ctx->operation = psa_cipher_operation_init();65psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT;66}67#endif6869/*70* CTR_DRBG context initialization71*/72void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)73{74memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));75#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)76ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;77ctx->psa_ctx.operation = psa_cipher_operation_init();78#else79mbedtls_aes_init(&ctx->aes_ctx);80#endif81/* Indicate that the entropy nonce length is not set explicitly.82* See mbedtls_ctr_drbg_set_nonce_len(). */83ctx->reseed_counter = -1;8485ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;86}8788/*89* This function resets CTR_DRBG context to the state immediately90* after initial call of mbedtls_ctr_drbg_init().91*/92void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)93{94if (ctx == NULL) {95return;96}9798#if defined(MBEDTLS_THREADING_C)99/* The mutex is initialized iff f_entropy is set. */100if (ctx->f_entropy != NULL) {101mbedtls_mutex_free(&ctx->mutex);102}103#endif104#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)105ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);106#else107mbedtls_aes_free(&ctx->aes_ctx);108#endif109mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));110ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;111ctx->reseed_counter = -1;112}113114void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,115int resistance)116{117ctx->prediction_resistance = resistance;118}119120void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,121size_t len)122{123ctx->entropy_len = len;124}125126int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,127size_t len)128{129/* If mbedtls_ctr_drbg_seed() has already been called, it's130* too late. Return the error code that's closest to making sense. */131if (ctx->f_entropy != NULL) {132return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;133}134135if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {136return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;137}138139/* This shouldn't be an issue because140* MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible141* configuration, but make sure anyway. */142if (len > INT_MAX) {143return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;144}145146/* For backward compatibility with Mbed TLS <= 2.19, store the147* entropy nonce length in a field that already exists, but isn't148* used until after the initial seeding. */149/* Due to the capping of len above, the value fits in an int. */150ctx->reseed_counter = (int) len;151return 0;152}153154void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,155int interval)156{157ctx->reseed_interval = interval;158}159160static int block_cipher_df(unsigned char *output,161const unsigned char *data, size_t data_len)162{163unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +164MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];165unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];166unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];167unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];168unsigned char *p, *iv;169int ret = 0;170#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)171psa_status_t status;172size_t tmp_len;173mbedtls_ctr_drbg_psa_context psa_ctx;174175psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;176psa_ctx.operation = psa_cipher_operation_init();177#else178mbedtls_aes_context aes_ctx;179#endif180181int i, j;182size_t buf_len, use_len;183184if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {185return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;186}187188memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +189MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);190191/*192* Construct IV (16 bytes) and S in buffer193* IV = Counter (in 32-bits) padded to 16 with zeroes194* S = Length input string (in 32-bits) || Length of output (in 32-bits) ||195* data || 0x80196* (Total is padded to a multiple of 16-bytes with zeroes)197*/198p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;199MBEDTLS_PUT_UINT32_BE(data_len, p, 0);200p += 4 + 3;201*p++ = MBEDTLS_CTR_DRBG_SEEDLEN;202memcpy(p, data, data_len);203p[data_len] = 0x80;204205buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;206207for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {208key[i] = i;209}210211#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)212status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));213if (status != PSA_SUCCESS) {214ret = psa_generic_status_to_mbedtls(status);215goto exit;216}217#else218mbedtls_aes_init(&aes_ctx);219220if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,221MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {222goto exit;223}224#endif225226/*227* Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data228*/229for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {230p = buf;231memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);232use_len = buf_len;233234while (use_len > 0) {235mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);236p += MBEDTLS_CTR_DRBG_BLOCKSIZE;237use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?238MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;239240#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)241status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE,242chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);243if (status != PSA_SUCCESS) {244ret = psa_generic_status_to_mbedtls(status);245goto exit;246}247#else248if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,249chain, chain)) != 0) {250goto exit;251}252#endif253}254255memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);256257/*258* Update IV259*/260buf[3]++;261}262263/*264* Do final encryption with reduced data265*/266#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)267ctr_drbg_destroy_psa_contex(&psa_ctx);268269status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);270if (status != PSA_SUCCESS) {271ret = psa_generic_status_to_mbedtls(status);272goto exit;273}274#else275if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,276MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {277goto exit;278}279#endif280iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;281p = output;282283for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {284#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)285status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE,286iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);287if (status != PSA_SUCCESS) {288ret = psa_generic_status_to_mbedtls(status);289goto exit;290}291#else292if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,293iv, iv)) != 0) {294goto exit;295}296#endif297memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);298p += MBEDTLS_CTR_DRBG_BLOCKSIZE;299}300exit:301#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)302ctr_drbg_destroy_psa_contex(&psa_ctx);303#else304mbedtls_aes_free(&aes_ctx);305#endif306/*307* tidy up the stack308*/309mbedtls_platform_zeroize(buf, sizeof(buf));310mbedtls_platform_zeroize(tmp, sizeof(tmp));311mbedtls_platform_zeroize(key, sizeof(key));312mbedtls_platform_zeroize(chain, sizeof(chain));313if (0 != ret) {314/*315* wipe partial seed from memory316*/317mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);318}319320return ret;321}322323/* CTR_DRBG_Update (SP 800-90A §10.2.1.2)324* ctr_drbg_update_internal(ctx, provided_data)325* implements326* CTR_DRBG_Update(provided_data, Key, V)327* with inputs and outputs328* ctx->aes_ctx = Key329* ctx->counter = V330*/331static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,332const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])333{334unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];335unsigned char *p = tmp;336int j;337int ret = 0;338#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)339psa_status_t status;340size_t tmp_len;341#endif342343memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);344345for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {346/*347* Increase counter348*/349mbedtls_ctr_increment_counter(ctx->counter);350351/*352* Crypt counter block353*/354#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)355status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),356p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);357if (status != PSA_SUCCESS) {358ret = psa_generic_status_to_mbedtls(status);359goto exit;360}361#else362if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,363ctx->counter, p)) != 0) {364goto exit;365}366#endif367368p += MBEDTLS_CTR_DRBG_BLOCKSIZE;369}370371mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN);372373/*374* Update key and counter375*/376#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)377ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);378379status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);380if (status != PSA_SUCCESS) {381ret = psa_generic_status_to_mbedtls(status);382goto exit;383}384#else385if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,386MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {387goto exit;388}389#endif390memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,391MBEDTLS_CTR_DRBG_BLOCKSIZE);392393exit:394mbedtls_platform_zeroize(tmp, sizeof(tmp));395return ret;396}397398/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)399* mbedtls_ctr_drbg_update(ctx, additional, add_len)400* implements401* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,402* security_strength) -> initial_working_state403* with inputs404* ctx->counter = all-bits-0405* ctx->aes_ctx = context from all-bits-0 key406* additional[:add_len] = entropy_input || nonce || personalization_string407* and with outputs408* ctx = initial_working_state409*/410int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,411const unsigned char *additional,412size_t add_len)413{414unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];415int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;416417if (add_len == 0) {418return 0;419}420421if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {422goto exit;423}424if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {425goto exit;426}427428exit:429mbedtls_platform_zeroize(add_input, sizeof(add_input));430return ret;431}432433/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)434* mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)435* implements436* CTR_DRBG_Reseed(working_state, entropy_input, additional_input)437* -> new_working_state438* with inputs439* ctx contains working_state440* additional[:len] = additional_input441* and entropy_input comes from calling ctx->f_entropy442* for (ctx->entropy_len + nonce_len) bytes443* and with output444* ctx contains new_working_state445*/446static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,447const unsigned char *additional,448size_t len,449size_t nonce_len)450{451unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];452size_t seedlen = 0;453int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;454455if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {456return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;457}458if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {459return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;460}461if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {462return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;463}464465memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);466467/* Gather entropy_len bytes of entropy to seed state. */468if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {469return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;470}471seedlen += ctx->entropy_len;472473/* Gather entropy for a nonce if requested. */474if (nonce_len != 0) {475if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {476return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;477}478seedlen += nonce_len;479}480481/* Add additional data if provided. */482if (additional != NULL && len != 0) {483memcpy(seed + seedlen, additional, len);484seedlen += len;485}486487/* Reduce to 384 bits. */488if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {489goto exit;490}491492/* Update state. */493if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {494goto exit;495}496ctx->reseed_counter = 1;497498exit:499mbedtls_platform_zeroize(seed, sizeof(seed));500return ret;501}502503int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,504const unsigned char *additional, size_t len)505{506return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);507}508509/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length510* is sufficient to achieve the maximum security strength given the key511* size and entropy length. If there is enough entropy in the initial512* call to the entropy function to serve as both the entropy input and513* the nonce, don't make a second call to get a nonce. */514static size_t good_nonce_len(size_t entropy_len)515{516if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {517return 0;518} else {519return (entropy_len + 1) / 2;520}521}522523/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)524* mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)525* implements526* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,527* security_strength) -> initial_working_state528* with inputs529* custom[:len] = nonce || personalization_string530* where entropy_input comes from f_entropy for ctx->entropy_len bytes531* and with outputs532* ctx = initial_working_state533*/534int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,535int (*f_entropy)(void *, unsigned char *, size_t),536void *p_entropy,537const unsigned char *custom,538size_t len)539{540int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;541unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];542size_t nonce_len;543544memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);545546/* The mutex is initialized iff f_entropy is set. */547#if defined(MBEDTLS_THREADING_C)548mbedtls_mutex_init(&ctx->mutex);549#endif550551ctx->f_entropy = f_entropy;552ctx->p_entropy = p_entropy;553554if (ctx->entropy_len == 0) {555ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;556}557/* ctx->reseed_counter contains the desired amount of entropy to558* grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).559* If it's -1, indicating that the entropy nonce length was not set560* explicitly, use a sufficiently large nonce for security. */561nonce_len = (ctx->reseed_counter >= 0 ?562(size_t) ctx->reseed_counter :563good_nonce_len(ctx->entropy_len));564565/* Initialize with an empty key. */566#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)567psa_status_t status;568569status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);570if (status != PSA_SUCCESS) {571ret = psa_generic_status_to_mbedtls(status);572return status;573}574#else575if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,576MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {577return ret;578}579#endif580581/* Do the initial seeding. */582if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,583nonce_len)) != 0) {584return ret;585}586return 0;587}588589/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)590* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)591* implements592* CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])593* -> working_state_after_reseed594* if required, then595* CTR_DRBG_Generate(working_state_after_reseed,596* requested_number_of_bits, additional_input)597* -> status, returned_bits, new_working_state598* with inputs599* ctx contains working_state600* requested_number_of_bits = 8 * output_len601* additional[:add_len] = additional_input602* and entropy_input comes from calling ctx->f_entropy603* and with outputs604* status = SUCCESS (this function does the reseed internally)605* returned_bits = output[:output_len]606* ctx contains new_working_state607*/608int mbedtls_ctr_drbg_random_with_add(void *p_rng,609unsigned char *output, size_t output_len,610const unsigned char *additional, size_t add_len)611{612int ret = 0;613mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;614unsigned char *p = output;615struct {616unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];617unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];618} locals;619size_t use_len;620621if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {622return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;623}624625if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {626return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;627}628629memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);630631if (ctx->reseed_counter > ctx->reseed_interval ||632ctx->prediction_resistance) {633if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {634return ret;635}636add_len = 0;637}638639if (add_len > 0) {640if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) {641goto exit;642}643if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {644goto exit;645}646}647648while (output_len > 0) {649/*650* Increase counter (treat it as a 128-bit big-endian integer).651*/652mbedtls_ctr_increment_counter(ctx->counter);653654/*655* Crypt counter block656*/657#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)658psa_status_t status;659size_t tmp_len;660661status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),662locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);663if (status != PSA_SUCCESS) {664ret = psa_generic_status_to_mbedtls(status);665goto exit;666}667#else668if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,669ctx->counter, locals.tmp)) != 0) {670goto exit;671}672#endif673674use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)675? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;676/*677* Copy random block to destination678*/679memcpy(p, locals.tmp, use_len);680p += use_len;681output_len -= use_len;682}683684if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {685goto exit;686}687688ctx->reseed_counter++;689690exit:691mbedtls_platform_zeroize(&locals, sizeof(locals));692return ret;693}694695int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,696size_t output_len)697{698int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;699mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;700701#if defined(MBEDTLS_THREADING_C)702if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {703return ret;704}705#endif706707ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);708709#if defined(MBEDTLS_THREADING_C)710if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {711return MBEDTLS_ERR_THREADING_MUTEX_ERROR;712}713#endif714715return ret;716}717718#if defined(MBEDTLS_FS_IO)719int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,720const char *path)721{722int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;723FILE *f;724unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];725726if ((f = fopen(path, "wb")) == NULL) {727return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;728}729730/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */731mbedtls_setbuf(f, NULL);732733if ((ret = mbedtls_ctr_drbg_random(ctx, buf,734MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {735goto exit;736}737738if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=739MBEDTLS_CTR_DRBG_MAX_INPUT) {740ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;741} else {742ret = 0;743}744745exit:746mbedtls_platform_zeroize(buf, sizeof(buf));747748fclose(f);749return ret;750}751752int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,753const char *path)754{755int ret = 0;756FILE *f = NULL;757size_t n;758unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];759unsigned char c;760761if ((f = fopen(path, "rb")) == NULL) {762return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;763}764765/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */766mbedtls_setbuf(f, NULL);767768n = fread(buf, 1, sizeof(buf), f);769if (fread(&c, 1, 1, f) != 0) {770ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;771goto exit;772}773if (n == 0 || ferror(f)) {774ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;775goto exit;776}777fclose(f);778f = NULL;779780ret = mbedtls_ctr_drbg_update(ctx, buf, n);781782exit:783mbedtls_platform_zeroize(buf, sizeof(buf));784if (f != NULL) {785fclose(f);786}787if (ret != 0) {788return ret;789}790return mbedtls_ctr_drbg_write_seed_file(ctx, path);791}792#endif /* MBEDTLS_FS_IO */793794#if defined(MBEDTLS_SELF_TEST)795796/* The CTR_DRBG NIST test vectors used here are available at797* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip798*799* The parameters used to derive the test data are:800*801* [AES-128 use df]802* [PredictionResistance = True/False]803* [EntropyInputLen = 128]804* [NonceLen = 64]805* [PersonalizationStringLen = 128]806* [AdditionalInputLen = 0]807* [ReturnedBitsLen = 512]808*809* [AES-256 use df]810* [PredictionResistance = True/False]811* [EntropyInputLen = 256]812* [NonceLen = 128]813* [PersonalizationStringLen = 256]814* [AdditionalInputLen = 0]815* [ReturnedBitsLen = 512]816*817*/818819#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)820static const unsigned char entropy_source_pr[] =821{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,8220xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,8230x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,8240x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,8250xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,8260xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,8270xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };828829static const unsigned char entropy_source_nopr[] =830{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,8310x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,8320x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,8330x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,8340x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };835836static const unsigned char pers_pr[] =837{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,8380x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };839840static const unsigned char pers_nopr[] =841{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,8420xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };843844static const unsigned char result_pr[] =845{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,8460x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,8470x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,8480x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,8490xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,8500x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,8510xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,8520x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };853854static const unsigned char result_nopr[] =855{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,8560x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,8570x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,8580xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,8590x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,8600xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,8610xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,8620x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };863#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */864865static const unsigned char entropy_source_pr[] =866{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,8670xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,8680x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,8690x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,8700xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,8710x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,8720x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,8730x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,8740xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,8750x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,8760xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,8770x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,8780x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,8790xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };880881static const unsigned char entropy_source_nopr[] =882{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,8830x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,8840x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,8850x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,8860x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,8870x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,8880xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,8890x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,8900x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,8910x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };892893static const unsigned char pers_pr[] =894{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,8950x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,8960xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,8970xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };898899static const unsigned char pers_nopr[] =900{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,9010x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,9020x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,9030xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };904905static const unsigned char result_pr[] =906{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,9070x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,9080x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,9090x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,9100xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,9110xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,9120xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,9130x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };914915static const unsigned char result_nopr[] =916{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,9170xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,9180xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,9190x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,9200x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,9210xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,9220x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,9230xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };924#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */925926static size_t test_offset;927static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,928size_t len)929{930const unsigned char *p = data;931memcpy(buf, p + test_offset, len);932test_offset += len;933return 0;934}935936#define CHK(c) if ((c) != 0) \937{ \938if (verbose != 0) \939mbedtls_printf("failed\n"); \940return 1; \941}942943#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64944945/*946* Checkup routine947*/948int mbedtls_ctr_drbg_self_test(int verbose)949{950mbedtls_ctr_drbg_context ctx;951unsigned char buf[sizeof(result_pr)];952953mbedtls_ctr_drbg_init(&ctx);954955/*956* Based on a NIST CTR_DRBG test vector (PR = True)957*/958if (verbose != 0) {959mbedtls_printf(" CTR_DRBG (PR = TRUE) : ");960}961962test_offset = 0;963mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);964mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);965CHK(mbedtls_ctr_drbg_seed(&ctx,966ctr_drbg_self_test_entropy,967(void *) entropy_source_pr,968pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));969mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);970CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));971CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));972CHK(memcmp(buf, result_pr, sizeof(result_pr)));973974mbedtls_ctr_drbg_free(&ctx);975976if (verbose != 0) {977mbedtls_printf("passed\n");978}979980/*981* Based on a NIST CTR_DRBG test vector (PR = FALSE)982*/983if (verbose != 0) {984mbedtls_printf(" CTR_DRBG (PR = FALSE): ");985}986987mbedtls_ctr_drbg_init(&ctx);988989test_offset = 0;990mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);991mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);992CHK(mbedtls_ctr_drbg_seed(&ctx,993ctr_drbg_self_test_entropy,994(void *) entropy_source_nopr,995pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));996CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));997CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));998CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));999CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));10001001mbedtls_ctr_drbg_free(&ctx);10021003if (verbose != 0) {1004mbedtls_printf("passed\n");1005}10061007if (verbose != 0) {1008mbedtls_printf("\n");1009}10101011return 0;1012}1013#endif /* MBEDTLS_SELF_TEST */10141015#endif /* MBEDTLS_CTR_DRBG_C */101610171018