summaryrefslogtreecommitdiffstats
path: root/crypto/ec/ec_backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/ec/ec_backend.c')
-rw-r--r--crypto/ec/ec_backend.c219
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;
+}