CTR, HASH and HMAC DRBGs in provider

Move the three different DRBGs to the provider.

As part of the move, the DRBG specific data was pulled out of a common
structure and into their own structures.  Only these smaller structures are
securely allocated.  This saves quite a bit of secure memory:

    +-------------------------------+
    | DRBG         | Bytes | Secure |
    +--------------+-------+--------+
    | HASH         |  376  |   512  |
    | HMAC         |  168  |   256  |
    | CTR          |  176  |   256  |
    | Common (new) |  320  |     0  |
    | Common (old) |  592  |  1024  |
    +--------------+-------+--------+

Bytes is the structure size on the X86/64.
Secure is the number of bytes of secure memory used (power of two allocator).

Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from https://github.com/openssl/openssl/pull/11682)
This commit is contained in:
Pauli 2020-05-08 10:25:19 +10:00
parent a998b85a4f
commit f000e82898
24 changed files with 1968 additions and 1995 deletions

View File

@ -2,7 +2,7 @@ LIBS=../../libcrypto
$COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c \
mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c \
m_sigver.c pmeth_lib.c signature.c p_lib.c pmeth_gn.c exchange.c \
pmeth_check.c rand_meth.c
pmeth_check.c evp_rand.c
SOURCE[../../libcrypto]=$COMMON\
encode.c evp_key.c evp_cnf.c \

View File

