summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2021-02-03 13:50:23 +0100
committerPauli <ppzgs1@gmail.com>2021-02-05 15:53:29 +1000
commitf4a3799cc45cb986d5920403b3e0471678fee020 (patch)
treeb384cdedc7955627fb20ddfc88f37671ac11c970
parent7dc67708c8ae6ec06c7fec34781225ed60b5e68d (diff)
EVP: Make EVP_PKEY_set_params() increment the dirty count
When the internal key is changed, we must count it as muted, so that next time the affected key is considered for an operation, it gets re-exported to the signing provider. In other words, this will clear the EVP_PKEY export cache when the next export attempt occurs. This also updates evp_keymgmt_util_export_to_provider() to actually look at the dirty count for provider native origin keys, and act appropriately. Reviewed-by: Paul Dale <pauli@openssl.org> (Merged from https://github.com/openssl/openssl/pull/14056)
-rw-r--r--crypto/evp/keymgmt_lib.c31
-rw-r--r--crypto/evp/p_lib.c9
2 files changed, 29 insertions, 11 deletions
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
index 0c643b3b49..0112036263 100644
--- a/crypto/evp/keymgmt_lib.c
+++ b/crypto/evp/keymgmt_lib.c
@@ -101,15 +101,22 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
if (pk->keymgmt == keymgmt)
return pk->keydata;
- /* If this key is already exported to |keymgmt|, no more to do */
CRYPTO_THREAD_read_lock(pk->lock);
- i = evp_keymgmt_util_find_operation_cache_index(pk, keymgmt);
- if (i < OSSL_NELEM(pk->operation_cache)
- && pk->operation_cache[i].keymgmt != NULL) {
- void *ret = pk->operation_cache[i].keydata;
+ /*
+ * If the provider native "origin" hasn't changed since last time, we
+ * try to find our keymgmt in the operation cache. If it has changed,
+ * |i| remains zero, and we will clear the cache further down.
+ */
+ if (pk->dirty_cnt == pk->dirty_cnt_copy) {
+ /* If this key is already exported to |keymgmt|, no more to do */
+ i = evp_keymgmt_util_find_operation_cache_index(pk, keymgmt);
+ if (i < OSSL_NELEM(pk->operation_cache)
+ && pk->operation_cache[i].keymgmt != NULL) {
+ void *ret = pk->operation_cache[i].keydata;
- CRYPTO_THREAD_unlock(pk->lock);
- return ret;
+ CRYPTO_THREAD_unlock(pk->lock);
+ return ret;
+ }
}
CRYPTO_THREAD_unlock(pk->lock);
@@ -177,12 +184,22 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
return ret;
}
+ /*
+ * If the dirty counter changed since last time, then clear the
+ * operation cache. In that case, we know that |i| is zero.
+ */
+ if (pk->dirty_cnt != pk->dirty_cnt_copy)
+ evp_keymgmt_util_clear_operation_cache(pk, 0);
+
/* Add the new export to the operation cache */
if (!evp_keymgmt_util_cache_keydata(pk, i, keymgmt, import_data.keydata)) {
evp_keymgmt_freedata(keymgmt, import_data.keydata);
return NULL;
}
+ /* Synchronize the dirty count */
+ pk->dirty_cnt_copy = pk->dirty_cnt;
+
CRYPTO_THREAD_unlock(pk->lock);
return import_data.keydata;
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 558f378168..b97a8d16fa 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -2228,11 +2228,12 @@ const OSSL_PARAM *EVP_PKEY_settable_params(EVP_PKEY *pkey)
int EVP_PKEY_set_params(EVP_PKEY *pkey, OSSL_PARAM params[])
{
- if (pkey == NULL
- || pkey->keymgmt == NULL
- || pkey->keydata == NULL)
+ if (pkey == NULL)
return 0;
- return evp_keymgmt_set_params(pkey->keymgmt, pkey->keydata, params);
+
+ pkey->dirty_cnt++;
+ return evp_pkey_is_provided(pkey)
+ && evp_keymgmt_set_params(pkey->keymgmt, pkey->keydata, params);
}
#ifndef FIPS_MODULE