1 /* $OpenBSD: ec_point_conversion.c,v 1.13 2023/04/26 09:31:12 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/bn.h> 24 #include <openssl/ec.h> 25 #include <openssl/objects.h> 26 27 int bn_rand_interval(BIGNUM *, const BIGNUM *, const BIGNUM *); 28 29 int forms[] = { 30 POINT_CONVERSION_COMPRESSED, 31 POINT_CONVERSION_UNCOMPRESSED, 32 POINT_CONVERSION_HYBRID, 33 }; 34 35 static const size_t N_FORMS = sizeof(forms) / sizeof(forms[0]); 36 #define N_RANDOM_POINTS 10 37 38 static const char * 39 form2str(int form) 40 { 41 switch (form) { 42 case POINT_CONVERSION_COMPRESSED: 43 return "compressed form"; 44 case POINT_CONVERSION_UNCOMPRESSED: 45 return "uncompressed form"; 46 case POINT_CONVERSION_HYBRID: 47 return "hybrid form"; 48 default: 49 return "unknown form"; 50 } 51 } 52 53 static void 54 hexdump(const unsigned char *buf, size_t len) 55 { 56 size_t i; 57 58 for (i = 1; i <= len; i++) 59 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); 60 61 if (len % 8) 62 fprintf(stderr, "\n"); 63 } 64 65 static int 66 roundtrip(EC_GROUP *group, EC_POINT *point, int form, BIGNUM *x, BIGNUM *y) 67 { 68 BIGNUM *x_out = NULL, *y_out = NULL; 69 size_t len; 70 uint8_t *buf = NULL; 71 int failed = 1; 72 73 if ((len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL)) == 0) 74 errx(1, "point2oct"); 75 if ((buf = malloc(len)) == NULL) 76 errx(1, "malloc"); 77 if (EC_POINT_point2oct(group, point, form, buf, len, NULL) != len) 78 errx(1, "point2oct"); 79 80 if (!EC_POINT_oct2point(group, point, buf, len, NULL)) 81 errx(1, "%s oct2point", form2str(form)); 82 83 if ((x_out = BN_new()) == NULL) 84 errx(1, "new x_out"); 85 if ((y_out = BN_new()) == NULL) 86 errx(1, "new y_out"); 87 88 if (!EC_POINT_get_affine_coordinates(group, point, x_out, y_out, NULL)) 89 errx(1, "get affine"); 90 91 if (BN_cmp(x, x_out) != 0) { 92 warnx("%s: x", form2str(form)); 93 goto err; 94 } 95 if (BN_cmp(y, y_out) != 0) { 96 warnx("%s: y", form2str(form)); 97 goto err; 98 } 99 100 failed = 0; 101 102 err: 103 if (failed) 104 hexdump(buf, len); 105 106 free(buf); 107 BN_free(x_out); 108 BN_free(y_out); 109 110 return failed; 111 } 112 113 /* XXX This only tests multiples of the generator for now... */ 114 static int 115 test_random_points_on_curve(EC_builtin_curve *curve) 116 { 117 EC_GROUP *group; 118 BIGNUM *order = NULL; 119 BIGNUM *random; 120 BIGNUM *x, *y; 121 size_t i, j; 122 int failed = 0; 123 124 if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL) 125 errx(1, "EC_GROUP_new_by_curve_name(%s)", 126 OBJ_nid2sn(curve->nid)); 127 128 if ((order = BN_new()) == NULL) 129 errx(1, "BN_new order"); 130 if ((random = BN_new()) == NULL) 131 errx(1, "BN_new random"); 132 if ((x = BN_new()) == NULL) 133 errx(1, "BN_new x"); 134 if ((y = BN_new()) == NULL) 135 errx(1, "BN_new y"); 136 137 if (!EC_GROUP_get_order(group, order, NULL)) 138 errx(1, "EC_group_get_order"); 139 140 for (i = 0; i < N_RANDOM_POINTS; i++) { 141 EC_POINT *random_point; 142 143 do { 144 if (!BN_rand_range(random, order)) 145 errx(1, "BN_rand_range"); 146 } while (BN_is_zero(random)); 147 148 if ((random_point = EC_POINT_new(group)) == NULL) 149 errx(1, "EC_POINT_new"); 150 151 if (!EC_POINT_mul(group, random_point, random, NULL, NULL, NULL)) 152 errx(1, "EC_POINT_mul"); 153 154 if (EC_POINT_is_at_infinity(group, random_point)) { 155 EC_POINT_free(random_point); 156 157 warnx("info: got infinity"); 158 fprintf(stderr, "random = "); 159 BN_print_fp(stderr, random); 160 fprintf(stderr, "\n"); 161 162 continue; 163 } 164 165 if (!EC_POINT_get_affine_coordinates(group, random_point, 166 x, y, NULL)) 167 errx(1, "EC_POINT_get_affine_coordinates"); 168 169 for (j = 0; j < N_FORMS; j++) 170 failed |= roundtrip(group, random_point, forms[j], x, y); 171 172 EC_POINT_free(random_point); 173 } 174 175 BN_free(order); 176 BN_free(random); 177 BN_free(x); 178 BN_free(y); 179 EC_GROUP_free(group); 180 181 return failed; 182 } 183 184 static int 185 test_random_points(void) 186 { 187 EC_builtin_curve *all_curves = NULL; 188 size_t ncurves = 0; 189 size_t curve_id; 190 int failed = 0; 191 192 ncurves = EC_get_builtin_curves(NULL, 0); 193 if ((all_curves = calloc(ncurves, sizeof(EC_builtin_curve))) == NULL) 194 err(1, "calloc builtin curves"); 195 EC_get_builtin_curves(all_curves, ncurves); 196 197 for (curve_id = 0; curve_id < ncurves; curve_id++) 198 failed |= test_random_points_on_curve(&all_curves[curve_id]); 199 200 fprintf(stderr, "%s %s\n", __func__, failed ? ": FAILED" : ""); 201 202 free(all_curves); 203 return failed; 204 } 205 206 static const struct point_conversion { 207 const char *description; 208 int nid; 209 uint8_t octets[256]; 210 uint8_t octets_len; 211 int valid; 212 } point_conversions[] = { 213 /* XXX - now that sect571 is no longer tested, add another test? */ 214 { 215 .description = "point at infinity on secp256r1", 216 .nid = NID_X9_62_prime256v1, 217 .octets = { 0x00 }, 218 .octets_len = 1, 219 .valid = 1, 220 }, 221 { 222 .description = "point at infinity on secp256r1 (flipped y_bit)", 223 .nid = NID_X9_62_prime256v1, 224 .octets = { 0x01 }, 225 .octets_len = 1, 226 .valid = 0, 227 }, 228 { 229 .description = "zero x compressed point on secp256r1", 230 .nid = NID_X9_62_prime256v1, 231 .octets = { 232 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 236 0x00, 237 }, 238 .octets_len = 33, 239 .valid = 1, 240 }, 241 { 242 .description = 243 "zero x compressed point on secp256r1 (flipped y_bit)", 244 .nid = NID_X9_62_prime256v1, 245 .octets = { 246 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 250 0x00, 251 }, 252 .octets_len = 33, 253 .valid = 1, 254 }, 255 { 256 .description = "generic compressed point on secp256r1", 257 .nid = NID_X9_62_prime256v1, 258 .octets = { 259 0x03, 0xa3, 0x96, 0xa0, 0x42, 0x73, 0x1a, 0x8b, 260 0x90, 0xd8, 0xcb, 0xae, 0xda, 0x1b, 0x23, 0x11, 261 0x77, 0x5f, 0x6a, 0x4c, 0xb4, 0x57, 0xbf, 0xe0, 262 0x65, 0xd4, 0x09, 0x11, 0x5f, 0x54, 0xe4, 0xee, 263 0xdd, 264 }, 265 .octets_len = 33, 266 .valid = 1, 267 }, 268 { 269 .description = 270 "generic compressed point on secp256r1 (flipped y_bit)", 271 .nid = NID_X9_62_prime256v1, 272 .octets = { 273 0x02, 0xa3, 0x96, 0xa0, 0x42, 0x73, 0x1a, 0x8b, 274 0x90, 0xd8, 0xcb, 0xae, 0xda, 0x1b, 0x23, 0x11, 275 0x77, 0x5f, 0x6a, 0x4c, 0xb4, 0x57, 0xbf, 0xe0, 276 0x65, 0xd4, 0x09, 0x11, 0x5f, 0x54, 0xe4, 0xee, 277 0xdd, 278 }, 279 .octets_len = 33, 280 .valid = 1, 281 }, 282 { 283 .description = "zero x uncompressed point #1 on secp256r1", 284 .nid = NID_X9_62_prime256v1, 285 .octets = { 286 0x04, 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, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83, 291 0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b, 292 0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87, 293 0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93, 294 0xf4, 295 }, 296 .octets_len = 65, 297 .valid = 1, 298 }, 299 { 300 .description = 301 "zero x uncompressed point #1 on secp256r1 (flipped y_bit)", 302 .nid = NID_X9_62_prime256v1, 303 .octets = { 304 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 308 0x00, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83, 309 0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b, 310 0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87, 311 0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93, 312 0xf4, 313 }, 314 .octets_len = 65, 315 .valid = 0, 316 }, 317 { 318 .description = "zero x uncompressed point #2 on secp256r1", 319 .nid = NID_X9_62_prime256v1, 320 .octets = { 321 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 325 0x00, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c, 326 0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94, 327 0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78, 328 0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c, 329 0x0b, 330 }, 331 .octets_len = 65, 332 .valid = 1, 333 }, 334 { 335 .description = 336 "zero x uncompressed point #2 on secp256r1 (flipped y_bit)", 337 .nid = NID_X9_62_prime256v1, 338 .octets = { 339 0x05, 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, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c, 344 0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94, 345 0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78, 346 0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c, 347 0x0b, 348 }, 349 .octets_len = 65, 350 .valid = 0, 351 }, 352 { 353 .description = "generic uncompressed point on secp256r1", 354 .nid = NID_X9_62_prime256v1, 355 .octets = { 356 0x04, 0x23, 0xe5, 0x85, 0xa5, 0x4b, 0xda, 0x34, 357 0x7e, 0xe5, 0x65, 0x53, 0x7f, 0x3b, 0xce, 0xe4, 358 0x54, 0xd8, 0xa4, 0x5a, 0x53, 0x4b, 0xb0, 0x4c, 359 0xb9, 0x31, 0x09, 0x29, 0xa2, 0x03, 0x4c, 0x73, 360 0x20, 0xd2, 0xc6, 0x17, 0xca, 0xe3, 0xcf, 0xc2, 361 0xd8, 0x31, 0xfe, 0xf1, 0x7c, 0x6f, 0x9d, 0x7a, 362 0x01, 0x7c, 0x34, 0x65, 0x42, 0x05, 0xaf, 0xcc, 363 0x04, 0xa3, 0x2f, 0x44, 0x14, 0xbe, 0xd8, 0xc2, 364 0x03, 365 }, 366 .octets_len = 65, 367 .valid = 1, 368 }, 369 { 370 .description = 371 "generic uncompressed point on secp256r1 (flipped y_bit)", 372 .nid = NID_X9_62_prime256v1, 373 .octets = { 374 0x05, 0x23, 0xe5, 0x85, 0xa5, 0x4b, 0xda, 0x34, 375 0x7e, 0xe5, 0x65, 0x53, 0x7f, 0x3b, 0xce, 0xe4, 376 0x54, 0xd8, 0xa4, 0x5a, 0x53, 0x4b, 0xb0, 0x4c, 377 0xb9, 0x31, 0x09, 0x29, 0xa2, 0x03, 0x4c, 0x73, 378 0x20, 0xd2, 0xc6, 0x17, 0xca, 0xe3, 0xcf, 0xc2, 379 0xd8, 0x31, 0xfe, 0xf1, 0x7c, 0x6f, 0x9d, 0x7a, 380 0x01, 0x7c, 0x34, 0x65, 0x42, 0x05, 0xaf, 0xcc, 381 0x04, 0xa3, 0x2f, 0x44, 0x14, 0xbe, 0xd8, 0xc2, 382 0x03, 383 }, 384 .octets_len = 65, 385 .valid = 0, 386 }, 387 { 388 .description = "zero x hybrid point #1 on secp256r1", 389 .nid = NID_X9_62_prime256v1, 390 .octets = { 391 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 395 0x00, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83, 396 0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b, 397 0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87, 398 0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93, 399 0xf4, 400 }, 401 .octets_len = 65, 402 .valid = 1, 403 }, 404 { 405 .description = 406 "zero x hybrid point #1 on secp256r1 (flipped y_bit)", 407 .nid = NID_X9_62_prime256v1, 408 .octets = { 409 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 413 0x00, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83, 414 0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b, 415 0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87, 416 0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93, 417 0xf4, 418 }, 419 .octets_len = 65, 420 .valid = 0, 421 }, 422 { 423 .description = "zero x hybrid point #2 on secp256r1", 424 .nid = NID_X9_62_prime256v1, 425 .octets = { 426 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 430 0x00, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c, 431 0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94, 432 0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78, 433 0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c, 434 0x0b, 435 }, 436 .octets_len = 65, 437 .valid = 1, 438 }, 439 { 440 .description = 441 "zero x hybrid point #2 on secp256r1 (flipped y_bit)", 442 .nid = NID_X9_62_prime256v1, 443 .octets = { 444 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 448 0x00, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c, 449 0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94, 450 0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78, 451 0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c, 452 0x0b, 453 }, 454 .octets_len = 65, 455 .valid = 0, 456 }, 457 { 458 .description = "generic hybrid point on secp256r1", 459 .nid = NID_X9_62_prime256v1, 460 .octets = { 461 0x07, 0x38, 0xb2, 0x98, 0x38, 0x21, 0x6b, 0xec, 462 0x87, 0xcf, 0x50, 0xbb, 0x65, 0x11, 0x96, 0x63, 463 0xf3, 0x90, 0x64, 0xc3, 0x5c, 0x59, 0xa5, 0x6f, 464 0xaf, 0x56, 0x2a, 0x0c, 0xc0, 0x3a, 0x9b, 0x92, 465 0x85, 0x95, 0x54, 0xf3, 0x08, 0x0f, 0x78, 0x59, 466 0xa2, 0x44, 0x2f, 0x19, 0x5d, 0xd5, 0xcd, 0xf6, 467 0xa5, 0xbe, 0x2f, 0x83, 0x70, 0x94, 0xf5, 0xcd, 468 0x8c, 0x40, 0x7f, 0xd8, 0x97, 0x92, 0x14, 0xf7, 469 0xc5, 470 }, 471 .octets_len = 65, 472 .valid = 1, 473 }, 474 { 475 .description = 476 "generic hybrid point on secp256r1 (flipped y_bit)", 477 .nid = NID_X9_62_prime256v1, 478 .octets = { 479 0x06, 0x38, 0xb2, 0x98, 0x38, 0x21, 0x6b, 0xec, 480 0x87, 0xcf, 0x50, 0xbb, 0x65, 0x11, 0x96, 0x63, 481 0xf3, 0x90, 0x64, 0xc3, 0x5c, 0x59, 0xa5, 0x6f, 482 0xaf, 0x56, 0x2a, 0x0c, 0xc0, 0x3a, 0x9b, 0x92, 483 0x85, 0x95, 0x54, 0xf3, 0x08, 0x0f, 0x78, 0x59, 484 0xa2, 0x44, 0x2f, 0x19, 0x5d, 0xd5, 0xcd, 0xf6, 485 0xa5, 0xbe, 0x2f, 0x83, 0x70, 0x94, 0xf5, 0xcd, 486 0x8c, 0x40, 0x7f, 0xd8, 0x97, 0x92, 0x14, 0xf7, 487 0xc5, 488 }, 489 .octets_len = 65, 490 .valid = 0, 491 }, 492 }; 493 494 static const size_t N_POINT_CONVERSIONS = 495 sizeof(point_conversions) / sizeof(point_conversions[0]); 496 497 static int 498 point_conversion_form_y_bit(const struct point_conversion *test) 499 { 500 EC_GROUP *group = NULL; 501 EC_POINT *point = NULL; 502 int ret; 503 int failed = 0; 504 505 if ((group = EC_GROUP_new_by_curve_name(test->nid)) == NULL) 506 errx(1, "group"); 507 if ((point = EC_POINT_new(group)) == NULL) 508 errx(1, "point"); 509 510 ret = EC_POINT_oct2point(group, point, test->octets, test->octets_len, 511 NULL); 512 if (ret != test->valid) { 513 fprintf(stderr, "%s want %d got %d\n", test->description, 514 test->valid, ret); 515 failed |= 1; 516 } 517 518 EC_GROUP_free(group); 519 EC_POINT_free(point); 520 521 return failed; 522 } 523 524 static int 525 test_point_conversions(void) 526 { 527 size_t i; 528 int failed = 0; 529 530 for (i = 0; i < N_POINT_CONVERSIONS; i++) 531 failed |= point_conversion_form_y_bit(&point_conversions[i]); 532 533 fprintf(stderr, "%s %s\n", __func__, failed ? ": FAILED" : ""); 534 535 return failed; 536 } 537 538 int 539 main(int argc, char **argv) 540 { 541 int failed = 0; 542 543 failed |= test_random_points(); 544 failed |= test_point_conversions(); 545 546 return failed; 547 } 548