#include <err.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/sha.h>
#include "ec_local.h"
EC_GROUP *EC_GROUP_new(const EC_METHOD *);
#define NEGATIVE_CURVE_COEFFICIENTS_ALLOWED 1
static const uint8_t ec_secp256r1_pkparameters_named_curve[] = {
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
0x01, 0x07,
};
static const uint8_t ec_secp256r1_pkparameters_parameters[] = {
0x30, 0x81, 0xf7, 0x02, 0x01, 0x01, 0x30, 0x2c,
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x30, 0x5b, 0x04, 0x20,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a,
0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98,
0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2,
0x60, 0x4b, 0x03, 0x15, 0x00, 0xc4, 0x9d, 0x36,
0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e,
0x90, 0x04, 0x41, 0x04, 0x6b, 0x17, 0xd1, 0xf2,
0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81,
0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45,
0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3,
0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, 0x02,
0x01, 0x01,
};
static const uint8_t ec_secp256k1_pkparameters_parameters[] = {
0x30, 0x81, 0xe0, 0x02, 0x01, 0x01, 0x30, 0x2c,
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xff, 0xff, 0xfc, 0x2f, 0x30, 0x44, 0x04, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0x04, 0x41, 0x04, 0x79, 0xbe, 0x66,
0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62,
0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc,
0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81,
0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a, 0xda,
0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb,
0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4,
0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0,
0x8f, 0xfb, 0x10, 0xd4, 0xb8, 0x02, 0x21, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41,
0x02, 0x01, 0x01,
};
static void
hexdump(const unsigned char *buf, size_t len)
{
size_t i;
for (i = 1; i <= len; i++)
fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
fprintf(stderr, "\n");
}
static int
compare_data(const char *label, const unsigned char *d1, size_t d1_len,
const unsigned char *d2, size_t d2_len)
{
if (d1_len != d2_len) {
fprintf(stderr, "FAIL: got %s with length %zu, want %zu\n",
label, d1_len, d2_len);
return -1;
}
if (memcmp(d1, d2, d1_len) != 0) {
fprintf(stderr, "FAIL: %s differ\n", label);
fprintf(stderr, "got:\n");
hexdump(d1, d1_len);
fprintf(stderr, "want:\n");
hexdump(d2, d2_len);
return -1;
}
return 0;
}
static int
ec_group_pkparameters_test(const char *label, int nid, int asn1_flag,
const uint8_t *test_data, size_t test_data_len)
{
EC_GROUP *group_a = NULL, *group_b = NULL;
unsigned char *out = NULL, *data = NULL;
const unsigned char *p;
BIO *bio_mem = NULL;
int failure = 1;
int len;
if ((group_a = EC_GROUP_new_by_curve_name(nid)) == NULL)
errx(1, "failed to create EC_GROUP");
EC_GROUP_set_asn1_flag(group_a, asn1_flag);
if ((len = i2d_ECPKParameters(group_a, &out)) < 0) {
fprintf(stderr, "FAIL: i2d_ECPKParameters failed\n");
goto done;
}
if (compare_data(label, out, len, test_data, test_data_len) == -1)
goto done;
p = out;
if ((group_b = d2i_ECPKParameters(NULL, &p, len)) == NULL) {
fprintf(stderr, "FAIL: d2i_ECPKParameters failed\n");
goto done;
}
if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) {
fprintf(stderr, "FAIL: EC_GROUPs do not match!\n");
goto done;
}
p = out;
if ((group_a = d2i_ECPKParameters(&group_a, &p, len)) == NULL) {
fprintf(stderr, "FAIL: d2i_ECPKParameters failed\n");
goto done;
}
if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) {
fprintf(stderr, "FAIL: EC_GROUPs do not match!\n");
goto done;
}
if ((bio_mem = BIO_new(BIO_s_mem())) == NULL)
errx(1, "BIO_new failed for BIO_s_mem");
if (i2d_ECPKParameters_bio(bio_mem, group_a) < 0) {
fprintf(stderr, "FAIL: i2d_ECPKParameters_bio failed\n");
goto done;
}
len = BIO_get_mem_data(bio_mem, &data);
if (compare_data(label, out, len, test_data, test_data_len) == -1)
goto done;
EC_GROUP_free(group_b);
if ((group_b = d2i_ECPKParameters_bio(bio_mem, NULL)) == NULL) {
fprintf(stderr, "FAIL: d2i_ECPKParameters_bio failed\n");
goto done;
}
if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) {
fprintf(stderr, "FAIL: EC_GROUPs do not match!\n");
goto done;
}
failure = 0;
done:
BIO_free_all(bio_mem);
EC_GROUP_free(group_a);
EC_GROUP_free(group_b);
free(out);
return failure;
}
static int
ec_group_pkparameters_named_curve_test(void)
{
return ec_group_pkparameters_test("ECPKPARAMETERS named curve",
NID_X9_62_prime256v1, OPENSSL_EC_NAMED_CURVE,
ec_secp256r1_pkparameters_named_curve,
sizeof(ec_secp256r1_pkparameters_named_curve));
}
static int
ec_group_pkparameters_parameters_test(void)
{
return ec_group_pkparameters_test("ECPKPARAMETERS parameters",
NID_X9_62_prime256v1, OPENSSL_EC_EXPLICIT_CURVE,
ec_secp256r1_pkparameters_parameters,
sizeof(ec_secp256r1_pkparameters_parameters));
}
static int
ec_group_pkparameters_correct_padding_test(void)
{
return ec_group_pkparameters_test("ECPKPARAMETERS parameters",
NID_secp256k1, OPENSSL_EC_EXPLICIT_CURVE,
ec_secp256k1_pkparameters_parameters,
sizeof(ec_secp256k1_pkparameters_parameters));
}
static EC_GROUP *
ec_group_simple_from_builtin(const EC_GROUP *group, int nid, BN_CTX *ctx)
{
EC_GROUP *simple_group;
BIGNUM *p, *a, *b, *x, *y, *order, *cofactor;
const EC_POINT *generator;
EC_POINT *simple_generator = NULL;
BN_CTX_start(ctx);
if ((p = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((a = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((b = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((x = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((y = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((order = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((cofactor = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if (!EC_GROUP_get_curve(group, p, a, b, ctx))
errx(1, "EC_GROUP_get_curve");
if (!EC_GROUP_get_order(group, order, ctx))
errx(1, "EC_GROUP_get_order");
if (!EC_GROUP_get_cofactor(group, cofactor, ctx))
errx(1, "EC_GROUP_get_cofactor");
if ((generator = EC_GROUP_get0_generator(group)) == NULL)
errx(1, "EC_GROUP_get0_generator");
if (!EC_POINT_get_affine_coordinates(group, generator, x, y, ctx))
errx(1, "EC_POINT_get_affine_coordinates");
if ((simple_group = EC_GROUP_new(EC_GFp_simple_method())) == NULL)
errx(1, "EC_GROUP_new");
if (!EC_GROUP_set_curve(simple_group, p, a, b, ctx))
errx(1, "EC_GROUP_set_curve");
EC_GROUP_set_curve_name(simple_group, nid);
if ((simple_generator = EC_POINT_new(simple_group)) == NULL)
errx(1, "EC_POINT_new");
if (!EC_POINT_set_compressed_coordinates(simple_group, simple_generator,
x, BN_is_odd(y), ctx))
errx(1, "EC_POINT_set_affine_coordinates");
if (!EC_GROUP_set_generator(simple_group, simple_generator, order,
cofactor))
errx(1, "EC_GROUP_set_generator");
BN_CTX_end(ctx);
EC_POINT_free(simple_generator);
return simple_group;
}
static int
ec_group_roundtrip_curve(const EC_GROUP *group, const char *descr, int nid)
{
EC_GROUP *new_group = NULL;
unsigned char *der = NULL, *new_der = NULL;
int der_len = 0, new_der_len = 0;
const unsigned char *p;
int failed = 1;
der = NULL;
if ((der_len = i2d_ECPKParameters(group, &der)) <= 0)
errx(1, "failed to serialize %s %d", descr, nid);
p = der;
if ((new_group = d2i_ECPKParameters(NULL, &p, der_len)) == NULL)
errx(1, "failed to deserialize %s %d", descr, nid);
new_der = NULL;
if ((new_der_len = i2d_ECPKParameters(new_group, &new_der)) <= 0)
errx(1, "failed to serialize new %s %d", descr, nid);
if (compare_data(__func__, der, der_len, new_der, new_der_len) == -1) {
fprintf(stderr, "FAIL: new and old der for %s %d\n", descr, nid);
goto err;
}
if (EC_GROUP_get_asn1_flag(group) != EC_GROUP_get_asn1_flag(new_group)) {
fprintf(stderr, "FAIL: %s %d asn1_flag %x != %x\n", descr, nid,
EC_GROUP_get_asn1_flag(group),
EC_GROUP_get_asn1_flag(new_group));
goto err;
}
if (EC_GROUP_get_point_conversion_form(group) !=
EC_GROUP_get_point_conversion_form(new_group)) {
fprintf(stderr, "FAIL: %s %d form %02x != %02x\n", descr, nid,
EC_GROUP_get_point_conversion_form(group),
EC_GROUP_get_point_conversion_form(new_group));
goto err;
}
failed = 0;
err:
EC_GROUP_free(new_group);
freezero(der, der_len);
freezero(new_der, new_der_len);
return failed;
}
static int
ec_group_roundtrip_group(EC_GROUP *group, int nid)
{
int failed = 1;
if (EC_GROUP_get_asn1_flag(group) != OPENSSL_EC_NAMED_CURVE) {
fprintf(stderr, "FAIL: ASN.1 flag not set for %d\n", nid);
goto err;
}
if (EC_GROUP_get_point_conversion_form(group) !=
POINT_CONVERSION_UNCOMPRESSED) {
fprintf(stderr, "FAIL: %d has point conversion form %02x\n",
nid, EC_GROUP_get_point_conversion_form(group));
goto err;
}
failed = 0;
failed |= ec_group_roundtrip_curve(group, "named", nid);
EC_GROUP_set_asn1_flag(group, 0);
failed |= ec_group_roundtrip_curve(group, "explicit", nid);
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_COMPRESSED);
failed |= ec_group_roundtrip_curve(group, "compressed", nid);
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_HYBRID);
failed |= ec_group_roundtrip_curve(group, "hybrid", nid);
err:
return failed;
}
static int
ec_group_roundtrip_builtin_curve(const EC_builtin_curve *curve, BN_CTX *ctx)
{
EC_GROUP *group = NULL, *simple_group = NULL;
int failed = 0;
if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL)
errx(1, "failed to instantiate curve %d", curve->nid);
if (!EC_GROUP_check(group, NULL)) {
fprintf(stderr, "FAIL: EC_GROUP_check(%d) failed\n", curve->nid);
goto err;
}
if ((simple_group = ec_group_simple_from_builtin(group, curve->nid,
ctx)) == NULL)
errx(1, "failed to instantiate simple group %d", curve->nid);
if (!EC_GROUP_check(group, NULL)) {
fprintf(stderr, "FAIL: EC_GROUP_check(%d) failed\n", curve->nid);
goto err;
}
failed |= ec_group_roundtrip_group(group, curve->nid);
failed |= ec_group_roundtrip_group(simple_group, curve->nid);
err:
EC_GROUP_free(group);
EC_GROUP_free(simple_group);
return failed;
}
static int
ec_group_roundtrip_builtin_curves(void)
{
BN_CTX *ctx = NULL;
EC_builtin_curve *all_curves = NULL;
size_t curve_id, ncurves;
int failed = 0;
if ((ctx = BN_CTX_new()) == NULL)
errx(1, "BN_CTX_new");
ncurves = EC_get_builtin_curves(NULL, 0);
if ((all_curves = calloc(ncurves, sizeof(*all_curves))) == NULL)
err(1, "calloc builtin curves");
EC_get_builtin_curves(all_curves, ncurves);
for (curve_id = 0; curve_id < ncurves; curve_id++)
failed |= ec_group_roundtrip_builtin_curve(&all_curves[curve_id], ctx);
free(all_curves);
BN_CTX_free(ctx);
return failed;
}
struct curve {
const char *descr;
const char *oid;
const char *sn;
const char *ln;
const char *p;
const char *a;
const char *b;
const char *order;
const char *cofactor;
const char *x;
const char *y;
int known_named_curve;
const char *named;
size_t named_len;
const char *param;
size_t param_len;
};
static const uint8_t ec_wei25519_pkparameters_named_curve[] = {
0x06, 0x03, 0x2b, 0x65, 0x6c,
};
static const uint8_t ec_wei25519_pkparameters_parameters[] = {
0x30, 0x81, 0xde, 0x02, 0x01, 0x01, 0x30, 0x2b,
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
0x01, 0x02, 0x20, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xed, 0x30, 0x44, 0x04, 0x20, 0x2a,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0x98, 0x49, 0x14, 0xa1, 0x44, 0x04,
0x20, 0x7b, 0x42, 0x5e, 0xd0, 0x97, 0xb4, 0x25,
0xed, 0x09, 0x7b, 0x42, 0x5e, 0xd0, 0x97, 0xb4,
0x25, 0xed, 0x09, 0x7b, 0x42, 0x5e, 0xd0, 0x97,
0xb4, 0x26, 0x0b, 0x5e, 0x9c, 0x77, 0x10, 0xc8,
0x64, 0x04, 0x41, 0x04, 0x2a, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xad, 0x24, 0x5a, 0x20, 0xae, 0x19, 0xa1,
0xb8, 0xa0, 0x86, 0xb4, 0xe0, 0x1e, 0xdd, 0x2c,
0x77, 0x48, 0xd1, 0x4c, 0x92, 0x3d, 0x4d, 0x7e,
0x6d, 0x7c, 0x61, 0xb2, 0x29, 0xe9, 0xc5, 0xa2,
0x7e, 0xce, 0xd3, 0xd9, 0x02, 0x20, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde,
0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6, 0x58, 0x12,
0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed, 0x02, 0x01,
0x08,
};
static const struct curve wei25519 = {
.descr = "short Weierstrass 25519",
.oid = "1.3.101.108",
.sn = "Wei25519",
.p = "7fffffff" "ffffffff" "ffffffff" "ffffffff"
"ffffffff" "ffffffff" "ffffffff" "ffffffed",
.a = "2aaaaaaa" "aaaaaaaa" "aaaaaaaa" "aaaaaaaa"
"aaaaaaaa" "aaaaaaaa" "aaaaaa98" "4914a144",
.b = "7b425ed0" "97b425ed" "097b425e" "d097b425"
"ed097b42" "5ed097b4" "260b5e9c" "7710c864",
.x = "2aaaaaaa" "aaaaaaaa" "aaaaaaaa" "aaaaaaaa"
"aaaaaaaa" "aaaaaaaa" "aaaaaaaa" "aaad245a",
.y = "20ae19a1" "b8a086b4" "e01edd2c" "7748d14c"
"923d4d7e" "6d7c61b2" "29e9c5a2" "7eced3d9",
.order = "10000000" "00000000" "00000000" "00000000"
"14def9de" "a2f79cd6" "5812631a" "5cf5d3ed",
.cofactor = "8",
.named = ec_wei25519_pkparameters_named_curve,
.named_len = sizeof(ec_wei25519_pkparameters_named_curve),
.param = ec_wei25519_pkparameters_parameters,
.param_len = sizeof(ec_wei25519_pkparameters_parameters),
};
static const uint8_t ec_wei25519_2_pkparameters_parameters[] = {
0x30, 0x81, 0xde, 0x02, 0x01, 0x01, 0x30, 0x2b,
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
0x01, 0x02, 0x20, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xed, 0x30, 0x44, 0x04, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04,
0x20, 0x1a, 0xc1, 0xda, 0x05, 0xb5, 0x5b, 0xc1,
0x46, 0x33, 0xbd, 0x39, 0xe4, 0x7f, 0x94, 0x30,
0x2e, 0xf1, 0x98, 0x43, 0xdc, 0xf6, 0x69, 0x91,
0x6f, 0x6a, 0x5d, 0xfd, 0x01, 0x65, 0x53, 0x8c,
0xd1, 0x04, 0x41, 0x04, 0x17, 0xcf, 0xea, 0xc3,
0x78, 0xae, 0xd6, 0x61, 0x31, 0x8e, 0x86, 0x34,
0x58, 0x22, 0x75, 0xb6, 0xd9, 0xad, 0x4d, 0xef,
0x07, 0x2e, 0xa1, 0x93, 0x5e, 0xe3, 0xc4, 0xe8,
0x7a, 0x94, 0x0f, 0xfa, 0x0c, 0x08, 0xa9, 0x52,
0xc5, 0x5d, 0xfa, 0xd6, 0x2c, 0x4f, 0x13, 0xf1,
0xa8, 0xf6, 0x8d, 0xca, 0xdc, 0x5c, 0x33, 0x1d,
0x29, 0x7a, 0x37, 0xb6, 0xf0, 0xd7, 0xfd, 0xcc,
0x51, 0xe1, 0x6b, 0x4d, 0x02, 0x20, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde,
0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6, 0x58, 0x12,
0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed, 0x02, 0x01,
0x08,
};
static const struct curve wei25519_2 = {
.descr = "short Weierstrass 25519.2",
.oid = "1.3.101.108",
.sn = "Wei25519",
.p = "7fffffff" "ffffffff" "ffffffff" "ffffffff"
"ffffffff" "ffffffff" "ffffffff" "ffffffed",
.a = "02",
.b = "1ac1da05" "b55bc146" "33bd39e4" "7f94302e"
"f19843dc" "f669916f" "6a5dfd01" "65538cd1",
.x = "17cfeac3" "78aed661" "318e8634" "582275b6"
"d9ad4def" "072ea193" "5ee3c4e8" "7a940ffa",
.y = "0c08a952" "c55dfad6" "2c4f13f1" "a8f68dca"
"dc5c331d" "297a37b6" "f0d7fdcc" "51e16b4d",
.order = "10000000" "00000000" "00000000" "00000000"
"14def9de" "a2f79cd6" "5812631a" "5cf5d3ed",
.cofactor = "8",
.named = ec_wei25519_pkparameters_named_curve,
.named_len = sizeof(ec_wei25519_pkparameters_named_curve),
.param = ec_wei25519_2_pkparameters_parameters,
.param_len = sizeof(ec_wei25519_2_pkparameters_parameters),
};
static const uint8_t ec_wei25519_3_pkparameters_parameters[] = {
0x30, 0x81, 0xde, 0x02, 0x01, 0x01, 0x30, 0x2b,
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
0x01, 0x02, 0x20, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xed, 0x30, 0x44, 0x04, 0x20, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0x04,
0x20, 0x41, 0xa3, 0xb6, 0xbf, 0xc6, 0x68, 0x77,
0x8e, 0xbe, 0x29, 0x54, 0xa4, 0xb1, 0xdf, 0x36,
0xd1, 0x48, 0x5e, 0xce, 0xf1, 0xea, 0x61, 0x42,
0x95, 0x79, 0x6e, 0x10, 0x22, 0x40, 0x89, 0x1f,
0xaa, 0x04, 0x41, 0x04, 0x77, 0x06, 0xc3, 0x7b,
0x5a, 0x84, 0x12, 0x8a, 0x38, 0x84, 0xa5, 0xd7,
0x18, 0x11, 0xf1, 0xb5, 0x5d, 0xa3, 0x23, 0x0f,
0xfb, 0x17, 0xa8, 0xab, 0x0b, 0x32, 0xe4, 0x8d,
0x31, 0xa6, 0x68, 0x5c, 0x0f, 0x60, 0x48, 0x0c,
0x7a, 0x5c, 0x0e, 0x11, 0x40, 0x34, 0x0a, 0xdc,
0x79, 0xd6, 0xa2, 0xbf, 0x0c, 0xb5, 0x7a, 0xd0,
0x49, 0xd0, 0x25, 0xdc, 0x38, 0xd8, 0x0c, 0x77,
0x98, 0x5f, 0x03, 0x29, 0x02, 0x20, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde,
0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6, 0x58, 0x12,
0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed, 0x02, 0x01,
0x08,
};
static const struct curve wei25519_3 = {
.descr = "short Weierstrass 25519.-3",
.oid = "1.3.101.108",
.sn = "Wei25519",
.p = "7fffffff" "ffffffff" "ffffffff" "ffffffff"
"ffffffff" "ffffffff" "ffffffff" "ffffffed",
.a = "7fffffff" "ffffffff" "ffffffff" "ffffffff"
"ffffffff" "ffffffff" "ffffffff" "ffffffea",
.b = "41a3b6bf" "c668778e" "be2954a4" "b1df36d1"
"485ecef1" "ea614295" "796e1022" "40891faa",
.x = "7706c37b" "5a84128a" "3884a5d7" "1811f1b5"
"5da3230f" "fb17a8ab" "0b32e48d" "31a6685c",
.y = "0f60480c" "7a5c0e11" "40340adc" "79d6a2bf"
"0cb57ad0" "49d025dc" "38d80c77" "985f0329",
.order = "10000000" "00000000" "00000000" "00000000"
"14def9de" "a2f79cd6" "5812631a" "5cf5d3ed",
.cofactor = "8",
.named = ec_wei25519_pkparameters_named_curve,
.named_len = sizeof(ec_wei25519_pkparameters_named_curve),
.param = ec_wei25519_3_pkparameters_parameters,
.param_len = sizeof(ec_wei25519_3_pkparameters_parameters),
};
#if NEGATIVE_CURVE_COEFFICIENTS_ALLOWED
static const struct curve wei25519_3_neg = {
.descr = "short Weierstrass 25519.-3 with negative a",
.oid = "1.3.101.108",
.sn = "Wei25519",
.p = "7fffffff" "ffffffff" "ffffffff" "ffffffff"
"ffffffff" "ffffffff" "ffffffff" "ffffffed",
.a = "-03",
.b = "41a3b6bf" "c668778e" "be2954a4" "b1df36d1"
"485ecef1" "ea614295" "796e1022" "40891faa",
.x = "7706c37b" "5a84128a" "3884a5d7" "1811f1b5"
"5da3230f" "fb17a8ab" "0b32e48d" "31a6685c",
.y = "0f60480c" "7a5c0e11" "40340adc" "79d6a2bf"
"0cb57ad0" "49d025dc" "38d80c77" "985f0329",
.order = "10000000" "00000000" "00000000" "00000000"
"14def9de" "a2f79cd6" "5812631a" "5cf5d3ed",
.cofactor = "8",
.named = ec_wei25519_pkparameters_named_curve,
.named_len = sizeof(ec_wei25519_pkparameters_named_curve),
.param = ec_wei25519_3_pkparameters_parameters,
.param_len = sizeof(ec_wei25519_3_pkparameters_parameters),
};
#endif
static const uint8_t ec_secp256k1_m_pkparameters_named_curve[] = {
0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a,
};
static const uint8_t ec_secp256k1_m_pkparameters_parameters[] = {
0x30, 0x81, 0xe0, 0x02, 0x01, 0x01, 0x30, 0x2c,
0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xff, 0xff, 0xfc, 0x2f, 0x30, 0x44, 0x04, 0x20,
0xcf, 0xcd, 0x5c, 0x21, 0x75, 0xe2, 0xef, 0x7d,
0xcc, 0xdc, 0xe7, 0x37, 0x77, 0x0b, 0x73, 0x81,
0x5a, 0x2f, 0x13, 0xc5, 0x09, 0x03, 0x5c, 0xa2,
0x54, 0xa1, 0x4a, 0xc9, 0xf0, 0x89, 0x74, 0xaf,
0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x06, 0xeb, 0x04, 0x41, 0x04, 0x3a, 0xca, 0x53,
0x00, 0x95, 0x9f, 0xa1, 0xd0, 0xba, 0xf7, 0x8d,
0xcf, 0xf7, 0x7a, 0x61, 0x6f, 0x39, 0x5e, 0x58,
0x6d, 0x67, 0xac, 0xed, 0x0a, 0x88, 0x79, 0x81,
0x29, 0x0c, 0x27, 0x91, 0x45, 0x95, 0x80, 0xfc,
0xe5, 0x3a, 0x17, 0x0f, 0x4f, 0xb7, 0x44, 0x57,
0x9f, 0xf3, 0xd6, 0x20, 0x86, 0x12, 0xcd, 0x6a,
0x23, 0x3e, 0x2d, 0xe2, 0x37, 0xf9, 0x76, 0xc6,
0xa7, 0x86, 0x11, 0xc8, 0x00, 0x02, 0x21, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41,
0x02, 0x01, 0x01,
};
static const struct curve secp256k1_m = {
.descr = "short Weierstrass secp256k1.m",
.oid = "1.3.132.0.10",
.sn = SN_secp256k1,
.p = "ffffffff" "ffffffff" "ffffffff" "ffffffff"
"ffffffff" "ffffffff" "fffffffe" "fffffc2f",
.a = "cfcd5c21" "75e2ef7d" "ccdce737" "770b7381"
"5a2f13c5" "09035ca2" "54a14ac9" "f08974af",
.b = "06eb",
.x = "3aca5300" "959fa1d0" "baf78dcf" "f77a616f"
"395e586d" "67aced0a" "88798129" "0c279145",
.y = "9580fce5" "3a170f4f" "b744579f" "f3d62086"
"12cd6a23" "3e2de237" "f976c6a7" "8611c800",
.order = "ffffffff" "ffffffff" "ffffffff" "fffffffe"
"baaedce6" "af48a03b" "bfd25e8c" "d0364141",
.cofactor = "1",
.known_named_curve = 1,
.named = ec_secp256k1_m_pkparameters_named_curve,
.named_len = sizeof(ec_secp256k1_m_pkparameters_named_curve),
.param = ec_secp256k1_m_pkparameters_parameters,
.param_len = sizeof(ec_secp256k1_m_pkparameters_parameters),
};
static const uint8_t ec_bls12_377_pkparameters_named_curve[] = {
0x06, 0x04, 0x29, 0x01, 0x01, 0x01,
};
static const uint8_t ec_bls12_377_pkparameters_parameters[] = {
0x30, 0x82, 0x01, 0x3d, 0x02, 0x01, 0x01, 0x30,
0x3b, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x01, 0x01, 0x02, 0x30, 0x01, 0xae, 0x3a, 0x46,
0x17, 0xc5, 0x10, 0xea, 0xc6, 0x3b, 0x05, 0xc0,
0x6c, 0xa1, 0x49, 0x3b, 0x1a, 0x22, 0xd9, 0xf3,
0x00, 0xf5, 0x13, 0x8f, 0x1e, 0xf3, 0x62, 0x2f,
0xba, 0x09, 0x48, 0x00, 0x17, 0x0b, 0x5d, 0x44,
0x30, 0x00, 0x00, 0x00, 0x85, 0x08, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x01, 0x30, 0x64, 0x04, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x04, 0x61, 0x04, 0x00, 0x88, 0x48,
0xde, 0xfe, 0x74, 0x0a, 0x67, 0xc8, 0xfc, 0x62,
0x25, 0xbf, 0x87, 0xff, 0x54, 0x85, 0x95, 0x1e,
0x2c, 0xaa, 0x9d, 0x41, 0xbb, 0x18, 0x82, 0x82,
0xc8, 0xbd, 0x37, 0xcb, 0x5c, 0xd5, 0x48, 0x15,
0x12, 0xff, 0xcd, 0x39, 0x4e, 0xea, 0xb9, 0xb1,
0x6e, 0xb2, 0x1b, 0xe9, 0xef, 0x01, 0x91, 0x4a,
0x69, 0xc5, 0x10, 0x2e, 0xff, 0x1f, 0x67, 0x4f,
0x5d, 0x30, 0xaf, 0xee, 0xc4, 0xbd, 0x7f, 0xb3,
0x48, 0xca, 0x3e, 0x52, 0xd9, 0x6d, 0x18, 0x2a,
0xd4, 0x4f, 0xb8, 0x23, 0x05, 0xc2, 0xfe, 0x3d,
0x36, 0x34, 0xa9, 0x59, 0x1a, 0xfd, 0x82, 0xde,
0x55, 0x55, 0x9c, 0x8e, 0xa6, 0x02, 0x20, 0x12,
0xab, 0x65, 0x5e, 0x9a, 0x2c, 0xa5, 0x56, 0x60,
0xb4, 0x4d, 0x1e, 0x5c, 0x37, 0xb0, 0x01, 0x59,
0xaa, 0x76, 0xfe, 0xd0, 0x00, 0x00, 0x01, 0x0a,
0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
0x10, 0x17, 0x0b, 0x5d, 0x44, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
};
static const struct curve bls12_377 = {
.descr = "BLS12-377",
.oid = "1.1.1.1.1",
.sn = "BLS12-377",
.p = "01ae3a46" "17c510ea" "c63b05c0" "6ca1493b"
"1a22d9f3" "00f5138f" "1ef3622f" "ba094800"
"170b5d44" "30000000" "8508c000" "00000001",
.a = "0",
.b = "1",
.x = "008848de" "fe740a67" "c8fc6225" "bf87ff54"
"85951e2c" "aa9d41bb" "188282c8" "bd37cb5c"
"d5481512" "ffcd394e" "eab9b16e" "b21be9ef",
.y = "01914a69" "c5102eff" "1f674f5d" "30afeec4"
"bd7fb348" "ca3e52d9" "6d182ad4" "4fb82305"
"c2fe3d36" "34a9591a" "fd82de55" "559c8ea6",
.order = "12ab655e" "9a2ca556" "60b44d1e" "5c37b001"
"59aa76fe" "d0000001" "0a118000" "00000001",
.cofactor = "170b5d44" "30000000" "00000000" "00000000",
.named = ec_bls12_377_pkparameters_named_curve,
.named_len = sizeof(ec_bls12_377_pkparameters_named_curve),
.param = ec_bls12_377_pkparameters_parameters,
.param_len = sizeof(ec_bls12_377_pkparameters_parameters),
};
static EC_GROUP *
ec_group_from_curve_method(const struct curve *curve, const EC_METHOD *method,
BN_CTX *ctx)
{
EC_GROUP *group;
EC_POINT *generator = NULL;
BIGNUM *p, *a, *b;
BIGNUM *order, *x, *y;
BN_CTX_start(ctx);
if ((p = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((a = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((b = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((order = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((x = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((y = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if (BN_hex2bn(&p, curve->p) == 0)
errx(1, "BN_hex2bn(p)");
if (BN_hex2bn(&a, curve->a) == 0)
errx(1, "BN_hex2bn(a)");
if (BN_hex2bn(&b, curve->b) == 0)
errx(1, "BN_hex2bn(b)");
if ((group = EC_GROUP_new(method)) == NULL)
errx(1, "EC_GROUP_new");
if (!EC_GROUP_set_curve(group, p, a, b, ctx))
errx(1, "EC_GROUP_set_curve");
if (BN_hex2bn(&x, curve->x) == 0)
errx(1, "BN_hex2bn(x)");
if (BN_hex2bn(&x, curve->x) == 0)
errx(1, "BN_hex2bn(x)");
if (BN_hex2bn(&y, curve->y) == 0)
errx(1, "BN_hex2bn(y)");
if ((generator = EC_POINT_new(group)) == NULL)
errx(1, "EC_POINT_new()");
if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx)) {
fprintf(stderr, "FAIL: %s EC_POINT_set_affine_coordinates\n",
curve->descr);
ERR_print_errors_fp(stderr);
goto err;
}
if (BN_hex2bn(&order, curve->order) == 0)
errx(1, "BN_hex2bn(order)");
if (!EC_GROUP_set_generator(group, generator, order, NULL)) {
fprintf(stderr, "FAIL: %s EC_GROUP_set_generator\n", curve->descr);
ERR_print_errors_fp(stderr);
goto err;
}
EC_POINT_free(generator);
BN_CTX_end(ctx);
return group;
err:
BN_CTX_end(ctx);
EC_POINT_free(generator);
EC_GROUP_free(group);
return NULL;
}
static EC_GROUP *
ec_group_new(const struct curve *curve, const EC_METHOD *method, BN_CTX *ctx)
{
EC_GROUP *group = NULL;
BIGNUM *cofactor, *guessed_cofactor;
int nid;
BN_CTX_start(ctx);
if ((nid = OBJ_txt2nid(curve->oid)) == NID_undef)
nid = OBJ_create(curve->oid, curve->sn, curve->ln);
if (nid == NID_undef) {
fprintf(stderr, "FAIL: OBJ_create(%s)\n", curve->descr);
goto err;
}
if ((cofactor = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if ((guessed_cofactor = BN_CTX_get(ctx)) == NULL)
errx(1, "BN_CTX_get");
if (BN_hex2bn(&cofactor, curve->cofactor) == 0)
errx(1, "BN_hex2bn(cofactor)");
if ((group = ec_group_from_curve_method(curve, method, ctx)) == NULL) {
fprintf(stderr, "FAIL: %s ec_group_from_curve_method\n", curve->descr);
ERR_print_errors_fp(stderr);
goto err;
}
if (!EC_GROUP_get_cofactor(group, guessed_cofactor, ctx)) {
fprintf(stderr, "FAIL: %s EC_GROUP_get_cofactor\n", curve->descr);
ERR_print_errors_fp(stderr);
goto err;
}
if (BN_cmp(cofactor, guessed_cofactor) != 0) {
fprintf(stderr, "FAIL: %s cofactor: want ", curve->descr);
BN_print_fp(stderr, cofactor);
fprintf(stderr, ", got ");
BN_print_fp(stderr, guessed_cofactor);
fprintf(stderr, "\n");
goto err;
}
if (!EC_GROUP_check(group, ctx)) {
fprintf(stderr, "FAIL: %s EC_GROUP_check\n", curve->descr);
ERR_print_errors_fp(stderr);
goto err;
}
EC_GROUP_set_curve_name(group, nid);
BN_CTX_end(ctx);
return group;
err:
BN_CTX_end(ctx);
EC_GROUP_free(group);
return NULL;
}
static int
ec_group_non_builtin_curve(const struct curve *curve, const EC_METHOD *method,
BN_CTX *ctx)
{
EC_GROUP *group = NULL, *new_group = NULL;
const unsigned char *pder;
unsigned char *der = NULL;
#ifndef OPENSSL_SUPPRESS_DEPRECATED
long error;
#endif
int der_len = 0;
int failed = 1;
ERR_clear_error();
BN_CTX_start(ctx);
if ((group = ec_group_new(curve, method, ctx)) == NULL)
goto err;
if (EC_GROUP_get_curve_name(group) == NID_undef) {
fprintf(stderr, "FAIL: no curve name set for %s\n", curve->descr);
goto err;
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
der = NULL;
if ((der_len = i2d_ECPKParameters(group, &der)) <= 0) {
fprintf(stderr, "FAIL: %s i2d_ECPKParameters (named)\n",
curve->descr);
ERR_print_errors_fp(stderr);
goto err;
}
if (compare_data(curve->descr, der, der_len,
curve->named, curve->named_len) == -1)
goto err;
freezero(der, der_len);
der = NULL;
EC_GROUP_set_curve_name(group, NID_undef);
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
der = NULL;
if ((der_len = i2d_ECPKParameters(group, &der)) <= 0) {
fprintf(stderr, "FAIL: i2d_ECPKParameters (explicit) %s\n",
curve->descr);
ERR_print_errors_fp(stderr);
goto err;
}
if (compare_data(curve->descr, der, der_len,
curve->param, curve->param_len) == -1)
goto err;
freezero(der, der_len);
der = NULL;
if (ERR_peek_last_error() != 0) {
fprintf(stderr, "FAIL: %s unexpected error %lu\n", curve->descr,
ERR_peek_last_error());
goto err;
}
pder = curve->named;
der_len = curve->named_len;
new_group = d2i_ECPKParameters(NULL, &pder, der_len);
if (!curve->known_named_curve && new_group != NULL) {
fprintf(stderr, "FAIL: managed to decode unknown named curve %s\n",
curve->descr);
goto err;
}
EC_GROUP_free(new_group);
new_group = NULL;
#ifndef OPENSSL_SUPPRESS_DEPRECATED
error = ERR_get_error();
if (!curve->known_named_curve &&
ERR_GET_REASON(error) != EC_R_UNKNOWN_GROUP) {
fprintf(stderr, "FAIL: %s unexpected error: want %d, got %d\n",
curve->descr, EC_R_UNKNOWN_GROUP, ERR_GET_REASON(error));
goto err;
}
#endif
ERR_clear_error();
pder = curve->param;
der_len = curve->param_len;
if ((new_group = d2i_ECPKParameters(NULL, &pder, der_len)) != NULL) {
fprintf(stderr, "FAIL: managed to decode non-builtin parameters %s\n",
curve->descr);
goto err;
}
#ifndef OPENSSL_SUPPRESS_DEPRECATED
error = ERR_peek_last_error();
if (ERR_GET_REASON(error) != EC_R_PKPARAMETERS2GROUP_FAILURE) {
fprintf(stderr, "FAIL: %s unexpected error: want %d, got %d\n",
curve->descr, EC_R_UNKNOWN_GROUP, ERR_GET_REASON(error));
goto err;
}
#endif
failed = 0;
err:
BN_CTX_end(ctx);
EC_GROUP_free(group);
EC_GROUP_free(new_group);
freezero(der, der_len);
return failed;
}
static int
ec_group_non_builtin_curves(void)
{
BN_CTX *ctx;
int failed = 0;
if ((ctx = BN_CTX_new()) == NULL)
errx(1, "BN_CTX_new");
failed |= ec_group_non_builtin_curve(&wei25519, EC_GFp_mont_method(), ctx);
failed |= ec_group_non_builtin_curve(&wei25519, EC_GFp_simple_method(), ctx);
failed |= ec_group_non_builtin_curve(&wei25519_2, EC_GFp_mont_method(), ctx);
failed |= ec_group_non_builtin_curve(&wei25519_2, EC_GFp_simple_method(), ctx);
failed |= ec_group_non_builtin_curve(&wei25519_3, EC_GFp_mont_method(), ctx);
failed |= ec_group_non_builtin_curve(&wei25519_3, EC_GFp_simple_method(), ctx);
#if NEGATIVE_CURVE_COEFFICIENTS_ALLOWED
failed |= ec_group_non_builtin_curve(&wei25519_3_neg, EC_GFp_mont_method(), ctx);
failed |= ec_group_non_builtin_curve(&wei25519_3_neg, EC_GFp_simple_method(), ctx);
#endif
failed |= ec_group_non_builtin_curve(&secp256k1_m, EC_GFp_mont_method(), ctx);
failed |= ec_group_non_builtin_curve(&secp256k1_m, EC_GFp_simple_method(), ctx);
failed |= ec_group_non_builtin_curve(&bls12_377, EC_GFp_mont_method(), ctx);
failed |= ec_group_non_builtin_curve(&bls12_377, EC_GFp_simple_method(), ctx);
BN_CTX_free(ctx);
return failed;
}
static int
ec_group_check_prime_order(EC_builtin_curve *curve, BN_CTX *ctx)
{
EC_GROUP *group;
BIGNUM *order;
int rv;
int failed = 0;
if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL)
errx(1, "EC_GROUP_new_by_curve_name");
BN_CTX_start(ctx);
if ((order = BN_CTX_get(ctx)) == NULL)
errx(1, "order = BN_CTX_get()");
if (!EC_GROUP_get_order(group, order, ctx))
errx(1, "EC_GROUP_get_order");
if ((rv = BN_is_prime_ex(order, 0, ctx, NULL)) != 1) {
fprintf(stderr, "%s: nid %d: BN_is_prime_ex() returned %d, want 1\n",
__func__, curve->nid, rv);
failed = 1;
}
BN_CTX_end(ctx);
EC_GROUP_free(group);
return failed;
}
static int
ec_group_builtin_curves_have_prime_order(void)
{
BN_CTX *ctx = NULL;
EC_builtin_curve *all_curves = NULL;
size_t curve_id, ncurves;
int failed = 0;
if ((ctx = BN_CTX_new()) == NULL)
errx(1, "BN_CTX_new");
ncurves = EC_get_builtin_curves(NULL, 0);
if ((all_curves = calloc(ncurves, sizeof(*all_curves))) == NULL)
err(1, "calloc builtin curves");
EC_get_builtin_curves(all_curves, ncurves);
for (curve_id = 0; curve_id < ncurves; curve_id++)
failed |= ec_group_check_prime_order(&all_curves[curve_id], ctx);
free(all_curves);
BN_CTX_free(ctx);
return failed;
}
static const struct ec_private_key {
const char *name;
size_t der_len;
uint8_t der[256];
const char *hex;
int oct_len;
uint8_t oct[256];
} ec_private_keys[] = {
{
.name = "secp224k1",
.der_len = 107,
.der = {
0x30, 0x69, 0x02, 0x01, 0x01, 0x04, 0x1d, 0x00,
0x32, 0x2b, 0x6d, 0xe3, 0x62, 0x60, 0xda, 0xb2,
0x62, 0x0a, 0x38, 0x3e, 0xd3, 0x8c, 0x70, 0x9e,
0x76, 0x38, 0xac, 0x26, 0x17, 0xa9, 0x00, 0xdf,
0xfb, 0x1e, 0xf3, 0xbd, 0xa0, 0x07, 0x06, 0x05,
0x2b, 0x81, 0x04, 0x00, 0x20, 0xa1, 0x3c, 0x03,
0x3a, 0x00, 0x04, 0x51, 0xc4, 0x69, 0xdf, 0x2d,
0x49, 0x7b, 0x05, 0x6c, 0x12, 0x5f, 0x9a, 0x83,
0x51, 0x7d, 0xf3, 0x4a, 0x6c, 0xe1, 0x3a, 0xea,
0x44, 0x35, 0x3e, 0x7a, 0xa4, 0x40, 0xdf, 0xc4,
0x90, 0x18, 0xfc, 0x2f, 0x5d, 0x4b, 0x12, 0x37,
0x87, 0x4d, 0x2a, 0xf8, 0xbd, 0x29, 0xfb, 0x13,
0x34, 0xef, 0xfb, 0x04, 0xa1, 0x28, 0x7d, 0x51,
0xbe, 0xe7, 0x0b,
},
.hex = "0451C469DF2D497B"
"056C125F9A83517D"
"F34A6CE13AEA4435"
"3E7AA440DFC49018"
"FC2F5D4B1237874D"
"2AF8BD29FB1334EF"
"FB04A1287D51BEE7"
"0B",
.oct_len = 57,
.oct = {
0x04, 0x51, 0xc4, 0x69, 0xdf, 0x2d, 0x49, 0x7b,
0x05, 0x6c, 0x12, 0x5f, 0x9a, 0x83, 0x51, 0x7d,
0xf3, 0x4a, 0x6c, 0xe1, 0x3a, 0xea, 0x44, 0x35,
0x3e, 0x7a, 0xa4, 0x40, 0xdf, 0xc4, 0x90, 0x18,
0xfc, 0x2f, 0x5d, 0x4b, 0x12, 0x37, 0x87, 0x4d,
0x2a, 0xf8, 0xbd, 0x29, 0xfb, 0x13, 0x34, 0xef,
0xfb, 0x04, 0xa1, 0x28, 0x7d, 0x51, 0xbe, 0xe7,
0x0b,
},
},
{
.name = "secp224r1",
.der_len = 106,
.der = {
0x30, 0x68, 0x02, 0x01, 0x01, 0x04, 0x1c, 0x76,
0x9b, 0x2f, 0x62, 0xff, 0x5f, 0x84, 0x6c, 0x7e,
0x90, 0xda, 0xfb, 0x70, 0x62, 0xc1, 0xb9, 0xa2,
0xc9, 0xf7, 0x1b, 0x76, 0x7f, 0xbb, 0xb1, 0xd4,
0xa4, 0xa0, 0x42, 0xa0, 0x07, 0x06, 0x05, 0x2b,
0x81, 0x04, 0x00, 0x21, 0xa1, 0x3c, 0x03, 0x3a,
0x00, 0x04, 0x94, 0x84, 0xb0, 0xcd, 0x65, 0xef,
0xc5, 0x5d, 0xc9, 0xe4, 0x91, 0x71, 0xcb, 0xc7,
0xf1, 0x8e, 0x44, 0x39, 0xc2, 0xd3, 0x07, 0xf0,
0x6c, 0xb6, 0xef, 0x77, 0xc0, 0x84, 0x30, 0x2c,
0xd2, 0xf2, 0xf0, 0xb5, 0xb6, 0x6f, 0x0a, 0xf4,
0x43, 0xab, 0x5e, 0x5d, 0xd8, 0x97, 0xbf, 0xab,
0xf4, 0x2d, 0x34, 0x25, 0xee, 0x4c, 0xec, 0xfb,
0x4d, 0x0b,
},
.hex = "049484B0CD65EFC5"
"5DC9E49171CBC7F1"
"8E4439C2D307F06C"
"B6EF77C084302CD2"
"F2F0B5B66F0AF443"
"AB5E5DD897BFABF4"
"2D3425EE4CECFB4D"
"0B",
.oct_len = 57,
.oct = {
0x04, 0x94, 0x84, 0xb0, 0xcd, 0x65, 0xef, 0xc5,
0x5d, 0xc9, 0xe4, 0x91, 0x71, 0xcb, 0xc7, 0xf1,
0x8e, 0x44, 0x39, 0xc2, 0xd3, 0x07, 0xf0, 0x6c,
0xb6, 0xef, 0x77, 0xc0, 0x84, 0x30, 0x2c, 0xd2,
0xf2, 0xf0, 0xb5, 0xb6, 0x6f, 0x0a, 0xf4, 0x43,
0xab, 0x5e, 0x5d, 0xd8, 0x97, 0xbf, 0xab, 0xf4,
0x2d, 0x34, 0x25, 0xee, 0x4c, 0xec, 0xfb, 0x4d,
0x0b,
},
},
{
.name = "secp256k1",
.der_len = 118,
.der = {
0x30, 0x74, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf2,
0xe5, 0x5c, 0x24, 0x66, 0x01, 0x2b, 0x95, 0x96,
0xbf, 0xbd, 0x0e, 0x33, 0x3d, 0xfd, 0x8a, 0x22,
0x79, 0x12, 0xc5, 0x93, 0x28, 0x1b, 0x74, 0x39,
0x61, 0x80, 0x1c, 0x17, 0xb1, 0x36, 0xab, 0xa0,
0x07, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a,
0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x9f, 0xd2,
0xbe, 0xcc, 0xf8, 0x00, 0xe8, 0xd0, 0x40, 0x73,
0x11, 0xb9, 0x34, 0x76, 0x68, 0xb2, 0x6b, 0x88,
0xea, 0xa6, 0x64, 0x37, 0xe7, 0x06, 0xdf, 0x9f,
0x20, 0xb8, 0xc3, 0x7f, 0x9f, 0x8f, 0xbc, 0x80,
0x65, 0xe9, 0x73, 0xcb, 0x1d, 0xa1, 0xfa, 0x34,
0x23, 0x66, 0xb9, 0x47, 0x89, 0xe9, 0x08, 0x92,
0x5e, 0xb5, 0x37, 0x44, 0x40, 0x1c, 0x34, 0x6c,
0xf2, 0xdb, 0x44, 0x71, 0x26, 0xeb,
},
.hex = "049FD2BECCF800E8"
"D0407311B9347668"
"B26B88EAA66437E7"
"06DF9F20B8C37F9F"
"8FBC8065E973CB1D"
"A1FA342366B94789"
"E908925EB5374440"
"1C346CF2DB447126"
"EB",
.oct_len = 65,
.oct = {
0x04, 0x9f, 0xd2, 0xbe, 0xcc, 0xf8, 0x00, 0xe8,
0xd0, 0x40, 0x73, 0x11, 0xb9, 0x34, 0x76, 0x68,
0xb2, 0x6b, 0x88, 0xea, 0xa6, 0x64, 0x37, 0xe7,
0x06, 0xdf, 0x9f, 0x20, 0xb8, 0xc3, 0x7f, 0x9f,
0x8f, 0xbc, 0x80, 0x65, 0xe9, 0x73, 0xcb, 0x1d,
0xa1, 0xfa, 0x34, 0x23, 0x66, 0xb9, 0x47, 0x89,
0xe9, 0x08, 0x92, 0x5e, 0xb5, 0x37, 0x44, 0x40,
0x1c, 0x34, 0x6c, 0xf2, 0xdb, 0x44, 0x71, 0x26,
0xeb,
},
},
{
.name = "secp384r1",
.der_len = 167,
.der = {
0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30,
0xa0, 0xd3, 0x78, 0x23, 0x51, 0xe1, 0x20, 0x5c,
0xbe, 0x84, 0x11, 0x2f, 0x82, 0x55, 0xfc, 0xd1,
0x5d, 0xae, 0xfc, 0x72, 0x60, 0x50, 0x3c, 0x2d,
0x70, 0xb4, 0x00, 0xe2, 0xe6, 0x0a, 0xdf, 0xc5,
0x56, 0xe6, 0xb8, 0x69, 0xf8, 0xad, 0xf5, 0xfc,
0x95, 0xb3, 0x5b, 0x3d, 0xda, 0x6c, 0x5f, 0x74,
0xa0, 0x07, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xce,
0x9a, 0x3b, 0x4b, 0x01, 0xe6, 0xc4, 0x5a, 0xfa,
0x97, 0x03, 0xc1, 0xce, 0x18, 0xd5, 0x6c, 0x47,
0x27, 0x4d, 0x6c, 0x9a, 0xbd, 0x47, 0xab, 0x20,
0x0f, 0x99, 0x83, 0x19, 0x8b, 0xcb, 0x18, 0xd7,
0xa3, 0xb2, 0xe7, 0x3b, 0xd0, 0xf1, 0xf3, 0x29,
0xb2, 0x6d, 0x38, 0xd6, 0xcc, 0x8e, 0x5e, 0xf0,
0xb2, 0xb9, 0xbd, 0x85, 0x2c, 0xab, 0x4b, 0xb6,
0x9d, 0x98, 0xa1, 0xce, 0xf1, 0x8a, 0xdb, 0x92,
0x75, 0x7d, 0xf7, 0x82, 0x4c, 0x0a, 0xc7, 0x3b,
0x52, 0x6e, 0x97, 0xc6, 0x23, 0xc9, 0x6f, 0x3f,
0xe5, 0xd2, 0xa2, 0x79, 0x47, 0xb0, 0x6e, 0x5f,
0x85, 0x39, 0x94, 0x57, 0xbf, 0x54, 0x76,
},
.hex = "04CE9A3B4B01E6C4"
"5AFA9703C1CE18D5"
"6C47274D6C9ABD47"
"AB200F9983198BCB"
"18D7A3B2E73BD0F1"
"F329B26D38D6CC8E"
"5EF0B2B9BD852CAB"
"4BB69D98A1CEF18A"
"DB92757DF7824C0A"
"C73B526E97C623C9"
"6F3FE5D2A27947B0"
"6E5F85399457BF54"
"76",
.oct_len = 97,
.oct = {
0x04, 0xce, 0x9a, 0x3b, 0x4b, 0x01, 0xe6, 0xc4,
0x5a, 0xfa, 0x97, 0x03, 0xc1, 0xce, 0x18, 0xd5,
0x6c, 0x47, 0x27, 0x4d, 0x6c, 0x9a, 0xbd, 0x47,
0xab, 0x20, 0x0f, 0x99, 0x83, 0x19, 0x8b, 0xcb,
0x18, 0xd7, 0xa3, 0xb2, 0xe7, 0x3b, 0xd0, 0xf1,
0xf3, 0x29, 0xb2, 0x6d, 0x38, 0xd6, 0xcc, 0x8e,
0x5e, 0xf0, 0xb2, 0xb9, 0xbd, 0x85, 0x2c, 0xab,
0x4b, 0xb6, 0x9d, 0x98, 0xa1, 0xce, 0xf1, 0x8a,
0xdb, 0x92, 0x75, 0x7d, 0xf7, 0x82, 0x4c, 0x0a,
0xc7, 0x3b, 0x52, 0x6e, 0x97, 0xc6, 0x23, 0xc9,
0x6f, 0x3f, 0xe5, 0xd2, 0xa2, 0x79, 0x47, 0xb0,
0x6e, 0x5f, 0x85, 0x39, 0x94, 0x57, 0xbf, 0x54,
0x76,
},
},
{
.name = "secp521r1",
.der_len = 223,
.der = {
0x30, 0x81, 0xdc, 0x02, 0x01, 0x01, 0x04, 0x42,
0x01, 0x6e, 0xff, 0x5d, 0x18, 0x50, 0x5b, 0x09,
0xf8, 0x38, 0x10, 0x6c, 0x54, 0x19, 0x59, 0xdb,
0x30, 0xc5, 0x60, 0x28, 0xb1, 0x7f, 0xba, 0x22,
0x06, 0x4d, 0x8a, 0x69, 0x53, 0xb0, 0xc5, 0x8f,
0x17, 0x4d, 0x51, 0xc6, 0x2f, 0x41, 0x4e, 0xf0,
0xab, 0xb4, 0x3a, 0x8f, 0x00, 0x6f, 0x32, 0xe7,
0xe6, 0x56, 0xb7, 0xe9, 0xb1, 0xcd, 0x3a, 0x93,
0xe6, 0x8f, 0xe6, 0x60, 0xb6, 0x80, 0xbd, 0x02,
0xfb, 0x90, 0xa0, 0x07, 0x06, 0x05, 0x2b, 0x81,
0x04, 0x00, 0x23, 0xa1, 0x81, 0x89, 0x03, 0x81,
0x86, 0x00, 0x04, 0x01, 0xd2, 0xc3, 0x78, 0x41,
0xb1, 0x86, 0x24, 0xca, 0x6d, 0x80, 0x5c, 0x97,
0xcf, 0x96, 0xf0, 0x87, 0xb4, 0x25, 0xbe, 0x37,
0x9a, 0xf3, 0xe5, 0x4a, 0x70, 0xd1, 0xe6, 0x36,
0x9e, 0x69, 0xcc, 0xfb, 0x83, 0xd6, 0xa1, 0x62,
0x6d, 0xa8, 0xe6, 0xca, 0xe7, 0x0e, 0x24, 0xe6,
0x26, 0xcd, 0xc0, 0x0d, 0x2a, 0x01, 0x81, 0x6a,
0xd6, 0x94, 0xf2, 0x90, 0xcd, 0x26, 0x68, 0x28,
0x2c, 0x57, 0xd3, 0xf0, 0x37, 0x00, 0xbc, 0x5e,
0xfa, 0xf9, 0x36, 0xcd, 0x0f, 0xeb, 0x4f, 0x82,
0x17, 0x6a, 0xa0, 0x73, 0xd2, 0x48, 0xfc, 0xfb,
0xf0, 0x54, 0xc3, 0x23, 0x29, 0x76, 0xc7, 0x21,
0x98, 0x09, 0x29, 0x8b, 0xce, 0x6e, 0x6b, 0xe3,
0x97, 0x94, 0xb2, 0x30, 0xaa, 0xf6, 0x43, 0x5c,
0x15, 0xd7, 0xb8, 0xdb, 0x06, 0x92, 0xa8, 0x36,
0x8f, 0x89, 0xb6, 0x39, 0x2c, 0x2c, 0x23, 0x0a,
0xb6, 0x95, 0x9c, 0x6b, 0xce, 0xc4, 0x8e,
},
.hex = "0401D2C37841B186"
"24CA6D805C97CF96"
"F087B425BE379AF3"
"E54A70D1E6369E69"
"CCFB83D6A1626DA8"
"E6CAE70E24E626CD"
"C00D2A01816AD694"
"F290CD2668282C57"
"D3F03700BC5EFAF9"
"36CD0FEB4F82176A"
"A073D248FCFBF054"
"C3232976C7219809"
"298BCE6E6BE39794"
"B230AAF6435C15D7"
"B8DB0692A8368F89"
"B6392C2C230AB695"
"9C6BCEC48E",
.oct_len = 133,
.oct = {
0x04, 0x01, 0xd2, 0xc3, 0x78, 0x41, 0xb1, 0x86,
0x24, 0xca, 0x6d, 0x80, 0x5c, 0x97, 0xcf, 0x96,
0xf0, 0x87, 0xb4, 0x25, 0xbe, 0x37, 0x9a, 0xf3,
0xe5, 0x4a, 0x70, 0xd1, 0xe6, 0x36, 0x9e, 0x69,
0xcc, 0xfb, 0x83, 0xd6, 0xa1, 0x62, 0x6d, 0xa8,
0xe6, 0xca, 0xe7, 0x0e, 0x24, 0xe6, 0x26, 0xcd,
0xc0, 0x0d, 0x2a, 0x01, 0x81, 0x6a, 0xd6, 0x94,
0xf2, 0x90, 0xcd, 0x26, 0x68, 0x28, 0x2c, 0x57,
0xd3, 0xf0, 0x37, 0x00, 0xbc, 0x5e, 0xfa, 0xf9,
0x36, 0xcd, 0x0f, 0xeb, 0x4f, 0x82, 0x17, 0x6a,
0xa0, 0x73, 0xd2, 0x48, 0xfc, 0xfb, 0xf0, 0x54,
0xc3, 0x23, 0x29, 0x76, 0xc7, 0x21, 0x98, 0x09,
0x29, 0x8b, 0xce, 0x6e, 0x6b, 0xe3, 0x97, 0x94,
0xb2, 0x30, 0xaa, 0xf6, 0x43, 0x5c, 0x15, 0xd7,
0xb8, 0xdb, 0x06, 0x92, 0xa8, 0x36, 0x8f, 0x89,
0xb6, 0x39, 0x2c, 0x2c, 0x23, 0x0a, 0xb6, 0x95,
0x9c, 0x6b, 0xce, 0xc4, 0x8e,
},
},
{
.name = "prime256v1",
.der_len = 121,
.der = {
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x6c,
0x83, 0x81, 0x90, 0x65, 0x7b, 0x45, 0x98, 0x66,
0x4b, 0x91, 0x8e, 0xcf, 0x71, 0x61, 0x22, 0xb6,
0xd6, 0x93, 0x74, 0x84, 0xa3, 0xc6, 0x44, 0x71,
0x25, 0xc5, 0xef, 0x77, 0x52, 0xd2, 0x32, 0xa0,
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00,
0x04, 0x96, 0x8a, 0xc3, 0x66, 0x1e, 0xf7, 0xcf,
0xf6, 0xcc, 0x4e, 0x73, 0xae, 0xe2, 0x64, 0xc4,
0x56, 0x5f, 0x2d, 0xfe, 0xde, 0xac, 0x92, 0xbe,
0x10, 0x40, 0x37, 0xce, 0x24, 0x12, 0x30, 0x19,
0x08, 0x66, 0xcf, 0x90, 0xc9, 0x37, 0x03, 0xd1,
0xd5, 0x8d, 0xaa, 0x18, 0x2a, 0xbc, 0xed, 0x82,
0x32, 0xc9, 0x43, 0x4b, 0x98, 0x7f, 0xdc, 0xb1,
0x0b, 0xa6, 0xdd, 0x16, 0xc5, 0x8d, 0x5a, 0xcf,
0xe3,
},
.hex = "04968AC3661EF7CF"
"F6CC4E73AEE264C4"
"565F2DFEDEAC92BE"
"104037CE24123019"
"0866CF90C93703D1"
"D58DAA182ABCED82"
"32C9434B987FDCB1"
"0BA6DD16C58D5ACF"
"E3",
.oct_len = 65,
.oct = {
0x04, 0x96, 0x8a, 0xc3, 0x66, 0x1e, 0xf7, 0xcf,
0xf6, 0xcc, 0x4e, 0x73, 0xae, 0xe2, 0x64, 0xc4,
0x56, 0x5f, 0x2d, 0xfe, 0xde, 0xac, 0x92, 0xbe,
0x10, 0x40, 0x37, 0xce, 0x24, 0x12, 0x30, 0x19,
0x08, 0x66, 0xcf, 0x90, 0xc9, 0x37, 0x03, 0xd1,
0xd5, 0x8d, 0xaa, 0x18, 0x2a, 0xbc, 0xed, 0x82,
0x32, 0xc9, 0x43, 0x4b, 0x98, 0x7f, 0xdc, 0xb1,
0x0b, 0xa6, 0xdd, 0x16, 0xc5, 0x8d, 0x5a, 0xcf,
0xe3,
},
},
{
.name = "brainpoolP224r1",
.der_len = 110,
.der = {
0x30, 0x6c, 0x02, 0x01, 0x01, 0x04, 0x1c, 0xae,
0x9c, 0xe1, 0x9c, 0xaf, 0xbd, 0x9d, 0xec, 0x9a,
0xe4, 0xdc, 0x5a, 0x9f, 0xdb, 0x0d, 0x51, 0x65,
0xe2, 0x49, 0xa7, 0x35, 0xea, 0xbc, 0x8b, 0x4a,
0x27, 0xfd, 0xa8, 0xa0, 0x0b, 0x06, 0x09, 0x2b,
0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x05,
0xa1, 0x3c, 0x03, 0x3a, 0x00, 0x04, 0x30, 0x88,
0x20, 0xb3, 0x47, 0x2e, 0x40, 0x1e, 0x68, 0xae,
0xe1, 0x00, 0x58, 0xa2, 0x4b, 0xb9, 0xac, 0xf7,
0x5d, 0xc1, 0xee, 0xf5, 0xfb, 0xdd, 0x34, 0xae,
0xbe, 0x3c, 0x93, 0xdd, 0xc2, 0xd8, 0x3a, 0x9a,
0x72, 0x65, 0x41, 0xac, 0xcc, 0x25, 0x6a, 0xcf,
0x71, 0x50, 0x6b, 0xed, 0xe3, 0xc5, 0xd4, 0xe9,
0x1b, 0x59, 0x92, 0xa4, 0xa8, 0x81,
},
.hex = "04308820B3472E40"
"1E68AEE10058A24B"
"B9ACF75DC1EEF5FB"
"DD34AEBE3C93DDC2"
"D83A9A726541ACCC"
"256ACF71506BEDE3"
"C5D4E91B5992A4A8"
"81",
.oct_len = 57,
.oct = {
0x04, 0x30, 0x88, 0x20, 0xb3, 0x47, 0x2e, 0x40,
0x1e, 0x68, 0xae, 0xe1, 0x00, 0x58, 0xa2, 0x4b,
0xb9, 0xac, 0xf7, 0x5d, 0xc1, 0xee, 0xf5, 0xfb,
0xdd, 0x34, 0xae, 0xbe, 0x3c, 0x93, 0xdd, 0xc2,
0xd8, 0x3a, 0x9a, 0x72, 0x65, 0x41, 0xac, 0xcc,
0x25, 0x6a, 0xcf, 0x71, 0x50, 0x6b, 0xed, 0xe3,
0xc5, 0xd4, 0xe9, 0x1b, 0x59, 0x92, 0xa4, 0xa8,
0x81,
},
},
{
.name = "brainpoolP224t1",
.der_len = 110,
.der = {
0x30, 0x6c, 0x02, 0x01, 0x01, 0x04, 0x1c, 0xc0,
0x10, 0xc2, 0xf4, 0xab, 0xbb, 0x00, 0xa0, 0x14,
0x62, 0x13, 0x24, 0xc2, 0x8d, 0x9e, 0x78, 0x92,
0x24, 0x3b, 0xa8, 0xd0, 0xf1, 0x06, 0x69, 0x77,
0x1d, 0x9d, 0x6c, 0xa0, 0x0b, 0x06, 0x09, 0x2b,
0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x06,
0xa1, 0x3c, 0x03, 0x3a, 0x00, 0x04, 0x0b, 0xbf,
0x95, 0xea, 0x8b, 0xa8, 0x24, 0x94, 0x68, 0x54,
0x69, 0xd9, 0x55, 0xa5, 0x36, 0x34, 0xf1, 0x4a,
0x45, 0xf9, 0x9f, 0x66, 0x7b, 0x5d, 0xc9, 0x8b,
0x0a, 0x7a, 0x5d, 0xef, 0x25, 0x9a, 0xa3, 0x86,
0xe1, 0x98, 0x1b, 0x5b, 0xe3, 0xe3, 0x55, 0xa0,
0x59, 0xb2, 0xfd, 0xe7, 0xdf, 0x41, 0xff, 0x4f,
0x36, 0xe9, 0x56, 0xe9, 0x07, 0xc2,
},
.hex = "040BBF95EA8BA824"
"94685469D955A536"
"34F14A45F99F667B"
"5DC98B0A7A5DEF25"
"9AA386E1981B5BE3"
"E355A059B2FDE7DF"
"41FF4F36E956E907"
"C2",
.oct_len = 57,
.oct = {
0x04, 0x0b, 0xbf, 0x95, 0xea, 0x8b, 0xa8, 0x24,
0x94, 0x68, 0x54, 0x69, 0xd9, 0x55, 0xa5, 0x36,
0x34, 0xf1, 0x4a, 0x45, 0xf9, 0x9f, 0x66, 0x7b,
0x5d, 0xc9, 0x8b, 0x0a, 0x7a, 0x5d, 0xef, 0x25,
0x9a, 0xa3, 0x86, 0xe1, 0x98, 0x1b, 0x5b, 0xe3,
0xe3, 0x55, 0xa0, 0x59, 0xb2, 0xfd, 0xe7, 0xdf,
0x41, 0xff, 0x4f, 0x36, 0xe9, 0x56, 0xe9, 0x07,
0xc2,
},
},
{
.name = "brainpoolP256r1",
.der_len = 122,
.der = {
0x30, 0x78, 0x02, 0x01, 0x01, 0x04, 0x20, 0x98,
0x48, 0x86, 0x7a, 0x5b, 0x60, 0xb9, 0xba, 0xab,
0xa2, 0x34, 0x55, 0x43, 0x17, 0xbc, 0xfd, 0xc2,
0x18, 0xc9, 0xa8, 0x4b, 0x28, 0xbe, 0x5e, 0xa0,
0x37, 0xab, 0x0d, 0xe0, 0x54, 0x65, 0x87, 0xa0,
0x0b, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03, 0x02,
0x08, 0x01, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42,
0x00, 0x04, 0x08, 0xd7, 0x77, 0xf5, 0x10, 0xa9,
0x83, 0xd9, 0xdf, 0xfd, 0x40, 0xe4, 0x42, 0xce,
0xd8, 0x3b, 0x9b, 0xef, 0xe6, 0x4d, 0x4e, 0xca,
0x2d, 0xea, 0xe6, 0x69, 0xfe, 0xd3, 0xa9, 0x3f,
0x30, 0xfa, 0x7e, 0xa7, 0x14, 0x9d, 0x37, 0x77,
0xc5, 0xcc, 0x1e, 0x32, 0xf6, 0xce, 0x17, 0x91,
0x1b, 0xeb, 0xa3, 0x8f, 0xce, 0x70, 0x55, 0xc1,
0xcf, 0xe3, 0x38, 0xa0, 0xb7, 0x95, 0x85, 0x26,
0xf5, 0xb2,
},
.hex = "0408D777F510A983"
"D9DFFD40E442CED8"
"3B9BEFE64D4ECA2D"
"EAE669FED3A93F30"
"FA7EA7149D3777C5"
"CC1E32F6CE17911B"
"EBA38FCE7055C1CF"
"E338A0B7958526F5"
"B2",
.oct_len = 65,
.oct = {
0x04, 0x08, 0xd7, 0x77, 0xf5, 0x10, 0xa9, 0x83,
0xd9, 0xdf, 0xfd, 0x40, 0xe4, 0x42, 0xce, 0xd8,
0x3b, 0x9b, 0xef, 0xe6, 0x4d, 0x4e, 0xca, 0x2d,
0xea, 0xe6, 0x69, 0xfe, 0xd3, 0xa9, 0x3f, 0x30,
0xfa, 0x7e, 0xa7, 0x14, 0x9d, 0x37, 0x77, 0xc5,
0xcc, 0x1e, 0x32, 0xf6, 0xce, 0x17, 0x91, 0x1b,
0xeb, 0xa3, 0x8f, 0xce, 0x70, 0x55, 0xc1, 0xcf,
0xe3, 0x38, 0xa0, 0xb7, 0x95, 0x85, 0x26, 0xf5,
0xb2,
},
},
{
.name = "brainpoolP256t1",
.der_len = 122,
.der = {
0x30, 0x78, 0x02, 0x01, 0x01, 0x04, 0x20, 0x21,
0xb0, 0x02, 0x6c, 0xac, 0x68, 0xe7, 0xaf, 0xb6,
0x8b, 0xb9, 0xe6, 0x68, 0xec, 0x2a, 0xfa, 0x55,
0xb0, 0xd4, 0x23, 0xaa, 0xb9, 0xfb, 0x7c, 0xf5,
0xd1, 0x2f, 0x61, 0x52, 0x19, 0xc0, 0x19, 0xa0,
0x0b, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03, 0x02,
0x08, 0x01, 0x01, 0x08, 0xa1, 0x44, 0x03, 0x42,
0x00, 0x04, 0x7b, 0x1d, 0x55, 0x29, 0x0b, 0x0a,
0x0d, 0x02, 0x7a, 0x1d, 0x72, 0x53, 0xc1, 0x84,
0xb9, 0x90, 0x00, 0xb9, 0x45, 0xe5, 0xa5, 0xd4,
0xee, 0xd6, 0x9a, 0x1d, 0xb0, 0x3a, 0x91, 0xa8,
0x95, 0x56, 0x58, 0x32, 0xcb, 0xf3, 0x28, 0x95,
0xa6, 0x82, 0x46, 0xe6, 0x0a, 0x33, 0x00, 0xd1,
0x0c, 0x61, 0xac, 0x1e, 0xa0, 0xb0, 0xad, 0x3a,
0xbd, 0x1e, 0x53, 0x8d, 0x26, 0x96, 0xab, 0x44,
0x6b, 0x84,
},
.hex = "047B1D55290B0A0D"
"027A1D7253C184B9"
"9000B945E5A5D4EE"
"D69A1DB03A91A895"
"565832CBF32895A6"
"8246E60A3300D10C"
"61AC1EA0B0AD3ABD"
"1E538D2696AB446B"
"84",
.oct_len = 65,
.oct = {
0x04, 0x7b, 0x1d, 0x55, 0x29, 0x0b, 0x0a, 0x0d,
0x02, 0x7a, 0x1d, 0x72, 0x53, 0xc1, 0x84, 0xb9,
0x90, 0x00, 0xb9, 0x45, 0xe5, 0xa5, 0xd4, 0xee,
0xd6, 0x9a, 0x1d, 0xb0, 0x3a, 0x91, 0xa8, 0x95,
0x56, 0x58, 0x32, 0xcb, 0xf3, 0x28, 0x95, 0xa6,
0x82, 0x46, 0xe6, 0x0a, 0x33, 0x00, 0xd1, 0x0c,
0x61, 0xac, 0x1e, 0xa0, 0xb0, 0xad, 0x3a, 0xbd,
0x1e, 0x53, 0x8d, 0x26, 0x96, 0xab, 0x44, 0x6b,
0x84,
},
},
{
.name = "brainpoolP320r1",
.der_len = 147,
.der = {
0x30, 0x81, 0x90, 0x02, 0x01, 0x01, 0x04, 0x28,
0x1f, 0x7e, 0x6e, 0x51, 0x13, 0x87, 0x9b, 0x09,
0x2b, 0x3f, 0x1c, 0x39, 0x0f, 0x9f, 0x48, 0x79,
0x48, 0xa1, 0x44, 0xe0, 0x5c, 0x73, 0x2a, 0x6c,
0x6e, 0x60, 0x59, 0xd0, 0xf6, 0x6f, 0x32, 0x0e,
0x6b, 0x2b, 0x0c, 0xf2, 0x39, 0xbd, 0x42, 0xaf,
0xa0, 0x0b, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03,
0x02, 0x08, 0x01, 0x01, 0x09, 0xa1, 0x54, 0x03,
0x52, 0x00, 0x04, 0xa3, 0x37, 0x85, 0xe2, 0xf2,
0x5f, 0xa1, 0x71, 0xa6, 0x75, 0xfe, 0xa1, 0xea,
0x66, 0x35, 0x7a, 0x53, 0x71, 0x24, 0x83, 0xcd,
0xc9, 0x5d, 0x3f, 0x43, 0xc4, 0x97, 0x6d, 0xcc,
0x0c, 0xed, 0x9a, 0x51, 0x51, 0x7d, 0x1e, 0xd0,
0xea, 0xd2, 0x8c, 0x36, 0xb0, 0x93, 0x62, 0xeb,
0x26, 0xda, 0xe1, 0xef, 0xc7, 0x1a, 0xfa, 0x0c,
0xea, 0x84, 0x7a, 0xf1, 0x50, 0x2c, 0xee, 0xf1,
0xb3, 0xcc, 0xb7, 0xa0, 0x98, 0x5d, 0xde, 0xc2,
0x54, 0xcc, 0x11, 0x2a, 0x84, 0xc6, 0x79, 0x10,
0x7b, 0x20, 0x26,
},
.hex = "04A33785E2F25FA1"
"71A675FEA1EA6635"
"7A53712483CDC95D"
"3F43C4976DCC0CED"
"9A51517D1ED0EAD2"
"8C36B09362EB26DA"
"E1EFC71AFA0CEA84"
"7AF1502CEEF1B3CC"
"B7A0985DDEC254CC"
"112A84C679107B20"
"26",
.oct_len = 81,
.oct = {
0x04, 0xa3, 0x37, 0x85, 0xe2, 0xf2, 0x5f, 0xa1,
0x71, 0xa6, 0x75, 0xfe, 0xa1, 0xea, 0x66, 0x35,
0x7a, 0x53, 0x71, 0x24, 0x83, 0xcd, 0xc9, 0x5d,
0x3f, 0x43, 0xc4, 0x97, 0x6d, 0xcc, 0x0c, 0xed,
0x9a, 0x51, 0x51, 0x7d, 0x1e, 0xd0, 0xea, 0xd2,
0x8c, 0x36, 0xb0, 0x93, 0x62, 0xeb, 0x26, 0xda,
0xe1, 0xef, 0xc7, 0x1a, 0xfa, 0x0c, 0xea, 0x84,
0x7a, 0xf1, 0x50, 0x2c, 0xee, 0xf1, 0xb3, 0xcc,
0xb7, 0xa0, 0x98, 0x5d, 0xde, 0xc2, 0x54, 0xcc,
0x11, 0x2a, 0x84, 0xc6, 0x79, 0x10, 0x7b, 0x20,
0x26,
},
},
{
.name = "brainpoolP320t1",
.der_len = 147,
.der = {
0x30, 0x81, 0x90, 0x02, 0x01, 0x01, 0x04, 0x28,
0x4a, 0x8a, 0x25, 0xd9, 0xfa, 0x04, 0x8f, 0x6b,
0xd5, 0xa3, 0x83, 0xd6, 0xf2, 0xca, 0x82, 0xd5,
0xe2, 0x8e, 0x3f, 0xe6, 0x07, 0xcd, 0xa2, 0x22,
0xa0, 0x3f, 0x0a, 0x7c, 0x09, 0x0f, 0x9f, 0xf4,
0xe3, 0x59, 0x4b, 0x43, 0x0c, 0xfd, 0x5a, 0x96,
0xa0, 0x0b, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03,
0x02, 0x08, 0x01, 0x01, 0x0a, 0xa1, 0x54, 0x03,
0x52, 0x00, 0x04, 0x3d, 0x8c, 0x4c, 0xbb, 0x30,
0x3f, 0xa0, 0x84, 0x61, 0x43, 0x50, 0x23, 0x70,
0xe3, 0x70, 0xb6, 0x4d, 0x89, 0xc8, 0x95, 0xa0,
0x09, 0xae, 0xfc, 0x55, 0x9c, 0x2f, 0xef, 0x16,
0xc0, 0x72, 0x3c, 0x3e, 0x07, 0xa1, 0xbb, 0xd8,
0x8a, 0xfa, 0xaf, 0x9f, 0xaf, 0x07, 0x7c, 0x15,
0x4d, 0x75, 0x6b, 0xf5, 0x25, 0x65, 0x5b, 0xc4,
0x78, 0x59, 0x22, 0xe5, 0x92, 0x5c, 0xc2, 0x8f,
0xdc, 0x97, 0x59, 0x82, 0xc5, 0x0d, 0x24, 0x70,
0x03, 0xbe, 0xa5, 0x05, 0x88, 0x16, 0x47, 0x9f,
0xe5, 0x3b, 0xb8,
},
.hex = "043D8C4CBB303FA0"
"846143502370E370"
"B64D89C895A009AE"
"FC559C2FEF16C072"
"3C3E07A1BBD88AFA"
"AF9FAF077C154D75"
"6BF525655BC47859"
"22E5925CC28FDC97"
"5982C50D247003BE"
"A5058816479FE53B"
"B8",
.oct_len = 81,
.oct = {
0x04, 0x3d, 0x8c, 0x4c, 0xbb, 0x30, 0x3f, 0xa0,
0x84, 0x61, 0x43, 0x50, 0x23, 0x70, 0xe3, 0x70,
0xb6, 0x4d, 0x89, 0xc8, 0x95, 0xa0, 0x09, 0xae,
0xfc, 0x55, 0x9c, 0x2f, 0xef, 0x16, 0xc0, 0x72,
0x3c, 0x3e, 0x07, 0xa1, 0xbb, 0xd8, 0x8a, 0xfa,
0xaf, 0x9f, 0xaf, 0x07, 0x7c, 0x15, 0x4d, 0x75,
0x6b, 0xf5, 0x25, 0x65, 0x5b, 0xc4, 0x78, 0x59,
0x22, 0xe5, 0x92, 0x5c, 0xc2, 0x8f, 0xdc, 0x97,
0x59, 0x82, 0xc5, 0x0d, 0x24, 0x70, 0x03, 0xbe,
0xa5, 0x05, 0x88, 0x16, 0x47, 0x9f, 0xe5, 0x3b,
0xb8,
},
},
{
.name = "brainpoolP384r1",
.der_len = 171,
.der = {
0x30, 0x81, 0xa8, 0x02, 0x01, 0x01, 0x04, 0x30,
0x02, 0x57, 0xb6, 0xfe, 0x31, 0xda, 0x87, 0xcd,
0x68, 0x2a, 0x67, 0x98, 0xd1, 0x72, 0x5c, 0xd8,
0x2e, 0x25, 0xf9, 0x39, 0x36, 0x3b, 0x93, 0x98,
0x79, 0x81, 0xc0, 0x7e, 0xa3, 0x44, 0x99, 0xd8,
0xe5, 0x07, 0x1f, 0xea, 0xa1, 0x66, 0x60, 0x00,
0x29, 0x84, 0xa3, 0x35, 0xdd, 0x64, 0x96, 0x93,
0xa0, 0x0b, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03,
0x02, 0x08, 0x01, 0x01, 0x0b, 0xa1, 0x64, 0x03,
0x62, 0x00, 0x04, 0x4f, 0x79, 0xe0, 0xe7, 0xf9,
0x57, 0x33, 0xf9, 0x9d, 0x6a, 0x5c, 0x00, 0x6e,
0xb8, 0xbc, 0xe6, 0x4f, 0x70, 0x1d, 0x73, 0x02,
0x5c, 0x87, 0xa1, 0x88, 0xea, 0xe3, 0x57, 0x5c,
0x1a, 0x27, 0x40, 0xcf, 0xcc, 0x6f, 0x7e, 0x6d,
0xfd, 0x96, 0x0b, 0xaa, 0xc5, 0x02, 0x92, 0x10,
0x6d, 0x7e, 0xd5, 0x17, 0xda, 0xab, 0x52, 0x9b,
0xcd, 0x87, 0x08, 0x64, 0x2a, 0x61, 0x03, 0xc9,
0xfe, 0x97, 0x79, 0xf0, 0x5c, 0x84, 0x72, 0x50,
0x53, 0x95, 0x56, 0x7a, 0x97, 0xce, 0x36, 0x13,
0x23, 0x78, 0x31, 0x82, 0x36, 0x07, 0x45, 0xad,
0x92, 0x00, 0xaf, 0x3d, 0xe8, 0x5a, 0x7d, 0x7b,
0x63, 0xc2, 0xde,
},
.hex = "044F79E0E7F95733"
"F99D6A5C006EB8BC"
"E64F701D73025C87"
"A188EAE3575C1A27"
"40CFCC6F7E6DFD96"
"0BAAC50292106D7E"
"D517DAAB529BCD87"
"08642A6103C9FE97"
"79F05C8472505395"
"567A97CE36132378"
"3182360745AD9200"
"AF3DE85A7D7B63C2"
"DE",
.oct_len = 97,
.oct = {
0x04, 0x4f, 0x79, 0xe0, 0xe7, 0xf9, 0x57, 0x33,
0xf9, 0x9d, 0x6a, 0x5c, 0x00, 0x6e, 0xb8, 0xbc,
0xe6, 0x4f, 0x70, 0x1d, 0x73, 0x02, 0x5c, 0x87,
0xa1, 0x88, 0xea, 0xe3, 0x57, 0x5c, 0x1a, 0x27,
0x40, 0xcf, 0xcc, 0x6f, 0x7e, 0x6d, 0xfd, 0x96,
0x0b, 0xaa, 0xc5, 0x02, 0x92, 0x10, 0x6d, 0x7e,
0xd5, 0x17, 0xda, 0xab, 0x52, 0x9b, 0xcd, 0x87,
0x08, 0x64, 0x2a, 0x61, 0x03, 0xc9, 0xfe, 0x97,
0x79, 0xf0, 0x5c, 0x84, 0x72, 0x50, 0x53, 0x95,
0x56, 0x7a, 0x97, 0xce, 0x36, 0x13, 0x23, 0x78,
0x31, 0x82, 0x36, 0x07, 0x45, 0xad, 0x92, 0x00,
0xaf, 0x3d, 0xe8, 0x5a, 0x7d, 0x7b, 0x63, 0xc2,
0xde,
},
},
{
.name = "brainpoolP384t1",
.der_len = 171,
.der = {
0x30, 0x81, 0xa8, 0x02, 0x01, 0x01, 0x04, 0x30,
0x35, 0xea, 0xbc, 0x66, 0xd4, 0xa9, 0xc0, 0xe1,
0xcd, 0xd4, 0xe5, 0xb1, 0xac, 0x8f, 0x66, 0x82,
0x56, 0xc1, 0xbd, 0xf2, 0xf5, 0x30, 0x95, 0xab,
0x30, 0xaa, 0xc0, 0xc3, 0x07, 0xca, 0x97, 0xc9,
0x53, 0x45, 0xd3, 0xff, 0xbf, 0xfe, 0xdf, 0x39,
0x32, 0x40, 0xe0, 0x45, 0x15, 0xa7, 0x22, 0x5f,
0xa0, 0x0b, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03,
0x02, 0x08, 0x01, 0x01, 0x0c, 0xa1, 0x64, 0x03,
0x62, 0x00, 0x04, 0x85, 0xdb, 0x57, 0x4b, 0x71,
0xb1, 0x65, 0x93, 0x51, 0x83, 0x7c, 0xb3, 0x24,
0x07, 0x6b, 0x7b, 0x57, 0x33, 0x73, 0x3a, 0xa6,
0x14, 0x86, 0x83, 0xa8, 0x88, 0x81, 0xf2, 0x90,
0xdf, 0x93, 0x4f, 0x67, 0x41, 0xef, 0xcb, 0x35,
0x14, 0xad, 0x4c, 0x67, 0x0b, 0xdb, 0x86, 0x03,
0x5e, 0x6d, 0x5e, 0x7e, 0x4b, 0x0f, 0x73, 0x9e,
0x73, 0x50, 0x86, 0x29, 0x09, 0x7c, 0x38, 0xfc,
0xbe, 0xaf, 0x59, 0x9c, 0x69, 0xdf, 0xb4, 0x60,
0x14, 0x3e, 0xb2, 0x1a, 0x72, 0x86, 0x57, 0xcb,
0x6b, 0x42, 0x20, 0x67, 0x7f, 0xbc, 0xa8, 0x57,
0x88, 0x76, 0x72, 0x9a, 0xb4, 0xea, 0xc0, 0x48,
0x01, 0x5d, 0x8e,
},
.hex = "0485DB574B71B165"
"9351837CB324076B"
"7B5733733AA61486"
"83A88881F290DF93"
"4F6741EFCB3514AD"
"4C670BDB86035E6D"
"5E7E4B0F739E7350"
"8629097C38FCBEAF"
"599C69DFB460143E"
"B21A728657CB6B42"
"20677FBCA8578876"
"729AB4EAC048015D"
"8E",
.oct_len = 97,
.oct = {
0x04, 0x85, 0xdb, 0x57, 0x4b, 0x71, 0xb1, 0x65,
0x93, 0x51, 0x83, 0x7c, 0xb3, 0x24, 0x07, 0x6b,
0x7b, 0x57, 0x33, 0x73, 0x3a, 0xa6, 0x14, 0x86,
0x83, 0xa8, 0x88, 0x81, 0xf2, 0x90, 0xdf, 0x93,
0x4f, 0x67, 0x41, 0xef, 0xcb, 0x35, 0x14, 0xad,
0x4c, 0x67, 0x0b, 0xdb, 0x86, 0x03, 0x5e, 0x6d,
0x5e, 0x7e, 0x4b, 0x0f, 0x73, 0x9e, 0x73, 0x50,
0x86, 0x29, 0x09, 0x7c, 0x38, 0xfc, 0xbe, 0xaf,
0x59, 0x9c, 0x69, 0xdf, 0xb4, 0x60, 0x14, 0x3e,
0xb2, 0x1a, 0x72, 0x86, 0x57, 0xcb, 0x6b, 0x42,
0x20, 0x67, 0x7f, 0xbc, 0xa8, 0x57, 0x88, 0x76,
0x72, 0x9a, 0xb4, 0xea, 0xc0, 0x48, 0x01, 0x5d,
0x8e,
},
},
{
.name = "brainpoolP512r1",
.der_len = 221,
.der = {
0x30, 0x81, 0xda, 0x02, 0x01, 0x01, 0x04, 0x40,
0x7e, 0x04, 0x7d, 0xab, 0x42, 0xc6, 0xdb, 0x95,
0xfb, 0x22, 0x0b, 0xe4, 0x09, 0xff, 0x4a, 0x1e,
0x7b, 0x42, 0x62, 0x82, 0x41, 0xf4, 0x1e, 0xc2,
0x1f, 0x9e, 0x52, 0xea, 0xce, 0x1b, 0x75, 0x07,
0x7c, 0xaf, 0x49, 0xdf, 0xf3, 0x20, 0xfa, 0x88,
0x23, 0xc4, 0x5e, 0x6d, 0x82, 0x45, 0x32, 0x19,
0x04, 0x4a, 0x3d, 0x80, 0xa1, 0xa8, 0x99, 0x09,
0xce, 0x78, 0xde, 0x32, 0x18, 0xf4, 0x83, 0x2c,
0xa0, 0x0b, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03,
0x02, 0x08, 0x01, 0x01, 0x0d, 0xa1, 0x81, 0x85,
0x03, 0x81, 0x82, 0x00, 0x04, 0x1e, 0x99, 0xea,
0x54, 0xb6, 0x1a, 0x4f, 0x44, 0x25, 0xf4, 0xf8,
0xbe, 0x33, 0x7c, 0xd1, 0x62, 0x35, 0xf5, 0xd1,
0x8e, 0x9f, 0xae, 0xa8, 0x8f, 0x6d, 0x61, 0x27,
0x2d, 0x2a, 0xb1, 0x96, 0x48, 0x6d, 0xb2, 0x63,
0x05, 0x9f, 0xec, 0xa1, 0xcd, 0x65, 0x45, 0xc8,
0xcd, 0xf1, 0xa4, 0xba, 0x20, 0xb7, 0xe4, 0xc7,
0x92, 0x3c, 0x1f, 0x16, 0xf4, 0x5b, 0x75, 0xe4,
0x2a, 0x2e, 0x44, 0x72, 0x65, 0x63, 0xc3, 0x78,
0x54, 0x50, 0xcb, 0x50, 0xe0, 0xbe, 0xe7, 0x6f,
0x2a, 0xdc, 0x24, 0x7b, 0xf8, 0x4b, 0xa8, 0xe2,
0x1b, 0x27, 0x00, 0x2d, 0xe8, 0x99, 0xdc, 0x5f,
0xa4, 0x43, 0xa8, 0xf7, 0xb1, 0x55, 0xea, 0xd7,
0x02, 0x09, 0x08, 0x97, 0x5f, 0x21, 0x1e, 0x16,
0xa0, 0xd8, 0x27, 0xe4, 0x5e, 0x3a, 0xa5, 0x51,
0x68, 0xe7, 0x19, 0xc1, 0x7d, 0xb6, 0x9d, 0xb9,
0xc6, 0xc2, 0x1b, 0x48, 0x7f,
},
.hex = "041E99EA54B61A4F"
"4425F4F8BE337CD1"
"6235F5D18E9FAEA8"
"8F6D61272D2AB196"
"486DB263059FECA1"
"CD6545C8CDF1A4BA"
"20B7E4C7923C1F16"
"F45B75E42A2E4472"
"6563C3785450CB50"
"E0BEE76F2ADC247B"
"F84BA8E21B27002D"
"E899DC5FA443A8F7"
"B155EAD702090897"
"5F211E16A0D827E4"
"5E3AA55168E719C1"
"7DB69DB9C6C21B48"
"7F",
.oct_len = 129,
.oct = {
0x04, 0x1e, 0x99, 0xea, 0x54, 0xb6, 0x1a, 0x4f,
0x44, 0x25, 0xf4, 0xf8, 0xbe, 0x33, 0x7c, 0xd1,
0x62, 0x35, 0xf5, 0xd1, 0x8e, 0x9f, 0xae, 0xa8,
0x8f, 0x6d, 0x61, 0x27, 0x2d, 0x2a, 0xb1, 0x96,
0x48, 0x6d, 0xb2, 0x63, 0x05, 0x9f, 0xec, 0xa1,
0xcd, 0x65, 0x45, 0xc8, 0xcd, 0xf1, 0xa4, 0xba,
0x20, 0xb7, 0xe4, 0xc7, 0x92, 0x3c, 0x1f, 0x16,
0xf4, 0x5b, 0x75, 0xe4, 0x2a, 0x2e, 0x44, 0x72,
0x65, 0x63, 0xc3, 0x78, 0x54, 0x50, 0xcb, 0x50,
0xe0, 0xbe, 0xe7, 0x6f, 0x2a, 0xdc, 0x24, 0x7b,
0xf8, 0x4b, 0xa8, 0xe2, 0x1b, 0x27, 0x00, 0x2d,
0xe8, 0x99, 0xdc, 0x5f, 0xa4, 0x43, 0xa8, 0xf7,
0xb1, 0x55, 0xea, 0xd7, 0x02, 0x09, 0x08, 0x97,
0x5f, 0x21, 0x1e, 0x16, 0xa0, 0xd8, 0x27, 0xe4,
0x5e, 0x3a, 0xa5, 0x51, 0x68, 0xe7, 0x19, 0xc1,
0x7d, 0xb6, 0x9d, 0xb9, 0xc6, 0xc2, 0x1b, 0x48,
0x7f,
},
},
{
.name = "brainpoolP512t1",
.der_len = 221,
.der = {
0x30, 0x81, 0xda, 0x02, 0x01, 0x01, 0x04, 0x40,
0xa0, 0xcb, 0xab, 0x2e, 0xdb, 0xb0, 0x17, 0x53,
0x91, 0x23, 0x8c, 0x86, 0x29, 0x8b, 0x33, 0x27,
0x27, 0x86, 0x71, 0xdd, 0x9f, 0x92, 0x8a, 0x8a,
0x28, 0xac, 0x1f, 0x4b, 0x67, 0x8d, 0xd3, 0x7a,
0x71, 0xd9, 0x95, 0x3c, 0xc2, 0x48, 0x9a, 0x1e,
0x75, 0xcf, 0x33, 0x6f, 0xdc, 0x88, 0x8c, 0x29,
0x1d, 0x41, 0xf8, 0xe1, 0xb3, 0x8f, 0xf9, 0x9e,
0x13, 0x14, 0xbc, 0x4f, 0xa5, 0x8e, 0x06, 0xba,
0xa0, 0x0b, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03,
0x02, 0x08, 0x01, 0x01, 0x0e, 0xa1, 0x81, 0x85,
0x03, 0x81, 0x82, 0x00, 0x04, 0x5b, 0x2b, 0x47,
0x83, 0x61, 0xea, 0x80, 0x14, 0x85, 0x06, 0xe7,
0x03, 0xbd, 0x24, 0x04, 0x47, 0x5d, 0x33, 0x4e,
0xde, 0x0c, 0x92, 0x09, 0x54, 0x77, 0x53, 0x0e,
0x33, 0x30, 0x73, 0xc0, 0xc0, 0x6a, 0xf2, 0xb5,
0xb5, 0xd4, 0xd3, 0x02, 0x2f, 0x20, 0xe2, 0x88,
0xb2, 0x07, 0x4a, 0x9f, 0x90, 0xbf, 0xba, 0xb5,
0x3d, 0xc4, 0x5b, 0x65, 0x76, 0xb5, 0xe5, 0xa1,
0x7d, 0x63, 0x39, 0x57, 0xaa, 0x1d, 0x1f, 0x99,
0x52, 0x43, 0x5d, 0x0b, 0x58, 0xa6, 0x51, 0x1e,
0x6f, 0x7b, 0x9e, 0x2f, 0x45, 0x5a, 0x2d, 0x6f,
0xaa, 0x2b, 0xfc, 0xe1, 0x9f, 0x78, 0x11, 0x70,
0x80, 0xf8, 0xfe, 0x51, 0x45, 0x12, 0xbf, 0x79,
0xd8, 0xaf, 0x05, 0x59, 0x14, 0x01, 0x81, 0x9c,
0x12, 0x5c, 0x8d, 0x4d, 0xed, 0xc7, 0x44, 0x61,
0x68, 0x0f, 0x3f, 0x34, 0xee, 0x90, 0x4e, 0xab,
0x80, 0x7c, 0x41, 0xd7, 0x8f,
},
.hex = "045B2B478361EA80"
"148506E703BD2404"
"475D334EDE0C9209"
"5477530E333073C0"
"C06AF2B5B5D4D302"
"2F20E288B2074A9F"
"90BFBAB53DC45B65"
"76B5E5A17D633957"
"AA1D1F9952435D0B"
"58A6511E6F7B9E2F"
"455A2D6FAA2BFCE1"
"9F78117080F8FE51"
"4512BF79D8AF0559"
"1401819C125C8D4D"
"EDC74461680F3F34"
"EE904EAB807C41D7"
"8F",
.oct_len = 129,
.oct = {
0x04, 0x5b, 0x2b, 0x47, 0x83, 0x61, 0xea, 0x80,
0x14, 0x85, 0x06, 0xe7, 0x03, 0xbd, 0x24, 0x04,
0x47, 0x5d, 0x33, 0x4e, 0xde, 0x0c, 0x92, 0x09,
0x54, 0x77, 0x53, 0x0e, 0x33, 0x30, 0x73, 0xc0,
0xc0, 0x6a, 0xf2, 0xb5, 0xb5, 0xd4, 0xd3, 0x02,
0x2f, 0x20, 0xe2, 0x88, 0xb2, 0x07, 0x4a, 0x9f,
0x90, 0xbf, 0xba, 0xb5, 0x3d, 0xc4, 0x5b, 0x65,
0x76, 0xb5, 0xe5, 0xa1, 0x7d, 0x63, 0x39, 0x57,
0xaa, 0x1d, 0x1f, 0x99, 0x52, 0x43, 0x5d, 0x0b,
0x58, 0xa6, 0x51, 0x1e, 0x6f, 0x7b, 0x9e, 0x2f,
0x45, 0x5a, 0x2d, 0x6f, 0xaa, 0x2b, 0xfc, 0xe1,
0x9f, 0x78, 0x11, 0x70, 0x80, 0xf8, 0xfe, 0x51,
0x45, 0x12, 0xbf, 0x79, 0xd8, 0xaf, 0x05, 0x59,
0x14, 0x01, 0x81, 0x9c, 0x12, 0x5c, 0x8d, 0x4d,
0xed, 0xc7, 0x44, 0x61, 0x68, 0x0f, 0x3f, 0x34,
0xee, 0x90, 0x4e, 0xab, 0x80, 0x7c, 0x41, 0xd7,
0x8f,
},
},
{
.name = "FRP256v1",
.der_len = 123,
.der = {
0x30, 0x79, 0x02, 0x01, 0x01, 0x04, 0x20, 0x66,
0xe4, 0xdb, 0x37, 0x46, 0x8d, 0xa1, 0xc8, 0x20,
0x0d, 0xdf, 0xcb, 0x3b, 0x5c, 0x5b, 0x84, 0xe1,
0x89, 0xed, 0x30, 0x37, 0xaa, 0xfa, 0xb2, 0x5b,
0xf4, 0xf6, 0x13, 0x66, 0xfe, 0xfc, 0x7c, 0xa0,
0x0c, 0x06, 0x0a, 0x2a, 0x81, 0x7a, 0x01, 0x81,
0x5f, 0x65, 0x82, 0x00, 0x01, 0xa1, 0x44, 0x03,
0x42, 0x00, 0x04, 0x17, 0xc7, 0xae, 0x1b, 0xe4,
0xc6, 0xd6, 0x3a, 0xcf, 0x6b, 0x7e, 0x43, 0x29,
0x9f, 0xdc, 0xc2, 0xa3, 0x90, 0x53, 0x62, 0x42,
0x6e, 0xa3, 0xa4, 0xca, 0xd3, 0xf6, 0x53, 0x53,
0xd4, 0xa6, 0x1f, 0xa8, 0x03, 0x1f, 0x6d, 0xd4,
0x75, 0x77, 0x23, 0xf7, 0x92, 0xa4, 0x7c, 0x5a,
0x4c, 0xc7, 0xc6, 0x96, 0x54, 0x62, 0x94, 0x9b,
0xa7, 0xe0, 0x31, 0x1c, 0x4d, 0x1c, 0xa8, 0x2a,
0x51, 0x11, 0x24,
},
.hex = "0417C7AE1BE4C6D6"
"3ACF6B7E43299FDC"
"C2A3905362426EA3"
"A4CAD3F65353D4A6"
"1FA8031F6DD47577"
"23F792A47C5A4CC7"
"C6965462949BA7E0"
"311C4D1CA82A5111"
"24",
.oct_len = 65,
.oct = {
0x04, 0x17, 0xc7, 0xae, 0x1b, 0xe4, 0xc6, 0xd6,
0x3a, 0xcf, 0x6b, 0x7e, 0x43, 0x29, 0x9f, 0xdc,
0xc2, 0xa3, 0x90, 0x53, 0x62, 0x42, 0x6e, 0xa3,
0xa4, 0xca, 0xd3, 0xf6, 0x53, 0x53, 0xd4, 0xa6,
0x1f, 0xa8, 0x03, 0x1f, 0x6d, 0xd4, 0x75, 0x77,
0x23, 0xf7, 0x92, 0xa4, 0x7c, 0x5a, 0x4c, 0xc7,
0xc6, 0x96, 0x54, 0x62, 0x94, 0x9b, 0xa7, 0xe0,
0x31, 0x1c, 0x4d, 0x1c, 0xa8, 0x2a, 0x51, 0x11,
0x24,
},
},
};
#define N_EC_PRIVATE_KEYS (sizeof(ec_private_keys) / sizeof(ec_private_keys[0]))
static EC_KEY *
ec_key_check_sanity(const struct ec_private_key *key)
{
EC_KEY *ec_key;
const unsigned char *p;
unsigned char *der = NULL;
int der_len = 0;
unsigned int flags;
uint8_t form;
p = key->der;
if ((ec_key = d2i_ECPrivateKey(NULL, &p, key->der_len)) == NULL) {
fprintf(stderr, "FAIL: d2i_ECPrivateKey for %s\n", key->name);
goto err;
}
if ((flags = EC_KEY_get_enc_flags(ec_key)) != 0) {
fprintf(stderr, "FAIL: EC_KEY_get_enc_flags() returned %x for %s\n",
flags, key->name);
goto err;
}
if ((form = EC_KEY_get_conv_form(ec_key)) != POINT_CONVERSION_UNCOMPRESSED) {
fprintf(stderr, "FAIL: got conversion form %02x, want %02x\n",
form, POINT_CONVERSION_UNCOMPRESSED);
goto err;
}
ERR_clear_error();
if (!EC_KEY_check_key(ec_key)) {
fprintf(stderr, "FAIL: EC_KEY_check_key() for %s\n", key->name);
ERR_print_errors_fp(stderr);
goto err;
}
der = NULL;
if ((der_len = i2d_ECPrivateKey(ec_key, &der)) <= 0) {
fprintf(stderr, "FAIL: i2d_ECPrivateKey() for %s\n", key->name);
der_len = 0;
goto err;
}
if (compare_data(key->name, der, der_len, key->der, key->der_len) == -1)
goto err;
freezero(der, der_len);
der = NULL;
return ec_key;
err:
EC_KEY_free(ec_key);
freezero(der, der_len);
return NULL;
}
static int
ec_key_test_point_encoding(const struct ec_private_key *key, const EC_KEY *ec_key)
{
const EC_GROUP *group;
const EC_POINT *ec_public_point;
char *hex = NULL;
unsigned char *ostr = NULL;
int hex_len = 0, ostr_len = 0;
int failed = 1;
if ((group = EC_KEY_get0_group(ec_key)) == NULL) {
fprintf(stderr, "FAIL: EC_KEY_get0_group() for %s\n", key->name);
goto err;
}
if ((ec_public_point = EC_KEY_get0_public_key(ec_key)) == NULL) {
fprintf(stderr, "FAIL: EC_KEY_get0_public_key() for %s\n", key->name);
goto err;
}
if ((hex = EC_POINT_point2hex(group, ec_public_point,
POINT_CONVERSION_UNCOMPRESSED, NULL)) == NULL) {
fprintf(stderr, "FAIL: EC_POINT_point2hex() for %s\n", key->name);
goto err;
}
if ((hex_len = strlen(hex)) != 2 * key->oct_len) {
fprintf(stderr, "FAIL: hex_len: %d, oct_len %d for %s\n",
hex_len, key->oct_len, key->name);
goto err;
}
if (compare_data(key->name, hex, hex_len, key->hex, hex_len) == -1) {
fprintf(stderr, "FAIL: EC_POINT_point2hex() comparison for %s\n",
key->name);
goto err;
}
if ((ostr_len = i2o_ECPublicKey(ec_key, &ostr)) <= 0) {
fprintf(stderr, "FAIL: i2o_ECPublicKey for %s\n", key->name);
goto err;
}
if (compare_data(key->name, ostr, ostr_len, key->oct, key->oct_len) == -1) {
fprintf(stderr, "FAIL: i2o_ECPublicKey comparison for %s\n",
key->name);
goto err;
}
failed = 0;
err:
free(hex);
freezero(ostr, ostr_len);
return failed;
}
static int
ec_key_test_point_versus_bn(const struct ec_private_key *key, const EC_KEY *ec_key)
{
const EC_GROUP *group;
const EC_POINT *ec_public_point;
EC_POINT *point = NULL;
BIGNUM *hex_bn = NULL, *point_bn = NULL;
int rv;
int failed = 1;
if ((group = EC_KEY_get0_group(ec_key)) == NULL) {
fprintf(stderr, "FAIL: EC_KEY_get0_group() for %s\n", key->name);
goto err;
}
if ((ec_public_point = EC_KEY_get0_public_key(ec_key)) == NULL) {
fprintf(stderr, "FAIL: EC_KEY_get0_public_key() for %s\n", key->name);
goto err;
}
if ((point_bn = BN_new()) == NULL)
err(1, "BN_new()");
if (EC_POINT_point2bn(group, ec_public_point,
POINT_CONVERSION_UNCOMPRESSED, point_bn, NULL) == NULL) {
fprintf(stderr, "FAIL: EC_POINT_point2bn() for %s\n", key->name);
goto err;
}
if (BN_hex2bn(&hex_bn, key->hex) == 0) {
fprintf(stderr, "FAIL: BN_hex2bn() for %s\n", key->name);
goto err;
}
if (BN_cmp(hex_bn, point_bn) != 0) {
fprintf(stderr, "FAIL: mismatch between "
"hex point and curve point for %s\n", key->name);
goto err;
}
if ((point = EC_POINT_hex2point(group, key->hex, NULL, NULL)) == NULL) {
fprintf(stderr, "FAIL: EC_POINT_hex2point() failed for %s\n",
key->name);
goto err;
}
if ((rv = EC_POINT_cmp(group, ec_public_point, point, NULL)) != 0) {
fprintf(stderr, "FAIL: EC_POINT_cmp() returned %d for %s\n",
rv, key->name);
goto err;
}
if (!EC_POINT_dbl(group, point, point, NULL)) {
fprintf(stderr, "FAIL: EC_POINT_dbl() failed for %s\n",
key->name);
goto err;
}
if (!EC_POINT_invert(group, point, NULL)) {
fprintf(stderr, "FAIL: EC_POINT_invert() failed for %s\n",
key->name);
goto err;
}
if (!EC_POINT_is_on_curve(group, point, NULL)) {
fprintf(stderr, "FAIL: EC_POINT_is_on_curve() failed for %s\n",
key->name);
goto err;
}
if (EC_POINT_is_at_infinity(group, point)) {
fprintf(stderr, "FAIL: EC_POINT_is_at_infinity() is true for %s\n",
key->name);
goto err;
}
if ((rv = EC_POINT_cmp(group, ec_public_point, point, NULL)) == 0) {
fprintf(stderr, "FAIL: EC_POINT_cmp() returned %d for %s\n",
rv, key->name);
goto err;
}
if (EC_POINT_hex2point(group, key->hex, point, NULL) == NULL) {
fprintf(stderr, "FAIL: EC_POINT_hex2point() 2 failed for %s\n",
key->name);
goto err;
}
if ((rv = EC_POINT_cmp(group, ec_public_point, point, NULL)) != 0) {
fprintf(stderr, "FAIL: EC_POINT_cmp() returned %d for %s\n",
rv, key->name);
goto err;
}
failed = 0;
err:
BN_free(hex_bn);
BN_free(point_bn);
EC_POINT_free(point);
return failed;
}
static int
ec_key_test_i2o_and_o2i(const struct ec_private_key *key, const EC_KEY *ec_key_orig)
{
EC_KEY *ec_key = NULL, *ec_pub_key = NULL;
const unsigned char *p;
unsigned char *ostr = NULL;
int ostr_len = 0;
uint8_t form;
int rv;
int failed = 1;
if ((ec_key = EC_KEY_dup(ec_key_orig)) == NULL) {
fprintf(stderr, "FAIL: EC_KEY_dup failed for %s", key->name);
goto err;
}
EC_KEY_set_conv_form(ec_key, POINT_CONVERSION_COMPRESSED);
ostr = NULL;
if ((ostr_len = i2o_ECPublicKey(ec_key, &ostr)) <= 0) {
fprintf(stderr, "FAIL: i2o_ECPublicKey for %s\n", key->name);
ostr_len = 0;
goto err;
}
if ((ec_pub_key = EC_KEY_new()) == NULL)
errx(1, "EC_KEY_new");
if (!EC_KEY_set_group(ec_pub_key, EC_KEY_get0_group(ec_key))) {
fprintf(stderr, "FAIL: EC_KEY_set_group() for %s\n", key->name);
goto err;
}
if ((form = EC_KEY_get_conv_form(ec_pub_key)) != POINT_CONVERSION_UNCOMPRESSED) {
fprintf(stderr, "FAIL: EC_KEY_get_conv_form() for %s:\n"
"got %02x, want %02x\n", key->name, form, POINT_CONVERSION_UNCOMPRESSED);
goto err;
}
p = ostr;
if (o2i_ECPublicKey(&ec_pub_key, &p, ostr_len) == NULL) {
fprintf(stderr, "FAIL: o2i_ECPublicKey() for %s\n", key->name);
goto err;
}
if ((form = EC_KEY_get_conv_form(ec_pub_key)) != POINT_CONVERSION_COMPRESSED) {
fprintf(stderr, "FAIL: EC_KEY_get_conv_form() for %s:\n"
"got %02x, want %02x\n", key->name, form, POINT_CONVERSION_COMPRESSED);
goto err;
}
if ((rv = EC_POINT_cmp(EC_KEY_get0_group(ec_pub_key),
EC_KEY_get0_public_key(ec_pub_key), EC_KEY_get0_public_key(ec_key),
NULL)) != 0) {
fprintf(stderr, "FAIL: EC_POINT_cmp() returned %d for %s\n",
rv, key->name);
goto err;
}
failed = 0;
err:
EC_KEY_free(ec_key);
EC_KEY_free(ec_pub_key);
freezero(ostr, ostr_len);
return failed;
}
static int
ec_key_test_hybrid_roundtrip(const struct ec_private_key *key,
const EC_KEY *ec_key_orig)
{
EC_KEY *ec_key = NULL, *ec_pub_key = NULL;
const unsigned char *p;
unsigned char *der = NULL;
int der_len = 0;
unsigned int flags;
int rv;
uint8_t form;
int failed = 1;
if ((ec_key = EC_KEY_new()) == NULL)
errx(1, "EC_KEY_new()");
if (EC_KEY_copy(ec_key, ec_key_orig) == NULL) {
fprintf(stderr, "FAIL: failed to kopy EC_KEY for %s\n", key->name);
goto err;
}
EC_KEY_set_conv_form(ec_key, POINT_CONVERSION_HYBRID);
EC_KEY_set_enc_flags(ec_key, EC_PKEY_NO_PARAMETERS | EC_PKEY_NO_PUBKEY);
if ((der_len = i2d_ECPrivateKey(ec_key, &der)) <= 0) {
fprintf(stderr, "FAIL: i2d_ECPrivateKey(2) for %s\n", key->name);
der_len = 0;
goto err;
}
if ((ec_pub_key = EC_KEY_new()) == NULL)
errx(1, "EC_KEY_new");
if (!EC_KEY_set_group(ec_pub_key, EC_KEY_get0_group(ec_key))) {
fprintf(stderr, "FAIL: EC_KEY_set_group() for %s\n", key->name);
goto err;
}
EC_KEY_set_conv_form(ec_pub_key, POINT_CONVERSION_COMPRESSED);
if ((flags = EC_KEY_get_enc_flags(ec_pub_key)) != 0) {
fprintf(stderr, "FAIL: EC_KEY_get_enc_flags() returned %x for %s\n",
flags, key->name);
goto err;
}
p = der;
if (d2i_ECPrivateKey(&ec_pub_key, &p, der_len) == NULL) {
fprintf(stderr, "FAIL: d2i_ECPrivateKey for public %s\n", key->name);
goto err;
}
if ((flags = EC_KEY_get_enc_flags(ec_pub_key)) != EC_PKEY_NO_PUBKEY) {
fprintf(stderr, "FAIL: EC_KEY_get_enc_flags() for public %s: "
" got %x, want %x\n", key->name, flags, EC_PKEY_NO_PUBKEY);
goto err;
}
if ((form = EC_KEY_get_conv_form(ec_pub_key)) != POINT_CONVERSION_COMPRESSED) {
fprintf(stderr, "FAIL: EC_KEY_get_conv_form() not compressed for %s:\n"
"got %02x, want %02x\n", key->name, form, POINT_CONVERSION_COMPRESSED);
goto err;
}
if ((rv = EC_POINT_cmp(EC_KEY_get0_group(ec_pub_key),
EC_KEY_get0_public_key(ec_pub_key), EC_KEY_get0_public_key(ec_key),
NULL)) != 0) {
fprintf(stderr, "FAIL: EC_POINT_cmp() returned %d for %s "
"after DER roundtrip\n", rv, key->name);
goto err;
}
failed = 0;
err:
EC_KEY_free(ec_key);
EC_KEY_free(ec_pub_key);
freezero(der, der_len);
return failed;
}
static int
ec_key_test_parameter_roundtrip(const struct ec_private_key *key,
EC_KEY *ec_key)
{
EC_KEY *ec_pub_key = NULL;
const unsigned char *p;
unsigned char *der = NULL;
int der_len = 0;
int rv;
int failed = 1;
if ((der_len = i2d_ECParameters(ec_key, &der)) <= 0) {
fprintf(stderr, "FAIL: i2d_ECParameters returned %d for %s\n",
der_len, key->name);
goto err;
}
if ((ec_pub_key = EC_KEY_new_by_curve_name(NID_secp256k1)) == NULL)
errx(1, "EC_KEY_new_by_curve_name");
p = der;
if (d2i_ECParameters(&ec_pub_key, &p, der_len) == NULL) {
fprintf(stderr, "FAIL: d2i_ECParameters for %s\n", key->name);
goto err;
}
if ((rv = EC_GROUP_cmp(EC_KEY_get0_group(ec_key),
EC_KEY_get0_group(ec_pub_key), NULL)) != 0) {
fprintf(stderr, "FAIL: EC_GROUP_cmp returned %d for %s\n",
rv, key->name);
goto err;
}
failed = 0;
err:
EC_KEY_free(ec_pub_key);
freezero(der, der_len);
return failed;
}
static int
ec_group_check_private_key(const struct ec_private_key *key)
{
EC_KEY *ec_key = NULL;
int failed = 0;
if ((ec_key = ec_key_check_sanity(key)) == NULL) {
fprintf(stderr, "FAIL: ec_key_check_sanity() for %s\n", key->name);
failed = 1;
goto err;
}
failed |= ec_key_test_point_encoding(key, ec_key);
failed |= ec_key_test_point_versus_bn(key, ec_key);
failed |= ec_key_test_i2o_and_o2i(key, ec_key);
failed |= ec_key_test_hybrid_roundtrip(key, ec_key);
failed |= ec_key_test_parameter_roundtrip(key, ec_key);
err:
EC_KEY_free(ec_key);
return failed;
}
static int
ec_group_check_private_keys(void)
{
size_t i;
int failed = 0;
for (i = 0; i < N_EC_PRIVATE_KEYS; i++)
failed |= ec_group_check_private_key(&ec_private_keys[i]);
return failed;
}
static void
ec_group_sha1_bignum(BIGNUM *out, const BIGNUM *in)
{
char md[SHA_DIGEST_LENGTH];
unsigned char *bin;
size_t bin_len;
if (BN_num_bytes(in) <= 0)
errx(1, "%s: invalid bignum", __func__);
bin_len = BN_num_bytes(in);
if ((bin = calloc(1, bin_len)) == NULL)
err(1, "calloc");
if (BN_bn2bin(in, bin) <= 0)
errx(1, "BN_bn2bin");
SHA1(bin, bin_len, md);
free(bin);
if (BN_bin2bn(md, sizeof(md), out) == NULL)
errx(1, "BN_bin2bn");
}
static int
ec_group_check_seed(const EC_builtin_curve *curve, BN_CTX *ctx)
{
EC_GROUP *group = NULL;
BIGNUM *p, *a, *b, *pow2, *r, *seed_bn, *w;
const unsigned char *seed;
size_t seed_len;
int i, g, h, s, t;
int failed = 1;
if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL)
errx(1, "EC_GROUP_new_by_curve_name");
BN_CTX_start(ctx);
if ((p = BN_CTX_get(ctx)) == NULL)
errx(1, "p = BN_CTX_get()");
if ((a = BN_CTX_get(ctx)) == NULL)
errx(1, "a = BN_CTX_get()");
if ((b = BN_CTX_get(ctx)) == NULL)
errx(1, "b = BN_CTX_get()");
if ((r = BN_CTX_get(ctx)) == NULL)
errx(1, "r = BN_CTX_get()");
if ((pow2 = BN_CTX_get(ctx)) == NULL)
errx(1, "pow2 = BN_CTX_get()");
if ((seed_bn = BN_CTX_get(ctx)) == NULL)
errx(1, "seed_bn = BN_CTX_get()");
if ((w = BN_CTX_get(ctx)) == NULL)
errx(1, "w = BN_CTX_get()");
if ((seed = EC_GROUP_get0_seed(group)) == NULL)
goto done;
seed_len = EC_GROUP_get_seed_len(group);
if (seed_len != SHA_DIGEST_LENGTH) {
fprintf(stderr, "%s FAIL: unexpected seed length. "
"want %d, got %zu\n", __func__, SHA_DIGEST_LENGTH, seed_len);
goto err;
}
g = 8 * seed_len;
if (BN_bin2bn(seed, seed_len, seed_bn) == NULL)
errx(1, "BN_bin2bn");
if (!EC_GROUP_get_curve(group, p, a, b, ctx))
errx(1, "EC_GROUP_get_curve");
t = BN_num_bits(p);
s = (t - 1) / 160;
h = t - 160 * s;
ec_group_sha1_bignum(r, seed_bn);
BN_zero(pow2);
if (!BN_set_bit(pow2, h - 1))
errx(1, "BN_set_bit");
if (!BN_mod(r, r, pow2, ctx))
errx(1, "BN_nnmod");
BN_zero(pow2);
if (!BN_set_bit(pow2, g))
errx(1, "BN_set_bit");
for (i = 0; i < s; i++) {
if (!BN_mod_add(seed_bn, seed_bn, BN_value_one(), pow2, ctx))
errx(1, "BN_mod_add");
ec_group_sha1_bignum(w, seed_bn);
if (!BN_lshift(r, r, 8 * SHA_DIGEST_LENGTH))
errx(1, "BN_lshift");
if (!BN_add(r, r, w))
errx(1, "BN_add");
}
if (!BN_mod_sqr(b, b, p, ctx))
errx(1, "BN_mod_sqr");
if (!BN_mod_mul(r, r, b, p, ctx))
errx(1, "BN_mod_mul");
if (!BN_mod_sqr(b, a, p, ctx))
errx(1, "BN_mod_sqr");
if (!BN_mod_mul(a, a, b, p, ctx))
errx(1, "BN_mod_mul");
if (BN_cmp(r, a) != 0) {
fprintf(stderr, "FAIL: %s verification failed for %s\nr * b^2:\t",
__func__, curve->comment);
BN_print_fp(stderr, r);
fprintf(stderr, "\na^3:\t\t");
BN_print_fp(stderr, a);
fprintf(stderr, "\n");
goto err;
}
done:
failed = 0;
err:
BN_CTX_end(ctx);
EC_GROUP_free(group);
return failed;
}
static int
ec_group_check_seeds(void)
{
BN_CTX *ctx = NULL;
EC_builtin_curve *all_curves = NULL;
size_t curve_id, ncurves;
int failed = 0;
if ((ctx = BN_CTX_new()) == NULL)
errx(1, "BN_CTX_new");
ncurves = EC_get_builtin_curves(NULL, 0);
if ((all_curves = calloc(ncurves, sizeof(*all_curves))) == NULL)
err(1, "calloc builtin curves");
EC_get_builtin_curves(all_curves, ncurves);
for (curve_id = 0; curve_id < ncurves; curve_id++)
failed |= ec_group_check_seed(&all_curves[curve_id], ctx);
free(all_curves);
BN_CTX_free(ctx);
return failed;
}
int
main(int argc, char **argv)
{
int failed = 0;
failed |= ec_group_pkparameters_named_curve_test();
failed |= ec_group_pkparameters_parameters_test();
failed |= ec_group_pkparameters_correct_padding_test();
failed |= ec_group_roundtrip_builtin_curves();
failed |= ec_group_non_builtin_curves();
failed |= ec_group_builtin_curves_have_prime_order();
failed |= ec_group_check_private_keys();
failed |= ec_group_check_seeds();
return failed;
}