From 381f3f3bbc930abb98ddc6ddff847f2d55e73a0c Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 20 May 2020 14:47:39 +0100 Subject: [PATCH] Make EVP_PKEY_CTX_[get|set]_group_name work for ECX too The previous commits made EVP_PKEY_CTX_[get|set]_group_name work for EC and DH keys. We now extend this to ECX. Even though that keys with these key types only have one group we still allow it to be explicitly set so that we have only one codepath for all keys. Setting the group name for these types of keys is optional, but if you do so it must have the correct name. Additionally we enable parameter generation for these keys. Parameters aren't actually needed for this key type, but for the same reasons as above (to ensure a single codepath for users of these algorithms) we enable it anyway. Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/11914) --- providers/implementations/keymgmt/ecx_kmgmt.c | 85 ++++++++++++++++++- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index e5c7e8bf3a..813604f7b1 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -8,6 +8,9 @@ */ #include +#include +/* For strcasecmp on Windows */ +#include "e_os.h" #include #include #include @@ -66,6 +69,7 @@ static OSSL_OP_keymgmt_export_types_fn ecx_imexport_types; struct ecx_gen_ctx { OPENSSL_CTX *libctx; ECX_KEY_TYPE type; + int selection; }; #ifdef S390X_EC_ASM @@ -404,12 +408,10 @@ static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type) OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx); struct ecx_gen_ctx *gctx = NULL; - if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) - return NULL; - if ((gctx = OPENSSL_malloc(sizeof(*gctx))) != NULL) { gctx->libctx = libctx; gctx->type = type; + gctx->selection = selection; } return gctx; } @@ -434,6 +436,54 @@ static void *ed448_gen_init(void *provctx, int selection) return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448); } +static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[]) +{ + struct ecx_gen_ctx *gctx = genctx; + const OSSL_PARAM *p; + + if (gctx == NULL) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME); + if (p != NULL) { + const char *groupname = NULL; + + /* + * We optionally allow setting a group name - but each algorithm only + * support one such name, so all we do is verify that it is the one we + * expected. + */ + switch (gctx->type) { + case ECX_KEY_TYPE_X25519: + groupname = "x25519"; + break; + case ECX_KEY_TYPE_X448: + groupname = "x448"; + break; + default: + /* We only support this for key exchange at the moment */ + break; + } + if (p->data_type != OSSL_PARAM_UTF8_STRING + || groupname == NULL + || strcasecmp(p->data, groupname) != 0) { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + } + + return 1; +} + +static const OSSL_PARAM *ecx_gen_settable_params(void *provctx) +{ + static OSSL_PARAM settable[] = { + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), + OSSL_PARAM_END + }; + return settable; +} + static void *ecx_gen(struct ecx_gen_ctx *gctx) { ECX_KEY *key; @@ -445,6 +495,11 @@ static void *ecx_gen(struct ecx_gen_ctx *gctx) ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return NULL; } + + /* If we're doing parameter generation then we just return a blank key */ + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) + return key; + if ((privkey = ecx_key_allocate_privkey(key)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); goto err; @@ -472,6 +527,7 @@ static void *ecx_gen(struct ecx_gen_ctx *gctx) goto err; break; } + key->haspubkey = 1; return key; err: ecx_key_free(key); @@ -548,6 +604,9 @@ static void ecx_gen_cleanup(void *genctx) { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \ + { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \ + { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \ + (void (*)(void))ecx_gen_settable_params }, \ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \ { 0, NULL } \ @@ -576,6 +635,10 @@ static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx) goto err; } + /* If we're doing parameter generation then we just return a blank key */ + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) + return key; + pubkey = key->pubkey; privkey = ecx_key_allocate_privkey(key); @@ -593,6 +656,7 @@ static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx) if (s390x_x25519_mul(pubkey, generator, privkey) != 1) goto err; + key->haspubkey = 1; return key; err: ecx_key_free(key); @@ -616,6 +680,10 @@ static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx) goto err; } + /* If we're doing parameter generation then we just return a blank key */ + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) + return key; + pubkey = key->pubkey; privkey = ecx_key_allocate_privkey(key); @@ -632,6 +700,7 @@ static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx) if (s390x_x448_mul(pubkey, generator, privkey) != 1) goto err; + key->haspubkey = 1; return key; err: ecx_key_free(key); @@ -662,6 +731,10 @@ static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx) goto err; } + /* If we're doing parameter generation then we just return a blank key */ + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) + return key; + pubkey = key->pubkey; privkey = ecx_key_allocate_privkey(key); @@ -690,6 +763,7 @@ static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx) goto err; pubkey[31] |= ((x_dst[0] & 0x01) << 7); + key->haspubkey = 1; return key; err: ecx_key_free(key); @@ -723,6 +797,10 @@ static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx) goto err; } + /* If we're doing parameter generation then we just return a blank key */ + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) + return key; + pubkey = key->pubkey; privkey = ecx_key_allocate_privkey(key); @@ -758,6 +836,7 @@ static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx) pubkey[56] |= ((x_dst[0] & 0x01) << 7); EVP_MD_CTX_free(hashctx); EVP_MD_free(shake); + key->haspubkey = 1; return key; err: ecx_key_free(key); -- 2.25.1