@ -69,16 +69,18 @@ struct evp_kdf_ctx_st {
struct evp_rand_ctx_st {
EVP_RAND *meth; /* Method structure */
void *data; /* Algorithm-specific data */
EVP_RAND_CTX *parent; /* Parent seed source */
size_t max_request; /* Cached: maximum number of bytes generated */
unsigned int strength; /* Cache: bit strenght of generator */
size_t max_request; /*
* Cached: maximum number of bytes generated
* in a single call to the generate function
*/
unsigned int strength; /* Cached: bit strength of generator */
} /* EVP_RAND_CTX */ ;
struct evp_rand_st {
OSSL_PROVIDER *prov;
int name_id;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
CRYPTO_RWLOCK *refcnt_lock;
const OSSL_DISPATCH *dispatch;
OSSL_OP_rand_newctx_fn *newctx;
@ -88,16 +90,16 @@ struct evp_rand_st {
OSSL_OP_rand_generate_fn *generate;
OSSL_OP_rand_reseed_fn *reseed;
OSSL_OP_rand_nonce_fn *nonce;
OSSL_OP_rand_set_callbacks_fn *set_callbacks;
OSSL_OP_rand_enable_locking_fn *enable_prov_locking;
OSSL_OP_rand_lock_fn *prov_lock;
OSSL_OP_rand_unlock_fn *prov_unlock;
OSSL_OP_rand_enable_locking_fn *enable_locking;
OSSL_OP_rand_lock_fn *lock;
OSSL_OP_rand_unlock_fn *unlock;
OSSL_OP_rand_gettable_params_fn *gettable_params;
OSSL_OP_rand_gettable_ctx_params_fn *gettable_ctx_params;
OSSL_OP_rand_settable_ctx_params_fn *settable_ctx_params;
OSSL_OP_rand_get_params_fn *get_params;
OSSL_OP_rand_get_ctx_params_fn *get_ctx_params;
OSSL_OP_rand_set_ctx_params_fn *set_ctx_params;
OSSL_OP_rand_set_callbacks_fn *set_callbacks;
OSSL_OP_rand_verify_zeroization_fn *verify_zeroization;
} /* EVP_RAND */ ;

View File

@ -11,7 +11,6 @@
#include <stdio.h>
#include <stdlib.h>
#include "internal/cryptlib.h"
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
@ -21,6 +20,7 @@
#include <openssl/crypto.h>
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "internal/cryptlib.h"
#include "internal/numbers.h"
#include "internal/provider.h"
#include "evp_local.h"
@ -31,7 +31,7 @@ static int evp_rand_up_ref(void *vrand)
int ref = 0;
if (rand != NULL)
return CRYPTO_UP_REF(&rand->refcnt, &ref, rand->lock);
return CRYPTO_UP_REF(&rand->refcnt, &ref, rand->refcnt_lock);
return 1;
}
@ -40,10 +40,10 @@ static void evp_rand_free(void *vrand){
int ref = 0;
if (rand != NULL) {
CRYPTO_DOWN_REF(&rand->refcnt, &ref, rand->lock);
CRYPTO_DOWN_REF(&rand->refcnt, &ref, rand->refcnt_lock);
if (ref <= 0) {
ossl_provider_free(rand->prov);
CRYPTO_THREAD_lock_free(rand->lock);
CRYPTO_THREAD_lock_free(rand->refcnt_lock);
OPENSSL_free(rand);
}
}
@ -51,11 +51,11 @@ static void evp_rand_free(void *vrand){
static void *evp_rand_new(void)
{
EVP_RAND *rand = NULL;
EVP_RAND *rand = OPENSSL_zalloc(sizeof(*rand));
if ((rand = OPENSSL_zalloc(sizeof(*rand))) == NULL
|| (rand->lock = CRYPTO_THREAD_lock_new()) == NULL) {
evp_rand_free(rand);
if (rand == NULL
|| (rand->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL) {
OPENSSL_free(rand);
return NULL;
}
rand->refcnt = 1;
@ -63,26 +63,27 @@ static void *evp_rand_new(void)
}
/* Enable locking of the underlying DRBG/RAND if available */
int EVP_RAND_CTX_enable_locking(EVP_RAND_CTX *rand)
int EVP_RAND_enable_locking(EVP_RAND_CTX *rand)
{
if (rand->meth->enable_prov_locking != NULL)
return rand->meth->enable_prov_locking(rand->data);
return 1;
if (rand->meth->enable_locking != NULL)
return rand->meth->enable_locking(rand->data);
EVPerr(0, EVP_R_LOCKING_NOT_SUPPORTED);
return 0;
}
/* Lock the underlying DRBG/RAND if available */
static int evp_rand_lock(EVP_RAND_CTX *rand)
{
if (rand->meth->prov_lock != NULL)
return rand->meth->prov_lock(rand->data);
if (rand->meth->lock != NULL)
return rand->meth->lock(rand->data);
return 1;
}
/* Unlock the underlying DRBG/RAND if available */
static void evp_rand_unlock(EVP_RAND_CTX *rand)
{
if (rand->meth->prov_unlock != NULL)
rand->meth->prov_unlock(rand->data);
if (rand->meth->unlock != NULL)
rand->meth->unlock(rand->data);
}
static void *evp_rand_from_dispatch(int name_id,
@ -90,9 +91,9 @@ static void *evp_rand_from_dispatch(int name_id,
OSSL_PROVIDER *prov)
{
EVP_RAND *rand = NULL;
int fnrandcnt = 0, fnctxcnt = 0;
int fnrandcnt = 0, fnctxcnt = 0, fnlockcnt = 0;
#ifdef FIPS_MODULE
int fnfipscnt = 0;
int fnzeroizecnt = 0;
#endif
if ((rand = evp_rand_new()) == NULL) {
@ -149,19 +150,22 @@ static void *evp_rand_from_dispatch(int name_id,
rand->set_callbacks = OSSL_get_OP_rand_set_callbacks(fns);
break;
case OSSL_FUNC_RAND_ENABLE_LOCKING:
if (rand->enable_prov_locking != NULL)
if (rand->enable_locking != NULL)
break;
rand->enable_prov_locking = OSSL_get_OP_rand_enable_locking(fns);
rand->enable_locking = OSSL_get_OP_rand_enable_locking(fns);
fnlockcnt++;
break;
case OSSL_FUNC_RAND_LOCK:
if (rand->prov_lock != NULL)
if (rand->lock != NULL)
break;
rand->prov_lock = OSSL_get_OP_rand_lock(fns);
rand->lock = OSSL_get_OP_rand_lock(fns);
fnlockcnt++;
break;
case OSSL_FUNC_RAND_UNLOCK:
if (rand->prov_unlock != NULL)
if (rand->unlock != NULL)
break;
rand->prov_unlock = OSSL_get_OP_rand_unlock(fns);
rand->unlock = OSSL_get_OP_rand_unlock(fns);
fnlockcnt++;
break;
case OSSL_FUNC_RAND_GETTABLE_PARAMS:
if (rand->gettable_params != NULL)
@ -201,36 +205,44 @@ static void *evp_rand_from_dispatch(int name_id,
break;
rand->verify_zeroization = OSSL_get_OP_rand_verify_zeroization(fns);
#ifdef FIPS_MODULE
fnfipscnt++;
fnzeroizecnt++;
#endif
break;
}
}
/*
* In order to be a consistent set of functions we must have at least
* a complete set of "rand" functions and a complete set of context
* management functions. In FIPS mode, we also require the zeroization
* verification function.
*
* In addition, if locking can be enabled, we need a complete set of
* locking functions.
*/
if (fnrandcnt != 3
|| fnctxcnt != 2
|| (fnlockcnt != 0 && fnlockcnt != 3)
#ifdef FIPS_MODULE
|| fnfipscnt != 1
|| fnzeroizecnt != 1
#endif
) {
/*
* In order to be a consistent set of functions we must have at least
* a complete set of "rand" functions and a complete set of context
* management functions. In FIPS mode, we also require the zeroization
* verification function.
*/
evp_rand_free(rand);
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
return NULL;
}
if (prov != NULL && !ossl_provider_up_ref(prov)) {
evp_rand_free(rand);
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return NULL;
}
rand->prov = prov;
if (prov != NULL)
ossl_provider_up_ref(prov);
return rand;
}
EVP_RAND *EVP_RAND_fetch(OPENSSL_CTX *libctx, const char *algorithm,
const char *properties)
const char *properties)
{
return evp_generic_fetch(libctx, OSSL_OP_RAND, algorithm, properties,
evp_rand_from_dispatch, evp_rand_up_ref,
@ -274,25 +286,33 @@ int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[])
return 1;
}
EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, int secure, EVP_RAND_CTX *parent)
EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent)
{
EVP_RAND_CTX *ctx;
void *parent_ctx = NULL;
const OSSL_DISPATCH *parent_dispatch = NULL;
if (rand == NULL)
if (rand == NULL) {
EVPerr(0, EVP_R_INVALID_NULL_ALGORITHM);
return NULL;
}
ctx = OPENSSL_zalloc(sizeof(EVP_RAND_CTX));
if (ctx == NULL)
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
EVPerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (parent != NULL) {
EVP_RAND_CTX_enable_locking(parent);
if (!EVP_RAND_enable_locking(parent)) {
EVPerr(0, EVP_R_UNABLE_TO_ENABLE_PARENT_LOCKING);
OPENSSL_free(ctx);
return NULL;
}
parent_ctx = parent->data;
parent_dispatch = parent->meth->dispatch;
}
if ((ctx->data = rand->newctx(ossl_provider_ctx(rand->prov), secure,
parent_ctx, parent_dispatch)) == NULL
if ((ctx->data = rand->newctx(ossl_provider_ctx(rand->prov), parent_ctx,
parent_dispatch)) == NULL
|| !EVP_RAND_up_ref(rand)) {
EVPerr(0, ERR_R_MALLOC_FAILURE);
rand->freectx(ctx->data);
@ -308,7 +328,6 @@ void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx)
if (ctx != NULL) {
ctx->meth->freectx(ctx->data);
ctx->data = NULL;
EVP_RAND_CTX_free(ctx->parent);
EVP_RAND_free(ctx->meth);
OPENSSL_free(ctx);
}
@ -319,7 +338,7 @@ EVP_RAND *EVP_RAND_CTX_rand(EVP_RAND_CTX *ctx)
return ctx->meth;
}
int EVP_RAND_CTX_get_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[])
int EVP_RAND_get_ctx_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[])
{
int res = 1;
@ -332,7 +351,7 @@ int EVP_RAND_CTX_get_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[])
return res;
}
int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[])
int EVP_RAND_set_ctx_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[])
{
int res = 1;
@ -350,23 +369,19 @@ int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[])
const OSSL_PARAM *EVP_RAND_gettable_params(const EVP_RAND *rand)
{
if (rand->gettable_params == NULL)
return NULL;
return rand->gettable_params();
return rand->gettable_params == NULL ? NULL : rand->gettable_params();
}
const OSSL_PARAM *EVP_RAND_gettable_ctx_params(const EVP_RAND *rand)
{
if (rand->gettable_ctx_params == NULL)
return NULL;
return rand->gettable_ctx_params();
return rand->gettable_ctx_params == NULL ? NULL
: rand->gettable_ctx_params();
}
const OSSL_PARAM *EVP_RAND_settable_ctx_params(const EVP_RAND *rand)
{
if (rand->settable_ctx_params == NULL)
return NULL;
return rand->settable_ctx_params();
return rand->settable_ctx_params == NULL ? NULL
:rand->settable_ctx_params();
}
void EVP_RAND_do_all_provided(OPENSSL_CTX *libctx,
@ -386,9 +401,9 @@ void EVP_RAND_names_do_all(const EVP_RAND *rand,
evp_names_do_all(rand->prov, rand->name_id, fn, data);
}
int EVP_RAND_CTX_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr, size_t pstr_len)
int EVP_RAND_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr, size_t pstr_len)
{
int res;
@ -400,7 +415,7 @@ int EVP_RAND_CTX_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
return res;
}
int EVP_RAND_CTX_uninstantiate(EVP_RAND_CTX *ctx)
int EVP_RAND_uninstantiate(EVP_RAND_CTX *ctx)
{
int res;
@ -411,9 +426,9 @@ int EVP_RAND_CTX_uninstantiate(EVP_RAND_CTX *ctx)
return res;
}
int EVP_RAND_CTX_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
unsigned int strength, int prediction_resistance,
const unsigned char *addin, size_t addin_len)
int EVP_RAND_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
unsigned int strength, int prediction_resistance,
const unsigned char *addin, size_t addin_len)
{
size_t chunk;
OSSL_PARAM params[2];
@ -423,17 +438,26 @@ int EVP_RAND_CTX_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
return 0;
if (ctx->max_request == 0) {
params[0] = OSSL_PARAM_construct_size_t(OSSL_DRBG_PARAM_MAX_REQUEST,
&ctx->max_request);
&chunk);
params[1] = OSSL_PARAM_construct_end();
if (!EVP_RAND_CTX_get_params(ctx, params)
|| ctx->max_request == 0)
if (!EVP_RAND_get_ctx_params(ctx, params) || chunk == 0) {
EVPerr(0, EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE);
goto err;
}
ctx->max_request = chunk;
}
for (; outlen > 0; outlen -= chunk, out += chunk) {
chunk = outlen > ctx->max_request ? ctx->max_request : outlen;
if (!ctx->meth->generate(ctx->data, out, chunk, strength,
prediction_resistance, addin, addin_len))
prediction_resistance, addin, addin_len)) {
EVPerr(0, EVP_R_GENERATE_ERROR);
goto err;
}
/*
* Prediction resistance is only relevant the first time around,
* subsequently, the DRBG has already been properly reseeded.
*/
prediction_resistance = 0;
}
res = 1;
err:
@ -441,9 +465,9 @@ err:
return res;
}
int EVP_RAND_CTX_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *addin, size_t addin_len)
int EVP_RAND_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *addin, size_t addin_len)
{
int res = 1;
@ -456,39 +480,41 @@ int EVP_RAND_CTX_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
return res;
}
int EVP_RAND_CTX_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen)
int EVP_RAND_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen)
{
int res = 1;
unsigned int str = EVP_RAND_strength(ctx);
if (!evp_rand_lock(ctx))
return 0;
if (ctx->meth->nonce == NULL
|| !ctx->meth->nonce(ctx->data, out, 0, outlen, outlen))
res = ctx->meth->generate(ctx->data, out, outlen, 0, 0, NULL, 0);
|| !ctx->meth->nonce(ctx->data, out, str, outlen, outlen))
res = ctx->meth->generate(ctx->data, out, outlen, str, 0, NULL, 0);
evp_rand_unlock(ctx);
return res;
}
unsigned int EVP_RAND_CTX_strength(EVP_RAND_CTX *ctx)
unsigned int EVP_RAND_strength(EVP_RAND_CTX *ctx)
{
OSSL_PARAM params[2];
unsigned int t;
int res;
if (ctx->strength == 0) {
params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH,
&ctx->strength);
params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, &t);
params[1] = OSSL_PARAM_construct_end();
if (!evp_rand_lock(ctx))
return 0;
res = EVP_RAND_CTX_get_params(ctx, params);
res = EVP_RAND_get_ctx_params(ctx, params);
evp_rand_unlock(ctx);
if (!res)
return 0;
ctx->strength = t;
}
return ctx->strength;
}
int EVP_RAND_CTX_state(EVP_RAND_CTX *ctx)
int EVP_RAND_state(EVP_RAND_CTX *ctx)
{
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
int status, res;
@ -497,14 +523,29 @@ int EVP_RAND_CTX_state(EVP_RAND_CTX *ctx)
&status);
if (!evp_rand_lock(ctx))
return 0;
res = EVP_RAND_CTX_get_params(ctx, params);
res = EVP_RAND_get_ctx_params(ctx, params);
evp_rand_unlock(ctx);
if (!res)
status = EVP_RAND_STATE_ERROR;
return status;
}
int EVP_RAND_CTX_verify_zeroization(EVP_RAND_CTX *ctx)
int EVP_RAND_set_callbacks(EVP_RAND_CTX *ctx,
OSSL_INOUT_CALLBACK *get_entropy,
OSSL_CALLBACK *cleanup_entropy,
OSSL_INOUT_CALLBACK *get_nonce,
OSSL_CALLBACK *cleanup_nonce, void *arg)
{
if (ctx->meth->set_callbacks == NULL) {
EVPerr(0, EVP_R_UNABLE_TO_SET_CALLBACKS);
return 0;
}
ctx->meth->set_callbacks(ctx->data, get_entropy, cleanup_entropy,
get_nonce, cleanup_nonce, arg);
return 1;
}
int EVP_RAND_verify_zeroization(EVP_RAND_CTX *ctx)
{
int res = 0;

View File

@ -1,16 +1,10 @@
LIBS=../../libcrypto
$COMMON=rand_pool.c rand_lib.c drbg_lib.c drbg_ctr.c drbg_hash.c drbg_hmac.c
$CRYPTO=rand_unix.c rand_win.c randfile.c rand_err.c
$COMMON=drbg_lib.c rand_lib.c
$CRYPTO=randfile.c rand_err.c
IF[{- !$disabled{'egd'} -}]
$CYPTO=$CYPTO rand_egd.c
ENDIF
IF[{- $config{target} =~ /vxworks/i -}]
$CYPTO=$CYPTO rand_vxworks.c
ENDIF
IF[{- $config{target} =~ /vms/i -}]
$CYPTO=$CYPTO rand_vms.c
$CRYPTO=$CRYPTO rand_egd.c
ENDIF

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,9 @@
#include "e_os.h"
#ifndef FIPS_MODULE
# include "prov/rand_pool.h"
# include "prov/seeding.h"
# ifndef OPENSSL_NO_ENGINE
/* non-NULL if default_RAND_meth is ENGINE-provided */
static ENGINE *funct_ref;
@ -28,218 +31,7 @@ static const RAND_METHOD *default_RAND_meth;
static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
static int rand_inited = 0;
#endif /* FIPS_MODULE */
#ifdef OPENSSL_RAND_SEED_RDTSC
/*
* IMPORTANT NOTE: It is not currently possible to use this code
* because we are not sure about the amount of randomness it provides.
* Some SP900 tests have been run, but there is internal skepticism.
* So for now this code is not used.
*/
# error "RDTSC enabled? Should not be possible!"
/*
* Acquire entropy from high-speed clock
*
* Since we get some randomness from the low-order bits of the
* high-speed clock, it can help.
*
* Returns the total entropy count, if it exceeds the requested
* entropy count. Otherwise, returns an entropy count of 0.
*/
size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool)
{
unsigned char c;
int i;
if ((OPENSSL_ia32cap_P[0] & (1 << 4)) != 0) {
for (i = 0; i < TSC_READ_COUNT; i++) {
c = (unsigned char)(OPENSSL_rdtsc() & 0xFF);
rand_pool_add(pool, &c, 1, 4);
}
}
return rand_pool_entropy_available(pool);
}
#endif
#ifdef OPENSSL_RAND_SEED_RDCPU
size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len);
size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len);
/*
* Acquire entropy using Intel-specific cpu instructions
*
* Uses the RDSEED instruction if available, otherwise uses
* RDRAND if available.
*
* For the differences between RDSEED and RDRAND, and why RDSEED
* is the preferred choice, see https://goo.gl/oK3KcN
*
* Returns the total entropy count, if it exceeds the requested
* entropy count. Otherwise, returns an entropy count of 0.
*/
size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool)
{
size_t bytes_needed;
unsigned char *buffer;
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
if (bytes_needed > 0) {
buffer = rand_pool_add_begin(pool, bytes_needed);
if (buffer != NULL) {
/* Whichever comes first, use RDSEED, RDRAND or nothing */
if ((OPENSSL_ia32cap_P[2] & (1 << 18)) != 0) {
if (OPENSSL_ia32_rdseed_bytes(buffer, bytes_needed)
== bytes_needed) {
rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
}
} else if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) {
if (OPENSSL_ia32_rdrand_bytes(buffer, bytes_needed)
== bytes_needed) {
rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
}
} else {
rand_pool_add_end(pool, 0, 0);
}
}
}
return rand_pool_entropy_available(pool);
}
#endif
#if 0
/*
* Implements the get_entropy() callback (see RAND_DRBG_set_callbacks())
*
* If the DRBG has a parent, then the required amount of entropy input
* is fetched using the parent's RAND_DRBG_generate().
*
* Otherwise, the entropy is polled from the system entropy sources
* using rand_pool_acquire_entropy().
*
* If a random pool has been added to the DRBG using RAND_add(), then
* its entropy will be used up first.
*/
size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
unsigned char **pout,
int entropy, size_t min_len, size_t max_len,
int prediction_resistance)
{
size_t ret = 0;
size_t entropy_available = 0;
RAND_POOL *pool;
if (drbg->parent != NULL && drbg->strength > drbg->parent->strength) {
/*
* We currently don't support the algorithm from NIST SP 800-90C
* 10.1.2 to use a weaker DRBG as source
*/
RANDerr(RAND_F_RAND_DRBG_GET_ENTROPY, RAND_R_PARENT_STRENGTH_TOO_WEAK);
return 0;
}
if (drbg->seed_pool != NULL) {
pool = drbg->seed_pool;
pool->entropy_requested = entropy;
} else {
pool = rand_pool_new(entropy, drbg->secure, min_len, max_len);
if (pool == NULL)
return 0;
}
if (drbg->parent != NULL) {
size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed);
if (buffer != NULL) {
size_t bytes = 0;
/*
* Get random data from parent. Include our address as additional input,
* in order to provide some additional distinction between different
* DRBG child instances.
* Our lock is already held, but we need to lock our parent before
* generating bits from it. (Note: taking the lock will be a no-op
* if locking if drbg->parent->lock == NULL.)
*/
rand_drbg_lock(drbg->parent);
if (RAND_DRBG_generate(drbg->parent,
buffer, bytes_needed,
prediction_resistance,
(unsigned char *)&drbg, sizeof(drbg)) != 0)
bytes = bytes_needed;
drbg->reseed_next_counter
= tsan_load(&drbg->parent->reseed_prop_counter);
rand_drbg_unlock(drbg->parent);
rand_pool_add_end(pool, bytes, 8 * bytes);
entropy_available = rand_pool_entropy_available(pool);
}
} else {
/* Get entropy by polling system entropy sources. */
entropy_available = rand_pool_acquire_entropy(pool);
}
if (entropy_available > 0) {
ret = rand_pool_length(pool);
*pout = rand_pool_detach(pool);
}
if (drbg->seed_pool == NULL)
rand_pool_free(pool);
return ret;
}
/*
* Implements the cleanup_entropy() callback (see RAND_DRBG_set_callbacks())
*
*/
void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
unsigned char *out, size_t outlen)
{
if (drbg->seed_pool == NULL) {
if (drbg->secure)
OPENSSL_secure_clear_free(out, outlen);
else
OPENSSL_clear_free(out, outlen);
}
}
/*
* Generate additional data that can be used for the drbg. The data does
* not need to contain entropy, but it's useful if it contains at least
* some bits that are unpredictable.
*
* Returns 0 on failure.
*
* On success it allocates a buffer at |*pout| and returns the length of
* the data. The buffer should get freed using OPENSSL_secure_clear_free().
*/
size_t rand_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout)
{
size_t ret = 0;
if (rand_pool_add_additional_data(pool) == 0)
goto err;
ret = rand_pool_length(pool);
*pout = rand_pool_detach(pool);
err:
return ret;
}
void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out)
{
rand_pool_reattach(pool, out);
}
#endif
#ifndef FIPS_MODULE
DEFINE_RUN_ONCE_STATIC(do_rand_init)
{
# ifndef OPENSSL_NO_ENGINE
@ -288,10 +80,10 @@ void rand_cleanup_int(void)
rand_inited = 0;
}
/* TODO(3.0): Do we need to handle this somehow in the FIPS module? */
/*
* RAND_close_seed_files() ensures that any seed file descriptors are
* closed after use.
* closed after use. This only applies to libcrypto/default provider,
* it does not apply to other providers.
*/
void RAND_keep_random_devices_open(int keep)
{
@ -308,39 +100,24 @@ void RAND_keep_random_devices_open(int keep)
*/
int RAND_poll(void)
{
int ret = 0;
const RAND_METHOD *meth = RAND_get_rand_method();
int ret = meth == RAND_OpenSSL();
RAND_POOL *pool;
if (meth == NULL)
return 0;
if (meth == RAND_OpenSSL()) {
/* fill random pool and seed the master DRBG */
RAND_DRBG *drbg = RAND_DRBG_get0_master();
if (drbg == NULL)
return 0;
#if 0
ret = rand_drbg_restart(drbg, NULL, 0, 0);
#endif
return ret;
} else {
RAND_POOL *pool = NULL;
if (!ret) {
/* fill random pool and seed the current legacy RNG */
pool = rand_pool_new(RAND_DRBG_STRENGTH, 1,
(RAND_DRBG_STRENGTH + 7) / 8,
RAND_POOL_MAX_LENGTH);
if (pool == NULL)
return 0;
#if 0
if (rand_pool_acquire_entropy(pool) == 0)
if (prov_pool_acquire_entropy(pool) == 0)
goto err;
#endif
if (meth->add == NULL
|| meth->add(rand_pool_buffer(pool),
rand_pool_length(pool),
@ -348,11 +125,9 @@ int RAND_poll(void)
goto err;
ret = 1;
err:
rand_pool_free(pool);
}
return ret;
}
@ -370,13 +145,9 @@ int RAND_set_rand_method(const RAND_METHOD *meth)
CRYPTO_THREAD_unlock(rand_meth_lock);
return 1;
}
#endif /* FIPS_MODULE */
const RAND_METHOD *RAND_get_rand_method(void)
{
#ifdef FIPS_MODULE
return NULL;
#else
const RAND_METHOD *tmp_meth = NULL;
if (!RUN_ONCE(&rand_init, do_rand_init))
@ -403,10 +174,9 @@ const RAND_METHOD *RAND_get_rand_method(void)
tmp_meth = default_RAND_meth;
CRYPTO_THREAD_unlock(rand_meth_lock);
return tmp_meth;
#endif
}
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
# if !defined(OPENSSL_NO_ENGINE)
int RAND_set_rand_engine(ENGINE *engine)
{
const RAND_METHOD *tmp_meth = NULL;
@ -430,7 +200,7 @@ int RAND_set_rand_engine(ENGINE *engine)
CRYPTO_THREAD_unlock(rand_engine_lock);
return 1;
}
#endif
# endif
void RAND_seed(const void *buf, int num)
{
@ -448,6 +218,38 @@ void RAND_add(const void *buf, int num, double randomness)
meth->add(buf, num, randomness);
}
# if !defined(OPENSSL_NO_DEPRECATED_1_1_0)
int RAND_pseudo_bytes(unsigned char *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth->pseudorand != NULL)
return meth->pseudorand(buf, num);
RANDerr(RAND_F_RAND_PSEUDO_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED);
return -1;
}
# endif
int RAND_status(void)
{
RAND_DRBG *drbg;
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth != RAND_OpenSSL())
return meth->status != NULL ? meth->status() : 0;
if ((drbg = RAND_DRBG_get0_master()) == NULL || drbg->rand == NULL)
return EVP_RAND_STATE_UNINITIALISED;
return EVP_RAND_state(drbg->rand) == EVP_RAND_STATE_READY;
}
#else /* !FIPS_MODULE */
const RAND_METHOD *RAND_get_rand_method(void)
{
return NULL;
}
#endif /* !FIPS_MODULE */
/*
* This function is not part of RAND_METHOD, so if we're not using
* the default method, then just call RAND_bytes(). Otherwise make
@ -500,24 +302,3 @@ int RAND_bytes(unsigned char *buf, int num)
{
return RAND_bytes_ex(NULL, buf, num);
}
#if !defined(OPENSSL_NO_DEPRECATED_1_1_0) && !defined(FIPS_MODULE)
int RAND_pseudo_bytes(unsigned char *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth->pseudorand != NULL)
return meth->pseudorand(buf, num);
RANDerr(RAND_F_RAND_PSEUDO_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED);
return -1;
}
#endif
int RAND_status(void)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth != NULL && meth->status != NULL)
return meth->status();
return 0;
}

View File

@ -18,7 +18,6 @@
# include <openssl/rand_drbg.h>
# include "internal/tsan_assist.h"
# include "crypto/rand.h"
# include "crypto/rand_pool.h"
# include "internal/numbers.h"
@ -31,67 +30,14 @@
# define SLAVE_RESEED_INTERVAL (1 << 16)
# define MASTER_RESEED_TIME_INTERVAL (60 * 60) /* 1 hour */
# define SLAVE_RESEED_TIME_INTERVAL (7 * 60) /* 7 minutes */
/*
* The number of bytes that constitutes an atomic lump of entropy with respect
* to the FIPS 140-2 section 4.9.2 Conditional Tests. The size is somewhat
* arbitrary, the smaller the value, the less entropy is consumed on first
* read but the higher the probability of the test failing by accident.
*
* The value is in bytes.
*/
#define CRNGT_BUFSIZ 16
/*
* Maximum input size for the DRBG (entropy, nonce, personalization string)
*
* NIST SP800 90Ar1 allows a maximum of (1 << 35) bits i.e., (1 << 32) bytes.
*
* We lower it to 'only' INT32_MAX bytes, which is equivalent to 2 gigabytes.
*/
# define DRBG_MAX_LENGTH INT32_MAX
/* DRBG status values */
typedef enum drbg_status_e {
DRBG_UNINITIALISED,
DRBG_READY,
DRBG_ERROR
} DRBG_STATUS;
/* instantiate */
typedef int (*RAND_DRBG_instantiate_fn)(RAND_DRBG *ctx,
const unsigned char *ent,
size_t entlen,
const unsigned char *nonce,
size_t noncelen,
const unsigned char *pers,
size_t perslen);
/* reseed */
typedef int (*RAND_DRBG_reseed_fn)(RAND_DRBG *ctx,
const unsigned char *ent,
size_t entlen,
const unsigned char *adin,
size_t adinlen);
/* generate output */
typedef int (*RAND_DRBG_generate_fn)(RAND_DRBG *ctx,
unsigned char *out,
size_t outlen,
const unsigned char *adin,
size_t adinlen);
/* uninstantiate */
typedef int (*RAND_DRBG_uninstantiate_fn)(RAND_DRBG *ctx);
/*
* The state of all types of DRBGs, even though we only have CTR mode
* right now.
* The state of all types of DRBGs.
*/
struct rand_drbg_st {
CRYPTO_RWLOCK *lock;
/* The library context this DRBG is associated with, if any */
OPENSSL_CTX *libctx;
RAND_DRBG *parent;
int secure; /* 1: allocated on the secure heap, 0: otherwise */
int type; /* the nid of the underlying algorithm */
unsigned short flags; /* various external flags */
@ -113,20 +59,4 @@ struct rand_drbg_st {
/* The global RAND method, and the global buffer and DRBG instance. */
extern RAND_METHOD rand_meth;
/* DRBG helpers */
int rand_drbg_restart(RAND_DRBG *drbg,
const unsigned char *buffer, size_t len, size_t entropy);
size_t rand_drbg_seedlen(RAND_DRBG *drbg);
/*
* Entropy call back for the FIPS 140-2 section 4.9.2 Conditional Tests.
* These need to be exposed for the unit tests.
*/
int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx, RAND_POOL *pool,
unsigned char *buf, unsigned char *md,
unsigned int *md_size);
extern int (*crngt_get_entropy)(OPENSSL_CTX *ctx, RAND_POOL *pool,
unsigned char *buf, unsigned char *md,
unsigned int *md_size);
#endif

View File

@ -35,9 +35,6 @@ RAND_DRBG_free
unsigned int flags,
RAND_DRBG *parent);
int RAND_DRBG_set(RAND_DRBG *drbg,
int type, unsigned int flags);
int RAND_DRBG_set_defaults(int type, unsigned int flags);
int RAND_DRBG_instantiate(RAND_DRBG *drbg,
@ -47,18 +44,27 @@ RAND_DRBG_free
void RAND_DRBG_free(RAND_DRBG *drbg);
Deprecated since OpenSSL 3.0, can be hidden entirely by defining
B<OPENSSL_API_COMPAT> with a suitable version value, see
L<openssl_user_macros(7)>:
int RAND_DRBG_set(RAND_DRBG *drbg,
int type, unsigned int flags);
=head1 DESCRIPTION
RAND_DRBG_new_ex() and RAND_DRBG_secure_new_ex()
create a new DRBG instance of the given B<type>, allocated from the heap resp.
the secure heap, for the given OPENSSL_CTX <ctx>
(using OPENSSL_zalloc() resp. OPENSSL_secure_zalloc()). The <ctx> parameter can
be NULL in which case the default OPENSSL_CTX is used. RAND_DRBG_new() and
RAND_DRBG_secure_new() are the same as RAND_DRBG_new_ex() and
RAND_DRBG_secure_new_ex() except that the default OPENSSL_CTX is always used.
RAND_DRBG_new_ex() and RAND_DRBG_secure_new_ex() create a new DRBG instance
of the given B<type> for the given OPENSSL_CTX <ctx>.
The <ctx> parameter can be NULL in which case the default OPENSSL_CTX is used.
RAND_DRBG_new() and RAND_DRBG_secure_new() are the same as RAND_DRBG_new_ex()
and RAND_DRBG_secure_new_ex() except that the default OPENSSL_CTX is always
used.
As of OpenSSL 3.0, there is no different between the new and secure_new
functions.
RAND_DRBG_set() initializes the B<drbg> with the given B<type> and B<flags>.
This function is deprecated. Applications should instead use
RAND_DRBG_new_ex() to create a new DRBG.
RAND_DRBG_set_defaults() sets the default B<type> and B<flags> for new DRBG
instances.
@ -124,7 +130,7 @@ uninstantiated state.
RAND_DRBG_new_ex(), RAND_DRBG_new(), RAND_DRBG_secure_new_ex() and
RAND_DRBG_secure_new() return a pointer to a DRBG instance allocated on the
heap, resp. secure heap.
heap.
RAND_DRBG_set(),
RAND_DRBG_instantiate(), and
@ -149,6 +155,11 @@ To ensure that they are applied to the global and thread-local DRBG instances
RAND_DRBG_set_defaults() before creating any thread and before calling any
cryptographic routines that obtain random data directly or indirectly.
As of OpenSSL 3.0, RAND_DRBG_new() and RAND_DRBG_secure_new() are
functionally identical. The DRBG is allocated on the normal heap and its
sensitive state is allocated on the secure heap. Likewise for,
RAND_DRBG_new_ex() and RAND_DRBG_secure_new_ex().
=head1 SEE ALSO
L<OPENSSL_zalloc(3)>,
@ -158,6 +169,8 @@ L<RAND_DRBG(7)>
=head1 HISTORY
The RAND_DRBG_set() function was deprecated in OpenSSL 3.0.
The RAND_DRBG functions were added in OpenSSL 1.1.1.
=head1 COPYRIGHT

View File

@ -127,11 +127,12 @@ entropy from a live entropy source (section 5.5.2 of [NIST SP 800-90C]).
It is up to the user to ensure that a live entropy source is configured
and is being used.
The derivation function is disabled during initialization by calling the
RAND_DRBG_set() function with the RAND_DRBG_FLAG_CTR_NO_DF flag.
For more information on the derivation function and when it can be omitted,
see [NIST SP 800-90A Rev. 1]. Roughly speaking it can be omitted if the random
source has "full entropy", i.e., contains 8 bits of entropy per byte.
The derivation function is disabled by calling the RAND_DRBG_new_ex()
function with the RAND_DRBG_FLAG_CTR_NO_DF flag. For more information on
the derivation function and when it can be omitted, see [NIST SP 800-90A
Rev. 1]. Roughly speaking it can be omitted if the random source has "full
entropy", i.e., contains 8 bits of entropy per byte. In a FIPS context,
the derivation function can never be omitted.
Even if a nonce is required, the B<get_nonce>() and B<cleanup_nonce>()
callbacks can be omitted by setting them to NULL.

View File

@ -180,26 +180,38 @@ extern "C" {
#define OSSL_KDF_NAME_KBKDF "KBKDF"
#define OSSL_KDF_NAME_KRB5KDF "KRB5KDF"
/* Know RAND names */
#define OSSL_RAND_PARAM_STATUS "status"
/* Known RAND names */
#define OSSL_RAND_PARAM_STATE "state"
#define OSSL_RAND_PARAM_STRENGTH "strength"
#define OSSL_RAND_PARAM_RESEED_REQUESTS "reseed_requests"
#define OSSL_RAND_PARAM_RESEED_TIME_INTERVAL "reseed_time_interval"
#define OSSL_RAND_PARAM_MAX_REQUEST "max_request"
#define OSSL_RAND_PARAM_MIN_ENTROPYLEN "min_entropylen"
#define OSSL_RAND_PARAM_MAX_ENTROPYLEN "max_entropylen"
#define OSSL_RAND_PARAM_MIN_NONCELEN "min_noncelen"
#define OSSL_RAND_PARAM_MAX_NONCELEN "max_noncelen"
#define OSSL_RAND_PARAM_MAX_PERSLEN "max_perslen"
#define OSSL_RAND_PARAM_MAX_ADINLEN "max_adinlen"
#define OSSL_RAND_PARAM_RESEED_CTR "reseed_counter"
#define OSSL_RAND_PARAM_RESEED_PROP_CTR "reseed_prop_counter"
#define OSSL_RAND_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES
#define OSSL_RAND_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST
#define OSSL_RAND_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER
#define OSSL_RAND_PARAM_TEST_ENTROPY "test_entropy"
#define OSSL_RAND_PARAM_TEST_NONCE "test_nonce"
/* RAND/DRBG names */
#define OSSL_DRBG_PARAM_RESEED_REQUESTS "reseed_requests"
#define OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL "reseed_time_interval"
#define OSSL_DRBG_PARAM_MAX_REQUEST "max_request"
#define OSSL_DRBG_PARAM_MIN_ENTROPYLEN "min_entropylen"
#define OSSL_DRBG_PARAM_MAX_ENTROPYLEN "max_entropylen"
#define OSSL_DRBG_PARAM_MIN_NONCELEN "min_noncelen"
#define OSSL_DRBG_PARAM_MAX_NONCELEN "max_noncelen"
#define OSSL_DRBG_PARAM_MAX_PERSLEN "max_perslen"
#define OSSL_DRBG_PARAM_MAX_ADINLEN "max_adinlen"
#define OSSL_DRBG_PARAM_RESEED_CTR "reseed_counter"
#define OSSL_DRBG_PARAM_RESEED_TIME "reseed_time"
#define OSSL_DRBG_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES
#define OSSL_DRBG_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST
#define OSSL_DRBG_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER
#define OSSL_DRBG_PARAM_MAC OSSL_ALG_PARAM_MAC
#define OSSL_DRBG_PARAM_USE_DF "use_derivation_function"
/* DRBG call back parameters */
#define OSSL_DRBG_PARAM_ENTROPY_REQUIRED "entropy_required"
#define OSSL_DRBG_PARAM_PREDICTION_RESISTANCE "prediction_resistance"
#define OSSL_DRBG_PARAM_MIN_LENGTH "minium_length"
#define OSSL_DRBG_PARAM_MAX_LENGTH "maxium_length"
#define OSSL_DRBG_PARAM_RANDOM_DATA "random_data"
#define OSSL_DRBG_PARAM_SIZE "size"
/* PKEY parameters */
/* Common PKEY parameters */
#define OSSL_PKEY_PARAM_BITS "bits" /* integer */

View File

@ -362,7 +362,7 @@ OSSL_CORE_MAKE_FUNC(int, OP_kdf_set_ctx_params,
# define OSSL_FUNC_RAND_VERIFY_ZEROIZATION 18
OSSL_CORE_MAKE_FUNC(void *, OP_rand_newctx,
(void *provctx, int secure, void *parent,
(void *provctx, void *parent,
const OSSL_DISPATCH *parent_calls))
OSSL_CORE_MAKE_FUNC(void, OP_rand_freectx, (void *vctx))
OSSL_CORE_MAKE_FUNC(int, OP_rand_instantiate,
@ -379,12 +379,8 @@ OSSL_CORE_MAKE_FUNC(int, OP_rand_reseed,
const unsigned char *ent, size_t ent_len,
const unsigned char *addin, size_t addin_len))
OSSL_CORE_MAKE_FUNC(size_t, OP_rand_nonce,
(void *vctx, unsigned char *out, int strength,
(void *vctx, unsigned char *out, unsigned int strength,
size_t min_noncelen, size_t max_noncelen))
OSSL_CORE_MAKE_FUNC(int, OP_rand_set_callbacks,
(void *vctx,
OSSL_CALLBACK *get_entropy, OSSL_CALLBACK *cleanup_entropy,
OSSL_CALLBACK *get_nonce, OSSL_CALLBACK *cleanup_nonce))
OSSL_CORE_MAKE_FUNC(int, OP_rand_enable_locking, (void *vctx))
OSSL_CORE_MAKE_FUNC(int, OP_rand_lock, (void *vctx))
OSSL_CORE_MAKE_FUNC(void, OP_rand_unlock, (void *vctx))
@ -396,6 +392,11 @@ OSSL_CORE_MAKE_FUNC(int, OP_rand_get_ctx_params,
(void *vctx, OSSL_PARAM params[]))
OSSL_CORE_MAKE_FUNC(int, OP_rand_set_ctx_params,
(void *vctx, const OSSL_PARAM params[]))
OSSL_CORE_MAKE_FUNC(void, OP_rand_set_callbacks,
(void *vctx, OSSL_INOUT_CALLBACK *get_entropy,
OSSL_CALLBACK *cleanup_entropy,
OSSL_INOUT_CALLBACK *get_nonce,
OSSL_CALLBACK *cleanup_nonce, void *arg))
OSSL_CORE_MAKE_FUNC(int, OP_rand_verify_zeroization,
(void *vctx))

View File

@ -1082,12 +1082,11 @@ int EVP_RAND_is_a(const EVP_RAND *rand, const char *name);
const OSSL_PROVIDER *EVP_RAND_provider(const EVP_RAND *rand);
int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[]);
EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, int secure,
EVP_RAND_CTX *parent);
EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent);
void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx);
EVP_RAND *EVP_RAND_CTX_rand(EVP_RAND_CTX *ctx);
int EVP_RAND_CTX_get_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[]);
int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[]);
int EVP_RAND_get_ctx_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[]);
int EVP_RAND_set_ctx_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[]);
const OSSL_PARAM *EVP_RAND_gettable_params(const EVP_RAND *rand);
const OSSL_PARAM *EVP_RAND_gettable_ctx_params(const EVP_RAND *rand);
const OSSL_PARAM *EVP_RAND_settable_ctx_params(const EVP_RAND *rand);
@ -1099,26 +1098,27 @@ void EVP_RAND_names_do_all(const EVP_RAND *rand,
void (*fn)(const char *name, void *data),
void *data);
int EVP_RAND_CTX_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
__owur int EVP_RAND_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr, size_t pstr_len);
int EVP_RAND_uninstantiate(EVP_RAND_CTX *ctx);
__owur int EVP_RAND_generate(EVP_RAND_CTX *ctx, unsigned char *out,
size_t outlen, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr, size_t pstr_len);
int EVP_RAND_CTX_uninstantiate(EVP_RAND_CTX *ctx);
int EVP_RAND_CTX_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
unsigned int strength, int prediction_resistance,
const unsigned char *addin, size_t addin_len);
int EVP_RAND_CTX_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *addin, size_t addin_len);
int EVP_RAND_CTX_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen);
int EVP_RAND_CTX_set_callbacks(const EVP_RAND_CTX *rand,
OSSL_CALLBACK *get_entropy,
OSSL_CALLBACK *cleanup_entropy,
OSSL_CALLBACK *get_nonce,
OSSL_CALLBACK *cleanup_nonce);
int EVP_RAND_CTX_enable_locking(EVP_RAND_CTX *ctx);
int EVP_RAND_CTX_verify_zeroization(EVP_RAND_CTX *ctx);
unsigned int EVP_RAND_CTX_strength(EVP_RAND_CTX *ctx);
int EVP_RAND_CTX_state(EVP_RAND_CTX *ctx);
const unsigned char *addin, size_t addin_len);
int EVP_RAND_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *addin, size_t addin_len);
__owur int EVP_RAND_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen);
__owur int EVP_RAND_enable_locking(EVP_RAND_CTX *ctx);
int EVP_RAND_set_callbacks(EVP_RAND_CTX *ctx,
OSSL_INOUT_CALLBACK *get_entropy,
OSSL_CALLBACK *cleanup_entropy,
OSSL_INOUT_CALLBACK *get_nonce,
OSSL_CALLBACK *cleanup_nonce, void *arg);
int EVP_RAND_verify_zeroization(EVP_RAND_CTX *ctx);
unsigned int EVP_RAND_strength(EVP_RAND_CTX *ctx);
int EVP_RAND_state(EVP_RAND_CTX *ctx);
#define EVP_RAND_STATE_UNINITIALISED 0
#define EVP_RAND_STATE_READY 1

