diff options
Diffstat (limited to 'crypto/ec/ec_backend.c')
-rw-r--r-- | crypto/ec/ec_backend.c | 219 |
1 files changed, 212 insertions, 7 deletions
diff --git a/crypto/ec/ec_backend.c b/crypto/ec/ec_backend.c index f950657173..06acb7d607 100644 --- a/crypto/ec/ec_backend.c +++ b/crypto/ec/ec_backend.c @@ -7,6 +7,12 @@ * https://www.openssl.org/source/license.html */ +/* + * Low level APIs related to EC_KEY are deprecated for public use, + * but still ok for internal use. + */ +#include "internal/deprecated.h" + #include <openssl/core_names.h> #include <openssl/objects.h> #include <openssl/params.h> @@ -23,6 +29,18 @@ static const OSSL_ITEM encoding_nameid_map[] = { { OPENSSL_EC_NAMED_CURVE, OSSL_PKEY_EC_ENCODING_GROUP }, }; +static const OSSL_ITEM check_group_type_nameid_map[] = { + { 0, OSSL_PKEY_EC_GROUP_CHECK_DEFAULT }, + { EC_FLAG_CHECK_NAMED_GROUP, OSSL_PKEY_EC_GROUP_CHECK_NAMED }, + { EC_FLAG_CHECK_NAMED_GROUP_NIST, OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST }, +}; + +static const OSSL_ITEM format_nameid_map[] = { + { (int)POINT_CONVERSION_UNCOMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED }, + { (int)POINT_CONVERSION_COMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED }, + { (int)POINT_CONVERSION_HYBRID, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID }, +}; + int ec_encoding_name2id(const char *name) { size_t i, sz; @@ -49,13 +67,95 @@ static char *ec_param_encoding_id2name(int id) return NULL; } +char *ec_check_group_type_id2name(int id) +{ + size_t i, sz; + + for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) { + if (id == (int)check_group_type_nameid_map[i].id) + return check_group_type_nameid_map[i].ptr; + } + return NULL; +} + +static int ec_check_group_type_name2id(const char *name) +{ + size_t i, sz; + + /* Return the default value if there is no name */ + if (name == NULL) + return 0; + + for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) { + if (strcasecmp(name, check_group_type_nameid_map[i].ptr) == 0) + return check_group_type_nameid_map[i].id; + } + return -1; +} + +int ec_set_check_group_type_from_name(EC_KEY *ec, const char *name) +{ + int flags = ec_check_group_type_name2id(name); + + if (flags == -1) + return 0; + EC_KEY_clear_flags(ec, EC_FLAG_CHECK_NAMED_GROUP_MASK); + EC_KEY_set_flags(ec, flags); + return 1; +} + +static int ec_set_check_group_type_from_param(EC_KEY *ec, const OSSL_PARAM *p) +{ + const char *name = NULL; + int status = 0; + + switch (p->data_type) { + case OSSL_PARAM_UTF8_STRING: + name = p->data; + status = (name != NULL); + break; + case OSSL_PARAM_UTF8_PTR: + status = OSSL_PARAM_get_utf8_ptr(p, &name); + break; + } + if (status) + return ec_set_check_group_type_from_name(ec, name); + return 0; +} + +int ec_pt_format_name2id(const char *name) +{ + size_t i, sz; + + /* Return the default value if there is no name */ + if (name == NULL) + return (int)POINT_CONVERSION_UNCOMPRESSED; + + for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) { + if (strcasecmp(name, format_nameid_map[i].ptr) == 0) + return format_nameid_map[i].id; + } + return -1; +} + +char *ec_pt_format_id2name(int id) +{ + size_t i, sz; + + for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) { + if (id == (int)format_nameid_map[i].id) + return format_nameid_map[i].ptr; + } + return NULL; +} + int ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, OSSL_PARAM params[], OSSL_LIB_CTX *libctx, const char *propq, BN_CTX *bnctx, unsigned char **genbuf) { int ret = 0, curve_nid, encoding_flag; - const char *field_type, *encoding_name; + const char *field_type, *encoding_name, *pt_form_name; const BIGNUM *cofactor, *order; BIGNUM *p = NULL, *a = NULL, *b = NULL; point_conversion_form_t genform; @@ -68,6 +168,15 @@ int ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, return 0; } + genform = EC_GROUP_get_point_conversion_form(group); + pt_form_name = ec_pt_format_id2name(genform); + if (pt_form_name == NULL + || !ossl_param_build_set_utf8_string( + tmpl, params, + OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, pt_form_name)) { + ECerr(0, EC_R_INVALID_FORM); + return 0; + } encoding_flag = EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE; encoding_name = ec_param_encoding_id2name(encoding_flag); if (encoding_name == NULL @@ -115,7 +224,6 @@ int ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); goto err; } - genform = EC_GROUP_get_point_conversion_form(group); genbuf_len = EC_POINT_point2buf(group, genpt, genform, genbuf, bnctx); if (genbuf_len == 0) { ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); @@ -336,17 +444,50 @@ int ec_group_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) if (!EC_KEY_set_group(ec, group)) goto err; - - /* - * TODO(3.0): if the group has changed, should we invalidate the private and - * public key? - */ ok = 1; err: EC_GROUP_free(group); return ok; } +static int ec_key_point_format_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + int format = -1; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT); + if (p != NULL) { + if (!ec_pt_format_param2id(p, &format)) { + ECerr(0, EC_R_INVALID_FORM); + return 0; + } + EC_KEY_set_conv_form(ec, format); + } + return 1; +} + +static int ec_key_group_check_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE); + if (p != NULL) + return ec_set_check_group_type_from_param(ec, p); + return 1; +} + +static int ec_set_include_public(EC_KEY *ec, int include) +{ + int flags = EC_KEY_get_enc_flags(ec); + + if (!include) + flags |= EC_PKEY_NO_PUBKEY; + else + flags &= ~EC_PKEY_NO_PUBKEY; + EC_KEY_set_enc_flags(ec, flags); + return 1; +} + int ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) { const OSSL_PARAM *p; @@ -363,5 +504,69 @@ int ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) return 0; } + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC); + if (p != NULL) { + int include = 1; + + if (!OSSL_PARAM_get_int(p, &include) + || !ec_set_include_public(ec, include)) + return 0; + } + if (!ec_key_point_format_fromdata(ec, params)) + return 0; + if (!ec_key_group_check_fromdata(ec, params)) + return 0; return 1; } + +int ec_encoding_param2id(const OSSL_PARAM *p, int *id) +{ + const char *name = NULL; + int status = 0; + + switch (p->data_type) { + case OSSL_PARAM_UTF8_STRING: + /* The OSSL_PARAM functions have no support for this */ + name = p->data; + status = (name != NULL); + break; + case OSSL_PARAM_UTF8_PTR: + status = OSSL_PARAM_get_utf8_ptr(p, &name); + break; + } + if (status) { + int i = ec_encoding_name2id(name); + + if (i >= 0) { + *id = i; + return 1; + } + } + return 0; +} + +int ec_pt_format_param2id(const OSSL_PARAM *p, int *id) +{ + const char *name = NULL; + int status = 0; + + switch (p->data_type) { + case OSSL_PARAM_UTF8_STRING: + /* The OSSL_PARAM functions have no support for this */ + name = p->data; + status = (name != NULL); + break; + case OSSL_PARAM_UTF8_PTR: + status = OSSL_PARAM_get_utf8_ptr(p, &name); + break; + } + if (status) { + int i = ec_pt_format_name2id(name); + + if (i >= 0) { + *id = i; + return 1; + } + } + return 0; +} |