/*
- * 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
#include <openssl/rand.h>
#include <openssl/aes.h>
#include <openssl/proverr.h>
-#include "e_os.h" /* strcasecmp */
#include "crypto/modes.h"
#include "internal/thread_once.h"
#include "prov/implementations.h"
static OSSL_FUNC_rand_get_ctx_params_fn drbg_ctr_get_ctx_params;
static OSSL_FUNC_rand_verify_zeroization_fn drbg_ctr_verify_zeroization;
+static int drbg_ctr_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[]);
+
/*
* The state of a DRBG AES-CTR.
*/
const OSSL_PARAM params[])
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+ int ret = 0;
- if (!ossl_prov_is_running() || !drbg_ctr_set_ctx_params(drbg, params))
+ if (drbg->lock != NULL && !CRYPTO_THREAD_write_lock(drbg->lock))
return 0;
- return ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,
- pstr, pstr_len);
+
+ if (!ossl_prov_is_running()
+ || !drbg_ctr_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_ctr_reseed(PROV_DRBG *drbg,
static int drbg_ctr_uninstantiate_wrapper(void *vdrbg)
{
- return drbg_ctr_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_ctr_uninstantiate(drbg);
+
+ if (drbg->lock != NULL)
+ CRYPTO_THREAD_unlock(drbg->lock);
+
+ return ret;
}
static int drbg_ctr_verify_zeroization(void *vdrbg)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
+ int ret = 0;
- PROV_DRBG_VERYIFY_ZEROIZATION(ctr->K);
- PROV_DRBG_VERYIFY_ZEROIZATION(ctr->V);
- PROV_DRBG_VERYIFY_ZEROIZATION(ctr->bltmp);
- PROV_DRBG_VERYIFY_ZEROIZATION(ctr->KX);
- if (ctr->bltmp_pos != 0)
+ if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock))
return 0;
- return 1;
+
+ PROV_DRBG_VERIFY_ZEROIZATION(ctr->K);
+ PROV_DRBG_VERIFY_ZEROIZATION(ctr->V);
+ PROV_DRBG_VERIFY_ZEROIZATION(ctr->bltmp);
+ PROV_DRBG_VERIFY_ZEROIZATION(ctr->KX);
+ if (ctr->bltmp_pos != 0)
+ goto err;
+
+ ret = 1;
+ err:
+ if (drbg->lock != NULL)
+ CRYPTO_THREAD_unlock(drbg->lock);
+ return ret;
}
static int drbg_ctr_init_lengths(PROV_DRBG *drbg)
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
int res = 1;
-#ifdef FIPS_MODULE
- if (!ctr->use_df) {
- ERR_raise(ERR_LIB_PROV, RAND_R_DERIVATION_FUNCTION_MANDATORY_FOR_FIPS);
- ctr->use_df = 1;
- res = 0;
- }
-#endif
/* Maximum number of bits per request = 2^19 = 2^16 bytes */
drbg->max_request = 1 << 16;
if (ctr->use_df) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER);
return 0;
}
- ctr->keylen = keylen = EVP_CIPHER_key_length(ctr->cipher_ctr);
+ ctr->keylen = keylen = EVP_CIPHER_get_key_length(ctr->cipher_ctr);
if (ctr->ctx_ecb == NULL)
ctr->ctx_ecb = EVP_CIPHER_CTX_new();
if (ctr->ctx_ctr == NULL)
ctr->ctx_ctr = EVP_CIPHER_CTX_new();
if (ctr->ctx_ecb == NULL || ctr->ctx_ctr == NULL) {
- ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PROV, ERR_R_EVP_LIB);
goto err;
}
if (ctr->ctx_df == NULL)
ctr->ctx_df = EVP_CIPHER_CTX_new();
if (ctr->ctx_df == NULL) {
- ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_PROV, ERR_R_EVP_LIB);
goto err;
}
/* Set key schedule for df_key */
EVP_CIPHER_CTX_free(ctr->ctx_ecb);
EVP_CIPHER_CTX_free(ctr->ctx_ctr);
ctr->ctx_ecb = ctr->ctx_ctr = NULL;
- return 0;
+ return 0;
}
static int drbg_ctr_new(PROV_DRBG *drbg)
PROV_DRBG_CTR *ctr;
ctr = OPENSSL_secure_zalloc(sizeof(*ctr));
- if (ctr == NULL) {
- ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ if (ctr == NULL)
return 0;
- }
ctr->use_df = 1;
drbg->data = ctr;
static void *drbg_ctr_new_wrapper(void *provctx, void *parent,
const OSSL_DISPATCH *parent_dispatch)
{
- return ossl_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_ctr_new,
+ return ossl_rand_drbg_new(provctx, parent, parent_dispatch,
+ &drbg_ctr_new, &drbg_ctr_free,
&drbg_ctr_instantiate, &drbg_ctr_uninstantiate,
&drbg_ctr_reseed, &drbg_ctr_generate);
}
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
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_USE_DF);
if (p != NULL && !OSSL_PARAM_set_int(p, ctr->use_df))
- return 0;
+ goto err;
p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_CIPHER);
if (p != NULL) {
if (ctr->cipher_ctr == NULL
- || !OSSL_PARAM_set_utf8_string(p, EVP_CIPHER_name(ctr->cipher_ctr)))
- return 0;
+ || !OSSL_PARAM_set_utf8_string(p,
+ EVP_CIPHER_get0_name(ctr->cipher_ctr)))
+ 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_ctr_gettable_ctx_params(ossl_unused void *vctx,
return known_gettable_ctx_params;
}
-static int drbg_ctr_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+static int drbg_ctr_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[])
{
PROV_DRBG *ctx = (PROV_DRBG *)vctx;
PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)ctx->data;
if (p->data_type != OSSL_PARAM_UTF8_STRING
|| p->data_size < ctr_str_len)
return 0;
- if (strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) {
+ if (OPENSSL_strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER);
return 0;
}
- if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL) {
- ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL)
return 0;
- }
strcpy(ecb + p->data_size - ecb_str_len, "ECB");
EVP_CIPHER_free(ctr->cipher_ecb);
EVP_CIPHER_free(ctr->cipher_ctr);
return ossl_drbg_set_ctx_params(ctx, params);
}
+static int drbg_ctr_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_ctr_set_ctx_params_locked(vctx, params);
+
+ if (drbg->lock != NULL)
+ CRYPTO_THREAD_unlock(drbg->lock);
+
+ return ret;
+}
+
static const OSSL_PARAM *drbg_ctr_settable_ctx_params(ossl_unused void *vctx,
ossl_unused void *provctx)
{
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0),
-#ifndef FIPS_MODULE
- /*
- * Don't advertise this for FIPS, it isn't allowed to change.
- * The parameter can still be passed and will be processed but errors
- * out.
- */
OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),
-#endif
OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON,
OSSL_PARAM_END
};
(void(*)(void))drbg_ctr_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
};