ec: recognise known parameters when written in full.
Some EC ASN.1 structures are using a named curve, but include the full
parameters anyway. With this change, BoringSSL will recognise the order
of the curve.
Change-Id: Iff057178453f9fdc98c8c03bcabbccef89709887
Reviewed-on: https://boringssl-review.googlesource.com/1270
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/ec/ec.c b/crypto/ec/ec.c
index ef022bc..5e3325d 100644
--- a/crypto/ec/ec.c
+++ b/crypto/ec/ec.c
@@ -75,21 +75,6 @@
#include "internal.h"
-/* curve_data contains data about a built-in elliptic curve. */
-struct curve_data {
- /* comment is a human-readable string describing the curve. */
- const char *comment;
- /* param_len is the number of bytes needed to store a field element. */
- uint8_t param_len;
- /* cofactor is the cofactor of the group (i.e. the number of elements in the
- * group divided by the size of the main subgroup. */
- uint8_t cofactor; /* promoted to BN_ULONG */
- /* data points to an array of 6*|param_len| bytes which hold the field
- * elements of the following (in big-endian order): prime, a, b, generator x,
- * generator y, order. */
- const uint8_t data[];
-};
-
static const struct curve_data P224 = {
"NIST P-224",
28,
@@ -231,13 +216,7 @@
0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09}};
-struct built_in_curve {
- int nid;
- const struct curve_data *data;
- const EC_METHOD *(*method)(void);
-};
-
-static const struct built_in_curve built_in_curves[] = {
+const struct built_in_curve OPENSSL_built_in_curves[] = {
{NID_secp224r1, &P224, 0},
{NID_X9_62_prime256v1, &P256, 0},
{NID_secp384r1, &P384, 0},
@@ -401,8 +380,8 @@
const struct built_in_curve *curve;
EC_GROUP *ret = NULL;
- for (i = 0; built_in_curves[i].nid != NID_undef; i++) {
- curve = &built_in_curves[i];
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ curve = &OPENSSL_built_in_curves[i];
if (curve->nid == nid) {
ret = ec_group_new_from_data(curve);
break;
diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c
index 35fff74..7920ae8 100644
--- a/crypto/ec/ec_asn1.c
+++ b/crypto/ec/ec_asn1.c
@@ -190,19 +190,39 @@
EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) {
EC_GROUP *ret = NULL;
- int nid = 0;
+ int nid = NID_undef;
if (params == NULL) {
OPENSSL_PUT_ERROR(EC, ec_asn1_pkparameters2group, EC_R_MISSING_PARAMETERS);
return NULL;
}
- if (params->type != 0) {
+ if (params->type == 0) {
+ nid = OBJ_obj2nid(params->value.named_curve);
+ } else if (params->type == 1) {
+ /* We don't support arbitary curves so we attempt to recognise it from the
+ * group order. */
+ const ECPARAMETERS *ecparams = params->value.parameters;
+ unsigned i;
+ const struct built_in_curve *curve;
+
+ for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+ curve = &OPENSSL_built_in_curves[i];
+ const unsigned param_len = curve->data->param_len;
+ if (ecparams->order->length == param_len &&
+ memcmp(ecparams->order->data, &curve->data->data[param_len * 5],
+ param_len) == 0) {
+ nid = curve->nid;
+ break;
+ }
+ }
+ }
+
+ if (nid == NID_undef) {
OPENSSL_PUT_ERROR(EC, ec_asn1_pkparameters2group, EC_R_NON_NAMED_CURVE);
return NULL;
}
- nid = OBJ_obj2nid(params->value.named_curve);
ret = EC_GROUP_new_by_curve_name(nid);
if (ret == NULL) {
OPENSSL_PUT_ERROR(EC, ec_asn1_pkparameters2group,
diff --git a/crypto/ec/internal.h b/crypto/ec/internal.h
index dc79186..76c3a80 100644
--- a/crypto/ec/internal.h
+++ b/crypto/ec/internal.h
@@ -349,6 +349,30 @@
CRYPTO_EX_DATA ex_data;
} /* EC_KEY */;
+/* curve_data contains data about a built-in elliptic curve. */
+struct curve_data {
+ /* comment is a human-readable string describing the curve. */
+ const char *comment;
+ /* param_len is the number of bytes needed to store a field element. */
+ uint8_t param_len;
+ /* cofactor is the cofactor of the group (i.e. the number of elements in the
+ * group divided by the size of the main subgroup. */
+ uint8_t cofactor; /* promoted to BN_ULONG */
+ /* data points to an array of 6*|param_len| bytes which hold the field
+ * elements of the following (in big-endian order): prime, a, b, generator x,
+ * generator y, order. */
+ const uint8_t data[];
+};
+
+struct built_in_curve {
+ int nid;
+ const struct curve_data *data;
+ const EC_METHOD *(*method)(void);
+};
+
+/* OPENSSL_built_in_curves is terminated with an entry where |nid| is
+ * |NID_undef|. */
+extern const struct built_in_curve OPENSSL_built_in_curves[];
#if defined(__cplusplus)
} /* extern C */