View File

@ -82,7 +82,6 @@ DEPRECATEDIN_1_1_0(void RAND_screen(void))
DEPRECATEDIN_1_1_0(int RAND_event(UINT, WPARAM, LPARAM))
# endif
#ifdef __cplusplus
}
#endif

View File

@ -80,11 +80,9 @@ extern "C" {
*/
RAND_DRBG *RAND_DRBG_new_ex(OPENSSL_CTX *ctx, int type, unsigned int flags,
RAND_DRBG *parent);
RAND_DRBG *RAND_DRBG_secure_new_ex(OPENSSL_CTX *ctx, int type,
unsigned int flags, RAND_DRBG *parent);
RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent);
RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent);
int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags);
DEPRECATEDIN_3_0(int RAND_DRBG_set(RAND_DRBG *drbg, int type,
unsigned int flags))
int RAND_DRBG_set_defaults(int type, unsigned int flags);
int RAND_DRBG_instantiate(RAND_DRBG *drbg,
const unsigned char *pers, size_t perslen);

View File

@ -338,13 +338,10 @@ static const OSSL_ALGORITHM deflt_keyexch[] = {
};
static const OSSL_ALGORITHM deflt_rands[] = {
{ "TEST-RAND", "provider=default", test_rng_functions },
{ "HASH-DRBG", "provider=default", drbg_hash_functions },
/*
{ "HMAC-DRBG", "provider=default", drbg_hmac_functions },
{ "CTR-DRBG", "provider=default", drbg_ctr_functions },
*/
{ "CRNGT:continuous-rng-test", "provider=default", crngt_functions },
{ "HASH-DRBG", "provider=default", drbg_hash_functions },
{ "HMAC-DRBG", "provider=default", drbg_hmac_functions },
{ "TEST-RAND", "provider=default", test_rng_functions },
{ NULL, NULL, NULL }
};

