summaryrefslogtreecommitdiffstats
path: root/crypto/ec
diff options
context:
space:
mode:
authorTomas Mraz <tomas@openssl.org>2021-04-07 19:35:13 +0200
committerTomas Mraz <tomas@openssl.org>2021-04-15 09:19:39 +0200
commit4a9fe33c8e12f4fefae0471c0834f8e674dc7e4e (patch)
tree479171af7347523257b843893173927cbbc6e572 /crypto/ec
parentb9cd82f95bf99eab4e1b0420918e7139db091c4b (diff)
Implement provider-side keymgmt_dup function
To avoid mutating key data add OSSL_FUNC_KEYMGMT_DUP function to the provider API and implement it for all asym-key key managements. Use it when copying everything to an empty EVP_PKEY which is the case with EVP_PKEY_dup(). Fixes #14658 Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/14793)
Diffstat (limited to 'crypto/ec')
-rw-r--r--crypto/ec/ecx_backend.c43
-rw-r--r--crypto/ec/ecx_key.c3
-rw-r--r--crypto/ec/ecx_meth.c14
3 files changed, 53 insertions, 7 deletions
diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c
index 8f8fdc7705..d3ffb13916 100644
--- a/crypto/ec/ecx_backend.c
+++ b/crypto/ec/ecx_backend.c
@@ -92,6 +92,49 @@ int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
return 1;
}
+ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key)
+{
+ ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+
+ ret->libctx = key->libctx;
+ ret->haspubkey = key->haspubkey;
+ ret->keylen = key->keylen;
+ ret->type = key->type;
+ ret->references = 1;
+
+ if (key->propq != NULL) {
+ ret->propq = OPENSSL_strdup(key->propq);
+ if (ret->propq == NULL)
+ goto err;
+ }
+
+ memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey));
+
+ if (key->privkey != NULL) {
+ if (ossl_ecx_key_allocate_privkey(ret) == NULL)
+ goto err;
+ memcpy(ret->privkey, key->privkey, ret->keylen);
+ }
+
+ return ret;
+
+err:
+ ossl_ecx_key_free(ret);
+ ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+ return NULL;
+}
+
#ifndef FIPS_MODULE
ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg,
const unsigned char *p, int plen,
diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c
index 60d9f3cc9f..90253372ce 100644
--- a/crypto/ec/ecx_key.c
+++ b/crypto/ec/ecx_key.c
@@ -7,6 +7,7 @@
* https://www.openssl.org/source/license.html
*/
+#include <string.h>
#include <openssl/err.h>
#include "crypto/ecx.h"
@@ -39,7 +40,6 @@ ECX_KEY *ossl_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type, int haspubkey
if (propq != NULL) {
ret->propq = OPENSSL_strdup(propq);
- ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
if (ret->propq == NULL)
goto err;
}
@@ -96,3 +96,4 @@ unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key)
return key->privkey;
}
+
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index 609d8609ea..df4b620829 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -406,16 +406,18 @@ static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
{
- ECX_KEY *ecx = from->pkey.ecx;
+ ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL;
int ret;
- /* We can do just up-ref as ECX keys are immutable */
- if (ecx != NULL && !ossl_ecx_key_up_ref(ecx))
- return 0;
+ if (ecx != NULL) {
+ dupkey = ossl_ecx_key_dup(ecx);
+ if (dupkey == NULL)
+ return 0;
+ }
- ret = EVP_PKEY_assign(to, from->type, ecx);
+ ret = EVP_PKEY_assign(to, from->type, dupkey);
if (!ret)
- ossl_ecx_key_free(ecx);
+ ossl_ecx_key_free(dupkey);
return ret;
}