/*
- * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2023 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
{
EVP_KEYEXCH *exchange = OPENSSL_zalloc(sizeof(EVP_KEYEXCH));
- if (exchange == NULL) {
- ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ if (exchange == NULL)
return NULL;
- }
- exchange->lock = CRYPTO_THREAD_lock_new();
- if (exchange->lock == NULL) {
- ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ if (!CRYPTO_NEW_REF(&exchange->refcnt, 1)) {
OPENSSL_free(exchange);
return NULL;
}
exchange->prov = prov;
ossl_provider_up_ref(prov);
- exchange->refcnt = 1;
return exchange;
}
int fncnt = 0, sparamfncnt = 0, gparamfncnt = 0;
if ((exchange = evp_keyexch_new(prov)) == NULL) {
- ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
goto err;
}
if (exchange == NULL)
return;
- CRYPTO_DOWN_REF(&exchange->refcnt, &i, exchange->lock);
+ CRYPTO_DOWN_REF(&exchange->refcnt, &i);
if (i > 0)
return;
OPENSSL_free(exchange->type_name);
ossl_provider_free(exchange->prov);
- CRYPTO_THREAD_lock_free(exchange->lock);
+ CRYPTO_FREE_REF(&exchange->refcnt);
OPENSSL_free(exchange);
}
{
int ref = 0;
- CRYPTO_UP_REF(&exchange->refcnt, &ref, exchange->lock);
+ CRYPTO_UP_REF(&exchange->refcnt, &ref);
return 1;
}
* the second iteration, or jump to legacy.
*/
for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
- EVP_KEYMGMT *tmp_keymgmt_tofree;
+ EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
/*
* If we're on the second iteration, free the results from the first.
/*
* Ensure that the key is provided, either natively, or as a cached
* export. We start by fetching the keymgmt with the same name as
- * |ctx->pkey|, but from the provider of the exchange method, using
+ * |ctx->keymgmt|, but from the provider of the exchange method, using
* the same property query as when fetching the exchange method.
* With the keymgmt we found (if we did), we try to export |ctx->pkey|
* to it (evp_pkey_export_to_provider() is smart enough to only actually
/* No more legacy from here down to legacy: */
+ /* A Coverity false positive with up_ref/down_ref and free */
+ /* coverity[use_after_free] */
ctx->op.kex.exchange = exchange;
+ /* A Coverity false positive with up_ref/down_ref and free */
+ /* coverity[deref_arg] */
ctx->op.kex.algctx = exchange->newctx(ossl_provider_ctx(exchange->prov));
if (ctx->op.kex.algctx == NULL) {
/* The provider key can stay in the cache */
int ret = 0, check;
void *provkey = NULL;
EVP_PKEY_CTX *check_ctx = NULL;
+ EVP_KEYMGMT *tmp_keymgmt = NULL, *tmp_keymgmt_tofree = NULL;
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
- provkey = evp_pkey_export_to_provider(peer, ctx->libctx, &ctx->keymgmt,
- ctx->propquery);
+ /*
+ * Ensure that the |peer| is provided, either natively, or as a cached
+ * export. We start by fetching the keymgmt with the same name as
+ * |ctx->keymgmt|, but from the provider of the exchange method, using
+ * the same property query as when fetching the exchange method.
+ * With the keymgmt we found (if we did), we try to export |peer|
+ * to it (evp_pkey_export_to_provider() is smart enough to only actually
+ * export it if |tmp_keymgmt| is different from |peer|'s keymgmt)
+ */
+ tmp_keymgmt_tofree = tmp_keymgmt =
+ evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)
+ EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange),
+ EVP_KEYMGMT_get0_name(ctx->keymgmt),
+ ctx->propquery);
+ if (tmp_keymgmt != NULL)
+ /* A Coverity issue with up_ref/down_ref and free */
+ /* coverity[pass_freed_arg] */
+ provkey = evp_pkey_export_to_provider(peer, ctx->libctx,
+ &tmp_keymgmt, ctx->propquery);
+ EVP_KEYMGMT_free(tmp_keymgmt_tofree);
+
/*
* If making the key provided wasn't possible, legacy may be able to pick
* it up
int EVP_KEYEXCH_is_a(const EVP_KEYEXCH *keyexch, const char *name)
{
- return evp_is_a(keyexch->prov, keyexch->name_id, NULL, name);
+ return keyexch != NULL
+ && evp_is_a(keyexch->prov, keyexch->name_id, NULL, name);
}
void EVP_KEYEXCH_do_all_provided(OSSL_LIB_CTX *libctx,