Decouple crypto/ec from the OID table.
Instead, embed the (very short) encoding of the OID into built_in_curve. BUG=chromium:499653 Change-Id: I0db36f83c71fbd3321831f54fa5022f8304b30cd Reviewed-on: https://boringssl-review.googlesource.com/7564 Reviewed-by: Steven Valdez <svaldez@google.com> Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
981936791e
commit
0d76c402b8
@ -228,10 +228,25 @@ static const struct curve_data P521 = {
|
||||
#endif
|
||||
|
||||
const struct built_in_curve OPENSSL_built_in_curves[] = {
|
||||
{NID_secp521r1, &P521, 0},
|
||||
{NID_secp384r1, &P384, 0},
|
||||
{
|
||||
NID_X9_62_prime256v1, &P256,
|
||||
NID_secp521r1,
|
||||
/* 1.3.132.0.35 */
|
||||
{0x2b, 0x81, 0x04, 0x00, 0x23}, 5,
|
||||
&P521,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
NID_secp384r1,
|
||||
/* 1.3.132.0.34 */
|
||||
{0x2b, 0x81, 0x04, 0x00, 0x22}, 5,
|
||||
&P384,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
NID_X9_62_prime256v1,
|
||||
/* 1.2.840.10045.3.1.7 */
|
||||
{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, 8,
|
||||
&P256,
|
||||
#if defined(BORINGSSL_USE_INT128_CODE)
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
|
||||
!defined(OPENSSL_SMALL)
|
||||
@ -240,18 +255,21 @@ const struct built_in_curve OPENSSL_built_in_curves[] = {
|
||||
EC_GFp_nistp256_method,
|
||||
#endif
|
||||
#else
|
||||
0,
|
||||
NULL,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
NID_secp224r1, &P224,
|
||||
NID_secp224r1,
|
||||
/* 1.3.132.0.33 */
|
||||
{0x2b, 0x81, 0x04, 0x00, 0x21}, 5,
|
||||
&P224,
|
||||
#if defined(BORINGSSL_USE_INT128_CODE) && !defined(OPENSSL_SMALL)
|
||||
EC_GFp_nistp224_method,
|
||||
#else
|
||||
0,
|
||||
NULL,
|
||||
#endif
|
||||
},
|
||||
{NID_undef, 0, 0},
|
||||
{NID_undef, {0}, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
/* built_in_curve_scalar_field_monts contains Montgomery contexts for
|
||||
|
@ -60,7 +60,7 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/nid.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../bytestring/internal.h"
|
||||
@ -207,14 +207,9 @@ int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
|
||||
}
|
||||
|
||||
if (!(enc_flags & EC_PKEY_NO_PARAMETERS)) {
|
||||
int curve_nid = EC_GROUP_get_curve_name(key->group);
|
||||
if (curve_nid == NID_undef) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
|
||||
return 0;
|
||||
}
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(&ec_private_key, &child, kParametersTag) ||
|
||||
!OBJ_nid2cbb(&child, curve_nid) ||
|
||||
!EC_KEY_marshal_curve_name(&child, key->group) ||
|
||||
!CBB_flush(&ec_private_key)) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
@ -260,6 +255,9 @@ static int is_unsigned_integer(const CBS *cbs) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* kPrimeFieldOID is the encoding of 1.2.840.10045.1.1. */
|
||||
static const uint8_t kPrimeField[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01};
|
||||
|
||||
static int parse_explicit_prime_curve(CBS *in, CBS *out_prime, CBS *out_a,
|
||||
CBS *out_b, CBS *out_base_x,
|
||||
CBS *out_base_y, CBS *out_order) {
|
||||
@ -272,7 +270,8 @@ static int parse_explicit_prime_curve(CBS *in, CBS *out_prime, CBS *out_a,
|
||||
version != 1 ||
|
||||
!CBS_get_asn1(¶ms, &field_id, CBS_ASN1_SEQUENCE) ||
|
||||
!CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) ||
|
||||
OBJ_cbs2nid(&field_type) != NID_X9_62_prime_field ||
|
||||
CBS_len(&field_type) != sizeof(kPrimeField) ||
|
||||
memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) != 0 ||
|
||||
!CBS_get_asn1(&field_id, out_prime, CBS_ASN1_INTEGER) ||
|
||||
!is_unsigned_integer(out_prime) ||
|
||||
CBS_len(&field_id) != 0 ||
|
||||
@ -324,51 +323,86 @@ static int integers_equal(const CBS *a, const uint8_t *b, size_t b_len) {
|
||||
return CBS_mem_equal(&a_copy, b, b_len);
|
||||
}
|
||||
|
||||
EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
|
||||
if (CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) {
|
||||
/* OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions
|
||||
* of named curves.
|
||||
*
|
||||
* TODO(davidben): Remove support for this. */
|
||||
CBS prime, a, b, base_x, base_y, order;
|
||||
if (!parse_explicit_prime_curve(cbs, &prime, &a, &b, &base_x, &base_y,
|
||||
&order)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Look for a matching prime curve. */
|
||||
unsigned i;
|
||||
for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
|
||||
const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
|
||||
const unsigned param_len = curve->data->param_len;
|
||||
/* |curve->data->data| is ordered p, a, b, x, y, order, each component
|
||||
* zero-padded up to the field length. Although SEC 1 states that the
|
||||
* Field-Element-to-Octet-String conversion also pads, OpenSSL mis-encodes
|
||||
* |a| and |b|, so this comparison must allow omitting leading zeros.
|
||||
* (This is relevant for P-521 whose |b| has a leading 0.) */
|
||||
if (integers_equal(&prime, curve->data->data, param_len) &&
|
||||
integers_equal(&a, curve->data->data + param_len, param_len) &&
|
||||
integers_equal(&b, curve->data->data + param_len * 2, param_len) &&
|
||||
integers_equal(&base_x, curve->data->data + param_len * 3,
|
||||
param_len) &&
|
||||
integers_equal(&base_y, curve->data->data + param_len * 4,
|
||||
param_len) &&
|
||||
integers_equal(&order, curve->data->data + param_len * 5,
|
||||
param_len)) {
|
||||
return EC_GROUP_new_by_curve_name(curve->nid);
|
||||
}
|
||||
}
|
||||
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) {
|
||||
CBS named_curve;
|
||||
if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
return EC_GROUP_new_by_curve_name(OBJ_cbs2nid(&named_curve));
|
||||
|
||||
/* Look for a matching curve. */
|
||||
unsigned i;
|
||||
for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
|
||||
const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
|
||||
if (CBS_len(&named_curve) == curve->oid_len &&
|
||||
memcmp(CBS_data(&named_curve), curve->oid, curve->oid_len) == 0) {
|
||||
return EC_GROUP_new_by_curve_name(curve->nid);
|
||||
}
|
||||
}
|
||||
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) {
|
||||
int nid = EC_GROUP_get_curve_name(group);
|
||||
if (nid == NID_undef) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
|
||||
const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
|
||||
if (curve->nid == nid) {
|
||||
CBB child;
|
||||
return CBB_add_asn1(cbb, &child, CBS_ASN1_OBJECT) &&
|
||||
CBB_add_bytes(&child, curve->oid, curve->oid_len) &&
|
||||
CBB_flush(cbb);
|
||||
}
|
||||
}
|
||||
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
|
||||
if (!CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) {
|
||||
return EC_KEY_parse_curve_name(cbs);
|
||||
}
|
||||
|
||||
/* OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions
|
||||
* of named curves.
|
||||
*
|
||||
* TODO(davidben): Remove support for this. */
|
||||
CBS prime, a, b, base_x, base_y, order;
|
||||
if (!parse_explicit_prime_curve(cbs, &prime, &a, &b, &base_x, &base_y,
|
||||
&order)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Look for a matching prime curve. */
|
||||
unsigned i;
|
||||
for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
|
||||
const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
|
||||
const unsigned param_len = curve->data->param_len;
|
||||
/* |curve->data->data| is ordered p, a, b, x, y, order, each component
|
||||
* zero-padded up to the field length. Although SEC 1 states that the
|
||||
* Field-Element-to-Octet-String conversion also pads, OpenSSL mis-encodes
|
||||
* |a| and |b|, so this comparison must allow omitting leading zeros. (This
|
||||
* is relevant for P-521 whose |b| has a leading 0.) */
|
||||
if (integers_equal(&prime, curve->data->data, param_len) &&
|
||||
integers_equal(&a, curve->data->data + param_len, param_len) &&
|
||||
integers_equal(&b, curve->data->data + param_len * 2, param_len) &&
|
||||
integers_equal(&base_x, curve->data->data + param_len * 3, param_len) &&
|
||||
integers_equal(&base_y, curve->data->data + param_len * 4, param_len) &&
|
||||
integers_equal(&order, curve->data->data + param_len * 5, param_len)) {
|
||||
return EC_GROUP_new_by_curve_name(curve->nid);
|
||||
}
|
||||
}
|
||||
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EC_KEY *d2i_ECPrivateKey(EC_KEY **out, const uint8_t **inp, long len) {
|
||||
@ -441,15 +475,9 @@ int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int curve_nid = EC_GROUP_get_curve_name(key->group);
|
||||
if (curve_nid == NID_undef) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
CBB cbb;
|
||||
if (!CBB_init(&cbb, 0) ||
|
||||
!OBJ_nid2cbb(&cbb, curve_nid)) {
|
||||
!EC_KEY_marshal_curve_name(&cbb, key->group)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return -1;
|
||||
}
|
||||
|
@ -271,6 +271,8 @@ struct curve_data {
|
||||
|
||||
struct built_in_curve {
|
||||
int nid;
|
||||
uint8_t oid[8];
|
||||
uint8_t oid_len;
|
||||
const struct curve_data *data;
|
||||
const EC_METHOD *(*method)(void);
|
||||
};
|
||||
|
@ -69,11 +69,6 @@
|
||||
static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) {
|
||||
const EC_KEY *ec_key = key->pkey.ec;
|
||||
const EC_GROUP *group = EC_KEY_get0_group(ec_key);
|
||||
int curve_nid = EC_GROUP_get_curve_name(group);
|
||||
if (curve_nid == NID_undef) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_NID_FOR_CURVE);
|
||||
return 0;
|
||||
}
|
||||
const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key);
|
||||
|
||||
/* See RFC 5480, section 2. */
|
||||
@ -81,7 +76,7 @@ static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) {
|
||||
if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
|
||||
!CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
|
||||
!OBJ_nid2cbb(&algorithm, NID_X9_62_id_ecPublicKey) ||
|
||||
!OBJ_nid2cbb(&algorithm, curve_nid) ||
|
||||
!EC_KEY_marshal_curve_name(&algorithm, group) ||
|
||||
!CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
|
||||
!CBB_add_u8(&key_bitstring, 0 /* padding */) ||
|
||||
!EC_POINT_point2cbb(&key_bitstring, group, public_key,
|
||||
@ -98,31 +93,32 @@ static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
|
||||
/* See RFC 5480, section 2. */
|
||||
|
||||
/* The parameters are a named curve. */
|
||||
CBS named_curve;
|
||||
if (!CBS_get_asn1(params, &named_curve, CBS_ASN1_OBJECT) ||
|
||||
CBS_len(params) != 0) {
|
||||
EC_GROUP *group = EC_KEY_parse_curve_name(params);
|
||||
if (group == NULL || CBS_len(params) != 0) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EC_KEY *eckey = EC_KEY_new_by_curve_name(OBJ_cbs2nid(&named_curve));
|
||||
if (eckey == NULL) {
|
||||
return 0;
|
||||
EC_POINT *point = NULL;
|
||||
EC_KEY *eckey = EC_KEY_new();
|
||||
if (eckey == NULL || !EC_KEY_set_group(eckey, group)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(eckey));
|
||||
point = EC_POINT_new(group);
|
||||
if (point == NULL ||
|
||||
!EC_POINT_oct2point(EC_KEY_get0_group(eckey), point, CBS_data(key),
|
||||
CBS_len(key), NULL) ||
|
||||
!EC_POINT_oct2point(group, point, CBS_data(key), CBS_len(key), NULL) ||
|
||||
!EC_KEY_set_public_key(eckey, point)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
EC_GROUP_free(group);
|
||||
EC_POINT_free(point);
|
||||
EVP_PKEY_assign_EC_KEY(out, eckey);
|
||||
return 1;
|
||||
|
||||
err:
|
||||
EC_GROUP_free(group);
|
||||
EC_POINT_free(point);
|
||||
EC_KEY_free(eckey);
|
||||
return 0;
|
||||
@ -166,11 +162,6 @@ static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
|
||||
|
||||
static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) {
|
||||
const EC_KEY *ec_key = key->pkey.ec;
|
||||
int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
|
||||
if (curve_nid == NID_undef) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_NID_FOR_CURVE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Omit the redundant copy of the curve name. This contradicts RFC 5915 but
|
||||
* aligns with PKCS #11. SEC 1 only says they may be omitted if known by other
|
||||
@ -184,7 +175,7 @@ static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) {
|
||||
!CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
|
||||
!CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
|
||||
!OBJ_nid2cbb(&algorithm, NID_X9_62_id_ecPublicKey) ||
|
||||
!OBJ_nid2cbb(&algorithm, curve_nid) ||
|
||||
!EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) ||
|
||||
!CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
|
||||
!EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) ||
|
||||
!CBB_flush(out)) {
|
||||
|
@ -192,10 +192,21 @@ OPENSSL_EXPORT EC_KEY *EC_KEY_parse_private_key(CBS *cbs,
|
||||
OPENSSL_EXPORT int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
|
||||
unsigned enc_flags);
|
||||
|
||||
/* EC_KEY_parse_parameters parses a DER-encoded OBJECT IDENTIFIER as a curve
|
||||
* name from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP|
|
||||
* or NULL on error. */
|
||||
OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs);
|
||||
|
||||
/* EC_KEY_marshal_curve_name marshals |group| as a DER-encoded OBJECT IDENTIFIER
|
||||
* and appends the result to |cbb|. It returns one on success and zero on
|
||||
* failure. */
|
||||
OPENSSL_EXPORT int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group);
|
||||
|
||||
/* EC_KEY_parse_parameters parses a DER-encoded ECParameters structure (RFC
|
||||
* 5480) from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP|
|
||||
* or NULL on error. It supports the namedCurve and specifiedCurve options, but
|
||||
* use of specifiedCurve is deprecated. */
|
||||
* use of specifiedCurve is deprecated. Use |EC_KEY_parse_curve_name|
|
||||
* instead. */
|
||||
OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_parameters(CBS *cbs);
|
||||
|
||||
|
||||
@ -279,7 +290,7 @@ OPENSSL_EXPORT int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp);
|
||||
* allocated and the previous one is freed. On successful exit, |*inp| is
|
||||
* advanced past the DER structure. It returns the result or NULL on error.
|
||||
*
|
||||
* Use EC_KEY_parse_parameters instead. */
|
||||
* Use |EC_KEY_parse_parameters| or |EC_KEY_parse_curve_name| instead. */
|
||||
OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp,
|
||||
long len);
|
||||
|
||||
@ -288,7 +299,7 @@ OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp,
|
||||
* |*outp| is advanced just past the output. It returns the number of bytes in
|
||||
* the result, whether written or not, or a negative value on error.
|
||||
*
|
||||
* Use |OBJ_nid2cbb| and |EC_GROUP_get_curve_name| instead. */
|
||||
* Use |EC_KEY_marshal_curve_name| instead. */
|
||||
OPENSSL_EXPORT int i2d_ECParameters(const EC_KEY *key, uint8_t **outp);
|
||||
|
||||
/* o2i_ECPublicKey parses an EC point from |len| bytes at |*inp| into
|
||||
|
Loading…
Reference in New Issue
Block a user