mirror of
https://github.com/openssl/openssl.git
synced 2025-03-31 20:10:45 +08:00
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:
parent
a998b85a4f
commit
f000e82898
@ -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 \
|
||||
|
@ -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 */ ;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 }
|
||||
};
|
||||
|
||||
|
@ -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 }
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
@ -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 }
|
||||
};
|
||||
|
@ -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 }
|
||||
};
|
||||
|
@ -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 }
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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 },
|
||||
|
Loading…
x
Reference in New Issue
Block a user