Add evp_keymgmt_clear_pkey_cache() and use it
authorRichard Levitte <levitte@openssl.org>
Wed, 10 Jul 2019 12:30:55 +0000 (14:30 +0200)
committerRichard Levitte <levitte@openssl.org>
Mon, 22 Jul 2019 04:19:42 +0000 (06:19 +0200)
This function clears the cache of provider key references, and is used
in evp_keymgmt_export_to_provider() when the internal key is dirty, as
well as by EVP_PKEY_free_it().

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9312)

crypto/evp/keymgmt_lib.c
crypto/evp/p_lib.c
crypto/include/internal/evp_int.h
doc/internal/man3/evp_keymgmt_export_to_provider.pod

index 76c4a30a1c80c53df00ea86cc82c16b6c9fe7cc5..7169f4270ed988838a78f6f8f4bec192e8a17b37 100644 (file)
@@ -80,13 +80,7 @@ void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
             return NULL;
 
         if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy)
-            for (i = 0;
-                 i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
-                 i++) {
-                pk->pkeys[i].keymgmt->freekey(pk->pkeys[i].provkey);
-                pk->pkeys[i].keymgmt = NULL;
-                pk->pkeys[i].provkey = NULL;
-            }
+            evp_keymgmt_clear_pkey_cache(pk);
     }
 
     /*
@@ -186,3 +180,22 @@ void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
     }
     return provkey;
 }
+
+void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk)
+{
+    size_t i;
+
+    if (pk != NULL) {
+        for (i = 0;
+             i < OSSL_NELEM(pk->pkeys) && pk->pkeys[i].keymgmt != NULL;
+             i++) {
+            EVP_KEYMGMT *keymgmt = pk->pkeys[i].keymgmt;
+            void *provkey = pk->pkeys[i].provkey;
+
+            pk->pkeys[i].keymgmt = NULL;
+            pk->pkeys[i].provkey = NULL;
+            keymgmt->freekey(provkey);
+            EVP_KEYMGMT_free(keymgmt);
+        }
+    }
+}
index c6ebfe6462d01ea5284ff9d4d34aeb2699010f54..653693e1dce0de1f356d349d25233f6a9fc9f8c3 100644 (file)
@@ -613,6 +613,9 @@ void EVP_PKEY_free(EVP_PKEY *x)
 static void EVP_PKEY_free_it(EVP_PKEY *x)
 {
     /* internal function; x is never NULL */
+
+    evp_keymgmt_clear_pkey_cache(x);
+
     if (x->ameth && x->ameth->pkey_free) {
         x->ameth->pkey_free(x);
         x->pkey.ptr = NULL;
index ff9b6e545bb87cbbcd8c5ed6ff3990a04c48acd9..af273f2bf3e940fb8493665e7f7c48666748bab1 100644 (file)
@@ -560,8 +560,9 @@ void openssl_add_all_kdfs_int(void);
 void evp_cleanup_int(void);
 void evp_app_cleanup_int(void);
 
+/* KEYMGMT helper functions */
 void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
-
+void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk);
 
 /* Pulling defines out of C source files */
 
index 51234bd6097433b518e650d5bf39e8549af93893..72b766fb9333de8b77ed71b9c974022ba938e6b9 100644 (file)
@@ -2,13 +2,16 @@
 
 =head1 NAME
 
-evp_keymgmt_export_to_provider - key material exporter to providers for EVP
+evp_keymgmt_export_to_provider,
+evp_keymgmt_clear_pkey_cache
+- key material provider export for EVP
 
 =head1 SYNOPSIS
 
  #include "internal/evp_int.h"
 
  void *evp_keymgmt_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt);
+ void evp_keymgmt_clear_pkey_cache(EVP_PKEY *pk);
 
 =head1 DESCRIPTION
 
@@ -24,10 +27,13 @@ is_dirty() method returns 1.
 If it has, the cache of already exported keys is cleared, and a new
 export is made with the new key material.
 
+evp_keymgmt_clear_pkey_cache() can be used to explicitly clear the
+cache of provider key references.
+
 =head1 RETURN VALUES
 
-evp_keymgmt_export_to_provider() returns a pointer to the newly
-created provider side key, or NULL on error.
+evp_keymgmt_export_to_provider() returns a pointer to the appropriate
+provider side key (created or found again), or NULL on error.
 
 =head1 NOTES