xref: /openbsd-src/regress/lib/libcrypto/ec/ec_point_conversion.c (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
1 /*	$OpenBSD: ec_point_conversion.c,v 1.5 2021/05/03 14:51:47 tb Exp $ */
2 /*
3  * Copyright (c) 2021 Theo Buehler <tb@openbsd.org>
4  * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <err.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 
23 #include <openssl/ec.h>
24 #include <openssl/objects.h>
25 
26 int bn_rand_interval(BIGNUM *, const BIGNUM *, const BIGNUM *);
27 
28 int forms[] = {
29 	POINT_CONVERSION_COMPRESSED,
30 	POINT_CONVERSION_UNCOMPRESSED,
31 	POINT_CONVERSION_HYBRID,
32 };
33 
34 static const size_t N_FORMS = sizeof(forms) / sizeof(forms[0]);
35 #define N_RANDOM_POINTS 10
36 
37 static const char *
38 form2str(int form)
39 {
40 	switch (form) {
41 	case POINT_CONVERSION_COMPRESSED:
42 		return "compressed form";
43 	case POINT_CONVERSION_UNCOMPRESSED:
44 		return "uncompressed form";
45 	case POINT_CONVERSION_HYBRID:
46 		return "hybrid form";
47 	default:
48 		return "unknown form";
49 	}
50 }
51 
52 static void
53 hexdump(const unsigned char *buf, size_t len)
54 {
55 	size_t i;
56 
57 	for (i = 1; i <= len; i++)
58 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
59 
60 	if (len % 8)
61 		fprintf(stderr, "\n");
62 }
63 
64 static int
65 roundtrip(EC_GROUP *group, EC_POINT *point, int form, BIGNUM *x, BIGNUM *y)
66 {
67 	BIGNUM *x_out = NULL, *y_out = NULL;
68 	size_t len;
69 	uint8_t *buf = NULL;
70 	int failed = 1;
71 
72 	if ((len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL)) == 0)
73 		errx(1, "point2oct");
74 	if ((buf = malloc(len)) == NULL)
75 		errx(1, "malloc");
76 	if (EC_POINT_point2oct(group, point, form, buf, len, NULL) != len)
77 		errx(1, "point2oct");
78 
79 	if (!EC_POINT_oct2point(group, point, buf, len, NULL))
80 		errx(1, "%s oct2point", form2str(form));
81 
82 	if ((x_out = BN_new()) == NULL)
83 		errx(1, "new x_out");
84 	if ((y_out = BN_new()) == NULL)
85 		errx(1, "new y_out");
86 
87 	if (!EC_POINT_get_affine_coordinates(group, point, x_out, y_out, NULL))
88 		errx(1, "get affine");
89 
90 	if (BN_cmp(x, x_out) != 0) {
91 		warnx("%s: x", form2str(form));
92 		goto err;
93 	}
94 	if (BN_cmp(y, y_out) != 0) {
95 		warnx("%s: y", form2str(form));
96 		goto err;
97 	}
98 
99 	failed = 0;
100 
101  err:
102 	if (failed)
103 		hexdump(buf, len);
104 
105 	free(buf);
106 	BN_free(x_out);
107 	BN_free(y_out);
108 
109 	return failed;
110 }
111 
112 static int
113 test_hybrid_corner_case(void)
114 {
115 	BIGNUM *x = NULL, *y = NULL;
116 	EC_GROUP *group;
117 	EC_POINT *point;
118 	size_t i;
119 	int failed = 0;
120 
121 	if (!BN_hex2bn(&x, "0"))
122 		errx(1, "BN_hex2bn x");
123 	if (!BN_hex2bn(&y, "01"))
124 		errx(1, "BN_hex2bn y");
125 
126 	if ((group = EC_GROUP_new_by_curve_name(NID_sect571k1)) == NULL)
127 		errx(1, "group");
128 	if ((point = EC_POINT_new(group)) == NULL)
129 		errx(1, "point");
130 
131 	if (!EC_POINT_set_affine_coordinates(group, point, x, y, NULL))
132 		errx(1, "set affine");
133 
134 	for (i = 0; i < N_FORMS; i++)
135 		failed |= roundtrip(group, point, forms[i], x, y);
136 
137 	fprintf(stderr, "%s: %s\n", __func__, failed ? "FAILED" : "SUCCESS");
138 
139 	EC_GROUP_free(group);
140 	EC_POINT_free(point);
141 	BN_free(x);
142 	BN_free(y);
143 
144 	return failed;
145 }
146 
147 /* XXX This only tests multiples of the generator for now... */
148 static int
149 test_random_points_on_curve(EC_builtin_curve *curve)
150 {
151 	EC_GROUP *group;
152 	BIGNUM *order = NULL;
153 	BIGNUM *random;
154 	BIGNUM *x, *y;
155 	size_t i, j;
156 	int failed = 0;
157 
158 	fprintf(stderr, "%s\n", OBJ_nid2sn(curve->nid));
159 	if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL)
160 		errx(1, "EC_GROUP_new_by_curve_name");
161 
162 	if ((order = BN_new()) == NULL)
163 		errx(1, "BN_new order");
164 	if ((random = BN_new()) == NULL)
165 		errx(1, "BN_new random");
166 	if ((x = BN_new()) == NULL)
167 		errx(1, "BN_new x");
168 	if ((y = BN_new()) == NULL)
169 		errx(1, "BN_new y");
170 
171 	if (!EC_GROUP_get_order(group, order, NULL))
172 		errx(1, "EC_group_get_order");
173 
174 	for (i = 0; i < N_RANDOM_POINTS; i++) {
175 		EC_POINT *random_point;
176 
177 		if (!bn_rand_interval(random, BN_value_one(), order))
178 			errx(1, "bn_rand_interval");
179 
180 		if ((random_point = EC_POINT_new(group)) == NULL)
181 			errx(1, "EC_POINT_new");
182 
183 		if (!EC_POINT_mul(group, random_point, random, NULL, NULL, NULL))
184 			errx(1, "EC_POINT_mul");
185 
186 		if (EC_POINT_is_at_infinity(group, random_point)) {
187 			EC_POINT_free(random_point);
188 
189 			warnx("info: got infinity");
190 			fprintf(stderr, "random = ");
191 			BN_print_fp(stderr, random);
192 			fprintf(stderr, "\n");
193 
194 			continue;
195 		}
196 
197 		if (!EC_POINT_get_affine_coordinates(group, random_point,
198 		    x, y, NULL))
199 			errx(1, "EC_POINT_get_affine_coordinates");
200 
201 		for (j = 0; j < N_FORMS; j++)
202 			failed |= roundtrip(group, random_point, forms[j], x, y);
203 
204 		EC_POINT_free(random_point);
205 	}
206 
207 	BN_free(order);
208 	BN_free(random);
209 	BN_free(x);
210 	BN_free(y);
211 	EC_GROUP_free(group);
212 
213 	return failed;
214 }
215 
216 static int
217 test_random_points(void)
218 {
219 	EC_builtin_curve *all_curves = NULL;
220 	size_t ncurves = 0;
221 	size_t curve_id;
222 	int failed = 0;
223 
224 	ncurves = EC_get_builtin_curves(NULL, 0);
225 	if ((all_curves = calloc(ncurves, sizeof(EC_builtin_curve))) == NULL)
226 		err(1, "calloc builtin curves");
227 	EC_get_builtin_curves(all_curves, ncurves);
228 
229 	for (curve_id = 0; curve_id < ncurves; curve_id++)
230 		test_random_points_on_curve(&all_curves[curve_id]);
231 
232 	fprintf(stderr, "%s: %s\n", __func__, failed ? "FAILED" : "SUCCESS");
233 
234 	free(all_curves);
235 	return failed;
236 }
237 
238 static const struct point_conversion {
239 	const char *description;
240 	int nid;
241 	uint8_t octets[256];
242 	uint8_t octets_len;
243 	int valid;
244 } point_conversions[] = {
245 	{
246 		.description = "point at infinity on sect571k1",
247 		.nid = NID_sect571k1,
248 		.octets = { 0x00 },
249 		.octets_len = 1,
250 		.valid = 1,
251 	},
252 	{
253 		.description = "point at infinity on sect571k1 (flipped y_bit)",
254 		.nid = NID_sect571k1,
255 		.octets = { 0x01 },
256 		.octets_len = 1,
257 		.valid = 0,
258 	},
259 	{
260 		.description = "zero x compressed point on sect571k1",
261 		.nid = NID_sect571k1,
262 		.octets = {
263 			0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 			0x00,
273 		},
274 		.octets_len = 73,
275 		.valid = 1,
276 	},
277 	{
278 		.description =
279 		    "zero x compressed point on sect571k1 (flipped y_bit)",
280 		.nid = NID_sect571k1,
281 		.octets = {
282 			0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 			0x00,
292 		},
293 		.octets_len = 73,
294 		.valid = 0,
295 	},
296 	{
297 		.description = "generic compressed point on sect571k1",
298 		.nid = NID_sect571k1,
299 		.octets = {
300 			0x02, 0x00, 0x5e, 0x33, 0x9f, 0xd6, 0xf1, 0xae,
301 			0x10, 0xbd, 0x48, 0xcf, 0xf1, 0x0d, 0x8e, 0x0e,
302 			0xd7, 0x83, 0xce, 0xf0, 0x3d, 0x14, 0x06, 0x41,
303 			0x29, 0x7d, 0x7e, 0xa3, 0x01, 0xf4, 0x9b, 0xa2,
304 			0x8c, 0xa6, 0xab, 0x24, 0xa0, 0x9e, 0xfd, 0xc4,
305 			0x2d, 0xc2, 0x95, 0xb4, 0xf9, 0xd4, 0xf4, 0x97,
306 			0x53, 0x5d, 0xe9, 0xe3, 0x47, 0xc3, 0xa8, 0x6b,
307 			0xbb, 0x27, 0x74, 0x6b, 0xfb, 0x26, 0xca, 0x96,
308 			0x76, 0x5b, 0x36, 0xe8, 0x87, 0xb5, 0xc5, 0x6a,
309 			0xc5,
310 		},
311 		.octets_len = 73,
312 		.valid = 1,
313 	},
314 	{
315 		.description =
316 		    "generic compressed point on sect571k1 (flipped y_bit)",
317 		.nid = NID_sect571k1,
318 		.octets = {
319 			0x03, 0x00, 0x5e, 0x33, 0x9f, 0xd6, 0xf1, 0xae,
320 			0x10, 0xbd, 0x48, 0xcf, 0xf1, 0x0d, 0x8e, 0x0e,
321 			0xd7, 0x83, 0xce, 0xf0, 0x3d, 0x14, 0x06, 0x41,
322 			0x29, 0x7d, 0x7e, 0xa3, 0x01, 0xf4, 0x9b, 0xa2,
323 			0x8c, 0xa6, 0xab, 0x24, 0xa0, 0x9e, 0xfd, 0xc4,
324 			0x2d, 0xc2, 0x95, 0xb4, 0xf9, 0xd4, 0xf4, 0x97,
325 			0x53, 0x5d, 0xe9, 0xe3, 0x47, 0xc3, 0xa8, 0x6b,
326 			0xbb, 0x27, 0x74, 0x6b, 0xfb, 0x26, 0xca, 0x96,
327 			0x76, 0x5b, 0x36, 0xe8, 0x87, 0xb5, 0xc5, 0x6a,
328 			0xc5,
329 		},
330 		.octets_len = 73,
331 		.valid = 1,
332 	},
333 	{
334 		.description = "zero x uncompressed point on sect571k1",
335 		.nid = NID_sect571k1,
336 		.octets = {
337 			0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
342 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 			0x01,
356 		},
357 		.octets_len = 145,
358 		.valid = 1,
359 	},
360 	{
361 		.description = "zero x uncompressed point on sect571k1",
362 		.nid = NID_sect571k1,
363 		.octets = {
364 			0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 			0x01,
383 		},
384 		.octets_len = 145,
385 		.valid = 0,
386 	},
387 	{
388 		.description = "generic uncompressed point on sect571k1",
389 		.nid = NID_sect571k1,
390 		.octets = {
391 			0x04, 0x02, 0x2d, 0xf4, 0x72, 0x38, 0xc2, 0xbe,
392 			0x0d, 0xa4, 0xf1, 0xfc, 0xe8, 0x78, 0xe6, 0xad,
393 			0x5c, 0xaa, 0xd9, 0x7f, 0x7c, 0xa9, 0x4c, 0xe4,
394 			0xd2, 0xae, 0xba, 0xaa, 0x8c, 0x9d, 0x4c, 0xac,
395 			0x85, 0x00, 0xe1, 0xfa, 0x33, 0x73, 0x51, 0x52,
396 			0x5a, 0x4e, 0x75, 0x67, 0x1d, 0x0a, 0x2a, 0xd2,
397 			0x38, 0xb2, 0x9b, 0xe8, 0xec, 0xbe, 0x07, 0x8b,
398 			0xc0, 0x95, 0x77, 0xe9, 0x55, 0x0c, 0x6c, 0x0e,
399 			0x02, 0x3b, 0x34, 0xe2, 0xa8, 0x29, 0xd2, 0x97,
400 			0xd9, 0x05, 0xa2, 0x6f, 0xa8, 0x6f, 0x1c, 0x3a,
401 			0xf6, 0x12, 0x42, 0x1a, 0x26, 0x6e, 0x87, 0xf3,
402 			0x19, 0x04, 0x20, 0xa5, 0x29, 0x78, 0xee, 0xcf,
403 			0x91, 0x06, 0xd2, 0x5a, 0x62, 0x2a, 0x7f, 0x1d,
404 			0xa0, 0x7b, 0xb4, 0x31, 0x9c, 0xd2, 0x14, 0x60,
405 			0xf5, 0x9b, 0xea, 0x4a, 0x41, 0xad, 0x47, 0x72,
406 			0xf9, 0x01, 0xed, 0x7f, 0x5a, 0x27, 0x64, 0xa2,
407 			0x53, 0x4e, 0x18, 0x51, 0x33, 0xa8, 0x1e, 0x3a,
408 			0xc2, 0xe7, 0x2c, 0xe3, 0x63, 0x6d, 0x06, 0x29,
409 			0x28,
410 		},
411 		.octets_len = 145,
412 		.valid = 1,
413 	},
414 	{
415 		.description =
416 		    "generic uncompressed point on sect571k1 (flipped y_bit)",
417 		.nid = NID_sect571k1,
418 		.octets = {
419 			0x05, 0x02, 0x2d, 0xf4, 0x72, 0x38, 0xc2, 0xbe,
420 			0x0d, 0xa4, 0xf1, 0xfc, 0xe8, 0x78, 0xe6, 0xad,
421 			0x5c, 0xaa, 0xd9, 0x7f, 0x7c, 0xa9, 0x4c, 0xe4,
422 			0xd2, 0xae, 0xba, 0xaa, 0x8c, 0x9d, 0x4c, 0xac,
423 			0x85, 0x00, 0xe1, 0xfa, 0x33, 0x73, 0x51, 0x52,
424 			0x5a, 0x4e, 0x75, 0x67, 0x1d, 0x0a, 0x2a, 0xd2,
425 			0x38, 0xb2, 0x9b, 0xe8, 0xec, 0xbe, 0x07, 0x8b,
426 			0xc0, 0x95, 0x77, 0xe9, 0x55, 0x0c, 0x6c, 0x0e,
427 			0x02, 0x3b, 0x34, 0xe2, 0xa8, 0x29, 0xd2, 0x97,
428 			0xd9, 0x05, 0xa2, 0x6f, 0xa8, 0x6f, 0x1c, 0x3a,
429 			0xf6, 0x12, 0x42, 0x1a, 0x26, 0x6e, 0x87, 0xf3,
430 			0x19, 0x04, 0x20, 0xa5, 0x29, 0x78, 0xee, 0xcf,
431 			0x91, 0x06, 0xd2, 0x5a, 0x62, 0x2a, 0x7f, 0x1d,
432 			0xa0, 0x7b, 0xb4, 0x31, 0x9c, 0xd2, 0x14, 0x60,
433 			0xf5, 0x9b, 0xea, 0x4a, 0x41, 0xad, 0x47, 0x72,
434 			0xf9, 0x01, 0xed, 0x7f, 0x5a, 0x27, 0x64, 0xa2,
435 			0x53, 0x4e, 0x18, 0x51, 0x33, 0xa8, 0x1e, 0x3a,
436 			0xc2, 0xe7, 0x2c, 0xe3, 0x63, 0x6d, 0x06, 0x29,
437 			0x28,
438 		},
439 		.octets_len = 145,
440 		.valid = 0,
441 	},
442 	{
443 		.description = "zero x hybrid point on sect571k1",
444 		.nid = NID_sect571k1,
445 		.octets = {
446 			0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 			0x01,
465 		},
466 		.octets_len = 145,
467 		.valid = 1,
468 	},
469 	{
470 		.description =
471 		    "zero x hybrid point on sect571k1 (flipped y_bit)",
472 		.nid = NID_sect571k1,
473 		.octets = {
474 			0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 			0x01,
493 		},
494 		.octets_len = 145,
495 		.valid = 0,
496 	},
497 	{
498 		.description = "generic hybrid point on sect571k1",
499 		.nid = NID_sect571k1,
500 		.octets = {
501 			0x07, 0x02, 0x2d, 0xf4, 0x72, 0x38, 0xc2, 0xbe,
502 			0x0d, 0xa4, 0xf1, 0xfc, 0xe8, 0x78, 0xe6, 0xad,
503 			0x5c, 0xaa, 0xd9, 0x7f, 0x7c, 0xa9, 0x4c, 0xe4,
504 			0xd2, 0xae, 0xba, 0xaa, 0x8c, 0x9d, 0x4c, 0xac,
505 			0x85, 0x00, 0xe1, 0xfa, 0x33, 0x73, 0x51, 0x52,
506 			0x5a, 0x4e, 0x75, 0x67, 0x1d, 0x0a, 0x2a, 0xd2,
507 			0x38, 0xb2, 0x9b, 0xe8, 0xec, 0xbe, 0x07, 0x8b,
508 			0xc0, 0x95, 0x77, 0xe9, 0x55, 0x0c, 0x6c, 0x0e,
509 			0x02, 0x3b, 0x34, 0xe2, 0xa8, 0x29, 0xd2, 0x97,
510 			0xd9, 0x05, 0xa2, 0x6f, 0xa8, 0x6f, 0x1c, 0x3a,
511 			0xf6, 0x12, 0x42, 0x1a, 0x26, 0x6e, 0x87, 0xf3,
512 			0x19, 0x04, 0x20, 0xa5, 0x29, 0x78, 0xee, 0xcf,
513 			0x91, 0x06, 0xd2, 0x5a, 0x62, 0x2a, 0x7f, 0x1d,
514 			0xa0, 0x7b, 0xb4, 0x31, 0x9c, 0xd2, 0x14, 0x60,
515 			0xf5, 0x9b, 0xea, 0x4a, 0x41, 0xad, 0x47, 0x72,
516 			0xf9, 0x01, 0xed, 0x7f, 0x5a, 0x27, 0x64, 0xa2,
517 			0x53, 0x4e, 0x18, 0x51, 0x33, 0xa8, 0x1e, 0x3a,
518 			0xc2, 0xe7, 0x2c, 0xe3, 0x63, 0x6d, 0x06, 0x29,
519 			0x28,
520 		},
521 		.octets_len = 145,
522 		.valid = 1,
523 	},
524 	{
525 		.description =
526 		    "generic hybrid point on sect571k1 (flipped y_bit)",
527 		.nid = NID_sect571k1,
528 		.octets = {
529 			0x06, 0x02, 0x2d, 0xf4, 0x72, 0x38, 0xc2, 0xbe,
530 			0x0d, 0xa4, 0xf1, 0xfc, 0xe8, 0x78, 0xe6, 0xad,
531 			0x5c, 0xaa, 0xd9, 0x7f, 0x7c, 0xa9, 0x4c, 0xe4,
532 			0xd2, 0xae, 0xba, 0xaa, 0x8c, 0x9d, 0x4c, 0xac,
533 			0x85, 0x00, 0xe1, 0xfa, 0x33, 0x73, 0x51, 0x52,
534 			0x5a, 0x4e, 0x75, 0x67, 0x1d, 0x0a, 0x2a, 0xd2,
535 			0x38, 0xb2, 0x9b, 0xe8, 0xec, 0xbe, 0x07, 0x8b,
536 			0xc0, 0x95, 0x77, 0xe9, 0x55, 0x0c, 0x6c, 0x0e,
537 			0x02, 0x3b, 0x34, 0xe2, 0xa8, 0x29, 0xd2, 0x97,
538 			0xd9, 0x05, 0xa2, 0x6f, 0xa8, 0x6f, 0x1c, 0x3a,
539 			0xf6, 0x12, 0x42, 0x1a, 0x26, 0x6e, 0x87, 0xf3,
540 			0x19, 0x04, 0x20, 0xa5, 0x29, 0x78, 0xee, 0xcf,
541 			0x91, 0x06, 0xd2, 0x5a, 0x62, 0x2a, 0x7f, 0x1d,
542 			0xa0, 0x7b, 0xb4, 0x31, 0x9c, 0xd2, 0x14, 0x60,
543 			0xf5, 0x9b, 0xea, 0x4a, 0x41, 0xad, 0x47, 0x72,
544 			0xf9, 0x01, 0xed, 0x7f, 0x5a, 0x27, 0x64, 0xa2,
545 			0x53, 0x4e, 0x18, 0x51, 0x33, 0xa8, 0x1e, 0x3a,
546 			0xc2, 0xe7, 0x2c, 0xe3, 0x63, 0x6d, 0x06, 0x29,
547 			0x28,
548 		},
549 		.octets_len = 145,
550 		.valid = 0,
551 	},
552 
553 	{
554 		.description = "point at infinity on secp256r1",
555 		.nid = NID_X9_62_prime256v1,
556 		.octets = { 0x00 },
557 		.octets_len = 1,
558 		.valid = 1,
559 	},
560 	{
561 		.description = "point at infinity on secp256r1 (flipped y_bit)",
562 		.nid = NID_X9_62_prime256v1,
563 		.octets = { 0x01 },
564 		.octets_len = 1,
565 		.valid = 0,
566 	},
567 	{
568 		.description = "zero x compressed point on secp256r1",
569 		.nid = NID_X9_62_prime256v1,
570 		.octets = {
571 			0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 			0x00,
576 		},
577 		.octets_len = 33,
578 		.valid = 1,
579 	},
580 	{
581 		.description =
582 		    "zero x compressed point on secp256r1 (flipped y_bit)",
583 		.nid = NID_X9_62_prime256v1,
584 		.octets = {
585 			0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 			0x00,
590 		},
591 		.octets_len = 33,
592 		.valid = 1,
593 	},
594 	{
595 		.description = "generic compressed point on secp256r1",
596 		.nid = NID_X9_62_prime256v1,
597 		.octets = {
598 			0x03, 0xa3, 0x96, 0xa0, 0x42, 0x73, 0x1a, 0x8b,
599 			0x90, 0xd8, 0xcb, 0xae, 0xda, 0x1b, 0x23, 0x11,
600 			0x77, 0x5f, 0x6a, 0x4c, 0xb4, 0x57, 0xbf, 0xe0,
601 			0x65, 0xd4, 0x09, 0x11, 0x5f, 0x54, 0xe4, 0xee,
602 			0xdd,
603 		},
604 		.octets_len = 33,
605 		.valid = 1,
606 	},
607 	{
608 		.description =
609 		    "generic compressed point on secp256r1 (flipped y_bit)",
610 		.nid = NID_X9_62_prime256v1,
611 		.octets = {
612 			0x02, 0xa3, 0x96, 0xa0, 0x42, 0x73, 0x1a, 0x8b,
613 			0x90, 0xd8, 0xcb, 0xae, 0xda, 0x1b, 0x23, 0x11,
614 			0x77, 0x5f, 0x6a, 0x4c, 0xb4, 0x57, 0xbf, 0xe0,
615 			0x65, 0xd4, 0x09, 0x11, 0x5f, 0x54, 0xe4, 0xee,
616 			0xdd,
617 		},
618 		.octets_len = 33,
619 		.valid = 1,
620 	},
621 	{
622 		.description = "zero x uncompressed point #1 on secp256r1",
623 		.nid = NID_X9_62_prime256v1,
624 		.octets = {
625 			0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 			0x00, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83,
630 			0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b,
631 			0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87,
632 			0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93,
633 			0xf4,
634 		},
635 		.octets_len = 65,
636 		.valid = 1,
637 	},
638 	{
639 		.description =
640 		    "zero x uncompressed point #1 on secp256r1 (flipped y_bit)",
641 		.nid = NID_X9_62_prime256v1,
642 		.octets = {
643 			0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 			0x00, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83,
648 			0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b,
649 			0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87,
650 			0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93,
651 			0xf4,
652 		},
653 		.octets_len = 65,
654 		.valid = 0,
655 	},
656 	{
657 		.description = "zero x uncompressed point #2 on secp256r1",
658 		.nid = NID_X9_62_prime256v1,
659 		.octets = {
660 			0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
664 			0x00, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c,
665 			0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94,
666 			0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78,
667 			0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c,
668 			0x0b,
669 		},
670 		.octets_len = 65,
671 		.valid = 1,
672 	},
673 	{
674 		.description =
675 		    "zero x uncompressed point #2 on secp256r1 (flipped y_bit)",
676 		.nid = NID_X9_62_prime256v1,
677 		.octets = {
678 			0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 			0x00, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c,
683 			0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94,
684 			0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78,
685 			0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c,
686 			0x0b,
687 		},
688 		.octets_len = 65,
689 		.valid = 0,
690 	},
691 	{
692 		.description = "generic uncompressed point on secp256r1",
693 		.nid = NID_X9_62_prime256v1,
694 		.octets = {
695 			0x04, 0x23, 0xe5, 0x85, 0xa5, 0x4b, 0xda, 0x34,
696 			0x7e, 0xe5, 0x65, 0x53, 0x7f, 0x3b, 0xce, 0xe4,
697 			0x54, 0xd8, 0xa4, 0x5a, 0x53, 0x4b, 0xb0, 0x4c,
698 			0xb9, 0x31, 0x09, 0x29, 0xa2, 0x03, 0x4c, 0x73,
699 			0x20, 0xd2, 0xc6, 0x17, 0xca, 0xe3, 0xcf, 0xc2,
700 			0xd8, 0x31, 0xfe, 0xf1, 0x7c, 0x6f, 0x9d, 0x7a,
701 			0x01, 0x7c, 0x34, 0x65, 0x42, 0x05, 0xaf, 0xcc,
702 			0x04, 0xa3, 0x2f, 0x44, 0x14, 0xbe, 0xd8, 0xc2,
703 			0x03,
704 		},
705 		.octets_len = 65,
706 		.valid = 1,
707 	},
708 	{
709 		.description =
710 		    "generic uncompressed point on secp256r1 (flipped y_bit)",
711 		.nid = NID_X9_62_prime256v1,
712 		.octets = {
713 			0x05, 0x23, 0xe5, 0x85, 0xa5, 0x4b, 0xda, 0x34,
714 			0x7e, 0xe5, 0x65, 0x53, 0x7f, 0x3b, 0xce, 0xe4,
715 			0x54, 0xd8, 0xa4, 0x5a, 0x53, 0x4b, 0xb0, 0x4c,
716 			0xb9, 0x31, 0x09, 0x29, 0xa2, 0x03, 0x4c, 0x73,
717 			0x20, 0xd2, 0xc6, 0x17, 0xca, 0xe3, 0xcf, 0xc2,
718 			0xd8, 0x31, 0xfe, 0xf1, 0x7c, 0x6f, 0x9d, 0x7a,
719 			0x01, 0x7c, 0x34, 0x65, 0x42, 0x05, 0xaf, 0xcc,
720 			0x04, 0xa3, 0x2f, 0x44, 0x14, 0xbe, 0xd8, 0xc2,
721 			0x03,
722 		},
723 		.octets_len = 65,
724 		.valid = 0,
725 	},
726 	{
727 		.description = "zero x hybrid point #1 on secp256r1",
728 		.nid = NID_X9_62_prime256v1,
729 		.octets = {
730 			0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
734 			0x00, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83,
735 			0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b,
736 			0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87,
737 			0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93,
738 			0xf4,
739 		},
740 		.octets_len = 65,
741 		.valid = 1,
742 	},
743 	{
744 		.description =
745 		    "zero x hybrid point #1 on secp256r1 (flipped y_bit)",
746 		.nid = NID_X9_62_prime256v1,
747 		.octets = {
748 			0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
751 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
752 			0x00, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83,
753 			0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b,
754 			0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87,
755 			0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93,
756 			0xf4,
757 		},
758 		.octets_len = 65,
759 		.valid = 0,
760 	},
761 	{
762 		.description = "zero x hybrid point #2 on secp256r1",
763 		.nid = NID_X9_62_prime256v1,
764 		.octets = {
765 			0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 			0x00, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c,
770 			0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94,
771 			0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78,
772 			0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c,
773 			0x0b,
774 		},
775 		.octets_len = 65,
776 		.valid = 1,
777 	},
778 	{
779 		.description =
780 		    "zero x hybrid point #2 on secp256r1 (flipped y_bit)",
781 		.nid = NID_X9_62_prime256v1,
782 		.octets = {
783 			0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
784 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
785 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787 			0x00, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c,
788 			0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94,
789 			0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78,
790 			0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c,
791 			0x0b,
792 		},
793 		.octets_len = 65,
794 		.valid = 0,
795 	},
796 	{
797 		.description = "generic hybrid point on secp256r1",
798 		.nid = NID_X9_62_prime256v1,
799 		.octets = {
800 			0x07, 0x38, 0xb2, 0x98, 0x38, 0x21, 0x6b, 0xec,
801 			0x87, 0xcf, 0x50, 0xbb, 0x65, 0x11, 0x96, 0x63,
802 			0xf3, 0x90, 0x64, 0xc3, 0x5c, 0x59, 0xa5, 0x6f,
803 			0xaf, 0x56, 0x2a, 0x0c, 0xc0, 0x3a, 0x9b, 0x92,
804 			0x85, 0x95, 0x54, 0xf3, 0x08, 0x0f, 0x78, 0x59,
805 			0xa2, 0x44, 0x2f, 0x19, 0x5d, 0xd5, 0xcd, 0xf6,
806 			0xa5, 0xbe, 0x2f, 0x83, 0x70, 0x94, 0xf5, 0xcd,
807 			0x8c, 0x40, 0x7f, 0xd8, 0x97, 0x92, 0x14, 0xf7,
808 			0xc5,
809 		},
810 		.octets_len = 65,
811 		.valid = 1,
812 	},
813 	{
814 		.description =
815 		    "generic hybrid point on secp256r1 (flipped y_bit)",
816 		.nid = NID_X9_62_prime256v1,
817 		.octets = {
818 			0x06, 0x38, 0xb2, 0x98, 0x38, 0x21, 0x6b, 0xec,
819 			0x87, 0xcf, 0x50, 0xbb, 0x65, 0x11, 0x96, 0x63,
820 			0xf3, 0x90, 0x64, 0xc3, 0x5c, 0x59, 0xa5, 0x6f,
821 			0xaf, 0x56, 0x2a, 0x0c, 0xc0, 0x3a, 0x9b, 0x92,
822 			0x85, 0x95, 0x54, 0xf3, 0x08, 0x0f, 0x78, 0x59,
823 			0xa2, 0x44, 0x2f, 0x19, 0x5d, 0xd5, 0xcd, 0xf6,
824 			0xa5, 0xbe, 0x2f, 0x83, 0x70, 0x94, 0xf5, 0xcd,
825 			0x8c, 0x40, 0x7f, 0xd8, 0x97, 0x92, 0x14, 0xf7,
826 			0xc5,
827 		},
828 		.octets_len = 65,
829 		.valid = 0,
830 	},
831 };
832 
833 static const size_t N_POINT_CONVERSIONS =
834     sizeof(point_conversions) / sizeof(point_conversions[0]);
835 
836 static int
837 point_conversion_form_y_bit(const struct point_conversion *test)
838 {
839 	EC_GROUP *group = NULL;
840 	EC_POINT *point = NULL;
841 	int ret;
842 	int failed = 0;
843 
844 	if ((group = EC_GROUP_new_by_curve_name(test->nid)) == NULL)
845 		errx(1, "group");
846 	if ((point = EC_POINT_new(group)) == NULL)
847 		errx(1, "point");
848 
849 	ret = EC_POINT_oct2point(group, point, test->octets, test->octets_len,
850 	    NULL);
851 	if (ret != test->valid) {
852 		fprintf(stderr, "%s want %d got %d\n", test->description,
853 		    test->valid, ret);
854 		failed |= 1;
855 	}
856 
857 	EC_GROUP_free(group);
858 	EC_POINT_free(point);
859 
860 	return failed;
861 }
862 
863 static int
864 test_point_conversions(void)
865 {
866 	size_t i;
867 	int failed = 0;
868 
869 	for (i = 0; i < N_POINT_CONVERSIONS; i++)
870 		failed |= point_conversion_form_y_bit(&point_conversions[i]);
871 
872 	fprintf(stderr, "%s: %s\n", __func__, failed ? "FAILED" : "SUCCESS");
873 
874 	return failed;
875 }
876 
877 int
878 main(int argc, char **argv)
879 {
880 	int failed = 0;
881 
882 	failed |= test_random_points();
883 	failed |= test_hybrid_corner_case();
884 	failed |= test_point_conversions();
885 
886 	fprintf(stderr, "%s\n", failed ? "FAILED" : "SUCCESS");
887 
888 	return failed;
889 }
890