View File

@ -470,17 +470,10 @@ static const OSSL_ALGORITHM fips_kdfs[] = {
};
static const OSSL_ALGORITHM fips_rands[] = {
/*
* The TEST RNG must be first, so it can be suppressed after the power up
* tests are completed.
*/
{ "TEST-RAND", "provider=fips", test_rng_functions },
{ "HASH-DRBG", "provider=fips", drbg_hash_functions },
/*
{ "HMAC-DRBG", "provider=fips", drbg_hmac_functions },
{ "CTR-DRBG", "provider=fips", drbg_ctr_functions },
*/
{ "CRNGT:continuous-rng-test", "provider=fips", crngt_functions },
{ "HASH-DRBG", "provider=fips", drbg_hash_functions },
{ "HMAC-DRBG", "provider=fips", drbg_hmac_functions },
{ "TEST-RAND", "provider=fips", test_rng_functions },
{ NULL, NULL, NULL }
};

View File

@ -1,8 +1,6 @@
SUBDIRS=seeding
# Missing: drbg_ctr.c
SOURCE[../../libfips.a]=drbg.c
SOURCE[../../libnonfips.a]=drbg.c
$COMMON=drbg.c test_rng.c drbg_ctr.c drbg_hash.c drbg_hmac.c crngt.c rand_pool.c
# Missing: drbg_hmac.c
SOURCE[../../libimplementations.a]=test_rng.c drbg_hash.c crngt.c
SOURCE[../../libfips.a]=$COMMON
SOURCE[../../libnonfips.a]=$COMMON

View File

