Path: blob/main/crypto/openssl/providers/implementations/rands/drbg_ctr.c
48383 views
/*1* Copyright 2011-2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include <stdlib.h>10#include <string.h>11#include <openssl/crypto.h>12#include <openssl/err.h>13#include <openssl/rand.h>14#include <openssl/aes.h>15#include <openssl/proverr.h>16#include "crypto/modes.h"17#include "internal/thread_once.h"18#include "prov/implementations.h"19#include "prov/providercommon.h"20#include "prov/provider_ctx.h"21#include "drbg_local.h"22#include "crypto/evp.h"23#include "crypto/evp/evp_local.h"24#include "internal/provider.h"25#include "internal/common.h"2627static OSSL_FUNC_rand_newctx_fn drbg_ctr_new_wrapper;28static OSSL_FUNC_rand_freectx_fn drbg_ctr_free;29static OSSL_FUNC_rand_instantiate_fn drbg_ctr_instantiate_wrapper;30static OSSL_FUNC_rand_uninstantiate_fn drbg_ctr_uninstantiate_wrapper;31static OSSL_FUNC_rand_generate_fn drbg_ctr_generate_wrapper;32static OSSL_FUNC_rand_reseed_fn drbg_ctr_reseed_wrapper;33static OSSL_FUNC_rand_settable_ctx_params_fn drbg_ctr_settable_ctx_params;34static OSSL_FUNC_rand_set_ctx_params_fn drbg_ctr_set_ctx_params;35static OSSL_FUNC_rand_gettable_ctx_params_fn drbg_ctr_gettable_ctx_params;36static OSSL_FUNC_rand_get_ctx_params_fn drbg_ctr_get_ctx_params;37static OSSL_FUNC_rand_verify_zeroization_fn drbg_ctr_verify_zeroization;3839static int drbg_ctr_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[]);4041/*42* The state of a DRBG AES-CTR.43*/44typedef struct rand_drbg_ctr_st {45EVP_CIPHER_CTX *ctx_ecb;46EVP_CIPHER_CTX *ctx_ctr;47EVP_CIPHER_CTX *ctx_df;48EVP_CIPHER *cipher_ecb;49EVP_CIPHER *cipher_ctr;50size_t keylen;51int use_df;52unsigned char K[32];53unsigned char V[16];54/* Temporary block storage used by ctr_df */55unsigned char bltmp[16];56size_t bltmp_pos;57unsigned char KX[48];58} PROV_DRBG_CTR;5960/*61* Implementation of NIST SP 800-90A CTR DRBG.62*/63static void inc_128(PROV_DRBG_CTR *ctr)64{65unsigned char *p = &ctr->V[0];66u32 n = 16, c = 1;6768do {69--n;70c += p[n];71p[n] = (u8)c;72c >>= 8;73} while (n);74}7576static void ctr_XOR(PROV_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)77{78size_t i, n;7980if (in == NULL || inlen == 0)81return;8283/*84* Any zero padding will have no effect on the result as we85* are XORing. So just process however much input we have.86*/87n = inlen < ctr->keylen ? inlen : ctr->keylen;88if (!ossl_assert(n <= sizeof(ctr->K)))89return;90for (i = 0; i < n; i++)91ctr->K[i] ^= in[i];92if (inlen <= ctr->keylen)93return;9495n = inlen - ctr->keylen;96if (n > 16) {97/* Should never happen */98n = 16;99}100for (i = 0; i < n; i++)101ctr->V[i] ^= in[i + ctr->keylen];102}103104/*105* Process a complete block using BCC algorithm of SP 800-90A 10.3.3106*/107__owur static int ctr_BCC_block(PROV_DRBG_CTR *ctr, unsigned char *out,108const unsigned char *in, int len)109{110int i, outlen = AES_BLOCK_SIZE;111112for (i = 0; i < len; i++)113out[i] ^= in[i];114115if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, len)116|| outlen != len)117return 0;118return 1;119}120121122/*123* Handle several BCC operations for as much data as we need for K and X124*/125__owur static int ctr_BCC_blocks(PROV_DRBG_CTR *ctr, const unsigned char *in)126{127unsigned char in_tmp[48];128unsigned char num_of_blk = 2;129130memcpy(in_tmp, in, 16);131memcpy(in_tmp + 16, in, 16);132if (ctr->keylen != 16) {133memcpy(in_tmp + 32, in, 16);134num_of_blk = 3;135}136return ctr_BCC_block(ctr, ctr->KX, in_tmp, AES_BLOCK_SIZE * num_of_blk);137}138139/*140* Initialise BCC blocks: these have the value 0,1,2 in leftmost positions:141* see 10.3.1 stage 7.142*/143__owur static int ctr_BCC_init(PROV_DRBG_CTR *ctr)144{145unsigned char bltmp[48] = {0};146unsigned char num_of_blk;147148memset(ctr->KX, 0, 48);149num_of_blk = ctr->keylen == 16 ? 2 : 3;150bltmp[(AES_BLOCK_SIZE * 1) + 3] = 1;151bltmp[(AES_BLOCK_SIZE * 2) + 3] = 2;152return ctr_BCC_block(ctr, ctr->KX, bltmp, num_of_blk * AES_BLOCK_SIZE);153}154155/*156* Process several blocks into BCC algorithm, some possibly partial157*/158__owur static int ctr_BCC_update(PROV_DRBG_CTR *ctr,159const unsigned char *in, size_t inlen)160{161if (in == NULL || inlen == 0)162return 1;163164/* If we have partial block handle it first */165if (ctr->bltmp_pos) {166size_t left = 16 - ctr->bltmp_pos;167168/* If we now have a complete block process it */169if (inlen >= left) {170memcpy(ctr->bltmp + ctr->bltmp_pos, in, left);171if (!ctr_BCC_blocks(ctr, ctr->bltmp))172return 0;173ctr->bltmp_pos = 0;174inlen -= left;175in += left;176}177}178179/* Process zero or more complete blocks */180for (; inlen >= 16; in += 16, inlen -= 16) {181if (!ctr_BCC_blocks(ctr, in))182return 0;183}184185/* Copy any remaining partial block to the temporary buffer */186if (inlen > 0) {187memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen);188ctr->bltmp_pos += inlen;189}190return 1;191}192193__owur static int ctr_BCC_final(PROV_DRBG_CTR *ctr)194{195if (ctr->bltmp_pos) {196memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);197if (!ctr_BCC_blocks(ctr, ctr->bltmp))198return 0;199}200return 1;201}202203__owur static int ctr_df(PROV_DRBG_CTR *ctr,204const unsigned char *in1, size_t in1len,205const unsigned char *in2, size_t in2len,206const unsigned char *in3, size_t in3len)207{208static unsigned char c80 = 0x80;209size_t inlen;210unsigned char *p = ctr->bltmp;211int outlen = AES_BLOCK_SIZE;212213if (!ctr_BCC_init(ctr))214return 0;215if (in1 == NULL)216in1len = 0;217if (in2 == NULL)218in2len = 0;219if (in3 == NULL)220in3len = 0;221inlen = in1len + in2len + in3len;222/* Initialise L||N in temporary block */223*p++ = (inlen >> 24) & 0xff;224*p++ = (inlen >> 16) & 0xff;225*p++ = (inlen >> 8) & 0xff;226*p++ = inlen & 0xff;227228/* NB keylen is at most 32 bytes */229*p++ = 0;230*p++ = 0;231*p++ = 0;232*p = (unsigned char)((ctr->keylen + 16) & 0xff);233ctr->bltmp_pos = 8;234if (!ctr_BCC_update(ctr, in1, in1len)235|| !ctr_BCC_update(ctr, in2, in2len)236|| !ctr_BCC_update(ctr, in3, in3len)237|| !ctr_BCC_update(ctr, &c80, 1)238|| !ctr_BCC_final(ctr))239return 0;240/* Set up key K */241if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->KX, NULL, -1))242return 0;243/* X follows key K */244if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX, &outlen, ctr->KX + ctr->keylen,245AES_BLOCK_SIZE)246|| outlen != AES_BLOCK_SIZE)247return 0;248if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 16, &outlen, ctr->KX,249AES_BLOCK_SIZE)250|| outlen != AES_BLOCK_SIZE)251return 0;252if (ctr->keylen != 16)253if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 32, &outlen,254ctr->KX + 16, AES_BLOCK_SIZE)255|| outlen != AES_BLOCK_SIZE)256return 0;257return 1;258}259260/*261* NB the no-df Update in SP800-90A specifies a constant input length262* of seedlen, however other uses of this algorithm pad the input with263* zeroes if necessary and have up to two parameters XORed together,264* so we handle both cases in this function instead.265*/266__owur static int ctr_update(PROV_DRBG *drbg,267const unsigned char *in1, size_t in1len,268const unsigned char *in2, size_t in2len,269const unsigned char *nonce, size_t noncelen)270{271PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;272int outlen = AES_BLOCK_SIZE;273unsigned char V_tmp[48], out[48];274unsigned char len;275276/* correct key is already set up. */277memcpy(V_tmp, ctr->V, 16);278inc_128(ctr);279memcpy(V_tmp + 16, ctr->V, 16);280if (ctr->keylen == 16) {281len = 32;282} else {283inc_128(ctr);284memcpy(V_tmp + 32, ctr->V, 16);285len = 48;286}287if (!EVP_CipherUpdate(ctr->ctx_ecb, out, &outlen, V_tmp, len)288|| outlen != len)289return 0;290memcpy(ctr->K, out, ctr->keylen);291memcpy(ctr->V, out + ctr->keylen, 16);292293if (ctr->use_df) {294/* If no input reuse existing derived value */295if (in1 != NULL || nonce != NULL || in2 != NULL)296if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))297return 0;298/* If this a reuse input in1len != 0 */299if (in1len)300ctr_XOR(ctr, ctr->KX, drbg->seedlen);301} else {302ctr_XOR(ctr, in1, in1len);303ctr_XOR(ctr, in2, in2len);304}305306if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1)307|| !EVP_CipherInit_ex(ctr->ctx_ctr, NULL, NULL, ctr->K, NULL, -1))308return 0;309return 1;310}311312static int drbg_ctr_instantiate(PROV_DRBG *drbg,313const unsigned char *entropy, size_t entropylen,314const unsigned char *nonce, size_t noncelen,315const unsigned char *pers, size_t perslen)316{317PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;318319if (entropy == NULL)320return 0;321322memset(ctr->K, 0, sizeof(ctr->K));323memset(ctr->V, 0, sizeof(ctr->V));324if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1))325return 0;326327inc_128(ctr);328if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen))329return 0;330return 1;331}332333static int drbg_ctr_instantiate_wrapper(void *vdrbg, unsigned int strength,334int prediction_resistance,335const unsigned char *pstr,336size_t pstr_len,337const OSSL_PARAM params[])338{339PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;340int ret = 0;341342if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))343return 0;344345if (!ossl_prov_is_running()346|| !drbg_ctr_set_ctx_params_locked(drbg, params))347goto err;348ret = ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,349pstr, pstr_len);350err:351if (drbg->lock != NULL)352CRYPTO_THREAD_unlock(drbg->lock);353return ret;354}355356static int drbg_ctr_reseed(PROV_DRBG *drbg,357const unsigned char *entropy, size_t entropylen,358const unsigned char *adin, size_t adinlen)359{360PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;361362if (entropy == NULL)363return 0;364365inc_128(ctr);366if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0))367return 0;368return 1;369}370371static int drbg_ctr_reseed_wrapper(void *vdrbg, int prediction_resistance,372const unsigned char *ent, size_t ent_len,373const unsigned char *adin, size_t adin_len)374{375PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;376377return ossl_prov_drbg_reseed(drbg, prediction_resistance, ent, ent_len,378adin, adin_len);379}380381static void ctr96_inc(unsigned char *counter)382{383u32 n = 12, c = 1;384385do {386--n;387c += counter[n];388counter[n] = (u8)c;389c >>= 8;390} while (n);391}392393static int drbg_ctr_generate(PROV_DRBG *drbg,394unsigned char *out, size_t outlen,395const unsigned char *adin, size_t adinlen)396{397PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;398unsigned int ctr32, blocks;399int outl, buflen;400401if (adin != NULL && adinlen != 0) {402inc_128(ctr);403404if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))405return 0;406/* This means we reuse derived value */407if (ctr->use_df) {408adin = NULL;409adinlen = 1;410}411} else {412adinlen = 0;413}414415inc_128(ctr);416417if (outlen == 0) {418inc_128(ctr);419420if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))421return 0;422return 1;423}424425memset(out, 0, outlen);426427do {428if (!EVP_CipherInit_ex(ctr->ctx_ctr,429NULL, NULL, NULL, ctr->V, -1))430return 0;431432/*-433* outlen has type size_t while EVP_CipherUpdate takes an434* int argument and thus cannot be guaranteed to process more435* than 2^31-1 bytes at a time. We process such huge generate436* requests in 2^30 byte chunks, which is the greatest multiple437* of AES block size lower than or equal to 2^31-1.438*/439buflen = outlen > (1U << 30) ? (1U << 30) : outlen;440blocks = (buflen + 15) / 16;441442ctr32 = GETU32(ctr->V + 12) + blocks;443if (ctr32 < blocks) {444/* 32-bit counter overflow into V. */445if (ctr32 != 0) {446blocks -= ctr32;447buflen = blocks * 16;448ctr32 = 0;449}450ctr96_inc(ctr->V);451}452PUTU32(ctr->V + 12, ctr32);453454if (!EVP_CipherUpdate(ctr->ctx_ctr, out, &outl, out, buflen)455|| outl != buflen)456return 0;457458out += buflen;459outlen -= buflen;460} while (outlen);461462if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))463return 0;464return 1;465}466467static int drbg_ctr_generate_wrapper468(void *vdrbg, unsigned char *out, size_t outlen,469unsigned int strength, int prediction_resistance,470const unsigned char *adin, size_t adin_len)471{472PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;473474return ossl_prov_drbg_generate(drbg, out, outlen, strength,475prediction_resistance, adin, adin_len);476}477478static int drbg_ctr_uninstantiate(PROV_DRBG *drbg)479{480PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;481482OPENSSL_cleanse(ctr->K, sizeof(ctr->K));483OPENSSL_cleanse(ctr->V, sizeof(ctr->V));484OPENSSL_cleanse(ctr->bltmp, sizeof(ctr->bltmp));485OPENSSL_cleanse(ctr->KX, sizeof(ctr->KX));486ctr->bltmp_pos = 0;487return ossl_prov_drbg_uninstantiate(drbg);488}489490static int drbg_ctr_uninstantiate_wrapper(void *vdrbg)491{492PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;493int ret;494495if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))496return 0;497498ret = drbg_ctr_uninstantiate(drbg);499500if (drbg->lock != NULL)501CRYPTO_THREAD_unlock(drbg->lock);502503return ret;504}505506static int drbg_ctr_verify_zeroization(void *vdrbg)507{508PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;509PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;510int ret = 0;511512if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))513return 0;514515PROV_DRBG_VERIFY_ZEROIZATION(ctr->K);516PROV_DRBG_VERIFY_ZEROIZATION(ctr->V);517PROV_DRBG_VERIFY_ZEROIZATION(ctr->bltmp);518PROV_DRBG_VERIFY_ZEROIZATION(ctr->KX);519if (ctr->bltmp_pos != 0)520goto err;521522ret = 1;523err:524if (drbg->lock != NULL)525CRYPTO_THREAD_unlock(drbg->lock);526return ret;527}528529static int drbg_ctr_init_lengths(PROV_DRBG *drbg)530{531PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;532int res = 1;533534/* Maximum number of bits per request = 2^19 = 2^16 bytes */535drbg->max_request = 1 << 16;536if (ctr->use_df) {537drbg->min_entropylen = 0;538drbg->max_entropylen = DRBG_MAX_LENGTH;539drbg->min_noncelen = 0;540drbg->max_noncelen = DRBG_MAX_LENGTH;541drbg->max_perslen = DRBG_MAX_LENGTH;542drbg->max_adinlen = DRBG_MAX_LENGTH;543544if (ctr->keylen > 0) {545drbg->min_entropylen = ctr->keylen;546drbg->min_noncelen = drbg->min_entropylen / 2;547}548} else {549const size_t len = ctr->keylen > 0 ? drbg->seedlen : DRBG_MAX_LENGTH;550551drbg->min_entropylen = len;552drbg->max_entropylen = len;553/* Nonce not used */554drbg->min_noncelen = 0;555drbg->max_noncelen = 0;556drbg->max_perslen = len;557drbg->max_adinlen = len;558}559return res;560}561562static int drbg_ctr_init(PROV_DRBG *drbg)563{564PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;565size_t keylen;566567if (ctr->cipher_ctr == NULL) {568ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER);569return 0;570}571ctr->keylen = keylen = EVP_CIPHER_get_key_length(ctr->cipher_ctr);572if (ctr->ctx_ecb == NULL)573ctr->ctx_ecb = EVP_CIPHER_CTX_new();574if (ctr->ctx_ctr == NULL)575ctr->ctx_ctr = EVP_CIPHER_CTX_new();576if (ctr->ctx_ecb == NULL || ctr->ctx_ctr == NULL) {577ERR_raise(ERR_LIB_PROV, ERR_R_EVP_LIB);578goto err;579}580581if (!EVP_CipherInit_ex(ctr->ctx_ecb,582ctr->cipher_ecb, NULL, NULL, NULL, 1)583|| !EVP_CipherInit_ex(ctr->ctx_ctr,584ctr->cipher_ctr, NULL, NULL, NULL, 1)) {585ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_INITIALISE_CIPHERS);586goto err;587}588589drbg->strength = keylen * 8;590drbg->seedlen = keylen + 16;591592if (ctr->use_df) {593/* df initialisation */594static const unsigned char df_key[32] = {5950x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,5960x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,5970x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,5980x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f599};600601if (ctr->ctx_df == NULL)602ctr->ctx_df = EVP_CIPHER_CTX_new();603if (ctr->ctx_df == NULL) {604ERR_raise(ERR_LIB_PROV, ERR_R_EVP_LIB);605goto err;606}607/* Set key schedule for df_key */608if (!EVP_CipherInit_ex(ctr->ctx_df,609ctr->cipher_ecb, NULL, df_key, NULL, 1)) {610ERR_raise(ERR_LIB_PROV, PROV_R_DERIVATION_FUNCTION_INIT_FAILED);611goto err;612}613}614return drbg_ctr_init_lengths(drbg);615616err:617EVP_CIPHER_CTX_free(ctr->ctx_ecb);618EVP_CIPHER_CTX_free(ctr->ctx_ctr);619ctr->ctx_ecb = ctr->ctx_ctr = NULL;620return 0;621}622623static int drbg_ctr_new(PROV_DRBG *drbg)624{625PROV_DRBG_CTR *ctr;626627ctr = OPENSSL_secure_zalloc(sizeof(*ctr));628if (ctr == NULL)629return 0;630631ctr->use_df = 1;632drbg->data = ctr;633OSSL_FIPS_IND_INIT(drbg)634return drbg_ctr_init_lengths(drbg);635}636637static void *drbg_ctr_new_wrapper(void *provctx, void *parent,638const OSSL_DISPATCH *parent_dispatch)639{640return ossl_rand_drbg_new(provctx, parent, parent_dispatch,641&drbg_ctr_new, &drbg_ctr_free,642&drbg_ctr_instantiate, &drbg_ctr_uninstantiate,643&drbg_ctr_reseed, &drbg_ctr_generate);644}645646static void drbg_ctr_free(void *vdrbg)647{648PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;649PROV_DRBG_CTR *ctr;650651if (drbg != NULL && (ctr = (PROV_DRBG_CTR *)drbg->data) != NULL) {652EVP_CIPHER_CTX_free(ctr->ctx_ecb);653EVP_CIPHER_CTX_free(ctr->ctx_ctr);654EVP_CIPHER_CTX_free(ctr->ctx_df);655EVP_CIPHER_free(ctr->cipher_ecb);656EVP_CIPHER_free(ctr->cipher_ctr);657658OPENSSL_secure_clear_free(ctr, sizeof(*ctr));659}660ossl_rand_drbg_free(drbg);661}662663static int drbg_ctr_get_ctx_params(void *vdrbg, OSSL_PARAM params[])664{665PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;666PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;667OSSL_PARAM *p;668int ret = 0, complete = 0;669670if (!ossl_drbg_get_ctx_params_no_lock(drbg, params, &complete))671return 0;672673if (complete)674return 1;675676if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))677return 0;678679p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_USE_DF);680if (p != NULL && !OSSL_PARAM_set_int(p, ctr->use_df))681goto err;682683p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_CIPHER);684if (p != NULL) {685if (ctr->cipher_ctr == NULL686|| !OSSL_PARAM_set_utf8_string(p,687EVP_CIPHER_get0_name(ctr->cipher_ctr)))688goto err;689}690691ret = ossl_drbg_get_ctx_params(drbg, params);692err:693if (drbg->lock != NULL)694CRYPTO_THREAD_unlock(drbg->lock);695696return ret;697}698699static const OSSL_PARAM *drbg_ctr_gettable_ctx_params(ossl_unused void *vctx,700ossl_unused void *provctx)701{702static const OSSL_PARAM known_gettable_ctx_params[] = {703OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0),704OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),705OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON,706OSSL_FIPS_IND_GETTABLE_CTX_PARAM()707OSSL_PARAM_END708};709return known_gettable_ctx_params;710}711712static int drbg_ctr_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[])713{714PROV_DRBG *ctx = (PROV_DRBG *)vctx;715PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)ctx->data;716OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);717OSSL_PROVIDER *prov = NULL;718const OSSL_PARAM *p;719char *ecb;720const char *propquery = NULL;721int i, cipher_init = 0;722723if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_USE_DF)) != NULL724&& OSSL_PARAM_get_int(p, &i)) {725/* FIPS errors out in the drbg_ctr_init() call later */726ctr->use_df = i != 0;727cipher_init = 1;728}729730if ((p = OSSL_PARAM_locate_const(params,731OSSL_DRBG_PARAM_PROPERTIES)) != NULL) {732if (p->data_type != OSSL_PARAM_UTF8_STRING)733return 0;734propquery = (const char *)p->data;735}736737if ((p = OSSL_PARAM_locate_const(params,738OSSL_PROV_PARAM_CORE_PROV_NAME)) != NULL) {739if (p->data_type != OSSL_PARAM_UTF8_STRING)740return 0;741if ((prov = ossl_provider_find(libctx,742(const char *)p->data, 1)) == NULL)743return 0;744}745746if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_CIPHER)) != NULL) {747const char *base = (const char *)p->data;748size_t ctr_str_len = sizeof("CTR") - 1;749size_t ecb_str_len = sizeof("ECB") - 1;750751if (p->data_type != OSSL_PARAM_UTF8_STRING752|| p->data_size < ctr_str_len) {753ossl_provider_free(prov);754return 0;755}756if (OPENSSL_strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) {757ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER);758ossl_provider_free(prov);759return 0;760}761if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL) {762ossl_provider_free(prov);763return 0;764}765strcpy(ecb + p->data_size - ecb_str_len, "ECB");766EVP_CIPHER_free(ctr->cipher_ecb);767EVP_CIPHER_free(ctr->cipher_ctr);768/*769* Try to fetch algorithms from our own provider code, fallback770* to generic fetch only if that fails771*/772(void)ERR_set_mark();773ctr->cipher_ctr = evp_cipher_fetch_from_prov(prov, base, NULL);774if (ctr->cipher_ctr == NULL) {775(void)ERR_pop_to_mark();776ctr->cipher_ctr = EVP_CIPHER_fetch(libctx, base, propquery);777} else {778(void)ERR_clear_last_mark();779}780(void)ERR_set_mark();781ctr->cipher_ecb = evp_cipher_fetch_from_prov(prov, ecb, NULL);782if (ctr->cipher_ecb == NULL) {783(void)ERR_pop_to_mark();784ctr->cipher_ecb = EVP_CIPHER_fetch(libctx, ecb, propquery);785} else {786(void)ERR_clear_last_mark();787}788OPENSSL_free(ecb);789if (ctr->cipher_ctr == NULL || ctr->cipher_ecb == NULL) {790ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_FIND_CIPHERS);791ossl_provider_free(prov);792return 0;793}794cipher_init = 1;795}796ossl_provider_free(prov);797798if (cipher_init && !drbg_ctr_init(ctx))799return 0;800801return ossl_drbg_set_ctx_params(ctx, params);802}803804static int drbg_ctr_set_ctx_params(void *vctx, const OSSL_PARAM params[])805{806PROV_DRBG *drbg = (PROV_DRBG *)vctx;807int ret;808809if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))810return 0;811812ret = drbg_ctr_set_ctx_params_locked(vctx, params);813814if (drbg->lock != NULL)815CRYPTO_THREAD_unlock(drbg->lock);816817return ret;818}819820static const OSSL_PARAM *drbg_ctr_settable_ctx_params(ossl_unused void *vctx,821ossl_unused void *provctx)822{823static const OSSL_PARAM known_settable_ctx_params[] = {824OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),825OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0),826OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),827OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON,828OSSL_PARAM_END829};830return known_settable_ctx_params;831}832833const OSSL_DISPATCH ossl_drbg_ctr_functions[] = {834{ OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_ctr_new_wrapper },835{ OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_ctr_free },836{ OSSL_FUNC_RAND_INSTANTIATE,837(void(*)(void))drbg_ctr_instantiate_wrapper },838{ OSSL_FUNC_RAND_UNINSTANTIATE,839(void(*)(void))drbg_ctr_uninstantiate_wrapper },840{ OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_ctr_generate_wrapper },841{ OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_ctr_reseed_wrapper },842{ OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))ossl_drbg_enable_locking },843{ OSSL_FUNC_RAND_LOCK, (void(*)(void))ossl_drbg_lock },844{ OSSL_FUNC_RAND_UNLOCK, (void(*)(void))ossl_drbg_unlock },845{ OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,846(void(*)(void))drbg_ctr_settable_ctx_params },847{ OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_ctr_set_ctx_params },848{ OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,849(void(*)(void))drbg_ctr_gettable_ctx_params },850{ OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_ctr_get_ctx_params },851{ OSSL_FUNC_RAND_VERIFY_ZEROIZATION,852(void(*)(void))drbg_ctr_verify_zeroization },853{ OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },854{ OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },855OSSL_DISPATCH_END856};857858859