summaryrefslogtreecommitdiffstats
path: root/crypto/evp
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/evp
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/evp')
-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
3 files changed, 130 insertions, 87 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;