@ -21,7 +21,7 @@
#include "internal/cryptlib.h"
#include "prov/rand_pool.h"
#include "drbg_local.h"
#include "seeding/seeding.h"
#include "prov/seeding.h"
typedef struct crng_test_global_st {
unsigned char crngt_prev[EVP_MAX_MD_SIZE];

File diff suppressed because it is too large Load Diff

View File

@ -12,14 +12,50 @@
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/aes.h>
#include "e_os.h" /* strcasecmp */
#include "crypto/modes.h"
#include "internal/thread_once.h"
#include "rand_local.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "prov/providercommonerr.h"
#include "drbg_local.h"
static OSSL_OP_rand_newctx_fn drbg_ctr_new_wrapper;
static OSSL_OP_rand_freectx_fn drbg_ctr_free;
static OSSL_OP_rand_instantiate_fn drbg_ctr_instantiate_wrapper;
static OSSL_OP_rand_uninstantiate_fn drbg_ctr_uninstantiate_wrapper;
static OSSL_OP_rand_generate_fn drbg_ctr_generate_wrapper;
static OSSL_OP_rand_reseed_fn drbg_ctr_reseed_wrapper;
static OSSL_OP_rand_settable_ctx_params_fn drbg_ctr_settable_ctx_params;
static OSSL_OP_rand_set_ctx_params_fn drbg_ctr_set_ctx_params;
static OSSL_OP_rand_gettable_ctx_params_fn drbg_ctr_gettable_ctx_params;
static OSSL_OP_rand_get_ctx_params_fn drbg_ctr_get_ctx_params;
static OSSL_OP_rand_verify_zeroization_fn drbg_ctr_verify_zeroization;
/*
* The state of a DRBG AES-CTR.
*/
typedef struct rand_drbg_ctr_st {
EVP_CIPHER_CTX *ctx_ecb;
EVP_CIPHER_CTX *ctx_ctr;
EVP_CIPHER_CTX *ctx_df;
EVP_CIPHER *cipher_ecb;
EVP_CIPHER *cipher_ctr;
size_t keylen;
int use_df;
unsigned char K[32];
unsigned char V[16];
/* Temporary block storage used by ctr_df */
unsigned char bltmp[16];
size_t bltmp_pos;
unsigned char KX[48];
} PROV_DRBG_CTR;
/*
* Implementation of NIST SP 800-90A CTR DRBG.
*/
static void inc_128(RAND_DRBG_CTR *ctr)
static void inc_128(PROV_DRBG_CTR *ctr)
{
unsigned char *p = &ctr->V[0];
u32 n = 16, c = 1;
@ -32,7 +68,7 @@ static void inc_128(RAND_DRBG_CTR *ctr)
} while (n);
}
static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
static void ctr_XOR(PROV_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
{
size_t i, n;
@ -61,7 +97,7 @@ static void ctr_XOR(RAND_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
/*
* Process a complete block using BCC algorithm of SP 800-90A 10.3.3
*/
__owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out,
__owur static int ctr_BCC_block(PROV_DRBG_CTR *ctr, unsigned char *out,
const unsigned char *in, int len)
{
int i, outlen = AES_BLOCK_SIZE;
@ -79,7 +115,7 @@ __owur static int ctr_BCC_block(RAND_DRBG_CTR *ctr, unsigned char *out,
/*
* Handle several BCC operations for as much data as we need for K and X
*/
__owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in)
__owur static int ctr_BCC_blocks(PROV_DRBG_CTR *ctr, const unsigned char *in)
{
unsigned char in_tmp[48];
unsigned char num_of_blk = 2;
@ -97,7 +133,7 @@ __owur static int ctr_BCC_blocks(RAND_DRBG_CTR *ctr, const unsigned char *in)
* Initialise BCC blocks: these have the value 0,1,2 in leftmost positions:
* see 10.3.1 stage 7.
*/
__owur static int ctr_BCC_init(RAND_DRBG_CTR *ctr)
__owur static int ctr_BCC_init(PROV_DRBG_CTR *ctr)
{
unsigned char bltmp[48] = {0};
unsigned char num_of_blk;
@ -112,7 +148,7 @@ __owur static int ctr_BCC_init(RAND_DRBG_CTR *ctr)
/*
* Process several blocks into BCC algorithm, some possibly partial
*/
__owur static int ctr_BCC_update(RAND_DRBG_CTR *ctr,
__owur static int ctr_BCC_update(PROV_DRBG_CTR *ctr,
const unsigned char *in, size_t inlen)
{
if (in == NULL || inlen == 0)
@ -147,7 +183,7 @@ __owur static int ctr_BCC_update(RAND_DRBG_CTR *ctr,
return 1;
}
__owur static int ctr_BCC_final(RAND_DRBG_CTR *ctr)
__owur static int ctr_BCC_final(PROV_DRBG_CTR *ctr)
{
if (ctr->bltmp_pos) {
memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);
@ -157,7 +193,7 @@ __owur static int ctr_BCC_final(RAND_DRBG_CTR *ctr)
return 1;
}
__owur static int ctr_df(RAND_DRBG_CTR *ctr,
__owur static int ctr_df(PROV_DRBG_CTR *ctr,
const unsigned char *in1, size_t in1len,
const unsigned char *in2, size_t in2len,
const unsigned char *in3, size_t in3len)
@ -220,12 +256,12 @@ __owur static int ctr_df(RAND_DRBG_CTR *ctr,
* zeroes if necessary and have up to two parameters XORed together,
* so we handle both cases in this function instead.
*/
__owur static int ctr_update(RAND_DRBG *drbg,
__owur static int ctr_update(PROV_DRBG *drbg,
const unsigned char *in1, size_t in1len,
const unsigned char *in2, size_t in2len,
const unsigned char *nonce, size_t noncelen)
{
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
int outlen = AES_BLOCK_SIZE;
unsigned char V_tmp[48], out[48];
unsigned char len;
@ -247,7 +283,7 @@ __owur static int ctr_update(RAND_DRBG *drbg,
memcpy(ctr->K, out, ctr->keylen);
memcpy(ctr->V, out + ctr->keylen, 16);
if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
if (ctr->use_df) {
/* If no input reuse existing derived value */
if (in1 != NULL || nonce != NULL || in2 != NULL)
if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))
@ -266,12 +302,12 @@ __owur static int ctr_update(RAND_DRBG *drbg,
return 1;
}
__owur static int drbg_ctr_instantiate(RAND_DRBG *drbg,
const unsigned char *entropy, size_t entropylen,
const unsigned char *nonce, size_t noncelen,
const unsigned char *pers, size_t perslen)
static int drbg_ctr_instantiate(PROV_DRBG *drbg,
const unsigned char *entropy, size_t entropylen,
const unsigned char *nonce, size_t noncelen,
const unsigned char *pers, size_t perslen)
{
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
if (entropy == NULL)
return 0;
@ -287,11 +323,22 @@ __owur static int drbg_ctr_instantiate(RAND_DRBG *drbg,
return 1;
}
__owur static int drbg_ctr_reseed(RAND_DRBG *drbg,
const unsigned char *entropy, size_t entropylen,
const unsigned char *adin, size_t adinlen)
static int drbg_ctr_instantiate_wrapper(void *vdrbg, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr,
size_t pstr_len)
{
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return PROV_DRBG_instantiate(drbg, strength, prediction_resistance,
pstr, pstr_len);
}
static int drbg_ctr_reseed(PROV_DRBG *drbg,
const unsigned char *entropy, size_t entropylen,
const unsigned char *adin, size_t adinlen)
{
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
if (entropy == NULL)
return 0;
@ -302,6 +349,16 @@ __owur static int drbg_ctr_reseed(RAND_DRBG *drbg,
return 1;
}
static int drbg_ctr_reseed_wrapper(void *vdrbg, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adin_len)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return PROV_DRBG_reseed(drbg, prediction_resistance, ent, ent_len,
adin, adin_len);
}
static void ctr96_inc(unsigned char *counter)
{
u32 n = 12, c = 1;
@ -314,11 +371,11 @@ static void ctr96_inc(unsigned char *counter)
} while (n);
}
__owur static int drbg_ctr_generate(RAND_DRBG *drbg,
unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adinlen)
static int drbg_ctr_generate(PROV_DRBG *drbg,
unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adinlen)
{
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
unsigned int ctr32, blocks;
int outl, buflen;
@ -328,7 +385,7 @@ __owur static int drbg_ctr_generate(RAND_DRBG *drbg,
if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
return 0;
/* This means we reuse derived value */
if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
if (ctr->use_df) {
adin = NULL;
adinlen = 1;
}
@ -388,116 +445,299 @@ __owur static int drbg_ctr_generate(RAND_DRBG *drbg,
return 1;
}
static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
static int drbg_ctr_generate_wrapper
(void *vdrbg, unsigned char *out, size_t outlen,
unsigned int strength, int prediction_resistance,
const unsigned char *adin, size_t adin_len)
{
EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_ecb);
EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_ctr);
EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df);
EVP_CIPHER_free(drbg->data.ctr.cipher_ecb);
EVP_CIPHER_free(drbg->data.ctr.cipher_ctr);
OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return PROV_DRBG_generate(drbg, out, outlen, strength,
prediction_resistance, adin, adin_len);
}
static int drbg_ctr_uninstantiate(PROV_DRBG *drbg)
{
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
OPENSSL_cleanse(ctr->K, sizeof(ctr->K));
OPENSSL_cleanse(ctr->V, sizeof(ctr->V));
OPENSSL_cleanse(ctr->bltmp, sizeof(ctr->bltmp));
OPENSSL_cleanse(ctr->KX, sizeof(ctr->KX));
ctr->bltmp_pos = 0;
return PROV_DRBG_uninstantiate(drbg);
}
static int drbg_ctr_uninstantiate_wrapper(void *vdrbg)
{
return drbg_ctr_uninstantiate((PROV_DRBG *)vdrbg);
}
static int drbg_ctr_verify_zeroization(void *vdrbg)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
PROV_DRBG_VERYIFY_ZEROIZATION(ctr->K);
PROV_DRBG_VERYIFY_ZEROIZATION(ctr->V);
PROV_DRBG_VERYIFY_ZEROIZATION(ctr->bltmp);
PROV_DRBG_VERYIFY_ZEROIZATION(ctr->KX);
if (ctr->bltmp_pos != 0)
return 0;
return 1;
}
static RAND_DRBG_METHOD drbg_ctr_meth = {
drbg_ctr_instantiate,
drbg_ctr_reseed,
drbg_ctr_generate,
drbg_ctr_uninstantiate
};
int drbg_ctr_init(RAND_DRBG *drbg)
static int drbg_ctr_init_lengths(PROV_DRBG *drbg)
{
RAND_DRBG_CTR *ctr = &drbg->data.ctr;
size_t keylen;
EVP_CIPHER *cipher_ecb = NULL;
EVP_CIPHER *cipher_ctr = NULL;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
int res = 1;
switch (drbg->type) {
default:
/* This can't happen, but silence the compiler warning. */
return 0;
case NID_aes_128_ctr:
keylen = 16;
cipher_ecb = EVP_CIPHER_fetch(drbg->libctx, "AES-128-ECB", "");
cipher_ctr = EVP_CIPHER_fetch(drbg->libctx, "AES-128-CTR", "");
break;
case NID_aes_192_ctr:
keylen = 24;
cipher_ecb = EVP_CIPHER_fetch(drbg->libctx, "AES-192-ECB", "");
cipher_ctr = EVP_CIPHER_fetch(drbg->libctx, "AES-192-CTR", "");
break;
case NID_aes_256_ctr:
keylen = 32;
cipher_ecb = EVP_CIPHER_fetch(drbg->libctx, "AES-256-ECB", "");
cipher_ctr = EVP_CIPHER_fetch(drbg->libctx, "AES-256-CTR", "");
break;
#ifdef FIPS_MODULE
if (!ctr->use_df) {
PROVerr(0, RAND_R_DERIVATION_FUNCTION_MANDATORY_FOR_FIPS);
ctr->use_df = 1;
res = 0;
}
if (cipher_ecb == NULL || cipher_ctr == NULL)
return 0;
#endif
/* Maximum number of bits per request = 2^19 = 2^16 bytes */
drbg->max_request = 1 << 16;
if (ctr->use_df) {
drbg->min_entropylen = 0;
drbg->max_entropylen = DRBG_MAX_LENGTH;
drbg->min_noncelen = 0;
drbg->max_noncelen = DRBG_MAX_LENGTH;
drbg->max_perslen = DRBG_MAX_LENGTH;
drbg->max_adinlen = DRBG_MAX_LENGTH;
EVP_CIPHER_free(ctr->cipher_ecb);
ctr->cipher_ecb = cipher_ecb;
EVP_CIPHER_free(ctr->cipher_ctr);
ctr->cipher_ctr = cipher_ctr;
if (ctr->keylen > 0) {
drbg->min_entropylen = ctr->keylen;
drbg->min_noncelen = drbg->min_entropylen / 2;
}
} else {
const size_t len = ctr->keylen > 0 ? drbg->seedlen : DRBG_MAX_LENGTH;
drbg->min_entropylen = len;
drbg->max_entropylen = len;
/* Nonce not used */
drbg->min_noncelen = 0;
drbg->max_noncelen = 0;
drbg->max_perslen = len;
drbg->max_adinlen = len;
}
return res;
}
static int drbg_ctr_init(PROV_DRBG *drbg)
{
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
const size_t keylen = EVP_CIPHER_key_length(ctr->cipher_ctr);
ctr->keylen = keylen;
if (ctr->ctx_ecb == NULL)
ctr->ctx_ecb = EVP_CIPHER_CTX_new();
if (ctr->ctx_ctr == NULL)
ctr->ctx_ctr = EVP_CIPHER_CTX_new();
if (ctr->ctx_ecb == NULL || ctr->ctx_ctr == NULL
|| !EVP_CipherInit_ex(ctr->ctx_ecb,
ctr->cipher_ecb, NULL, NULL, NULL, 1)
|| !EVP_CipherInit_ex(ctr->ctx_ctr,
ctr->cipher_ctr, NULL, NULL, NULL, 1))
return 0;
drbg->meth = &drbg_ctr_meth;
drbg->strength = keylen * 8;
drbg->seedlen = keylen + 16;
if ((drbg->flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0) {
/* df initialisation */
static const unsigned char df_key[32] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
if (ctr->ctx_df == NULL)
ctr->ctx_df = EVP_CIPHER_CTX_new();
if (ctr->ctx_df == NULL)
return 0;
/* Set key schedule for df_key */
if (!EVP_CipherInit_ex(ctr->ctx_df,
ctr->cipher_ecb, NULL, df_key, NULL, 1))
return 0;
drbg->min_entropylen = ctr->keylen;
drbg->max_entropylen = DRBG_MAX_LENGTH;
drbg->min_noncelen = drbg->min_entropylen / 2;
drbg->max_noncelen = DRBG_MAX_LENGTH;
drbg->max_perslen = DRBG_MAX_LENGTH;
drbg->max_adinlen = DRBG_MAX_LENGTH;
} else {
#ifdef FIPS_MODULE
RANDerr(RAND_F_DRBG_CTR_INIT,
RAND_R_DERIVATION_FUNCTION_MANDATORY_FOR_FIPS);
return 0;
#else
drbg->min_entropylen = drbg->seedlen;
drbg->max_entropylen = drbg->seedlen;
/* Nonce not used */
drbg->min_noncelen = 0;
drbg->max_noncelen = 0;
drbg->max_perslen = drbg->seedlen;
drbg->max_adinlen = drbg->seedlen;
#endif
if (ctr->ctx_ecb == NULL || ctr->ctx_ctr == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
drbg->max_request = 1 << 16;
if (ctr->cipher_ctr != NULL) {
if (!EVP_CipherInit_ex(ctr->ctx_ecb,
ctr->cipher_ecb, NULL, NULL, NULL, 1)
|| !EVP_CipherInit_ex(ctr->ctx_ctr,
ctr->cipher_ctr, NULL, NULL, NULL, 1)) {
ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_INITIALISE_CIPHERS);
goto err;
}
return 1;
drbg->strength = keylen * 8;
drbg->seedlen = keylen + 16;
if (ctr->use_df) {
/* df initialisation */
static const unsigned char df_key[32] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
if (ctr->ctx_df == NULL)
ctr->ctx_df = EVP_CIPHER_CTX_new();
if (ctr->ctx_df == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Set key schedule for df_key */
if (!EVP_CipherInit_ex(ctr->ctx_df,
ctr->cipher_ecb, NULL, df_key, NULL, 1)) {
ERR_raise(ERR_LIB_PROV, PROV_R_DERIVATION_FUNCTION_INIT_FAILED);
goto err;
}
}
}
return drbg_ctr_init_lengths(drbg);
err:
EVP_CIPHER_CTX_free(ctr->ctx_ecb);
EVP_CIPHER_CTX_free(ctr->ctx_ctr);
ctr->ctx_ecb = ctr->ctx_ctr = NULL;
return 0;
}
static int drbg_ctr_new(PROV_DRBG *drbg)
{
PROV_DRBG_CTR *ctr;
ctr = OPENSSL_secure_zalloc(sizeof(*ctr));
if (ctr == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
ctr->use_df = 1;
drbg->data = ctr;
return drbg_ctr_init_lengths(drbg);
}
static void *drbg_ctr_new_wrapper(void *provctx, void *parent,
const OSSL_DISPATCH *parent_dispatch)
{
return prov_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_ctr_new,
&drbg_ctr_instantiate, &drbg_ctr_uninstantiate,
&drbg_ctr_reseed, &drbg_ctr_generate);
}
static void drbg_ctr_free(void *vdrbg)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_CTR *ctr;
if (drbg != NULL && (ctr = (PROV_DRBG_CTR *)drbg->data) != NULL) {
EVP_CIPHER_CTX_free(ctr->ctx_ecb);
EVP_CIPHER_CTX_free(ctr->ctx_ctr);
EVP_CIPHER_CTX_free(ctr->ctx_df);
EVP_CIPHER_free(ctr->cipher_ecb);
EVP_CIPHER_free(ctr->cipher_ctr);
OPENSSL_secure_clear_free(ctr, sizeof(*ctr));
}
prov_rand_drbg_free(drbg);
}
static int drbg_ctr_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return drbg_get_ctx_params(drbg, params);
}
static const OSSL_PARAM *drbg_ctr_gettable_ctx_params(void)
{
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_DRBG_GETABLE_CTX_COMMON,
OSSL_PARAM_END
};
return known_gettable_ctx_params;
}
static int drbg_ctr_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_DRBG *ctx = (PROV_DRBG *)vctx;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)ctx->data;
OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
const OSSL_PARAM *p;
char *ecb;
const char *propquery = NULL;
int i, cipher_init = 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_USE_DF)) != NULL
&& OSSL_PARAM_get_int(p, &i)) {
/* FIPS errors out in the drbg_ctr_init() call later */
ctr->use_df = i != 0;
cipher_init = 1;
}
if ((p = OSSL_PARAM_locate_const(params,
OSSL_DRBG_PARAM_PROPERTIES)) != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
propquery = (const char *)p->data;
}
if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_CIPHER)) != NULL) {
const char *base = (const char *)p->data;
if (p->data_type != OSSL_PARAM_UTF8_STRING
|| p->data_size < 3)
return 0;
if (strcasecmp("CTR", base + p->data_size - sizeof("CTR")) != 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER);
return 0;
}
if ((ecb = OPENSSL_strdup(base)) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
strcpy(ecb + p->data_size - sizeof("ECB"), "ECB");
EVP_CIPHER_free(ctr->cipher_ecb);
EVP_CIPHER_free(ctr->cipher_ctr);
ctr->cipher_ctr = EVP_CIPHER_fetch(libctx, base, propquery);
ctr->cipher_ecb = EVP_CIPHER_fetch(libctx, ecb, propquery);
OPENSSL_free(ecb);
if (ctr->cipher_ctr == NULL || ctr->cipher_ecb == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_FIND_CIPHERS);
return 0;
}
cipher_init = 1;
}
if (cipher_init && !drbg_ctr_init(ctx))
return 0;
return drbg_set_ctx_params(ctx, params);
}
static const OSSL_PARAM *drbg_ctr_settable_ctx_params(void)
{
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0),
#ifndef FIPS_MODULE
/*
* Don't advertise this for FIPS, it isn't allowed to change.
* The parameter can still be passed and will be processed but errors
* out.
*/
OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),
#endif
OSSL_PARAM_DRBG_SETABLE_CTX_COMMON,
OSSL_PARAM_END
};
return known_settable_ctx_params;
}
const OSSL_DISPATCH drbg_ctr_functions[] = {
{ OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_ctr_new_wrapper },
{ OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_ctr_free },
{ OSSL_FUNC_RAND_INSTANTIATE,
(void(*)(void))drbg_ctr_instantiate_wrapper },
{ OSSL_FUNC_RAND_UNINSTANTIATE,
(void(*)(void))drbg_ctr_uninstantiate_wrapper },
{ OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_ctr_generate_wrapper },
{ OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_ctr_reseed_wrapper },
{ OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))drbg_enable_locking },
{ OSSL_FUNC_RAND_LOCK, (void(*)(void))drbg_lock },
{ OSSL_FUNC_RAND_UNLOCK, (void(*)(void))drbg_unlock },
{ OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
(void(*)(void))drbg_ctr_settable_ctx_params },
{ OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_ctr_set_ctx_params },
{ OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
(void(*)(void))drbg_ctr_gettable_ctx_params },
{ OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_ctr_get_ctx_params },
{ OSSL_FUNC_RAND_SET_CALLBACKS, (void(*)(void))drbg_set_callbacks },
{ OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
(void(*)(void))drbg_ctr_verify_zeroization },
{ 0, NULL }
};

View File

