From: Matt Caswell Date: Fri, 24 Apr 2020 14:32:34 +0000 (+0100) Subject: Add the ability to ECX to import keys with only the private key X-Git-Tag: openssl-3.0.0-alpha2~90 X-Git-Url: https://git.librecmc.org/?p=oweals%2Fopenssl.git;a=commitdiff_plain;h=969024b4580172b1cd836550e227d64515c628bc 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 (Merged from https://github.com/openssl/openssl/pull/11635) --- diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c index e613337029..042f9ca8da 100644 --- a/crypto/ec/ecx_backend.c +++ b/crypto/ec/ecx_backend.c @@ -9,6 +9,8 @@ #include #include +#include +#include #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 a9c71f33aa..b88d73a499 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 5ee6b8ce7e..ef3bf0f3a8 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 2ba8f53e5a..5cc11406f6 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; }