/*
- * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2024 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
static OSSL_FUNC_rand_get_ctx_params_fn drbg_hash_get_ctx_params;
static OSSL_FUNC_rand_verify_zeroization_fn drbg_hash_verify_zeroization;
+static int drbg_hash_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[]);
+
/* 888 bits from SP800-90Ar1 10.1 table 2 */
#define HASH_PRNG_MAX_SEEDLEN (888/8)
memcpy(out, vtmp, outlen);
OPENSSL_cleanse(vtmp, hash->blocklen);
break;
- } else if(!EVP_DigestFinal(ctx, out, NULL)) {
+ } else if (!EVP_DigestFinal(ctx, out, NULL)) {
return 0;
}
/* Add the carry to the top of the dst if inlen is not the same size */
for (i = drbg->seedlen - inlen; i > 0; --i, d--) {
*d += 1; /* Carry can only be 1 */
- if (*d != 0) /* exit if carry doesnt propagate to the next byte */
+ if (*d != 0) /* exit if carry doesn't propagate to the next byte */
break;
}
}
if (outlen == 0)
return 1;
memcpy(hash->vtmp, hash->V, drbg->seedlen);
- for(;;) {
+ for (;;) {
if (!EVP_DigestInit_ex(hash->ctx, ossl_prov_digest_md(&hash->digest),
NULL)
|| !EVP_DigestUpdate(hash->ctx, hash->vtmp, drbg->seedlen))
static int drbg_hash_instantiate_wrapper(void *vdrbg, unsigned int strength,
int prediction_resistance,
const unsigned char *pstr,
- size_t pstr_len)
+ size_t pstr_len,
+ const OSSL_PARAM params[])
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ int ret = 0;
- return ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,
- pstr, pstr_len);
+ if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))
+ return 0;
+
+ if (!ossl_prov_is_running()
+ || !drbg_hash_set_ctx_params_locked(drbg, params))
+ goto err;
+ ret = ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,
+ pstr, pstr_len);
+ err:
+ if (drbg->lock != NULL)
+ CRYPTO_THREAD_unlock(drbg->lock);
+ return ret;
}
/*
static int drbg_hash_uninstantiate_wrapper(void *vdrbg)
{
- return drbg_hash_uninstantiate((PROV_DRBG *)vdrbg);
+ PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ int ret;
+
+ if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))
+ return 0;
+
+ ret = drbg_hash_uninstantiate(drbg);
+
+ if (drbg->lock != NULL)
+ CRYPTO_THREAD_unlock(drbg->lock);
+
+ return ret;
}
static int drbg_hash_verify_zeroization(void *vdrbg)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
+ int ret = 0;
- PROV_DRBG_VERYIFY_ZEROIZATION(hash->V);
- PROV_DRBG_VERYIFY_ZEROIZATION(hash->C);
- PROV_DRBG_VERYIFY_ZEROIZATION(hash->vtmp);
- return 1;
+ if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))
+ return 0;
+
+ PROV_DRBG_VERIFY_ZEROIZATION(hash->V);
+ PROV_DRBG_VERIFY_ZEROIZATION(hash->C);
+ PROV_DRBG_VERIFY_ZEROIZATION(hash->vtmp);
+
+ ret = 1;
+ err:
+ if (drbg->lock != NULL)
+ CRYPTO_THREAD_unlock(drbg->lock);
+ return ret;
}
static int drbg_hash_new(PROV_DRBG *ctx)
PROV_DRBG_HASH *hash;
hash = OPENSSL_secure_zalloc(sizeof(*hash));
- if (hash == NULL) {
- ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ if (hash == NULL)
return 0;
- }
ctx->data = hash;
ctx->seedlen = HASH_PRNG_MAX_SEEDLEN;
static void *drbg_hash_new_wrapper(void *provctx, void *parent,
const OSSL_DISPATCH *parent_dispatch)
{
- return ossl_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_hash_new,
+ return ossl_rand_drbg_new(provctx, parent, parent_dispatch,
+ &drbg_hash_new, &drbg_hash_free,
&drbg_hash_instantiate, &drbg_hash_uninstantiate,
&drbg_hash_reseed, &drbg_hash_generate);
}
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)drbg->data;
const EVP_MD *md;
OSSL_PARAM *p;
+ int ret = 0, complete = 0;
+
+ if (!ossl_drbg_get_ctx_params_no_lock(drbg, params, &complete))
+ return 0;
+
+ if (complete)
+ return 1;
+
+ if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))
+ return 0;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_DIGEST);
if (p != NULL) {
md = ossl_prov_digest_md(&hash->digest);
- if (md == NULL || !OSSL_PARAM_set_utf8_string(p, EVP_MD_name(md)))
- return 0;
+ if (md == NULL || !OSSL_PARAM_set_utf8_string(p, EVP_MD_get0_name(md)))
+ goto err;
}
- return ossl_drbg_get_ctx_params(drbg, params);
+ ret = ossl_drbg_get_ctx_params(drbg, params);
+ err:
+ if (drbg->lock != NULL)
+ CRYPTO_THREAD_unlock(drbg->lock);
+
+ return ret;
}
static const OSSL_PARAM *drbg_hash_gettable_ctx_params(ossl_unused void *vctx,
return known_gettable_ctx_params;
}
-static int drbg_hash_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+static int drbg_hash_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[])
{
PROV_DRBG *ctx = (PROV_DRBG *)vctx;
PROV_DRBG_HASH *hash = (PROV_DRBG_HASH *)ctx->data;
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
const EVP_MD *md;
+ int md_size;
if (!ossl_prov_digest_load_from_params(&hash->digest, params, libctx))
return 0;
md = ossl_prov_digest_md(&hash->digest);
if (md != NULL) {
- if ((EVP_MD_flags(md) & EVP_MD_FLAG_XOF) != 0) {
- ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
- return 0;
- }
+ if (!ossl_drbg_verify_digest(libctx, md))
+ return 0; /* Error already raised for us */
/* These are taken from SP 800-90 10.1 Table 2 */
- hash->blocklen = EVP_MD_size(md);
+ md_size = EVP_MD_get_size(md);
+ if (md_size <= 0)
+ return 0;
+ hash->blocklen = md_size;
/* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
ctx->strength = 64 * (hash->blocklen >> 3);
if (ctx->strength > 256)
return ossl_drbg_set_ctx_params(ctx, params);
}
+static int drbg_hash_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_DRBG *drbg = (PROV_DRBG *)vctx;
+ int ret;
+
+ if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))
+ return 0;
+
+ ret = drbg_hash_set_ctx_params_locked(vctx, params);
+
+ if (drbg->lock != NULL)
+ CRYPTO_THREAD_unlock(drbg->lock);
+
+ return ret;
+}
+
static const OSSL_PARAM *drbg_hash_settable_ctx_params(ossl_unused void *vctx,
ossl_unused void *p_ctx)
{
(void(*)(void))drbg_hash_verify_zeroization },
{ OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
{ OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
- { 0, NULL }
+ OSSL_DISPATCH_END
};