@ -10,19 +10,50 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/core_numbers.h>
#include "internal/thread_once.h"
#include "prov/providercommon.h"
#include "rand_local.h"
#include "prov/provider_ctx.h"
#include "prov/provider_util.h"
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
#include "drbg_local.h"
static OSSL_OP_rand_newctx_fn drbg_hash_new_wrapper;
static OSSL_OP_rand_freectx_fn drbg_hash_free;
static OSSL_OP_rand_instantiate_fn drbg_hash_instantiate_wrapper;
static OSSL_OP_rand_uninstantiate_fn drbg_hash_uninstantiate_wrapper;
static OSSL_OP_rand_generate_fn drbg_hash_generate_wrapper;
static OSSL_OP_rand_reseed_fn drbg_hash_reseed_wrapper;
static OSSL_OP_rand_settable_ctx_params_fn drbg_hash_settable_ctx_params;
static OSSL_OP_rand_set_ctx_params_fn drbg_hash_set_ctx_params;
static OSSL_OP_rand_gettable_ctx_params_fn drbg_hash_gettable_ctx_params;
static OSSL_OP_rand_get_ctx_params_fn drbg_hash_get_ctx_params;
static OSSL_OP_rand_verify_zeroization_fn drbg_hash_verify_zeroization;
/* 888 bits from SP800-90Ar1 10.1 table 2 */
#define HASH_PRNG_MAX_SEEDLEN (888/8)
/* 440 bits from SP800-90Ar1 10.1 table 2 */
#define HASH_PRNG_SMALL_SEEDLEN (440/8)
/* Determine what seedlen to use based on the block length */
#define MAX_BLOCKLEN_USING_SMALL_SEEDLEN (256/8)
#define INBYTE_IGNORE ((unsigned char)0xFF)
typedef struct rand_drbg_hash_st {
PROV_DIGEST digest;
EVP_MD_CTX *ctx;
size_t blocklen;
unsigned char V[HASH_PRNG_MAX_SEEDLEN];
unsigned char C[HASH_PRNG_MAX_SEEDLEN];
/* Temporary value storage: should always exceed max digest length */
unsigned char vtmp[HASH_PRNG_MAX_SEEDLEN];
} PROV_DRBG_HASH;
/*
* SP800-90Ar1 10.3.1 Derivation function using a Hash Function (Hash_df).
@ -33,13 +64,13 @@
* in3 - optional input string (Can be NULL).
* These are concatenated as part of the DigestUpdate process.
*/
static int hash_df(RAND_DRBG *drbg, unsigned char *out,
static int hash_df(PROV_DRBG *drbg, unsigned char *out,
const unsigned char inbyte,
const unsigned char *in, size_t inlen,
const unsigned char *in2, size_t in2len,
const unsigned char *in3, size_t in3len)
{
RAND_DRBG_HASH *hash = &drbg->data.hash;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
EVP_MD_CTX *ctx = hash->ctx;
unsigned char *vtmp = hash->vtmp;
/* tmp = counter || num_bits_returned || [inbyte] */
@ -69,7 +100,7 @@ static int hash_df(RAND_DRBG *drbg, unsigned char *out,
* (Step 4.1) out = out || Hash(tmp || in || [in2] || [in3])
* (where tmp = counter || num_bits_returned || [inbyte])
*/
if (!(EVP_DigestInit_ex(ctx, hash->md, NULL)
if (!(EVP_DigestInit_ex(ctx, ossl_prov_digest_md(&hash->digest), NULL)
&& EVP_DigestUpdate(ctx, tmp, tmp_sz)
&& EVP_DigestUpdate(ctx, in, inlen)
&& (in2 == NULL || EVP_DigestUpdate(ctx, in2, in2len))
@ -97,7 +128,7 @@ static int hash_df(RAND_DRBG *drbg, unsigned char *out,
}
/* Helper function that just passes 2 input parameters to hash_df() */
static int hash_df1(RAND_DRBG *drbg, unsigned char *out,
static int hash_df1(PROV_DRBG *drbg, unsigned char *out,
const unsigned char in_byte,
const unsigned char *in1, size_t in1len)
{
@ -110,7 +141,7 @@ static int hash_df1(RAND_DRBG *drbg, unsigned char *out,
* The final carry is ignored i.e: dst = (dst + in) mod (2^seedlen_bits).
* where dst size is drbg->seedlen, and inlen <= drbg->seedlen.
*/
static int add_bytes(RAND_DRBG *drbg, unsigned char *dst,
static int add_bytes(PROV_DRBG *drbg, unsigned char *dst,
unsigned char *in, size_t inlen)
{
size_t i;
@ -141,13 +172,13 @@ static int add_bytes(RAND_DRBG *drbg, unsigned char *dst,
}
/* V = (V + Hash(inbyte || V || [additional_input]) mod (2^seedlen) */
static int add_hash_to_v(RAND_DRBG *drbg, unsigned char inbyte,
static int add_hash_to_v(PROV_DRBG *drbg, unsigned char inbyte,
const unsigned char *adin, size_t adinlen)
{
RAND_DRBG_HASH *hash = &drbg->data.hash;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
EVP_MD_CTX *ctx = hash->ctx;
return EVP_DigestInit_ex(ctx, hash->md, NULL)
return EVP_DigestInit_ex(ctx, ossl_prov_digest_md(&hash->digest), NULL)
&& EVP_DigestUpdate(ctx, &inbyte, 1)
&& EVP_DigestUpdate(ctx, hash->V, drbg->seedlen)
&& (adin == NULL || EVP_DigestUpdate(ctx, adin, adinlen))
@ -173,16 +204,17 @@ static int add_hash_to_v(RAND_DRBG *drbg, unsigned char inbyte,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int hash_gen(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
static int hash_gen(PROV_DRBG *drbg, unsigned char *out, size_t outlen)
{
RAND_DRBG_HASH *hash = &drbg->data.hash;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
unsigned char one = 1;
if (outlen == 0)
return 1;
memcpy(hash->vtmp, hash->V, drbg->seedlen);
for(;;) {
if (!EVP_DigestInit_ex(hash->ctx, hash->md, NULL)
if (!EVP_DigestInit_ex(hash->ctx, ossl_prov_digest_md(&hash->digest),
NULL)
|| !EVP_DigestUpdate(hash->ctx, hash->vtmp, drbg->seedlen))
return 0;
@ -213,20 +245,35 @@ static int hash_gen(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hash_instantiate(RAND_DRBG *drbg,
static int drbg_hash_instantiate(PROV_DRBG *drbg,
const unsigned char *ent, size_t ent_len,
const unsigned char *nonce, size_t nonce_len,
const unsigned char *pstr, size_t pstr_len)
{
RAND_DRBG_HASH *hash = &drbg->data.hash;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
EVP_MD_CTX_free(hash->ctx);
hash->ctx = EVP_MD_CTX_new();
/* (Step 1-3) V = Hash_df(entropy||nonce||pers, seedlen) */
return hash_df(drbg, hash->V, INBYTE_IGNORE,
ent, ent_len, nonce, nonce_len, pstr, pstr_len)
return hash->ctx != NULL
&& hash_df(drbg, hash->V, INBYTE_IGNORE,
ent, ent_len, nonce, nonce_len, pstr, pstr_len)
/* (Step 4) C = Hash_df(0x00||V, seedlen) */
&& hash_df1(drbg, hash->C, 0x00, hash->V, drbg->seedlen);
}
static int drbg_hash_instantiate_wrapper(void *vdrbg, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr,
size_t pstr_len)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return PROV_DRBG_instantiate(drbg, strength, prediction_resistance,
pstr, pstr_len);
}
/*
* SP800-90Ar1 10.1.1.3 Hash_DRBG_Reseed_Process:
*
@ -235,13 +282,13 @@ static int drbg_hash_instantiate(RAND_DRBG *drbg,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hash_reseed(RAND_DRBG *drbg,
static int drbg_hash_reseed(PROV_DRBG *drbg,
const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adin_len)
{
RAND_DRBG_HASH *hash = &drbg->data.hash;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
/* (Step 1-2) V = Hash_df(0x01 || V || entropy_input || additional_input)*/
/* (Step 1-2) V = Hash_df(0x01 || V || entropy_input || additional_input) */
/* V about to be updated so use C as output instead */
if (!hash_df(drbg, hash->C, 0x01, hash->V, drbg->seedlen, ent, ent_len,
adin, adin_len))
@ -251,6 +298,16 @@ static int drbg_hash_reseed(RAND_DRBG *drbg,
return hash_df1(drbg, hash->C, 0x00, hash->V, drbg->seedlen);
}
static int drbg_hash_reseed_wrapper(void *vdrbg, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adin_len)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return PROV_DRBG_reseed(drbg, prediction_resistance, ent, ent_len,
adin, adin_len);
}
/*
* SP800-90Ar1 10.1.1.4 Hash_DRBG_Generate_Process:
*
@ -260,11 +317,11 @@ static int drbg_hash_reseed(RAND_DRBG *drbg,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hash_generate(RAND_DRBG *drbg,
static int drbg_hash_generate(PROV_DRBG *drbg,
unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adin_len)
{
RAND_DRBG_HASH *hash = &drbg->data.hash;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
unsigned char counter[4];
int reseed_counter = drbg->reseed_gen_counter;
@ -273,10 +330,11 @@ static int drbg_hash_generate(RAND_DRBG *drbg,
counter[2] = (unsigned char)((reseed_counter >> 8) & 0xff);
counter[3] = (unsigned char)(reseed_counter & 0xff);
return (adin == NULL
return hash->ctx != NULL
&& (adin == NULL
/* (Step 2) if adin != NULL then V = V + Hash(0x02||V||adin) */
|| adin_len == 0
|| add_hash_to_v(drbg, 0x02, adin, adin_len))
|| adin_len == 0
|| add_hash_to_v(drbg, 0x02, adin, adin_len))
/* (Step 3) Hashgen(outlen, V) */
&& hash_gen(drbg, out, outlen)
/* (Step 4/5) H = V = (V + Hash(0x03||V) mod (2^seedlen_bits) */
@ -288,73 +346,167 @@ static int drbg_hash_generate(RAND_DRBG *drbg,
&& add_bytes(drbg, hash->V, counter, 4);
}
static int drbg_hash_uninstantiate(RAND_DRBG *drbg)
static int drbg_hash_generate_wrapper
(void *vdrbg, unsigned char *out, size_t outlen, unsigned int strength,
int prediction_resistance, const unsigned char *adin, size_t adin_len)
{
EVP_MD_free(drbg->data.hash.md);
EVP_MD_CTX_free(drbg->data.hash.ctx);
OPENSSL_cleanse(&drbg->data.hash, sizeof(drbg->data.hash));
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return PROV_DRBG_generate(drbg, out, outlen, strength,
prediction_resistance, adin, adin_len);
}
static int drbg_hash_uninstantiate(PROV_DRBG *drbg)
{
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
OPENSSL_cleanse(hash->V, sizeof(hash->V));
OPENSSL_cleanse(hash->C, sizeof(hash->C));
OPENSSL_cleanse(hash->vtmp, sizeof(hash->vtmp));
return PROV_DRBG_uninstantiate(drbg);
}
static int drbg_hash_uninstantiate_wrapper(void *vdrbg)
{
return drbg_hash_uninstantiate((PROV_DRBG *)vdrbg);
}
static int drbg_hash_verify_zeroization(void *vdrbg)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
PROV_DRBG_VERYIFY_ZEROIZATION(hash->V);
PROV_DRBG_VERYIFY_ZEROIZATION(hash->C);
PROV_DRBG_VERYIFY_ZEROIZATION(hash->vtmp);
return 1;
}
static RAND_DRBG_METHOD drbg_hash_meth = {
drbg_hash_instantiate,
drbg_hash_reseed,
drbg_hash_generate,
drbg_hash_uninstantiate
};
int drbg_hash_init(RAND_DRBG *drbg)
static int drbg_hash_new(PROV_DRBG *ctx)
{
EVP_MD *md;
RAND_DRBG_HASH *hash = &drbg->data.hash;
PROV_DRBG_HASH *hash;
/*
* Confirm digest is allowed. We allow all digests that are not XOF
* (such as SHAKE). In FIPS mode, the fetch will fail for non-approved
* digests.
*/
md = EVP_MD_fetch(drbg->libctx, ossl_prov_util_nid_to_name(drbg->type), "");
if (md == NULL)
hash = OPENSSL_secure_zalloc(sizeof(*hash));
if (hash == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
if ((EVP_MD_flags(md) & EVP_MD_FLAG_XOF) != 0)
return 0;
drbg->meth = &drbg_hash_meth;
if (hash->ctx == NULL) {
hash->ctx = EVP_MD_CTX_new();
if (hash->ctx == NULL) {
EVP_MD_free(md);
return 0;
}
}
EVP_MD_free(hash->md);
hash->md = md;
/* These are taken from SP 800-90 10.1 Table 2 */
hash->blocklen = EVP_MD_size(md);
/* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
drbg->strength = 64 * (hash->blocklen >> 3);
if (drbg->strength > 256)
drbg->strength = 256;
if (hash->blocklen > MAX_BLOCKLEN_USING_SMALL_SEEDLEN)
drbg->seedlen = HASH_PRNG_MAX_SEEDLEN;
else
drbg->seedlen = HASH_PRNG_SMALL_SEEDLEN;
drbg->min_entropylen = drbg->strength / 8;
drbg->max_entropylen = DRBG_MAX_LENGTH;
drbg->min_noncelen = drbg->min_entropylen / 2;
drbg->max_noncelen = DRBG_MAX_LENGTH;
drbg->max_perslen = DRBG_MAX_LENGTH;
drbg->max_adinlen = DRBG_MAX_LENGTH;
ctx->data = hash;
ctx->seedlen = HASH_PRNG_MAX_SEEDLEN;
ctx->max_entropylen = DRBG_MAX_LENGTH;
ctx->max_noncelen = DRBG_MAX_LENGTH;
ctx->max_perslen = DRBG_MAX_LENGTH;
ctx->max_adinlen = DRBG_MAX_LENGTH;
/* Maximum number of bits per request = 2^19 = 2^16 bytes */
drbg->max_request = 1 << 16;
ctx->max_request = 1 << 16;
return 1;
}
static void *drbg_hash_new_wrapper(void *provctx, void *parent,
const OSSL_DISPATCH *parent_dispatch)
{
return prov_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_hash_new,
&drbg_hash_instantiate, &drbg_hash_uninstantiate,
&drbg_hash_reseed, &drbg_hash_generate);
}
static void drbg_hash_free(void *vdrbg)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_HASH *hash;
if (drbg != NULL && (hash = (PROV_DRBG_HASH *)drbg->data) != NULL) {
EVP_MD_CTX_free(hash->ctx);
ossl_prov_digest_reset(&hash->digest);
OPENSSL_secure_clear_free(hash, sizeof(*hash));
}
prov_rand_drbg_free(drbg);
}
static int drbg_hash_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return drbg_get_ctx_params(drbg, params);
}
static const OSSL_PARAM *drbg_hash_gettable_ctx_params(void)
{
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_DRBG_GETABLE_CTX_COMMON,
OSSL_PARAM_END
};
return known_gettable_ctx_params;
}
static int drbg_hash_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_DRBG *ctx = (PROV_DRBG *)vctx;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)ctx->data;
OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
const EVP_MD *md;
if (!ossl_prov_digest_load_from_params(&hash->digest, params, libctx))
return 0;
md = ossl_prov_digest_md(&hash->digest);
if (md != NULL) {
if ((EVP_MD_flags(md) & EVP_MD_FLAG_XOF) != 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
return 0;
}
/* These are taken from SP 800-90 10.1 Table 2 */
hash->blocklen = EVP_MD_size(md);
/* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
ctx->strength = 64 * (hash->blocklen >> 3);
if (ctx->strength > 256)
ctx->strength = 256;
if (hash->blocklen > MAX_BLOCKLEN_USING_SMALL_SEEDLEN)
ctx->seedlen = HASH_PRNG_MAX_SEEDLEN;
else
ctx->seedlen = HASH_PRNG_SMALL_SEEDLEN;
ctx->min_entropylen = ctx->strength / 8;
ctx->min_noncelen = ctx->min_entropylen / 2;
}
return drbg_set_ctx_params(ctx, params);
}
static const OSSL_PARAM *drbg_hash_settable_ctx_params(void)
{
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_DRBG_SETABLE_CTX_COMMON,
OSSL_PARAM_END
};
return known_settable_ctx_params;
}
const OSSL_DISPATCH drbg_hash_functions[] = {
{ OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_hash_new_wrapper },
{ OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_hash_free },
{ OSSL_FUNC_RAND_INSTANTIATE,
(void(*)(void))drbg_hash_instantiate_wrapper },
{ OSSL_FUNC_RAND_UNINSTANTIATE,
(void(*)(void))drbg_hash_uninstantiate_wrapper },
{ OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_hash_generate_wrapper },
{ OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_hash_reseed_wrapper },
{ OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))drbg_enable_locking },
{ OSSL_FUNC_RAND_LOCK, (void(*)(void))drbg_lock },
{ OSSL_FUNC_RAND_UNLOCK, (void(*)(void))drbg_unlock },
{ OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
(void(*)(void))drbg_hash_settable_ctx_params },
{ OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_hash_set_ctx_params },
{ OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
(void(*)(void))drbg_hash_gettable_ctx_params },
{ OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_hash_get_ctx_params },
{ OSSL_FUNC_RAND_SET_CALLBACKS, (void(*)(void))drbg_set_callbacks },
{ OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
(void(*)(void))drbg_hash_verify_zeroization },
{ 0, NULL }
};

View File

@ -7,20 +7,38 @@
* https://www.openssl.org/source/license.html
*/
/*
* HMAC low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include <stdlib.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include "prov/provider_util.h"
#include "internal/thread_once.h"
#include "prov/providercommon.h"
#include "rand_local.h"
#include "prov/providercommonerr.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "drbg_local.h"
static OSSL_OP_rand_newctx_fn drbg_hmac_new_wrapper;
static OSSL_OP_rand_freectx_fn drbg_hmac_free;
static OSSL_OP_rand_instantiate_fn drbg_hmac_instantiate_wrapper;
static OSSL_OP_rand_uninstantiate_fn drbg_hmac_uninstantiate_wrapper;
static OSSL_OP_rand_generate_fn drbg_hmac_generate_wrapper;
static OSSL_OP_rand_reseed_fn drbg_hmac_reseed_wrapper;
static OSSL_OP_rand_settable_ctx_params_fn drbg_hmac_settable_ctx_params;
static OSSL_OP_rand_set_ctx_params_fn drbg_hmac_set_ctx_params;
static OSSL_OP_rand_gettable_ctx_params_fn drbg_hmac_gettable_ctx_params;
static OSSL_OP_rand_get_ctx_params_fn drbg_hmac_get_ctx_params;
static OSSL_OP_rand_verify_zeroization_fn drbg_hmac_verify_zeroization;
typedef struct rand_drbg_hmac_st {
EVP_MAC_CTX *ctx; /* H(x) = HMAC_hash OR H(x) = KMAC */
PROV_DIGEST digest; /* H(x) = hash(x) */
size_t blocklen;
unsigned char K[EVP_MAX_MD_SIZE];
unsigned char V[EVP_MAX_MD_SIZE];
} PROV_DRBG_HMAC;
/*
* Called twice by SP800-90Ar1 10.1.2.2 HMAC_DRBG_Update_Process.
@ -36,25 +54,34 @@
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int do_hmac(RAND_DRBG_HMAC *hmac, unsigned char inbyte,
static int do_hmac(PROV_DRBG_HMAC *hmac, unsigned char inbyte,
const unsigned char *in1, size_t in1len,
const unsigned char *in2, size_t in2len,
const unsigned char *in3, size_t in3len)
{
HMAC_CTX *ctx = hmac->ctx;
EVP_MAC_CTX *ctx = hmac->ctx;
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
return HMAC_Init_ex(ctx, hmac->K, hmac->blocklen, hmac->md, NULL)
/* K = HMAC(K, V || inbyte || [in1] || [in2] || [in3]) */
&& HMAC_Update(ctx, hmac->V, hmac->blocklen)
&& HMAC_Update(ctx, &inbyte, 1)
&& (in1 == NULL || in1len == 0 || HMAC_Update(ctx, in1, in1len))
&& (in2 == NULL || in2len == 0 || HMAC_Update(ctx, in2, in2len))
&& (in3 == NULL || in3len == 0 || HMAC_Update(ctx, in3, in3len))
&& HMAC_Final(ctx, hmac->K, NULL)
/* V = HMAC(K, V) */
&& HMAC_Init_ex(ctx, hmac->K, hmac->blocklen, hmac->md, NULL)
&& HMAC_Update(ctx, hmac->V, hmac->blocklen)
&& HMAC_Final(ctx, hmac->V, NULL);
*params = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, hmac->K,
hmac->blocklen);
if (!EVP_MAC_set_ctx_params(ctx, params)
|| !EVP_MAC_init(ctx)
/* K = HMAC(K, V || inbyte || [in1] || [in2] || [in3]) */
|| !EVP_MAC_update(ctx, hmac->V, hmac->blocklen)
|| !EVP_MAC_update(ctx, &inbyte, 1)
|| !(in1 == NULL || in1len == 0 || EVP_MAC_update(ctx, in1, in1len))
|| !(in2 == NULL || in2len == 0 || EVP_MAC_update(ctx, in2, in2len))
|| !(in3 == NULL || in3len == 0 || EVP_MAC_update(ctx, in3, in3len))
|| !EVP_MAC_final(ctx, hmac->K, NULL, sizeof(hmac->K)))
return 0;
/* V = HMAC(K, V) */
*params = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, hmac->K,
hmac->blocklen);
return EVP_MAC_set_ctx_params(ctx, params)
&& EVP_MAC_init(ctx)
&& EVP_MAC_update(ctx, hmac->V, hmac->blocklen)
&& EVP_MAC_final(ctx, hmac->V, NULL, sizeof(hmac->V));
}
/*
@ -71,12 +98,12 @@ static int do_hmac(RAND_DRBG_HMAC *hmac, unsigned char inbyte,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hmac_update(RAND_DRBG *drbg,
static int drbg_hmac_update(PROV_DRBG *drbg,
const unsigned char *in1, size_t in1len,
const unsigned char *in2, size_t in2len,
const unsigned char *in3, size_t in3len)
{
RAND_DRBG_HMAC *hmac = &drbg->data.hmac;
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
/* (Steps 1-2) K = HMAC(K, V||0x00||provided_data). V = HMAC(K,V) */
if (!do_hmac(hmac, 0x00, in1, in1len, in2, in2len, in3, in3len))
@ -99,12 +126,17 @@ static int drbg_hmac_update(RAND_DRBG *drbg,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hmac_instantiate(RAND_DRBG *drbg,
static int drbg_hmac_instantiate(PROV_DRBG *drbg,
const unsigned char *ent, size_t ent_len,
const unsigned char *nonce, size_t nonce_len,
const unsigned char *pstr, size_t pstr_len)
{
RAND_DRBG_HMAC *hmac = &drbg->data.hmac;
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
if (hmac->ctx == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC);
return 0;
}
/* (Step 2) Key = 0x00 00...00 */
memset(hmac->K, 0x00, hmac->blocklen);
@ -115,6 +147,17 @@ static int drbg_hmac_instantiate(RAND_DRBG *drbg,
pstr_len);
}
static int drbg_hmac_instantiate_wrapper(void *vdrbg, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr,
size_t pstr_len)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return PROV_DRBG_instantiate(drbg, strength, prediction_resistance,
pstr, pstr_len);
}
/*
* SP800-90Ar1 10.1.2.4 HMAC_DRBG_Reseed_Process:
*
@ -125,7 +168,7 @@ static int drbg_hmac_instantiate(RAND_DRBG *drbg,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hmac_reseed(RAND_DRBG *drbg,
static int drbg_hmac_reseed(PROV_DRBG *drbg,
const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adin_len)
{
@ -133,6 +176,16 @@ static int drbg_hmac_reseed(RAND_DRBG *drbg,
return drbg_hmac_update(drbg, ent, ent_len, adin, adin_len, NULL, 0);
}
static int drbg_hmac_reseed_wrapper(void *vdrbg, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adin_len)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return PROV_DRBG_reseed(drbg, prediction_resistance, ent, ent_len,
adin, adin_len);
}
/*
* SP800-90Ar1 10.1.2.5 HMAC_DRBG_Generate_Process:
*
@ -142,13 +195,14 @@ static int drbg_hmac_reseed(RAND_DRBG *drbg,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hmac_generate(RAND_DRBG *drbg,
static int drbg_hmac_generate(PROV_DRBG *drbg,
unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adin_len)
{
RAND_DRBG_HMAC *hmac = &drbg->data.hmac;
HMAC_CTX *ctx = hmac->ctx;
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
EVP_MAC_CTX *ctx = hmac->ctx;
const unsigned char *temp = hmac->V;
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
/* (Step 2) if adin != NULL then (K,V) = HMAC_DRBG_Update(adin, K, V) */
if (adin != NULL
@ -164,16 +218,19 @@ static int drbg_hmac_generate(RAND_DRBG *drbg,
* }
*/
for (;;) {
if (!HMAC_Init_ex(ctx, hmac->K, hmac->blocklen, hmac->md, NULL)
|| !HMAC_Update(ctx, temp, hmac->blocklen))
*params = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
hmac->K, hmac->blocklen);
if (!EVP_MAC_set_ctx_params(ctx, params)
|| !EVP_MAC_init(ctx)
|| !EVP_MAC_update(ctx, temp, hmac->blocklen))
return 0;
if (outlen > hmac->blocklen) {
if (!HMAC_Final(ctx, out, NULL))
if (!EVP_MAC_final(ctx, out, NULL, outlen))
return 0;
temp = out;
} else {
if (!HMAC_Final(ctx, hmac->V, NULL))
if (!EVP_MAC_final(ctx, hmac->V, NULL, sizeof(hmac->V)))
return 0;
memcpy(out, hmac->V, outlen);
break;
@ -188,69 +245,171 @@ static int drbg_hmac_generate(RAND_DRBG *drbg,
return 1;
}
static int drbg_hmac_uninstantiate(RAND_DRBG *drbg)
static int drbg_hmac_generate_wrapper
(void *vdrbg, unsigned char *out, size_t outlen, unsigned int strength,
int prediction_resistance, const unsigned char *adin, size_t adin_len)
{
EVP_MD_free(drbg->data.hmac.md);
HMAC_CTX_free(drbg->data.hmac.ctx);
OPENSSL_cleanse(&drbg->data.hmac, sizeof(drbg->data.hmac));
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return PROV_DRBG_generate(drbg, out, outlen, strength,
prediction_resistance, adin, adin_len);
}
static int drbg_hmac_uninstantiate(PROV_DRBG *drbg)
{
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
OPENSSL_cleanse(hmac->K, sizeof(hmac->K));
OPENSSL_cleanse(hmac->V, sizeof(hmac->V));
return PROV_DRBG_uninstantiate(drbg);
}
static int drbg_hmac_uninstantiate_wrapper(void *vdrbg)
{
return drbg_hmac_uninstantiate((PROV_DRBG *)vdrbg);
}
static int drbg_hmac_verify_zeroization(void *vdrbg)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
PROV_DRBG_VERYIFY_ZEROIZATION(hmac->K);
PROV_DRBG_VERYIFY_ZEROIZATION(hmac->V);
return 1;
}
static RAND_DRBG_METHOD drbg_hmac_meth = {
drbg_hmac_instantiate,
drbg_hmac_reseed,
drbg_hmac_generate,
drbg_hmac_uninstantiate
};
int drbg_hmac_init(RAND_DRBG *drbg)
static int drbg_hmac_new(PROV_DRBG *drbg)
{
EVP_MD *md = NULL;
RAND_DRBG_HMAC *hmac = &drbg->data.hmac;
PROV_DRBG_HMAC *hmac;
hmac = OPENSSL_secure_zalloc(sizeof(*hmac));
if (hmac == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
drbg->data = hmac;
/* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
drbg->max_entropylen = DRBG_MAX_LENGTH;
drbg->max_noncelen = DRBG_MAX_LENGTH;
drbg->max_perslen = DRBG_MAX_LENGTH;
drbg->max_adinlen = DRBG_MAX_LENGTH;
/* Maximum number of bits per request = 2^19 = 2^16 bytes */
drbg->max_request = 1 << 16;
return 1;
}
static void *drbg_hmac_new_wrapper(void *provctx, void *parent,
const OSSL_DISPATCH *parent_dispatch)
{
return prov_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_hmac_new,
&drbg_hmac_instantiate, &drbg_hmac_uninstantiate,
&drbg_hmac_reseed, &drbg_hmac_generate);
}
static void drbg_hmac_free(void *vdrbg)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_HMAC *hmac;
if (drbg != NULL && (hmac = (PROV_DRBG_HMAC *)drbg->data) != NULL) {
EVP_MAC_free_ctx(hmac->ctx);
ossl_prov_digest_reset(&hmac->digest);
OPENSSL_secure_clear_free(hmac, sizeof(*hmac));
}
prov_rand_drbg_free(drbg);
}
static int drbg_hmac_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
return drbg_get_ctx_params(drbg, params);
}
static const OSSL_PARAM *drbg_hmac_gettable_ctx_params(void)
{
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_DRBG_GETABLE_CTX_COMMON,
OSSL_PARAM_END
};
return known_gettable_ctx_params;
}
static int drbg_hmac_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_DRBG *ctx = (PROV_DRBG *)vctx;
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)ctx->data;
OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
const EVP_MD *md;
if (!ossl_prov_digest_load_from_params(&hmac->digest, params, libctx))
return 0;
/*
* Confirm digest is allowed. We allow all digests that are not XOF
* (such as SHAKE). In FIPS mode, the fetch will fail for non-approved
* digests.
*/
md = EVP_MD_fetch(drbg->libctx, ossl_prov_util_nid_to_name(drbg->type), "");
if (md == NULL)
md = ossl_prov_digest_md(&hmac->digest);
if (md != NULL && (EVP_MD_flags(md) & EVP_MD_FLAG_XOF) != 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
return 0;
if ((EVP_MD_flags(md) & EVP_MD_FLAG_XOF) != 0)
return 0;
drbg->meth = &drbg_hmac_meth;
if (hmac->ctx == NULL) {
hmac->ctx = HMAC_CTX_new();
if (hmac->ctx == NULL) {
EVP_MD_free(md);
return 0;
}
}
/* These are taken from SP 800-90 10.1 Table 2 */
EVP_MD_free(hmac->md);
hmac->md = md;
hmac->blocklen = EVP_MD_size(md);
/* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
drbg->strength = 64 * (int)(hmac->blocklen >> 3);
if (drbg->strength > 256)
drbg->strength = 256;
drbg->seedlen = hmac->blocklen;
if (!ossl_prov_macctx_load_from_params(&hmac->ctx, params,
NULL, NULL, NULL, libctx))
return 0;
drbg->min_entropylen = drbg->strength / 8;
drbg->max_entropylen = DRBG_MAX_LENGTH;
if (hmac->ctx != NULL) {
/* These are taken from SP 800-90 10.1 Table 2 */
hmac->blocklen = EVP_MD_size(md);
/* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
ctx->strength = 64 * (int)(hmac->blocklen >> 3);
if (ctx->strength > 256)
ctx->strength = 256;
ctx->seedlen = hmac->blocklen;
ctx->min_entropylen = ctx->strength / 8;
ctx->min_noncelen = ctx->min_entropylen / 2;
}
drbg->min_noncelen = drbg->min_entropylen / 2;
drbg->max_noncelen = DRBG_MAX_LENGTH;
drbg->max_perslen = DRBG_MAX_LENGTH;
drbg->max_adinlen = DRBG_MAX_LENGTH;
/* Maximum number of bits per request = 2^19 = 2^16 bytes*/
drbg->max_request = 1 << 16;
return 1;
return drbg_set_ctx_params(ctx, params);
}
static const OSSL_PARAM *drbg_hmac_settable_ctx_params(void)
{
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_MAC, NULL, 0),
OSSL_PARAM_DRBG_SETABLE_CTX_COMMON,
OSSL_PARAM_END
};
return known_settable_ctx_params;
}
const OSSL_DISPATCH drbg_hmac_functions[] = {
{ OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_hmac_new_wrapper },
{ OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_hmac_free },
{ OSSL_FUNC_RAND_INSTANTIATE,
(void(*)(void))drbg_hmac_instantiate_wrapper },
{ OSSL_FUNC_RAND_UNINSTANTIATE,
(void(*)(void))drbg_hmac_uninstantiate_wrapper },
{ OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_hmac_generate_wrapper },
{ OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_hmac_reseed_wrapper },
{ OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))drbg_enable_locking },
{ OSSL_FUNC_RAND_LOCK, (void(*)(void))drbg_lock },
{ OSSL_FUNC_RAND_UNLOCK, (void(*)(void))drbg_unlock },
{ OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
(void(*)(void))drbg_hmac_settable_ctx_params },
{ OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_hmac_set_ctx_params },
{ OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
(void(*)(void))drbg_hmac_gettable_ctx_params },
{ OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_hmac_get_ctx_params },
{ OSSL_FUNC_RAND_SET_CALLBACKS, (void(*)(void))drbg_set_callbacks },
{ OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
(void(*)(void))drbg_hmac_verify_zeroization },
{ 0, NULL }
};

View File

@ -15,7 +15,7 @@
# include <openssl/core_names.h>
# include <openssl/params.h>
# include "internal/tsan_assist.h"
# include "internal/nelem.h"
# include "internal/numbers.h"
/* How many times to read the TSC as a randomness source. */
@ -26,10 +26,8 @@
# define MAX_RESEED_TIME_INTERVAL (1 << 20) /* approx. 12 days */
/* Default reseed intervals */
# define MASTER_RESEED_INTERVAL (1 << 8)
# define SLAVE_RESEED_INTERVAL (1 << 16)
# define MASTER_RESEED_TIME_INTERVAL (60*60) /* 1 hour */
# define SLAVE_RESEED_TIME_INTERVAL (7*60) /* 7 minutes */
# define RESEED_INTERVAL (1 << 8)
# define TIME_INTERVAL (60*60) /* 1 hour */
/*
* The number of bytes that constitutes an atomic lump of entropy with respect
@ -69,47 +67,34 @@ typedef enum drbg_status_e {
} DRBG_STATUS;
/*
* The DRBG methods
*/
typedef struct rand_drbg_hmac_st {
EVP_MD *md;
HMAC_CTX *ctx;
size_t blocklen;
unsigned char K[EVP_MAX_MD_SIZE];
unsigned char V[EVP_MAX_MD_SIZE];
} PROV_DRBG_HMAC;
/*
* The state of a DRBG AES-CTR.
*/
typedef struct rand_drbg_ctr_st {
EVP_CIPHER_CTX *ctx_ecb;
EVP_CIPHER_CTX *ctx_ctr;
EVP_CIPHER_CTX *ctx_df;
EVP_CIPHER *cipher_ecb;
EVP_CIPHER *cipher_ctr;
size_t keylen;
unsigned char K[32];
unsigned char V[16];
/* Temporary block storage used by ctr_df */
unsigned char bltmp[16];
size_t bltmp_pos;
unsigned char KX[48];
} PROV_DRBG_CTR;
/*
* The state of all types of DRBGs, even though we only have CTR mode
* right now.
* The state of all types of DRBGs.
*/
struct prov_drbg_st {
CRYPTO_RWLOCK *lock;
/* The library context this DRBG is associated with, if any */
OPENSSL_CTX *libctx;
void *provctx;
/* Virtual functions are cache here */
int (*instantiate)(PROV_DRBG *drbg,
const unsigned char *entropy, size_t entropylen,
const unsigned char *nonce, size_t noncelen,
const unsigned char *pers, size_t perslen);
int (*uninstantiate)(PROV_DRBG *ctx);
int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adin_len);
int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adin_len);
/* Parent PROV_RAND and its dispatch table functions */
void *parent;
OSSL_OP_rand_enable_locking_fn *parent_enable_locking;
OSSL_OP_rand_lock_fn *parent_lock;
OSSL_OP_rand_unlock_fn *parent_unlock;
OSSL_OP_rand_get_ctx_params_fn *parent_get_ctx_params;
OSSL_OP_rand_generate_fn *parent_generate;
OSSL_OP_rand_nonce_fn *parent_nonce;
const OSSL_DISPATCH *parent_dispatch;
int secure; /* 1: allocated on the secure heap, 0: otherwise */
/*
* Stores the return value of openssl_get_fork_id() as of when we last
* reseeded. The DRBG reseeds automatically whenever drbg->fork_id !=
@ -154,7 +139,7 @@ struct prov_drbg_st {
* clarification.
*/
int strength;
unsigned int strength;
size_t max_request;
size_t min_entropylen, max_entropylen;
size_t min_noncelen, max_noncelen;
@ -188,83 +173,100 @@ struct prov_drbg_st {
* is added by PROV_add() or PROV_seed() will have an immediate effect on
* the output of PROV_bytes() resp. PROV_priv_bytes().
*/
TSAN_QUALIFIER unsigned int reseed_prop_counter;
TSAN_QUALIFIER unsigned int reseed_counter;
unsigned int reseed_next_counter;
unsigned int parent_reseed_counter;
size_t seedlen;
DRBG_STATUS state;
/* DRBG specific data */
void *data;
#ifndef FIPS_MODULE
/* Application data, mainly used in the KATs. */
CRYPTO_EX_DATA ex_data;
#endif
/* Entropy and nonce gathering callbacks */
void *callback_arg;
OSSL_INOUT_CALLBACK *get_entropy_fn;
OSSL_CALLBACK *cleanup_entropy_fn;
OSSL_INOUT_CALLBACK *get_nonce_fn;
OSSL_CALLBACK *cleanup_nonce_fn;
};
/* DRBG helpers */
int rand_drbg_restart(PROV_DRBG *drbg,
const unsigned char *buffer, size_t len, size_t entropy);
size_t rand_drbg_seedlen(PROV_DRBG *drbg);
PROV_DRBG *prov_rand_drbg_new
(void *provctx, void *parent, const OSSL_DISPATCH *parent_dispatch,
int (*dnew)(PROV_DRBG *ctx),
int (*instantiate)(PROV_DRBG *drbg,
const unsigned char *entropy, size_t entropylen,
const unsigned char *nonce, size_t noncelen,
const unsigned char *pers, size_t perslen),
int (*uninstantiate)(PROV_DRBG *ctx),
int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adin_len),
int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adin_len));
void prov_rand_drbg_free(PROV_DRBG *drbg);
PROV_DRBG *prov_rand_drbg_new(void *provctx, int secure, void *parent,
const OSSL_DISPATCH *parent_dispatch,
int (*dnew)(PROV_DRBG *ctx, int secure));
void prov_rand_free(PROV_DRBG *drbg);
int PROV_DRBG_instantiate(PROV_DRBG *drbg, int strength,
int PROV_DRBG_instantiate(PROV_DRBG *drbg, unsigned int strength,
int prediction_resistance,
const unsigned char *pers, size_t perslen,
int (*ifnc)(PROV_DRBG *drbg,
const unsigned char *ent, size_t ent_len,
const unsigned char *nonce,
size_t nonce_len,
const unsigned char *pstr,
size_t pstr_len));
const unsigned char *pers, size_t perslen);
int PROV_DRBG_uninstantiate(PROV_DRBG *drbg);
int PROV_DRBG_reseed(PROV_DRBG *drbg, int prediction_resistance,
const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adinlen,
int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent,
size_t ent_len, const unsigned char *adin,
size_t adin_len));
const unsigned char *adin, size_t adinlen);
int PROV_DRBG_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,
int strength, int prediction_resistance,
const unsigned char *adin, size_t adinlen,
int (*generate)(PROV_DRBG *, unsigned char *out,
size_t outlen, const unsigned char *adin,
size_t adin_len),
int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent,
size_t ent_len, const unsigned char *adin,
size_t adin_len));
unsigned int strength, int prediction_resistance,
const unsigned char *adin, size_t adinlen);
/*
* Entropy call back for the FIPS 140-2 section 4.9.2 Conditional Tests.
* These need to be exposed for the unit tests.
*/
int drbg_set_callbacks(void *vctx, OSSL_INOUT_CALLBACK *get_entropy_fn,
OSSL_CALLBACK *cleanup_entropy_fn,
OSSL_INOUT_CALLBACK *get_nonce_fn,
OSSL_CALLBACK *cleanup_nonce_fn, void *arg);
/* Verify that an array of numeric values is all zero */
#define PROV_DRBG_VERYIFY_ZEROIZATION(v) \
{ \
size_t i; \
\
for (i = 0; i < OSSL_NELEM(v); i++) \
if ((v)[i] != 0) \
return 0; \
}
/* locking api */
OSSL_OP_rand_enable_locking_fn drbg_enable_locking;
OSSL_OP_rand_lock_fn drbg_lock;
OSSL_OP_rand_unlock_fn drbg_unlock;
/* Common parameters for all of our DRBGs */
int drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[]);
int drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[]);
#define OSSL_PARAM_DRBG_SETABLE_CTX_COMMON \
OSSL_PARAM_uint(OSSL_RAND_PARAM_RESEED_REQUESTS, NULL), \
OSSL_PARAM_uint64(OSSL_RAND_PARAM_RESEED_TIME_INTERVAL, NULL)
OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, NULL), \
OSSL_PARAM_uint64(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, NULL)
#define OSSL_PARAM_DRBG_GETABLE_CTX_COMMON \
OSSL_PARAM_int(OSSL_RAND_PARAM_STATUS, NULL), \
OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL), \
OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL), \
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL), \
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MIN_ENTROPYLEN, NULL), \
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_ENTROPYLEN, NULL), \
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MIN_NONCELEN, NULL), \
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_NONCELEN, NULL), \
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_PERSLEN, NULL), \
OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_ADINLEN, NULL), \
OSSL_PARAM_uint(OSSL_RAND_PARAM_RESEED_CTR, NULL), \
OSSL_PARAM_uint(OSSL_RAND_PARAM_RESEED_REQUESTS, NULL), \
OSSL_PARAM_uint64(OSSL_RAND_PARAM_RESEED_TIME_INTERVAL, NULL)
OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_REQUEST, NULL), \
OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MIN_ENTROPYLEN, NULL), \
OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_ENTROPYLEN, NULL), \
OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MIN_NONCELEN, NULL), \
OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_NONCELEN, NULL), \
OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_PERSLEN, NULL), \
OSSL_PARAM_size_t(OSSL_DRBG_PARAM_MAX_ADINLEN, NULL), \
OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_CTR, NULL), \
OSSL_PARAM_time_t(OSSL_DRBG_PARAM_RESEED_TIME, NULL), \
OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, NULL), \
OSSL_PARAM_uint64(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, NULL)
/* Continuous test "entropy" calls */
size_t prov_crngt_get_entropy(PROV_DRBG *drbg,
unsigned char **pout,
int entropy, size_t min_len, size_t max_len,
@ -272,16 +274,4 @@ size_t prov_crngt_get_entropy(PROV_DRBG *drbg,
void prov_crngt_cleanup_entropy(PROV_DRBG *drbg,
unsigned char *out, size_t outlen);
/*
* Entropy call back for the FIPS 140-2 section 4.9.2 Conditional Tests.
* These need to be exposed for the unit tests.
*/
#if 0
int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx, PROV_POOL *pool,
unsigned char *buf, unsigned char *md,
unsigned int *md_size);
extern int (*crngt_get_entropy)(OPENSSL_CTX *ctx, PROV_POOL *pool,
unsigned char *buf, unsigned char *md,
unsigned int *md_size);
#endif
#endif

View File

@ -36,7 +36,7 @@ typedef struct {
unsigned int strength;
} PROV_TEST_RNG;
static int test_rng_new(PROV_DRBG *ctx, int secure)
static int test_rng_new(PROV_DRBG *ctx)
{
PROV_TEST_RNG *t;
@ -50,17 +50,9 @@ static int test_rng_new(PROV_DRBG *ctx, int secure)
ctx->max_perslen = INT_MAX;
ctx->max_adinlen = INT_MAX;
ctx->max_request = INT_MAX;
ctx->strength = 1024;
return 1;
}
static void *test_rng_new_wrapper(void *provctx, int secure, void *parent,
const OSSL_DISPATCH *parent_dispatch)
{
return prov_rand_drbg_new(provctx, secure, parent, parent_dispatch,
&test_rng_new);
}
static void test_rng_free(void *vdrbg)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
@ -111,7 +103,7 @@ static int test_rng_uninstantiate(PROV_DRBG *drbg)
PROV_TEST_RNG *t = (PROV_TEST_RNG *)drbg->data;
t->entropy_pos = 0;
return 1;
return PROV_DRBG_uninstantiate(drbg);
}
static int test_rng_uninstantiate_wrapper(void *vdrbg)
@ -169,15 +161,6 @@ static int test_rng_reseed_wrapper(void *vdrbg, int prediction_resistance,
return test_rng_reseed((PROV_DRBG *)vdrbg, ent, ent_len, adin, adin_len);
}
static void *test_rng_new_wrapper(void *provctx, void *parent,
const OSSL_DISPATCH *parent_dispatch)
{
return prov_rand_drbg_new(provctx, parent, parent_dispatch,
&test_rng_new, &test_rng_instantiate,
&test_rng_uninstantiate, &test_rng_reseed,
&test_rng_generate);
}
static size_t test_rng_nonce(void *vdrbg, unsigned char *out,
unsigned int strength, size_t min_noncelen,
size_t max_noncelen)
@ -307,6 +290,15 @@ static int test_rng_verify_zeroization(void *vdrbg)
return 1;
}
static void *test_rng_new_wrapper(void *provctx, void *parent,
const OSSL_DISPATCH *parent_dispatch)
{
return prov_rand_drbg_new(provctx, parent, parent_dispatch,
&test_rng_new, &test_rng_instantiate,
&test_rng_uninstantiate, &test_rng_reseed,
&test_rng_generate);
}
const OSSL_DISPATCH test_rng_functions[] = {
{ OSSL_FUNC_RAND_NEWCTX, (void(*)(void))test_rng_new_wrapper },
{ OSSL_FUNC_RAND_FREECTX, (void(*)(void))test_rng_free },