aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-04-24 15:32:34 +0100
committerMatt Caswell <matt@openssl.org>2020-05-04 09:30:55 +0100
commit969024b4580172b1cd836550e227d64515c628bc (patch)
treeb9a123f73674628424168b0362ba16a3a1e0275f
parenta6f8a834ba6f877baa427e3d25694d49beb29306 (diff)
downloadopenssl-969024b4580172b1cd836550e227d64515c628bc.zip
openssl-969024b4580172b1cd836550e227d64515c628bc.tar.gz
openssl-969024b4580172b1cd836550e227d64515c628bc.tar.bz2
Add the ability to ECX to import keys with only the private key
ECX keys can very easily crete the public key from the private key. Therefore when we import ecx keys it is sufficent to just have the private key. Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11635)
-rw-r--r--crypto/ec/ecx_backend.c48
-rw-r--r--crypto/ec/ecx_meth.c22
-rw-r--r--include/crypto/ecx.h1
-rw-r--r--providers/implementations/keymgmt/ecx_kmgmt.c5
4 files changed, 44 insertions, 32 deletions
diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c
index e613337..042f9ca 100644
--- a/crypto/ec/ecx_backend.c
+++ b/crypto/ec/ecx_backend.c
@@ -9,6 +9,8 @@
#include <openssl/core_names.h>
#include <openssl/params.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
#include "crypto/ecx.h"
#include "ecx_backend.h"
@@ -18,10 +20,35 @@
* implementations alike.
*/
+int ecx_public_from_private(ECX_KEY *key)
+{
+ switch (key->type) {
+ case ECX_KEY_TYPE_X25519:
+ X25519_public_from_private(key->pubkey, key->privkey);
+ break;
+ case ECX_KEY_TYPE_ED25519:
+ if (!ED25519_public_from_private(key->libctx, key->pubkey, key->privkey)) {
+ ECerr(0, EC_R_FAILED_MAKING_PUBLIC_KEY);
+ return 0;
+ }
+ break;
+ case ECX_KEY_TYPE_X448:
+ X448_public_from_private(key->pubkey, key->privkey);
+ break;
+ case ECX_KEY_TYPE_ED448:
+ if (!ED448_public_from_private(key->libctx, key->pubkey, key->privkey)) {
+ ECerr(0, EC_R_FAILED_MAKING_PUBLIC_KEY);
+ return 0;
+ }
+ break;
+ }
+ return 1;
+}
+
int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
int include_private)
{
- size_t privkeylen = 0, pubkeylen;
+ size_t privkeylen = 0, pubkeylen = 0;
const OSSL_PARAM *param_priv_key = NULL, *param_pub_key;
unsigned char *pubkey;
@@ -32,11 +59,8 @@ int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
if (include_private)
param_priv_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
- /*
- * If a private key is present then a public key must also be present.
- * Alternatively we've just got a public key.
- */
- if (param_pub_key == NULL)
+
+ if (param_pub_key == NULL && param_priv_key == NULL)
return 0;
if (param_priv_key != NULL
@@ -46,15 +70,19 @@ int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
return 0;
pubkey = ecx->pubkey;
- if (!OSSL_PARAM_get_octet_string(param_pub_key,
- (void **)&pubkey,
- sizeof(ecx->pubkey), &pubkeylen))
+ if (param_pub_key != NULL
+ && !OSSL_PARAM_get_octet_string(param_pub_key,
+ (void **)&pubkey,
+ sizeof(ecx->pubkey), &pubkeylen))
return 0;
- if (pubkeylen != ecx->keylen
+ if ((param_pub_key != NULL && pubkeylen != ecx->keylen)
|| (param_priv_key != NULL && privkeylen != ecx->keylen))
return 0;
+ if (param_pub_key == NULL && !ecx_public_from_private(ecx))
+ return 0;
+
ecx->haspubkey = 1;
return 1;
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index a9c71f3..b88d73a 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -88,25 +88,9 @@ static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
} else {
memcpy(privkey, p, KEYLENID(id));
}
- switch (id) {
- case EVP_PKEY_X25519:
- X25519_public_from_private(pubkey, privkey);
- break;
- case EVP_PKEY_ED25519:
- if (!ED25519_public_from_private(libctx, pubkey, privkey)) {
- ECerr(EC_F_ECX_KEY_OP, EC_R_FAILED_MAKING_PUBLIC_KEY);
- goto err;
- }
- break;
- case EVP_PKEY_X448:
- X448_public_from_private(pubkey, privkey);
- break;
- case EVP_PKEY_ED448:
- if (!ED448_public_from_private(libctx, pubkey, privkey)) {
- ECerr(EC_F_ECX_KEY_OP, EC_R_FAILED_MAKING_PUBLIC_KEY);
- goto err;
- }
- break;
+ if (!ecx_public_from_private(key)) {
+ ECerr(EC_F_ECX_KEY_OP, EC_R_FAILED_MAKING_PUBLIC_KEY);
+ goto err;
}
}
diff --git a/include/crypto/ecx.h b/include/crypto/ecx.h
index 5ee6b8c..ef3bf0f 100644
--- a/include/crypto/ecx.h
+++ b/include/crypto/ecx.h
@@ -109,6 +109,7 @@ void X448_public_from_private(uint8_t out_public_value[56],
const uint8_t private_key[56]);
/* Backend support */
+int ecx_public_from_private(ECX_KEY *key);
int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
int include_private);
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
index 2ba8f53..5cc1140 100644
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -113,12 +113,11 @@ static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
if (key == NULL)
return 0;
- if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
return 0;
include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
- if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
- ok = ok && ecx_key_fromdata(key, params, include_private);
+ ok = ok && ecx_key_fromdata(key, params, include_private);
return ok;
}