545 lines
15 KiB
C
545 lines
15 KiB
C
/* $OpenBSD: ec_point_conversion.c,v 1.14 2023/08/01 17:19:49 tb Exp $ */
|
|
/*
|
|
* Copyright (c) 2021 Theo Buehler <tb@openbsd.org>
|
|
* Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include <err.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <openssl/bn.h>
|
|
#include <openssl/ec.h>
|
|
#include <openssl/objects.h>
|
|
|
|
int forms[] = {
|
|
POINT_CONVERSION_COMPRESSED,
|
|
POINT_CONVERSION_UNCOMPRESSED,
|
|
POINT_CONVERSION_HYBRID,
|
|
};
|
|
|
|
static const size_t N_FORMS = sizeof(forms) / sizeof(forms[0]);
|
|
#define N_RANDOM_POINTS 10
|
|
|
|
static const char *
|
|
form2str(int form)
|
|
{
|
|
switch (form) {
|
|
case POINT_CONVERSION_COMPRESSED:
|
|
return "compressed form";
|
|
case POINT_CONVERSION_UNCOMPRESSED:
|
|
return "uncompressed form";
|
|
case POINT_CONVERSION_HYBRID:
|
|
return "hybrid form";
|
|
default:
|
|
return "unknown form";
|
|
}
|
|
}
|
|
|
|
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");
|
|
|
|
if (len % 8)
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
static int
|
|
roundtrip(EC_GROUP *group, EC_POINT *point, int form, BIGNUM *x, BIGNUM *y)
|
|
{
|
|
BIGNUM *x_out = NULL, *y_out = NULL;
|
|
size_t len;
|
|
uint8_t *buf = NULL;
|
|
int failed = 1;
|
|
|
|
if ((len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL)) == 0)
|
|
errx(1, "point2oct");
|
|
if ((buf = malloc(len)) == NULL)
|
|
errx(1, "malloc");
|
|
if (EC_POINT_point2oct(group, point, form, buf, len, NULL) != len)
|
|
errx(1, "point2oct");
|
|
|
|
if (!EC_POINT_oct2point(group, point, buf, len, NULL))
|
|
errx(1, "%s oct2point", form2str(form));
|
|
|
|
if ((x_out = BN_new()) == NULL)
|
|
errx(1, "new x_out");
|
|
if ((y_out = BN_new()) == NULL)
|
|
errx(1, "new y_out");
|
|
|
|
if (!EC_POINT_get_affine_coordinates(group, point, x_out, y_out, NULL))
|
|
errx(1, "get affine");
|
|
|
|
if (BN_cmp(x, x_out) != 0) {
|
|
warnx("%s: x", form2str(form));
|
|
goto err;
|
|
}
|
|
if (BN_cmp(y, y_out) != 0) {
|
|
warnx("%s: y", form2str(form));
|
|
goto err;
|
|
}
|
|
|
|
failed = 0;
|
|
|
|
err:
|
|
if (failed)
|
|
hexdump(buf, len);
|
|
|
|
free(buf);
|
|
BN_free(x_out);
|
|
BN_free(y_out);
|
|
|
|
return failed;
|
|
}
|
|
|
|
/* XXX This only tests multiples of the generator for now... */
|
|
static int
|
|
test_random_points_on_curve(EC_builtin_curve *curve)
|
|
{
|
|
EC_GROUP *group;
|
|
BIGNUM *order = NULL;
|
|
BIGNUM *random;
|
|
BIGNUM *x, *y;
|
|
size_t i, j;
|
|
int failed = 0;
|
|
|
|
if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL)
|
|
errx(1, "EC_GROUP_new_by_curve_name(%s)",
|
|
OBJ_nid2sn(curve->nid));
|
|
|
|
if ((order = BN_new()) == NULL)
|
|
errx(1, "BN_new order");
|
|
if ((random = BN_new()) == NULL)
|
|
errx(1, "BN_new random");
|
|
if ((x = BN_new()) == NULL)
|
|
errx(1, "BN_new x");
|
|
if ((y = BN_new()) == NULL)
|
|
errx(1, "BN_new y");
|
|
|
|
if (!EC_GROUP_get_order(group, order, NULL))
|
|
errx(1, "EC_group_get_order");
|
|
|
|
for (i = 0; i < N_RANDOM_POINTS; i++) {
|
|
EC_POINT *random_point;
|
|
|
|
do {
|
|
if (!BN_rand_range(random, order))
|
|
errx(1, "BN_rand_range");
|
|
} while (BN_is_zero(random));
|
|
|
|
if ((random_point = EC_POINT_new(group)) == NULL)
|
|
errx(1, "EC_POINT_new");
|
|
|
|
if (!EC_POINT_mul(group, random_point, random, NULL, NULL, NULL))
|
|
errx(1, "EC_POINT_mul");
|
|
|
|
if (EC_POINT_is_at_infinity(group, random_point)) {
|
|
EC_POINT_free(random_point);
|
|
|
|
warnx("info: got infinity");
|
|
fprintf(stderr, "random = ");
|
|
BN_print_fp(stderr, random);
|
|
fprintf(stderr, "\n");
|
|
|
|
continue;
|
|
}
|
|
|
|
if (!EC_POINT_get_affine_coordinates(group, random_point,
|
|
x, y, NULL))
|
|
errx(1, "EC_POINT_get_affine_coordinates");
|
|
|
|
for (j = 0; j < N_FORMS; j++)
|
|
failed |= roundtrip(group, random_point, forms[j], x, y);
|
|
|
|
EC_POINT_free(random_point);
|
|
}
|
|
|
|
BN_free(order);
|
|
BN_free(random);
|
|
BN_free(x);
|
|
BN_free(y);
|
|
EC_GROUP_free(group);
|
|
|
|
return failed;
|
|
}
|
|
|
|
static int
|
|
test_random_points(void)
|
|
{
|
|
EC_builtin_curve *all_curves = NULL;
|
|
size_t ncurves = 0;
|
|
size_t curve_id;
|
|
int failed = 0;
|
|
|
|
ncurves = EC_get_builtin_curves(NULL, 0);
|
|
if ((all_curves = calloc(ncurves, sizeof(EC_builtin_curve))) == NULL)
|
|
err(1, "calloc builtin curves");
|
|
EC_get_builtin_curves(all_curves, ncurves);
|
|
|
|
for (curve_id = 0; curve_id < ncurves; curve_id++)
|
|
failed |= test_random_points_on_curve(&all_curves[curve_id]);
|
|
|
|
fprintf(stderr, "%s %s\n", __func__, failed ? ": FAILED" : "");
|
|
|
|
free(all_curves);
|
|
return failed;
|
|
}
|
|
|
|
static const struct point_conversion {
|
|
const char *description;
|
|
int nid;
|
|
uint8_t octets[256];
|
|
uint8_t octets_len;
|
|
int valid;
|
|
} point_conversions[] = {
|
|
/* XXX - now that sect571 is no longer tested, add another test? */
|
|
{
|
|
.description = "point at infinity on secp256r1",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = { 0x00 },
|
|
.octets_len = 1,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description = "point at infinity on secp256r1 (flipped y_bit)",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = { 0x01 },
|
|
.octets_len = 1,
|
|
.valid = 0,
|
|
},
|
|
{
|
|
.description = "zero x compressed point on secp256r1",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x02, 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,
|
|
},
|
|
.octets_len = 33,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description =
|
|
"zero x compressed point on secp256r1 (flipped y_bit)",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x03, 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,
|
|
},
|
|
.octets_len = 33,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description = "generic compressed point on secp256r1",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x03, 0xa3, 0x96, 0xa0, 0x42, 0x73, 0x1a, 0x8b,
|
|
0x90, 0xd8, 0xcb, 0xae, 0xda, 0x1b, 0x23, 0x11,
|
|
0x77, 0x5f, 0x6a, 0x4c, 0xb4, 0x57, 0xbf, 0xe0,
|
|
0x65, 0xd4, 0x09, 0x11, 0x5f, 0x54, 0xe4, 0xee,
|
|
0xdd,
|
|
},
|
|
.octets_len = 33,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description =
|
|
"generic compressed point on secp256r1 (flipped y_bit)",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x02, 0xa3, 0x96, 0xa0, 0x42, 0x73, 0x1a, 0x8b,
|
|
0x90, 0xd8, 0xcb, 0xae, 0xda, 0x1b, 0x23, 0x11,
|
|
0x77, 0x5f, 0x6a, 0x4c, 0xb4, 0x57, 0xbf, 0xe0,
|
|
0x65, 0xd4, 0x09, 0x11, 0x5f, 0x54, 0xe4, 0xee,
|
|
0xdd,
|
|
},
|
|
.octets_len = 33,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description = "zero x uncompressed point #1 on secp256r1",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x04, 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, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83,
|
|
0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b,
|
|
0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87,
|
|
0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93,
|
|
0xf4,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description =
|
|
"zero x uncompressed point #1 on secp256r1 (flipped y_bit)",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x05, 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, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83,
|
|
0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b,
|
|
0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87,
|
|
0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93,
|
|
0xf4,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 0,
|
|
},
|
|
{
|
|
.description = "zero x uncompressed point #2 on secp256r1",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x04, 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, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c,
|
|
0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94,
|
|
0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78,
|
|
0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c,
|
|
0x0b,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description =
|
|
"zero x uncompressed point #2 on secp256r1 (flipped y_bit)",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x05, 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, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c,
|
|
0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94,
|
|
0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78,
|
|
0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c,
|
|
0x0b,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 0,
|
|
},
|
|
{
|
|
.description = "generic uncompressed point on secp256r1",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x04, 0x23, 0xe5, 0x85, 0xa5, 0x4b, 0xda, 0x34,
|
|
0x7e, 0xe5, 0x65, 0x53, 0x7f, 0x3b, 0xce, 0xe4,
|
|
0x54, 0xd8, 0xa4, 0x5a, 0x53, 0x4b, 0xb0, 0x4c,
|
|
0xb9, 0x31, 0x09, 0x29, 0xa2, 0x03, 0x4c, 0x73,
|
|
0x20, 0xd2, 0xc6, 0x17, 0xca, 0xe3, 0xcf, 0xc2,
|
|
0xd8, 0x31, 0xfe, 0xf1, 0x7c, 0x6f, 0x9d, 0x7a,
|
|
0x01, 0x7c, 0x34, 0x65, 0x42, 0x05, 0xaf, 0xcc,
|
|
0x04, 0xa3, 0x2f, 0x44, 0x14, 0xbe, 0xd8, 0xc2,
|
|
0x03,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description =
|
|
"generic uncompressed point on secp256r1 (flipped y_bit)",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x05, 0x23, 0xe5, 0x85, 0xa5, 0x4b, 0xda, 0x34,
|
|
0x7e, 0xe5, 0x65, 0x53, 0x7f, 0x3b, 0xce, 0xe4,
|
|
0x54, 0xd8, 0xa4, 0x5a, 0x53, 0x4b, 0xb0, 0x4c,
|
|
0xb9, 0x31, 0x09, 0x29, 0xa2, 0x03, 0x4c, 0x73,
|
|
0x20, 0xd2, 0xc6, 0x17, 0xca, 0xe3, 0xcf, 0xc2,
|
|
0xd8, 0x31, 0xfe, 0xf1, 0x7c, 0x6f, 0x9d, 0x7a,
|
|
0x01, 0x7c, 0x34, 0x65, 0x42, 0x05, 0xaf, 0xcc,
|
|
0x04, 0xa3, 0x2f, 0x44, 0x14, 0xbe, 0xd8, 0xc2,
|
|
0x03,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 0,
|
|
},
|
|
{
|
|
.description = "zero x hybrid point #1 on secp256r1",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x06, 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, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83,
|
|
0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b,
|
|
0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87,
|
|
0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93,
|
|
0xf4,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description =
|
|
"zero x hybrid point #1 on secp256r1 (flipped y_bit)",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x07, 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, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83,
|
|
0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b,
|
|
0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87,
|
|
0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93,
|
|
0xf4,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 0,
|
|
},
|
|
{
|
|
.description = "zero x hybrid point #2 on secp256r1",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x07, 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, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c,
|
|
0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94,
|
|
0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78,
|
|
0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c,
|
|
0x0b,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description =
|
|
"zero x hybrid point #2 on secp256r1 (flipped y_bit)",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x06, 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, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c,
|
|
0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94,
|
|
0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78,
|
|
0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c,
|
|
0x0b,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 0,
|
|
},
|
|
{
|
|
.description = "generic hybrid point on secp256r1",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x07, 0x38, 0xb2, 0x98, 0x38, 0x21, 0x6b, 0xec,
|
|
0x87, 0xcf, 0x50, 0xbb, 0x65, 0x11, 0x96, 0x63,
|
|
0xf3, 0x90, 0x64, 0xc3, 0x5c, 0x59, 0xa5, 0x6f,
|
|
0xaf, 0x56, 0x2a, 0x0c, 0xc0, 0x3a, 0x9b, 0x92,
|
|
0x85, 0x95, 0x54, 0xf3, 0x08, 0x0f, 0x78, 0x59,
|
|
0xa2, 0x44, 0x2f, 0x19, 0x5d, 0xd5, 0xcd, 0xf6,
|
|
0xa5, 0xbe, 0x2f, 0x83, 0x70, 0x94, 0xf5, 0xcd,
|
|
0x8c, 0x40, 0x7f, 0xd8, 0x97, 0x92, 0x14, 0xf7,
|
|
0xc5,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 1,
|
|
},
|
|
{
|
|
.description =
|
|
"generic hybrid point on secp256r1 (flipped y_bit)",
|
|
.nid = NID_X9_62_prime256v1,
|
|
.octets = {
|
|
0x06, 0x38, 0xb2, 0x98, 0x38, 0x21, 0x6b, 0xec,
|
|
0x87, 0xcf, 0x50, 0xbb, 0x65, 0x11, 0x96, 0x63,
|
|
0xf3, 0x90, 0x64, 0xc3, 0x5c, 0x59, 0xa5, 0x6f,
|
|
0xaf, 0x56, 0x2a, 0x0c, 0xc0, 0x3a, 0x9b, 0x92,
|
|
0x85, 0x95, 0x54, 0xf3, 0x08, 0x0f, 0x78, 0x59,
|
|
0xa2, 0x44, 0x2f, 0x19, 0x5d, 0xd5, 0xcd, 0xf6,
|
|
0xa5, 0xbe, 0x2f, 0x83, 0x70, 0x94, 0xf5, 0xcd,
|
|
0x8c, 0x40, 0x7f, 0xd8, 0x97, 0x92, 0x14, 0xf7,
|
|
0xc5,
|
|
},
|
|
.octets_len = 65,
|
|
.valid = 0,
|
|
},
|
|
};
|
|
|
|
static const size_t N_POINT_CONVERSIONS =
|
|
sizeof(point_conversions) / sizeof(point_conversions[0]);
|
|
|
|
static int
|
|
point_conversion_form_y_bit(const struct point_conversion *test)
|
|
{
|
|
EC_GROUP *group = NULL;
|
|
EC_POINT *point = NULL;
|
|
int ret;
|
|
int failed = 0;
|
|
|
|
if ((group = EC_GROUP_new_by_curve_name(test->nid)) == NULL)
|
|
errx(1, "group");
|
|
if ((point = EC_POINT_new(group)) == NULL)
|
|
errx(1, "point");
|
|
|
|
ret = EC_POINT_oct2point(group, point, test->octets, test->octets_len,
|
|
NULL);
|
|
if (ret != test->valid) {
|
|
fprintf(stderr, "%s want %d got %d\n", test->description,
|
|
test->valid, ret);
|
|
failed |= 1;
|
|
}
|
|
|
|
EC_GROUP_free(group);
|
|
EC_POINT_free(point);
|
|
|
|
return failed;
|
|
}
|
|
|
|
static int
|
|
test_point_conversions(void)
|
|
{
|
|
size_t i;
|
|
int failed = 0;
|
|
|
|
for (i = 0; i < N_POINT_CONVERSIONS; i++)
|
|
failed |= point_conversion_form_y_bit(&point_conversions[i]);
|
|
|
|
fprintf(stderr, "%s %s\n", __func__, failed ? ": FAILED" : "");
|
|
|
|
return failed;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int failed = 0;
|
|
|
|
failed |= test_random_points();
|
|
failed |= test_point_conversions();
|
|
|
|
return failed;
|
|
}
|