summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/evp/build.info2
-rw-r--r--crypto/evp/evp_local.h18
-rw-r--r--crypto/evp/evp_rand.c (renamed from crypto/evp/rand_meth.c)197
-rw-r--r--crypto/rand/build.info12
-rw-r--r--crypto/rand/drbg_lib.c1056
-rw-r--r--crypto/rand/rand_lib.c309
-rw-r--r--crypto/rand/rand_local.h72
7 files changed, 471 insertions, 1195 deletions
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index edef4930cb..ccd8357453 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -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 \
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index 03a1f36e1b..132534464f 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -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 */ ;
diff --git a/crypto/evp/rand_meth.c b/crypto/evp/evp_rand.c
index 0f1745411d..f7bc321f29 100644
--- a/crypto/evp/rand_meth.c
+++ b/crypto/evp/evp_rand.c
@@ -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;
diff --git a/crypto/rand/build.info b/crypto/rand/build.info
index 7840428045..b7a4d598f1 100644
--- a/crypto/rand/build.info
+++ b/crypto/rand/build.info
@@ -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
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
index 94a4e98d73..80759cbfaf 100644
--- a/crypto/rand/drbg_lib.c
+++ b/crypto/rand/drbg_lib.c
@@ -11,10 +11,10 @@
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
+#include <openssl/core_names.h>
#include "rand_local.h"
#include "internal/thread_once.h"
#include "crypto/rand.h"
-#include "crypto/rand_pool.h"
#include "crypto/cryptlib.h"
/*
@@ -37,6 +37,7 @@ typedef struct drbg_global_st {
*
* There are three shared DRBG instances: <master>, <public>, and <private>.
*/
+ CRYPTO_RWLOCK *lock;
/*
* The <master> DRBG
@@ -70,14 +71,6 @@ typedef struct drbg_global_st {
CRYPTO_THREAD_LOCAL private_drbg;
} DRBG_GLOBAL;
-typedef struct drbg_nonce_global_st {
- CRYPTO_RWLOCK *rand_nonce_lock;
- int rand_nonce_count;
-} DRBG_NONCE_GLOBAL;
-
-/* NIST SP 800-90A DRBG recommends the use of a personalization string. */
-static const char ossl_pers_string[] = DRBG_DEFAULT_PERS_STRING;
-
#define RAND_DRBG_TYPE_FLAGS ( \
RAND_DRBG_FLAG_MASTER | RAND_DRBG_FLAG_PUBLIC | RAND_DRBG_FLAG_PRIVATE )
@@ -110,45 +103,76 @@ static const unsigned int rand_drbg_used_flags =
static RAND_DRBG *drbg_setup(OPENSSL_CTX *ctx, RAND_DRBG *parent, int drbg_type);
-static RAND_DRBG *rand_drbg_new(OPENSSL_CTX *ctx,
- int secure,
- int type,
- unsigned int flags,
- RAND_DRBG *parent);
-
-static int rand_drbg_set(RAND_DRBG *drbg, int type, unsigned int flags);
-static int rand_drbg_init_method(RAND_DRBG *drbg);
-
-static int is_ctr(int type)
+static int get_drbg_params(int type, unsigned int flags, const char **name,
+ OSSL_PARAM params[3])
{
+ OSSL_PARAM *p = params;
+
switch (type) {
- case NID_aes_128_ctr:
- case NID_aes_192_ctr:
- case NID_aes_256_ctr:
+ case 0:
return 1;
default:
return 0;
+
+#define CTR(v) \
+ *name = "CTR-DRBG"; \
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, v, 0)
+
+ case NID_aes_128_ctr:
+ CTR(SN_aes_128_ctr);
+ break;
+ case NID_aes_192_ctr:
+ CTR(SN_aes_192_ctr);
+ break;
+ case NID_aes_256_ctr:
+ CTR(SN_aes_256_ctr);
+ break;
+
+#define DGST(v) \
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST, v, 0); \
+ if ((flags & RAND_DRBG_FLAG_HMAC) == 0) { \
+ *name = "HASH-DRBG"; \
+ } else { \
+ *name = "HMAC-DRBG"; \
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_MAC, \
+ SN_hmac, 0); \
}
-}
-static int is_digest(int type)
-{
- switch (type) {
case NID_sha1:
+ DGST(SN_sha1);
+ break;
case NID_sha224:
+ DGST(SN_sha224);
+ break;
case NID_sha256:
+ DGST(SN_sha256);
+ break;
case NID_sha384:
+ DGST(SN_sha384);
+ break;
case NID_sha512:
+ DGST(SN_sha512);
+ break;
case NID_sha512_224:
+ DGST(SN_sha512_224);
+ break;
case NID_sha512_256:
+ DGST(SN_sha512_256);
+ break;
case NID_sha3_224:
+ DGST(SN_sha3_224);
+ break;
case NID_sha3_256:
+ DGST(SN_sha3_256);
+ break;
case NID_sha3_384:
+ DGST(SN_sha3_384);
+ break;
case NID_sha3_512:
- return 1;
- default:
- return 0;
+ DGST(SN_sha3_512);
}
+ *p = OSSL_PARAM_construct_end();
+ return 1;
}
/*
@@ -170,23 +194,23 @@ static void *drbg_ossl_ctx_new(OPENSSL_CTX *libctx)
OPENSSL_init_crypto(0, NULL);
#endif
+ dgbl->lock = CRYPTO_THREAD_lock_new();
+ if (dgbl->lock == NULL)
+ goto err0;
+
if (!CRYPTO_THREAD_init_local(&dgbl->private_drbg, NULL))
goto err1;
if (!CRYPTO_THREAD_init_local(&dgbl->public_drbg, NULL))
goto err2;
- dgbl->master_drbg = drbg_setup(libctx, NULL, RAND_DRBG_TYPE_MASTER);
- if (dgbl->master_drbg == NULL)
- goto err3;
-
return dgbl;
- err3:
- CRYPTO_THREAD_cleanup_local(&dgbl->public_drbg);
err2:
CRYPTO_THREAD_cleanup_local(&dgbl->private_drbg);
err1:
+ CRYPTO_THREAD_lock_free(dgbl->lock);
+ err0:
OPENSSL_free(dgbl);
return NULL;
}
@@ -198,6 +222,7 @@ static void drbg_ossl_ctx_free(void *vdgbl)
if (dgbl == NULL)
return;
+ CRYPTO_THREAD_lock_free(dgbl->lock);
RAND_DRBG_free(dgbl->master_drbg);
CRYPTO_THREAD_cleanup_local(&dgbl->private_drbg);
CRYPTO_THREAD_cleanup_local(&dgbl->public_drbg);
@@ -210,104 +235,12 @@ static const OPENSSL_CTX_METHOD drbg_ossl_ctx_method = {
drbg_ossl_ctx_free,
};
-/*
- * drbg_ossl_ctx_new() calls drgb_setup() which calls rand_drbg_get_nonce()
- * which needs to get the rand_nonce_lock out of the OPENSSL_CTX...but since
- * drbg_ossl_ctx_new() hasn't finished running yet we need the rand_nonce_lock
- * to be in a different global data object. Otherwise we will go into an
- * infinite recursion loop.
- */
-static void *drbg_nonce_ossl_ctx_new(OPENSSL_CTX *libctx)
-{
- DRBG_NONCE_GLOBAL *dngbl = OPENSSL_zalloc(sizeof(*dngbl));
-
- if (dngbl == NULL)
- return NULL;
-
- dngbl->rand_nonce_lock = CRYPTO_THREAD_lock_new();
- if (dngbl->rand_nonce_lock == NULL) {
- OPENSSL_free(dngbl);
- return NULL;
- }
-
- return dngbl;
-}
-
-static void drbg_nonce_ossl_ctx_free(void *vdngbl)
-{
- DRBG_NONCE_GLOBAL *dngbl = vdngbl;
-
- if (dngbl == NULL)
- return;
-
- CRYPTO_THREAD_lock_free(dngbl->rand_nonce_lock);
-
- OPENSSL_free(dngbl);
-}
-
-static const OPENSSL_CTX_METHOD drbg_nonce_ossl_ctx_method = {
- drbg_nonce_ossl_ctx_new,
- drbg_nonce_ossl_ctx_free,
-};
-
static DRBG_GLOBAL *drbg_get_global(OPENSSL_CTX *libctx)
{
return openssl_ctx_get_data(libctx, OPENSSL_CTX_DRBG_INDEX,
&drbg_ossl_ctx_method);
}
-/* Implements the get_nonce() callback (see RAND_DRBG_set_callbacks()) */
-size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
- unsigned char **pout,
- int entropy, size_t min_len, size_t max_len)
-{
- size_t ret = 0;
- RAND_POOL *pool;
- DRBG_NONCE_GLOBAL *dngbl
- = openssl_ctx_get_data(drbg->libctx, OPENSSL_CTX_DRBG_NONCE_INDEX,
- &drbg_nonce_ossl_ctx_method);
- struct {
- void *instance;
- int count;
- } data;
-
- if (dngbl == NULL)
- return 0;
-
- memset(&data, 0, sizeof(data));
- pool = rand_pool_new(0, 0, min_len, max_len);
- if (pool == NULL)
- return 0;
-
- if (rand_pool_add_nonce_data(pool) == 0)
- goto err;
-
- data.instance = drbg;
- CRYPTO_atomic_add(&dngbl->rand_nonce_count, 1, &data.count,
- dngbl->rand_nonce_lock);
-
- if (rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0) == 0)
- goto err;
-
- ret = rand_pool_length(pool);
- *pout = rand_pool_detach(pool);
-
- err:
- rand_pool_free(pool);
-
- return ret;
-}
-
-/*
- * Implements the cleanup_nonce() callback (see RAND_DRBG_set_callbacks())
- *
- */
-void rand_drbg_cleanup_nonce(RAND_DRBG *drbg,
- unsigned char *out, size_t outlen)
-{
- OPENSSL_clear_free(out, outlen);
-}
-
/*
* Set the |drbg|'s callback data pointer for the entropy and nonce callbacks
*
@@ -322,8 +255,8 @@ void rand_drbg_cleanup_nonce(RAND_DRBG *drbg,
*/
int RAND_DRBG_set_callback_data(RAND_DRBG *drbg, void *data)
{
- if (drbg->state != DRBG_UNINITIALISED
- || drbg->parent != NULL)
+ if (EVP_RAND_state(drbg->rand) != EVP_RAND_STATE_UNINITIALISED
+ || drbg->parent != NULL)
return 0;
drbg->callback_data = data;
@@ -345,68 +278,71 @@ void *RAND_DRBG_get_callback_data(RAND_DRBG *drbg)
*/
int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags)
{
- return rand_drbg_set(drbg, type, flags) && rand_drbg_init_method(drbg);
-}
+ OSSL_PARAM params[6], *p = params;
+ unsigned int reseed_interval;
+ time_t reseed_time_interval;
+ const char *name = NULL;
+ EVP_RAND *rand;
+ EVP_RAND_CTX *pctx;
+ int use_df;
-static int rand_drbg_set(RAND_DRBG *drbg, int type, unsigned int flags)
-{
if (type == 0 && flags == 0) {
type = rand_drbg_type[RAND_DRBG_TYPE_MASTER];
flags = rand_drbg_flags[RAND_DRBG_TYPE_MASTER];
}
- /* If set is called multiple times - clear the old one */
- if (drbg->type != 0 && (type != drbg->type || flags != drbg->flags)) {
- if (drbg->meth != NULL)
- drbg->meth->uninstantiate(drbg);
- rand_pool_free(drbg->adin_pool);
- drbg->adin_pool = NULL;
+ if (drbg->parent == NULL) {
+ reseed_interval = master_reseed_interval;
+ reseed_time_interval = master_reseed_time_interval;
+ } else {
+ reseed_interval = slave_reseed_interval;
+ reseed_time_interval = slave_reseed_time_interval;
+ }
+ *p++ = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS,
+ &reseed_interval);
+ *p++ = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL,
+ &reseed_time_interval);
+ use_df = (flags & RAND_DRBG_FLAG_CTR_NO_DF) == 0;
+ *p++ = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_USE_DF, &use_df);
+
+ if (!get_drbg_params(type, flags, &name, p)) {
+ RANDerr(0, RAND_R_UNSUPPORTED_DRBG_TYPE);
+ return 0;
}
- drbg->state = DRBG_UNINITIALISED;
+ rand = EVP_RAND_fetch(drbg->libctx, name, NULL);
+ if (rand == NULL) {
+ RANDerr(0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
+ return 0;
+ }
+
+ EVP_RAND_CTX_free(drbg->rand);
+ drbg->rand = NULL;
+
drbg->flags = flags;
drbg->type = type;
- drbg->meth = NULL;
- if (type == 0 || is_ctr(type) || is_digest(type))
- return 1;
+ pctx = drbg->parent != NULL ? drbg->parent->rand : NULL;
+ drbg->rand = EVP_RAND_CTX_new(rand, pctx);
+ EVP_RAND_free(rand);
+ if (drbg->rand == NULL) {
+ RANDerr(0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
+ goto err;
+ }
+ if (!EVP_RAND_set_ctx_params(drbg->rand, params)) {
+ RANDerr(0, RAND_R_ERROR_INITIALISING_DRBG);
+ goto err;
+ }
+ return 1;
+err:
+ EVP_RAND_CTX_free(drbg->rand);
+ drbg->rand = NULL;
drbg->type = 0;
drbg->flags = 0;
- RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_UNSUPPORTED_DRBG_TYPE);
-
return 0;
}
-static int rand_drbg_init_method(RAND_DRBG *drbg)
-{
- int ret;
-
- if (drbg->meth != NULL)
- return 1;
-
- if (is_ctr(drbg->type)) {
- ret = drbg_ctr_init(drbg);
- } else if (is_digest(drbg->type)) {
- if (drbg->flags & RAND_DRBG_FLAG_HMAC)
- ret = drbg_hmac_init(drbg);
- else
- ret = drbg_hash_init(drbg);
- } else {
- /* other cases should already be excluded */
- RANDerr(RAND_F_RAND_DRBG_INIT_METHOD, ERR_R_INTERNAL_ERROR);
- drbg->type = 0;
- drbg->flags = 0;
- return 0;
- }
-
- if (ret == 0) {
- drbg->state = DRBG_ERROR;
- RANDerr(RAND_F_RAND_DRBG_INIT_METHOD, RAND_R_ERROR_INITIALISING_DRBG);
- }
- return ret;
-}
-
/*
* Set/initialize default |type| and |flag| for new drbg instances.
*
@@ -415,7 +351,10 @@ static int rand_drbg_init_method(RAND_DRBG *drbg)
int RAND_DRBG_set_defaults(int type, unsigned int flags)
{
int all;
- if (!(is_digest(type) || is_ctr(type))) {
+ const char *name;
+ OSSL_PARAM params[3];
+
+ if (!get_drbg_params(type, flags, &name, params)) {
RANDerr(RAND_F_RAND_DRBG_SET_DEFAULTS, RAND_R_UNSUPPORTED_DRBG_TYPE);
return 0;
}
@@ -443,20 +382,17 @@ int RAND_DRBG_set_defaults(int type, unsigned int flags)
/*
- * Allocate memory and initialize a new DRBG. The DRBG is allocated on
- * the secure heap if |secure| is nonzero and the secure heap is enabled.
+ * Allocate memory and initialize a new DRBG.
* The |parent|, if not NULL, will be used as random source for reseeding.
*
* Returns a pointer to the new DRBG instance on success, NULL on failure.
*/
static RAND_DRBG *rand_drbg_new(OPENSSL_CTX *ctx,
- int secure,
int type,
unsigned int flags,
RAND_DRBG *parent)
{
- RAND_DRBG *drbg = secure ? OPENSSL_secure_zalloc(sizeof(*drbg))
- : OPENSSL_zalloc(sizeof(*drbg));