diff options
author | Pauli <paul.dale@oracle.com> | 2020-05-08 10:25:19 +1000 |
---|---|---|
committer | Pauli <paul.dale@oracle.com> | 2020-06-24 20:05:42 +1000 |
commit | f000e82898af251442ca52e81fc1ee45996090dc (patch) | |
tree | b378db85b032065a595ce8d7b0422981f09e0d58 /crypto/evp | |
parent | a998b85a4f0e706fa6a07b7feab557d9e570d372 (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.info | 2 | ||||
-rw-r--r-- | crypto/evp/evp_local.h | 18 | ||||
-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; |