summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorPauli <paul.dale@oracle.com>2020-05-08 10:25:19 +1000
committerPauli <paul.dale@oracle.com>2020-06-24 20:05:42 +1000
commitf000e82898af251442ca52e81fc1ee45996090dc (patch)
treeb378db85b032065a595ce8d7b0422981f09e0d58 /crypto
parenta998b85a4f0e706fa6a07b7feab557d9e570d372 (diff)
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)
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