diff options
author | Richard Levitte <levitte@openssl.org> | 2020-03-19 14:02:28 +0100 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-04-15 11:03:59 +0200 |
commit | 1f185f51a7899e1eddc9161d7781e3d5ae86ab78 (patch) | |
tree | 7313267cbef2119ed88d959b086572cfc8502a90 /providers | |
parent | 2b9add696573131fc463d098ed8bcbff1b5829d9 (diff) | |
download | openssl-1f185f51a7899e1eddc9161d7781e3d5ae86ab78.zip openssl-1f185f51a7899e1eddc9161d7781e3d5ae86ab78.tar.gz openssl-1f185f51a7899e1eddc9161d7781e3d5ae86ab78.tar.bz2 |
PROV: Implement EC param / key generation
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/11328)
Diffstat (limited to 'providers')
-rw-r--r-- | providers/common/include/prov/providercommonerr.h | 2 | ||||
-rw-r--r-- | providers/common/provider_err.c | 2 | ||||
-rw-r--r-- | providers/implementations/keymgmt/ec_kmgmt.c | 199 |
3 files changed, 202 insertions, 1 deletions
diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h index f834a71..5b3bcbb 100644 --- a/providers/common/include/prov/providercommonerr.h +++ b/providers/common/include/prov/providercommonerr.h @@ -69,6 +69,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_INAVLID_UKM_LENGTH 146 # define PROV_R_INVALID_AAD 108 # define PROV_R_INVALID_CONSTANT_LENGTH 157 +# define PROV_R_INVALID_CURVE 176 # define PROV_R_INVALID_CUSTOM_LENGTH 111 # define PROV_R_INVALID_DATA 115 # define PROV_R_INVALID_DIGEST 122 @@ -108,6 +109,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_NOT_SUPPORTED 136 # define PROV_R_NOT_XOF_OR_INVALID_LENGTH 113 # define PROV_R_NO_KEY_SET 114 +# define PROV_R_NO_PARAMETERS_SET 177 # define PROV_R_OUTPUT_BUFFER_TOO_SMALL 106 # define PROV_R_PSS_SALTLEN_TOO_SMALL 172 # define PROV_R_READ_KEY 159 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 1a65e2c..1018fa3 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -47,6 +47,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AAD), "invalid aad"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CONSTANT_LENGTH), "invalid constant length"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CURVE), "invalid curve"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_CUSTOM_LENGTH), "invalid custom length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DATA), "invalid data"}, @@ -99,6 +100,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_XOF_OR_INVALID_LENGTH), "not xof or invalid length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_KEY_SET), "no key set"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_PARAMETERS_SET), "no parameters set"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OUTPUT_BUFFER_TOO_SMALL), "output buffer too small"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PSS_SALTLEN_TOO_SMALL), diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 661aa2d..0e310ec 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -16,15 +16,25 @@ #include <openssl/core_numbers.h> #include <openssl/core_names.h> #include <openssl/bn.h> +#include <openssl/err.h> #include <openssl/objects.h> #include "crypto/bn.h" #include "crypto/ec.h" #include "prov/implementations.h" #include "prov/providercommon.h" +#include "prov/providercommonerr.h" #include "prov/provider_ctx.h" #include "internal/param_build_set.h" static OSSL_OP_keymgmt_new_fn ec_newdata; +static OSSL_OP_keymgmt_gen_init_fn ec_gen_init; +static OSSL_OP_keymgmt_gen_set_template_fn ec_gen_set_template; +static OSSL_OP_keymgmt_gen_set_params_fn ec_gen_set_params; +static OSSL_OP_keymgmt_gen_settable_params_fn ec_gen_settable_params; +static OSSL_OP_keymgmt_gen_get_params_fn ec_gen_get_params; +static OSSL_OP_keymgmt_gen_gettable_params_fn ec_gen_gettable_params; +static OSSL_OP_keymgmt_gen_fn ec_gen; +static OSSL_OP_keymgmt_gen_cleanup_fn ec_gen_cleanup; static OSSL_OP_keymgmt_free_fn ec_freedata; static OSSL_OP_keymgmt_get_params_fn ec_get_params; static OSSL_OP_keymgmt_gettable_params_fn ec_gettable_params; @@ -558,8 +568,195 @@ int ec_validate(void *keydata, int selection) return ok; } +struct ec_gen_ctx { + OPENSSL_CTX *libctx; + + EC_GROUP *gen_group; + int selection; +}; + +static void *ec_gen_init(void *provctx, int selection) +{ + OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx); + struct ec_gen_ctx *gctx = NULL; + + if ((selection & (EC_POSSIBLE_SELECTIONS)) == 0) + return NULL; + + if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) { + gctx->libctx = libctx; + gctx->gen_group = NULL; + gctx->selection = selection; + } + return gctx; +} + +static int ec_gen_set_group(void *genctx, int nid) +{ + struct ec_gen_ctx *gctx = genctx; + EC_GROUP *group; + + group = EC_GROUP_new_by_curve_name_ex(gctx->libctx, nid); + if (group == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE); + return 0; + } + EC_GROUP_free(gctx->gen_group); + gctx->gen_group = group; + return 1; +} +static int ec_gen_set_template(void *genctx, void *templ) +{ + struct ec_gen_ctx *gctx = genctx; + EC_KEY *ec = templ; + const EC_GROUP *ec_group; + + if (gctx == NULL || ec == NULL) + return 0; + if ((ec_group = EC_KEY_get0_group(ec)) == NULL) + return 0; + return ec_gen_set_group(gctx, EC_GROUP_get_curve_name(ec_group)); +} + +static int ec_gen_set_params(void *genctx, const OSSL_PARAM params[]) +{ + struct ec_gen_ctx *gctx = genctx; + const OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME)) + != NULL) { + const char *curve_name = NULL; + int ret = 0; + + switch (p->data_type) { + case OSSL_PARAM_UTF8_STRING: + /* The OSSL_PARAM functions have no support for this */ + curve_name = p->data; + ret = (curve_name != NULL); + break; + case OSSL_PARAM_UTF8_PTR: + ret = OSSL_PARAM_get_utf8_ptr(p, &curve_name); + break; + } + + if (ret) { + int nid = ec_curve_name2nid(curve_name); + + if (nid == NID_undef) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE); + ret = 0; + } else { + ret = ec_gen_set_group(gctx, nid); + } + } + return ret; + } + return 1; +} + +static const OSSL_PARAM *ec_gen_settable_params(void *provctx) +{ + static OSSL_PARAM settable[] = { + { OSSL_PKEY_PARAM_EC_NAME, OSSL_PARAM_UTF8_STRING, NULL, 0, 0 }, + OSSL_PARAM_END + }; + + return settable; +} + +static int ec_gen_get_params(void *genctx, OSSL_PARAM params[]) +{ + struct ec_gen_ctx *gctx = genctx; + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_NAME)) != NULL) { + int nid = EC_GROUP_get_curve_name(gctx->gen_group); + int ret = 0; + const char *curve_name = ec_curve_nid2name(nid); + + switch (p->data_type) { + case OSSL_PARAM_UTF8_STRING: + ret = OSSL_PARAM_set_utf8_string(p, curve_name); + break; + case OSSL_PARAM_UTF8_PTR: + ret = OSSL_PARAM_set_utf8_ptr(p, curve_name); + break; + } + return ret; + } + return 1; +} + +static const OSSL_PARAM *ec_gen_gettable_params(void *provctx) +{ + static OSSL_PARAM gettable[] = { + { OSSL_PKEY_PARAM_EC_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 }, + OSSL_PARAM_END + }; + + return gettable; +} + +static int ec_gen_assign_group(EC_KEY *ec, EC_GROUP *group) +{ + if (group == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); + return 0; + } + return EC_KEY_set_group(ec, group) > 0; +} + +/* + * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation + */ +static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +{ + struct ec_gen_ctx *gctx = genctx; + EC_KEY *ec = NULL; + int ret = 1; /* Start optimistically */ + + if (gctx == NULL + || (ec = EC_KEY_new_ex(gctx->libctx)) == NULL) + return NULL; + + /* We must always assign a group, no matter what */ + ret = ec_gen_assign_group(ec, gctx->gen_group); + /* Whether you want it or not, you get a keypair, not just one half */ + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) + ret = ret && EC_KEY_generate_key(ec); + + if (ret) + return ec; + + /* Something went wrong, throw the key away */ + EC_KEY_free(ec); + return NULL; +} + +static void ec_gen_cleanup(void *genctx) +{ + struct ec_gen_ctx *gctx = genctx; + + if (gctx == NULL) + return; + + EC_GROUP_free(gctx->gen_group); + OPENSSL_free(gctx); +} + const OSSL_DISPATCH ec_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata }, + { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init }, + { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, + (void (*)(void))ec_gen_set_template }, + { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params }, + { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, + (void (*)(void))ec_gen_settable_params }, + { OSSL_FUNC_KEYMGMT_GEN_GET_PARAMS, (void (*)(void))ec_gen_get_params }, + { OSSL_FUNC_KEYMGMT_GEN_GETTABLE_PARAMS, + (void (*)(void))ec_gen_gettable_params }, + { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ec_gen }, + { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup }, { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata }, { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params }, { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params }, @@ -573,6 +770,6 @@ const OSSL_DISPATCH ec_keymgmt_functions[] = { { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types }, { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, - (void (*)(void))ec_query_operation_name }, + (void (*)(void))ec_query_operation_name }, { 0, NULL } }; |