summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorPauli <paul.dale@oracle.com>2020-04-30 14:46:12 +1000
committerPauli <paul.dale@oracle.com>2020-06-24 20:05:41 +1000
commit15dfa092d0e0bb9835942d1e3251e32b2f030d54 (patch)
tree5c182e8fa3d1d1066fade6444df7771a08b248db /crypto
parent922f156545c9c8397abbda49eb640f7a34969231 (diff)
rand: core APIs for provider friendly random.
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/err/openssl.txt47
-rw-r--r--crypto/evp/build.info2
-rw-r--r--crypto/evp/evp_err.c15
-rw-r--r--crypto/evp/evp_local.h36
-rw-r--r--crypto/evp/rand_meth.c384
-rw-r--r--crypto/rand/rand_err.c10
6 files changed, 492 insertions, 2 deletions
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index e5df6bc092..bc39b37cd0 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -375,10 +375,10 @@ CRMF_F_OSSL_CRMF_MSG_PUSH0_REGCTRL:110:OSSL_CRMF_MSG_push0_regCtrl
CRMF_F_OSSL_CRMF_MSG_PUSH0_REGINFO:111:OSSL_CRMF_MSG_push0_regInfo
CRMF_F_OSSL_CRMF_MSG_SET0_EXTENSIONS:112:OSSL_CRMF_MSG_set0_extensions
CRMF_F_OSSL_CRMF_MSG_SET0_SINGLEPUBINFO:113:OSSL_CRMF_MSG_set0_SinglePubInfo
+CRMF_F_OSSL_CRMF_MSG_SET0_VALIDITY:116:OSSL_CRMF_MSG_set0_validity
CRMF_F_OSSL_CRMF_MSG_SET_CERTREQID:114:OSSL_CRMF_MSG_set_certReqId
CRMF_F_OSSL_CRMF_MSG_SET_PKIPUBLICATIONINFO_ACTION:115:\
OSSL_CRMF_MSG_set_PKIPublicationInfo_action
-CRMF_F_OSSL_CRMF_MSG_SET0_VALIDITY:116:OSSL_CRMF_MSG_set0_validity
CRMF_F_OSSL_CRMF_PBMP_NEW:117:OSSL_CRMF_pbmp_new
CRMF_F_OSSL_CRMF_PBM_NEW:118:OSSL_CRMF_pbm_new
CRYPTO_F_CMAC_CTX_NEW:120:CMAC_CTX_new
@@ -2537,6 +2537,7 @@ EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key
EVP_R_FETCH_FAILED:202:fetch failed
EVP_R_FINAL_ERROR:188:final error
EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported
+EVP_R_GENERATE_ERROR:214:generate error
EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS:204:inaccessible domain parameters
@@ -2549,12 +2550,14 @@ EVP_R_INVALID_FIPS_MODE:168:invalid fips mode
EVP_R_INVALID_IV_LENGTH:194:invalid iv length
EVP_R_INVALID_KEY:163:invalid key
EVP_R_INVALID_KEY_LENGTH:130:invalid key length
+EVP_R_INVALID_NULL_ALGORITHM:218:invalid null algorithm
EVP_R_INVALID_OPERATION:148:invalid operation
EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions
EVP_R_INVALID_SALT_LENGTH:186:invalid salt length
EVP_R_KEYGEN_FAILURE:120:keygen failure
EVP_R_KEYMGMT_EXPORT_FAILURE:205:keymgmt export failure
EVP_R_KEY_SETUP_FAILED:180:key setup failed
+EVP_R_LOCKING_NOT_SUPPORTED:213:locking not supported
EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded
EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null
EVP_R_METHOD_NOT_SUPPORTED:144:method not supported
@@ -2584,6 +2587,11 @@ EVP_R_PRIVATE_KEY_ENCODE_ERROR:146:private key encode error
EVP_R_PUBLIC_KEY_NOT_RSA:106:public key not rsa
EVP_R_SET_DEFAULT_PROPERTY_FAILURE:209:set default property failure
EVP_R_TOO_MANY_RECORDS:183:too many records
+EVP_R_UNABLE_TO_ENABLE_PARENT_LOCKING:212:unable to enable parent locking
+EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE:215:unable to get maximum request size
+EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH:216:unable to get random strength
+EVP_R_UNABLE_TO_LOCK_CONTEXT:211:unable to lock context
+EVP_R_UNABLE_TO_SET_CALLBACKS:217:unable to set callbacks
EVP_R_UNKNOWN_CIPHER:160:unknown cipher
EVP_R_UNKNOWN_DIGEST:161:unknown digest
EVP_R_UNKNOWN_KEY_TYPE:207:unknown key type
@@ -2813,8 +2821,10 @@ PROP_R_NO_VALUE:107:no value
PROP_R_PARSE_FAILED:108:parse failed
PROP_R_STRING_TOO_LONG:109:string too long
PROP_R_TRAILING_CHARACTERS:110:trailing characters
+PROV_R_ADDITIONAL_INPUT_TOO_LONG:184:additional input too long
PROV_R_AES_KEY_SETUP_FAILED:101:aes key setup failed
PROV_R_ALGORITHM_MISMATCH:173:algorithm mismatch
+PROV_R_ALREADY_INSTANTIATED:185:already instantiated
PROV_R_BAD_DECRYPT:100:bad decrypt
PROV_R_BAD_ENCODING:141:bad encoding
PROV_R_BAD_LENGTH:142:bad length
@@ -2822,16 +2832,26 @@ PROV_R_BAD_TLS_CLIENT_VERSION:161:bad tls client version
PROV_R_BN_ERROR:160:bn error
PROV_R_BOTH_MODE_AND_MODE_INT:127:both mode and mode int
PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed
+PROV_R_DERIVATION_FUNCTION_INIT_FAILED:205:derivation function init failed
+PROV_R_DERIVATION_FUNCTION_MANDATORY_FOR_FIPS:186:\
+ derivation function mandatory for fips
PROV_R_DIGEST_NOT_ALLOWED:174:digest not allowed
+PROV_R_DRBG_ALREADY_INITIALIZED:187:drbg already initialized
+PROV_R_ERROR_INSTANTIATING_DRBG:188:error instantiating drbg
+PROV_R_ERROR_RETRIEVING_ENTROPY:189:error retrieving entropy
+PROV_R_ERROR_RETRIEVING_NONCE:190:error retrieving nonce
PROV_R_FAILED_DURING_DERIVATION:164:failed during derivation
+PROV_R_FAILED_TO_CREATE_LOCK:180:failed to create lock
PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt
PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key
PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter
PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter
PROV_R_FAILED_TO_SIGN:175:failed to sign
+PROV_R_GENERATE_ERROR:191:generate error
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\
illegal or unsupported padding mode
PROV_R_INAVLID_UKM_LENGTH:146:inavlid ukm length
+PROV_R_INSUFFICIENT_DRBG_STRENGTH:181:insufficient drbg strength
PROV_R_INVALID_AAD:108:invalid aad
PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length
PROV_R_INVALID_CURVE:176:invalid curve
@@ -2858,6 +2878,7 @@ PROV_R_INVALID_SIGNATURE_SIZE:179:invalid signature size
PROV_R_INVALID_TAG:110:invalid tag
PROV_R_INVALID_TAGLEN:118:invalid taglen
PROV_R_INVALID_X931_DIGEST:170:invalid x931 digest
+PROV_R_IN_ERROR_STATE:192:in error state
PROV_R_KEY_SIZE_TOO_SMALL:171:key size too small
PROV_R_MISSING_CEK_ALG:144:missing cek alg
PROV_R_MISSING_CIPHER:155:missing cipher
@@ -2872,6 +2893,7 @@ PROV_R_MISSING_SEED:140:missing seed
PROV_R_MISSING_SESSION_ID:133:missing session id
PROV_R_MISSING_TYPE:134:missing type
PROV_R_MISSING_XCGHASH:135:missing xcghash
+PROV_R_NOT_INSTANTIATED:193:not instantiated
PROV_R_NOT_SUPPORTED:136:not supported
PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length
PROV_R_NO_KEY_SET:114:no key set
@@ -2879,12 +2901,28 @@ PROV_R_NO_PARAMETERS_SET:177:no parameters set
PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:178:\
operation not supported for this keytype
PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
+PROV_R_PARENT_LOCKING_NOT_ENABLED:182:parent locking not enabled
+PROV_R_PARENT_STRENGTH_TOO_WEAK:194:parent strength too weak
+PROV_R_PERSONALISATION_STRING_TOO_LONG:195:personalisation string too long
PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small
PROV_R_READ_KEY:159:read key
+PROV_R_REQUEST_TOO_LARGE_FOR_DRBG:196:request too large for drbg
+PROV_R_REQUIRE_CTR_MODE_CIPHER:206:require ctr mode cipher
+PROV_R_RESEED_ERROR:197:reseed error
PROV_R_TAG_NOTSET:119:tag notset
PROV_R_TAG_NOT_NEEDED:120:tag not needed
+PROV_R_UNABLE_TO_FIND_CIPHERS:207:unable to find ciphers
+PROV_R_UNABLE_TO_GET_ENTROPY:202:unable to get entropy
+PROV_R_UNABLE_TO_GET_NONCE:203:unable to get nonce
+PROV_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER:198:\
+ unable to get parent reseed prop counter
+PROV_R_UNABLE_TO_GET_PARENT_STRENGTH:199:unable to get parent strength
+PROV_R_UNABLE_TO_GET_RESEED_PROP_CTR:200:unable to get reseed prop ctr
+PROV_R_UNABLE_TO_INITIALISE_CIPHERS:208:unable to initialise ciphers
PROV_R_UNABLE_TO_LOAD_SHA1:143:unable to load sha1
PROV_R_UNABLE_TO_LOAD_SHA256:147:unable to load sha256
+PROV_R_UNABLE_TO_LOCK_PARENT:201:unable to lock parent
+PROV_R_UNABLE_TO_RESEED:204:unable to reseed
PROV_R_UNKNOWN_PADDING_TYPE:163:unknown padding type
PROV_R_UNSUPPORTED_CEK_ALG:145:unsupported cek alg
PROV_R_UNSUPPORTED_KEY_SIZE:153:unsupported key size
@@ -2893,6 +2931,7 @@ PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS:152:unsupported number of rounds
PROV_R_VALUE_ERROR:138:value error
PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length
PROV_R_WRONG_OUTPUT_BUFFER_SIZE:139:wrong output buffer size
+PROV_R_XOF_DIGESTS_NOT_ALLOWED:183:xof digests not allowed
PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE:148:xts data unit is too large
PROV_R_XTS_DUPLICATED_KEYS:149:xts duplicated keys
RAND_R_ADDITIONAL_INPUT_TOO_LONG:102:additional input too long
@@ -2915,6 +2954,7 @@ RAND_R_FAILED_TO_CREATE_LOCK:126:failed to create lock
RAND_R_FUNC_NOT_IMPLEMENTED:101:Function not implemented
RAND_R_FWRITE_ERROR:123:Error writing file
RAND_R_GENERATE_ERROR:112:generate error
+RAND_R_INSUFFICIENT_DRBG_STRENGTH:139:insufficient drbg strength
RAND_R_INTERNAL_ERROR:113:internal error
RAND_R_IN_ERROR_STATE:114:in error state
RAND_R_NOT_A_REGULAR_FILE:122:Not a regular file
@@ -2933,6 +2973,11 @@ RAND_R_RESEED_ERROR:118:reseed error
RAND_R_SELFTEST_FAILURE:119:selftest failure
RAND_R_TOO_LITTLE_NONCE_REQUESTED:135:too little nonce requested
RAND_R_TOO_MUCH_NONCE_REQUESTED:136:too much nonce requested
+RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER:141:\
+ unable to get parent reseed prop counter
+RAND_R_UNABLE_TO_GET_PARENT_STRENGTH:138:unable to get parent strength
+RAND_R_UNABLE_TO_GET_RESEED_PROP_CTR:142:unable to get reseed prop ctr
+RAND_R_UNABLE_TO_LOCK_PARENT:140:unable to lock parent
RAND_R_UNSUPPORTED_DRBG_FLAGS:132:unsupported drbg flags
RAND_R_UNSUPPORTED_DRBG_TYPE:120:unsupported drbg type
RSA_R_ALGORITHM_MISMATCH:100:algorithm mismatch
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index 82669c1816..edef4930cb 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
+ pmeth_check.c rand_meth.c
SOURCE[../../libcrypto]=$COMMON\
encode.c evp_key.c evp_cnf.c \
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 3dba7f2931..239efaa51a 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -70,6 +70,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FINAL_ERROR), "final error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FIPS_MODE_NOT_SUPPORTED),
"fips mode not supported"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GENERATE_ERROR), "generate error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_SCRYPT_PARAMETERS),
"illegal scrypt parameters"},
@@ -87,6 +88,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_IV_LENGTH), "invalid iv length"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY), "invalid key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY_LENGTH), "invalid key length"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_NULL_ALGORITHM),
+ "invalid null algorithm"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "invalid operation"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PROVIDER_FUNCTIONS),
"invalid provider functions"},
@@ -96,6 +99,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYMGMT_EXPORT_FAILURE),
"keymgmt export failure"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEY_SETUP_FAILED), "key setup failed"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_LOCKING_NOT_SUPPORTED),
+ "locking not supported"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MEMORY_LIMIT_EXCEEDED),
"memory limit exceeded"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MESSAGE_DIGEST_IS_NULL),
@@ -138,6 +143,16 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_SET_DEFAULT_PROPERTY_FAILURE),
"set default property failure"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_TOO_MANY_RECORDS), "too many records"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_ENABLE_PARENT_LOCKING),
+ "unable to enable parent locking"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE),
+ "unable to get maximum request size"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH),
+ "unable to get random strength"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_LOCK_CONTEXT),
+ "unable to lock context"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_SET_CALLBACKS),
+ "unable to set callbacks"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_CIPHER), "unknown cipher"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_DIGEST), "unknown digest"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_KEY_TYPE), "unknown key type"},
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index de7d69a26c..03a1f36e1b 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -10,6 +10,7 @@
/* EVP_MD_CTX related stuff */
#include <openssl/core_numbers.h>
+#include "internal/refcount.h"
#define EVP_CTRL_RET_UNSUPPORTED -1
@@ -65,6 +66,41 @@ struct evp_kdf_ctx_st {
void *data; /* Algorithm-specific data */
} /* EVP_KDF_CTX */ ;
+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 */
+} /* EVP_RAND_CTX */ ;
+
+struct evp_rand_st {
+ OSSL_PROVIDER *prov;
+ int name_id;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ const OSSL_DISPATCH *dispatch;
+ OSSL_OP_rand_newctx_fn *newctx;
+ OSSL_OP_rand_freectx_fn *freectx;
+ OSSL_OP_rand_instantiate_fn *instantiate;
+ OSSL_OP_rand_uninstantiate_fn *uninstantiate;
+ 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_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_verify_zeroization_fn *verify_zeroization;
+} /* EVP_RAND */ ;
+
struct evp_keymgmt_st {
int id; /* libcrypto internal */
diff --git a/crypto/evp/rand_meth.c b/crypto/evp/rand_meth.c
new file mode 100644
index 0000000000..e2b1d68ce0
--- /dev/null
+++ b/crypto/evp/rand_meth.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/evp.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "internal/cryptlib.h"
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/x509v3.h>
+#include <openssl/rand.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
+#include <openssl/crypto.h>
+#include "crypto/asn1.h"
+#include "crypto/evp.h"
+#include "internal/numbers.h"
+#include "internal/provider.h"
+#include "evp_local.h"
+
+static int evp_rand_up_ref(void *vrand)
+{
+ EVP_RAND *rand = (EVP_RAND *)vrand;
+ int ref = 0;
+
+ if (rand != NULL)
+ return CRYPTO_UP_REF(&rand->refcnt, &ref, rand->lock);
+ return 1;
+}
+
+static void evp_rand_free(void *vrand){
+ EVP_RAND *rand = (EVP_RAND *)vrand;
+ int ref = 0;
+
+ if (rand != NULL) {
+ CRYPTO_DOWN_REF(&rand->refcnt, &ref, rand->lock);
+ if (ref <= 0) {
+ ossl_provider_free(rand->prov);
+ CRYPTO_THREAD_lock_free(rand->lock);
+ OPENSSL_free(rand);
+ }
+ }
+}
+
+static void *evp_rand_new(void)
+{
+ EVP_RAND *rand = NULL;
+
+ if ((rand = OPENSSL_zalloc(sizeof(*rand))) == NULL
+ || (rand->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ evp_rand_free(rand);
+ return NULL;
+ }
+
+ rand->refcnt = 1;
+
+ return rand;
+}
+
+static void *evp_rand_from_dispatch(int name_id,
+ const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov)
+{
+ EVP_RAND *rand = NULL;
+ int fnrandcnt = 0, fnctxcnt = 0;
+
+ if ((rand = evp_rand_new()) == NULL) {
+ EVPerr(0, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ rand->name_id = name_id;
+ rand->dispatch = fns;
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_RAND_NEWCTX:
+ if (rand->newctx != NULL)
+ break;
+ rand->newctx = OSSL_get_OP_rand_newctx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_RAND_FREECTX:
+ if (rand->freectx != NULL)
+ break;
+ rand->freectx = OSSL_get_OP_rand_freectx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_RAND_INSTANTIATE:
+ if (rand->instantiate != NULL)
+ break;
+ rand->instantiate = OSSL_get_OP_rand_instantiate(fns);
+ fnrandcnt++;
+ break;
+ case OSSL_FUNC_RAND_UNINSTANTIATE:
+ if (rand->uninstantiate != NULL)
+ break;
+ rand->uninstantiate = OSSL_get_OP_rand_uninstantiate(fns);
+ fnrandcnt++;
+ break;
+ case OSSL_FUNC_RAND_GENERATE:
+ if (rand->generate != NULL)
+ break;
+ rand->generate = OSSL_get_OP_rand_generate(fns);
+ fnrandcnt++;
+ break;
+ case OSSL_FUNC_RAND_RESEED:
+ if (rand->reseed != NULL)
+ break;
+ rand->reseed = OSSL_get_OP_rand_reseed(fns);
+ break;
+ case OSSL_FUNC_RAND_NONCE:
+ if (rand->nonce != NULL)
+ break;
+ rand->nonce = OSSL_get_OP_rand_nonce(fns);
+ break;
+ case OSSL_FUNC_RAND_SET_CALLBACKS:
+ if (rand->set_callbacks != NULL)
+ break;
+ rand->set_callbacks = OSSL_get_OP_rand_set_callbacks(fns);
+ break;
+ case OSSL_FUNC_RAND_ENABLE_LOCKING:
+ if (rand->enable_prov_locking != NULL)
+ break;
+ rand->enable_prov_locking = OSSL_get_OP_rand_enable_locking(fns);
+ break;
+ case OSSL_FUNC_RAND_LOCK:
+ if (rand->prov_lock != NULL)
+ break;
+ rand->prov_lock = OSSL_get_OP_rand_lock(fns);
+ break;
+ case OSSL_FUNC_RAND_UNLOCK:
+ if (rand->prov_unlock != NULL)
+ break;
+ rand->prov_unlock = OSSL_get_OP_rand_unlock(fns);
+ break;
+ case OSSL_FUNC_RAND_GETTABLE_PARAMS:
+ if (rand->gettable_params != NULL)
+ break;
+ rand->gettable_params =
+ OSSL_get_OP_rand_gettable_params(fns);
+ break;
+ case OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS:
+ if (rand->gettable_ctx_params != NULL)
+ break;
+ rand->gettable_ctx_params =
+ OSSL_get_OP_rand_gettable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS:
+ if (rand->settable_ctx_params != NULL)
+ break;
+ rand->settable_ctx_params =
+ OSSL_get_OP_rand_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_RAND_GET_PARAMS:
+ if (rand->get_params != NULL)
+ break;
+ rand->get_params = OSSL_get_OP_rand_get_params(fns);
+ break;
+ case OSSL_FUNC_RAND_GET_CTX_PARAMS:
+ if (rand->get_ctx_params != NULL)
+ break;
+ rand->get_ctx_params = OSSL_get_OP_rand_get_ctx_params(fns);
+ break;
+ case OSSL_FUNC_RAND_SET_CTX_PARAMS:
+ if (rand->set_ctx_params != NULL)
+ break;
+ rand->set_ctx_params = OSSL_get_OP_rand_set_ctx_params(fns);
+ break;
+ }
+ }
+ if (fnrandcnt != 3 || fnctxcnt != 2) {
+ /*
+ * 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.
+ */
+ evp_rand_free(rand);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ 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)
+{
+ return evp_generic_fetch(libctx, OSSL_OP_RAND, algorithm, properties,
+ evp_rand_from_dispatch, evp_rand_up_ref,
+ evp_rand_free);
+}
+
+int EVP_RAND_up_ref(EVP_RAND *rand)
+{
+ return evp_rand_up_ref(rand);
+}
+
+void EVP_RAND_free(EVP_RAND *rand)
+{
+ evp_rand_free(rand);
+}
+
+int EVP_RAND_number(const EVP_RAND *rand)
+{
+ return rand->name_id;
+}
+
+const char *EVP_RAND_name(const EVP_RAND *rand)
+{
+ return evp_first_name(rand->prov, rand->name_id);
+}
+
+int EVP_RAND_is_a(const EVP_RAND *rand, const char *name)
+{
+ return evp_is_a(rand->prov, rand->name_id, NULL, name);
+}
+
+const OSSL_PROVIDER *EVP_RAND_provider(const EVP_RAND *rand)
+{
+ return rand->prov;
+}
+
+int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[])
+{
+ if (rand->get_params != NULL)
+ return rand->get_params(params);
+ return 1;
+}
+
+EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, int secure, unsigned int df,
+ EVP_RAND_CTX *parent)
+{
+ EVP_RAND_CTX *ctx;
+ void *parent_ctx = NULL;
+ const OSSL_DISPATCH *parent_dispatch = NULL;
+
+ if (rand == NULL)
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(EVP_RAND_CTX));
+ if (ctx == NULL)
+ return NULL;
+ if (parent != NULL) {
+ parent_ctx = parent->data;
+ parent_dispatch = parent->meth->dispatch;
+ }
+ if ((ctx->data = rand->newctx(ossl_provider_ctx(rand->prov), secure, df,
+ parent_ctx, parent_dispatch)) == NULL
+ || !EVP_RAND_up_ref(rand)) {
+ EVPerr(0, ERR_R_MALLOC_FAILURE);
+ rand->freectx(ctx->data);
+ OPENSSL_free(ctx);
+ return NULL;
+ }
+ ctx->meth = rand;
+ return ctx;
+}
+
+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);
+ }
+}
+
+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[])
+{
+ if (ctx->meth->get_ctx_params != NULL)
+ return ctx->meth->get_ctx_params(ctx->data, params);
+ return 1;
+}
+
+int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[])
+{
+ if (ctx->meth->set_ctx_params != NULL)
+ return ctx->meth->set_ctx_params(ctx->data, params);
+ return 1;
+}
+
+const OSSL_PARAM *EVP_RAND_gettable_params(const EVP_RAND *rand)
+{
+ if (rand->gettable_params == NULL)
+ return NULL;
+ return 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();
+}
+
+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();
+}
+
+void EVP_RAND_do_all_provided(OPENSSL_CTX *libctx,
+ void (*fn)(EVP_RAND *rand, void *arg),
+ void *arg)
+{
+ evp_generic_do_all(libctx, OSSL_OP_RAND,
+ (void (*)(void *, void *))fn, arg,
+ evp_rand_from_dispatch, evp_rand_free);
+}
+
+void EVP_RAND_names_do_all(const EVP_RAND *rand,
+ void (*fn)(const char *name, void *data),
+ void *data)
+{
+ if (rand->prov != NULL)
+ evp_names_do_all(rand->prov, rand->name_id, fn, data);
+}
+
+int EVP_RAND_CTX_instantiate(EVP_RAND_CTX *ctx, int strength,
+ int prediction_resistance,
+ const unsigned char *pstr, size_t pstr_len)
+{
+ return ctx->meth->instantiate(ctx->data, strength, prediction_resistance,
+ pstr, pstr_len);
+}
+
+int EVP_RAND_CTX_uninstantiate(EVP_RAND_CTX *ctx)
+{
+ return ctx->meth->uninstantiate(ctx->data);
+}
+
+int EVP_RAND_CTX_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
+ int strength, int prediction_resistance,
+ const unsigned char *addin, size_t addin_len)
+{
+ return ctx->meth->generate(ctx->data, out, outlen, strength,
+ prediction_resistance, addin, addin_len);
+}
+
+int EVP_RAND_CTX_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
+ const unsigned char *addin, size_t addin_len)
+{
+ if (ctx->meth->reseed == NULL)
+ return 1;
+ return ctx->meth->reseed(ctx->data, prediction_resistance,
+ addin, addin_len);
+}
+
+int EVP_RAND_CTX_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen)
+{
+ if (ctx->meth->nonce != NULL)
+ return ctx->meth->nonce(ctx->data, out, outlen);
+ return ctx->meth->generate(ctx->data, out, outlen, 0, 0, NULL, 0);
+}
+
+int EVP_RAND_CTX_set_callbacks(const EVP_RAND_CTX *ctx,
+ OSSL_CALLBACK *get_entropy,
+ OSSL_CALLBACK *cleanup_entropy,
+ OSSL_CALLBACK *get_nonce,
+ OSSL_CALLBACK *cleanup_nonce)
+{
+ if (ctx->meth->set_callbacks == NULL)
+ return 0;
+ return ctx->meth->set_callbacks(ctx->data, get_entropy, cleanup_entropy,
+ get_nonce, cleanup_nonce);
+}
+
diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c
index 73b488fb90..39f547c7f1 100644
--- a/crypto/rand/rand_err.c
+++ b/crypto/rand/rand_err.c
@@ -49,6 +49,8 @@ static const ERR_STRING_DATA RAND_str_reasons[] = {
"Function not implemented"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FWRITE_ERROR), "Error writing file"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_GENERATE_ERROR), "generate error"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INSUFFICIENT_DRBG_STRENGTH),
+ "insufficient drbg strength"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INTERNAL_ERROR), "internal error"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_IN_ERROR_STATE), "in error state"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_A_REGULAR_FILE),
@@ -77,6 +79,14 @@ static const ERR_STRING_DATA RAND_str_reasons[] = {
"too little nonce requested"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_MUCH_NONCE_REQUESTED),
"too much nonce requested"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER),
+ "unable to get parent reseed prop counter"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_GET_PARENT_STRENGTH),
+ "unable to get parent strength"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_GET_RESEED_PROP_CTR),
+ "unable to get reseed prop ctr"},
+ {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_LOCK_PARENT),
+ "unable to lock parent"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_FLAGS),
"unsupported drbg flags"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_TYPE),