mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
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)
This commit is contained in:
parent
2b9add6965
commit
1f185f51a7
@ -2819,6 +2819,7 @@ PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\
|
||||
PROV_R_INAVLID_UKM_LENGTH:146:inavlid ukm length
|
||||
PROV_R_INVALID_AAD:108:invalid aad
|
||||
PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length
|
||||
PROV_R_INVALID_CURVE:176:invalid curve
|
||||
PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length
|
||||
PROV_R_INVALID_DATA:115:invalid data
|
||||
PROV_R_INVALID_DIGEST:122:invalid digest
|
||||
@ -2858,6 +2859,7 @@ PROV_R_MISSING_XCGHASH:135:missing xcghash
|
||||
PROV_R_NOT_SUPPORTED:136:not supported
|
||||
PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length
|
||||
PROV_R_NO_KEY_SET:114:no key set
|
||||
PROV_R_NO_PARAMETERS_SET:177:no parameters set
|
||||
PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
|
||||
PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small
|
||||
PROV_R_READ_KEY:159:read key
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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 }
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user