diff options
author | tb <> | 2024-10-16 23:49:49 +0000 |
---|---|---|
committer | tb <> | 2024-10-16 23:49:49 +0000 |
commit | a48647b52107fb4841167823522dcefbc307b626 (patch) | |
tree | 0353297dc65d1ddcd3f53190018fc56507b90f65 /src | |
parent | 8831aa1eb95f59bd490da67b63d9e7cded4cedfc (diff) | |
download | openbsd-a48647b52107fb4841167823522dcefbc307b626.tar.gz openbsd-a48647b52107fb4841167823522dcefbc307b626.tar.bz2 openbsd-a48647b52107fb4841167823522dcefbc307b626.zip |
Implement Wei25519 to exercise some more elliptic curve code
This provides a non-trivial non-builtin curve that is unlikely to ever
become a builtin curve. This exercises the cofactor guessing code and
and ensures that things work as far as they can with a custom OID. The
main reason for adding it is to have a "real-world" example for an
upcoming check that EC parameters represent a builtin curve.
Diffstat (limited to 'src')
-rw-r--r-- | src/regress/lib/libcrypto/ec/ec_asn1_test.c | 285 |
1 files changed, 284 insertions, 1 deletions
diff --git a/src/regress/lib/libcrypto/ec/ec_asn1_test.c b/src/regress/lib/libcrypto/ec/ec_asn1_test.c index 467fd17bc8..cc0f0f46f4 100644 --- a/src/regress/lib/libcrypto/ec/ec_asn1_test.c +++ b/src/regress/lib/libcrypto/ec/ec_asn1_test.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ec_asn1_test.c,v 1.4 2024/10/14 13:16:06 tb Exp $ */ | 1 | /* $OpenBSD: ec_asn1_test.c,v 1.5 2024/10/16 23:49:49 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> |
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <openssl/bio.h> | 22 | #include <openssl/bio.h> |
23 | #include <openssl/ec.h> | 23 | #include <openssl/ec.h> |
24 | #include <openssl/err.h> | ||
24 | #include <openssl/objects.h> | 25 | #include <openssl/objects.h> |
25 | 26 | ||
26 | const uint8_t ec_secp256r1_pkparameters_named_curve[] = { | 27 | const uint8_t ec_secp256r1_pkparameters_named_curve[] = { |
@@ -339,6 +340,287 @@ ec_group_roundtrip_builtin_curves(void) | |||
339 | return failed; | 340 | return failed; |
340 | } | 341 | } |
341 | 342 | ||
343 | /* | ||
344 | * From draft-ietf-lwig-curve-representation-23, Appendix E.3 | ||
345 | */ | ||
346 | |||
347 | static const struct { | ||
348 | const char *oid; | ||
349 | const char *sn; | ||
350 | const char *ln; | ||
351 | const char *p; | ||
352 | const char *a; | ||
353 | const char *b; | ||
354 | const char *order; | ||
355 | const char *cofactor; | ||
356 | const char *x; | ||
357 | const char *y; | ||
358 | } wei25519 = { | ||
359 | .oid = "1.3.101.108", | ||
360 | .sn = "Wei25519", | ||
361 | .p = "7fffffff" "ffffffff" "ffffffff" "ffffffff" | ||
362 | "ffffffff" "ffffffff" "ffffffff" "ffffffed", | ||
363 | .a = "2aaaaaaa" "aaaaaaaa" "aaaaaaaa" "aaaaaaaa" | ||
364 | "aaaaaaaa" "aaaaaaaa" "aaaaaa98" "4914a144", | ||
365 | .b = "7b425ed0" "97b425ed" "097b425e" "d097b425" | ||
366 | "ed097b42" "5ed097b4" "260b5e9c" "7710c864", | ||
367 | .x = "2aaaaaaa" "aaaaaaaa" "aaaaaaaa" "aaaaaaaa" | ||
368 | "aaaaaaaa" "aaaaaaaa" "aaaaaaaa" "aaad245a", | ||
369 | .y = "20ae19a1" "b8a086b4" "e01edd2c" "7748d14c" | ||
370 | "923d4d7e" "6d7c61b2" "29e9c5a2" "7eced3d9", | ||
371 | .order = "10000000" "00000000" "00000000" "00000000" | ||
372 | "14def9de" "a2f79cd6" "5812631a" "5cf5d3ed", | ||
373 | .cofactor = "8", | ||
374 | }; | ||
375 | |||
376 | const uint8_t ec_wei25519_pkparameters_named_curve[] = { | ||
377 | 0x06, 0x03, 0x2b, 0x65, 0x6c, | ||
378 | }; | ||
379 | |||
380 | const uint8_t ec_wei25519_pkparameters_parameters[] = { | ||
381 | 0x30, 0x81, 0xde, 0x02, 0x01, 0x01, 0x30, 0x2b, | ||
382 | 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, | ||
383 | 0x01, 0x02, 0x20, 0x7f, 0xff, 0xff, 0xff, 0xff, | ||
384 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
385 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
386 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
387 | 0xff, 0xff, 0xed, 0x30, 0x44, 0x04, 0x20, 0x2a, | ||
388 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, | ||
389 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, | ||
390 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, | ||
391 | 0xaa, 0xaa, 0x98, 0x49, 0x14, 0xa1, 0x44, 0x04, | ||
392 | 0x20, 0x7b, 0x42, 0x5e, 0xd0, 0x97, 0xb4, 0x25, | ||
393 | 0xed, 0x09, 0x7b, 0x42, 0x5e, 0xd0, 0x97, 0xb4, | ||
394 | 0x25, 0xed, 0x09, 0x7b, 0x42, 0x5e, 0xd0, 0x97, | ||
395 | 0xb4, 0x26, 0x0b, 0x5e, 0x9c, 0x77, 0x10, 0xc8, | ||
396 | 0x64, 0x04, 0x41, 0x04, 0x2a, 0xaa, 0xaa, 0xaa, | ||
397 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, | ||
398 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, | ||
399 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, | ||
400 | 0xaa, 0xad, 0x24, 0x5a, 0x20, 0xae, 0x19, 0xa1, | ||
401 | 0xb8, 0xa0, 0x86, 0xb4, 0xe0, 0x1e, 0xdd, 0x2c, | ||
402 | 0x77, 0x48, 0xd1, 0x4c, 0x92, 0x3d, 0x4d, 0x7e, | ||
403 | 0x6d, 0x7c, 0x61, 0xb2, 0x29, 0xe9, 0xc5, 0xa2, | ||
404 | 0x7e, 0xce, 0xd3, 0xd9, 0x02, 0x20, 0x10, 0x00, | ||
405 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
406 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, | ||
407 | 0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6, 0x58, 0x12, | ||
408 | 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed, 0x02, 0x01, | ||
409 | 0x08, | ||
410 | }; | ||
411 | |||
412 | static int | ||
413 | ec_weierstrass25519(void) | ||
414 | { | ||
415 | EC_GROUP *group = NULL, *new_group = NULL; | ||
416 | EC_POINT *generator = NULL; | ||
417 | BN_CTX *ctx = NULL; | ||
418 | BIGNUM *p, *a, *b; | ||
419 | BIGNUM *order, *cofactor, *guessed_cofactor, *x, *y; | ||
420 | const unsigned char *pder; | ||
421 | unsigned char *der = NULL; | ||
422 | long error; | ||
423 | int der_len = 0; | ||
424 | int nid; | ||
425 | int failed = 1; | ||
426 | |||
427 | ERR_clear_error(); | ||
428 | if ((ctx = BN_CTX_new()) == NULL) | ||
429 | goto err; | ||
430 | BN_CTX_start(ctx); | ||
431 | |||
432 | if ((nid = OBJ_create(wei25519.oid, wei25519.sn, NULL)) == NID_undef) { | ||
433 | fprintf(stderr, "FAIL: %s OBJ_create(wei25519)\n", __func__); | ||
434 | goto err; | ||
435 | } | ||
436 | |||
437 | if ((p = BN_CTX_get(ctx)) == NULL) | ||
438 | errx(1, "BN_CTX_get"); | ||
439 | if ((a = BN_CTX_get(ctx)) == NULL) | ||
440 | errx(1, "BN_CTX_get"); | ||
441 | if ((b = BN_CTX_get(ctx)) == NULL) | ||
442 | errx(1, "BN_CTX_get"); | ||
443 | if ((order = BN_CTX_get(ctx)) == NULL) | ||
444 | errx(1, "BN_CTX_get"); | ||
445 | if ((cofactor = BN_CTX_get(ctx)) == NULL) | ||
446 | errx(1, "BN_CTX_get"); | ||
447 | if ((guessed_cofactor = BN_CTX_get(ctx)) == NULL) | ||
448 | errx(1, "BN_CTX_get"); | ||
449 | if ((x = BN_CTX_get(ctx)) == NULL) | ||
450 | errx(1, "BN_CTX_get"); | ||
451 | if ((y = BN_CTX_get(ctx)) == NULL) | ||
452 | errx(1, "BN_CTX_get"); | ||
453 | |||
454 | if (BN_hex2bn(&p, wei25519.p) == 0) | ||
455 | errx(1, "BN_hex2bn(p)"); | ||
456 | if (BN_hex2bn(&a, wei25519.a) == 0) | ||
457 | errx(1, "BN_hex2bn(a)"); | ||
458 | if (BN_hex2bn(&b, wei25519.b) == 0) | ||
459 | errx(1, "BN_hex2bn(b)"); | ||
460 | |||
461 | if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { | ||
462 | fprintf(stderr, "FAIL: %s EC_GROUP_new_curve_GFp", __func__); | ||
463 | goto err; | ||
464 | } | ||
465 | |||
466 | if (BN_hex2bn(&x, wei25519.x) == 0) | ||
467 | errx(1, "BN_hex2bn(x)"); | ||
468 | if (BN_hex2bn(&x, wei25519.x) == 0) | ||
469 | errx(1, "BN_hex2bn(x)"); | ||
470 | if (BN_hex2bn(&y, wei25519.y) == 0) | ||
471 | errx(1, "BN_hex2bn(y)"); | ||
472 | |||
473 | if ((generator = EC_POINT_new(group)) == NULL) | ||
474 | errx(1, "EC_POINT_new()"); | ||
475 | |||
476 | if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx)) { | ||
477 | fprintf(stderr, "FAIL: %s EC_POINT_set_affine_coordinates", __func__); | ||
478 | ERR_print_errors_fp(stderr); | ||
479 | goto err; | ||
480 | } | ||
481 | |||
482 | if (BN_hex2bn(&order, wei25519.order) == 0) | ||
483 | errx(1, "BN_hex2bn(order)"); | ||
484 | if (BN_hex2bn(&cofactor, wei25519.cofactor) == 0) | ||
485 | errx(1, "BN_hex2bn(cofactor)"); | ||
486 | |||
487 | /* Don't set cofactor to exercise the cofactor guessing code. */ | ||
488 | if (!EC_GROUP_set_generator(group, generator, order, NULL)) { | ||
489 | fprintf(stderr, "FAIL: %s EC_GROUP_set_generator\n", __func__); | ||
490 | ERR_print_errors_fp(stderr); | ||
491 | goto err; | ||
492 | } | ||
493 | |||
494 | if (!EC_GROUP_get_cofactor(group, guessed_cofactor, ctx)) { | ||
495 | fprintf(stderr, "FAIL: %s EC_GROUP_get_cofactor\n", __func__); | ||
496 | ERR_print_errors_fp(stderr); | ||
497 | goto err; | ||
498 | } | ||
499 | |||
500 | if (BN_cmp(cofactor, guessed_cofactor) != 0) { | ||
501 | fprintf(stderr, "FAIL: %s cofactor: want ", __func__); | ||
502 | BN_print_fp(stderr, cofactor); | ||
503 | fprintf(stderr, ", got "); | ||
504 | BN_print_fp(stderr, guessed_cofactor); | ||
505 | fprintf(stderr, "\n"); | ||
506 | goto err; | ||
507 | } | ||
508 | |||
509 | if (!EC_GROUP_check(group, ctx)) { | ||
510 | fprintf(stderr, "FAIL: %s EC_GROUP_check\n", __func__); | ||
511 | ERR_print_errors_fp(stderr); | ||
512 | goto err; | ||
513 | } | ||
514 | |||
515 | /* Explicit curve parameter encoding should work without NID set. */ | ||
516 | if (EC_GROUP_get_curve_name(group) != NID_undef) { | ||
517 | fprintf(stderr, "FAIL: %s unexpected curve name %d\n", __func__, | ||
518 | EC_GROUP_get_curve_name(group)); | ||
519 | ERR_print_errors_fp(stderr); | ||
520 | goto err; | ||
521 | } | ||
522 | |||
523 | EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE); | ||
524 | |||
525 | der = NULL; | ||
526 | if ((der_len = i2d_ECPKParameters(group, &der)) <= 0) { | ||
527 | fprintf(stderr, "FAIL: %s i2d_ECPKParameters (explicit)\n", __func__); | ||
528 | ERR_print_errors_fp(stderr); | ||
529 | goto err; | ||
530 | } | ||
531 | |||
532 | if (compare_data("Weierstrass 25519 explicit", der, der_len, | ||
533 | ec_wei25519_pkparameters_parameters, | ||
534 | sizeof(ec_wei25519_pkparameters_parameters)) == -1) | ||
535 | goto err; | ||
536 | |||
537 | freezero(der, der_len); | ||
538 | der = NULL; | ||
539 | |||
540 | EC_GROUP_set_curve_name(group, nid); | ||
541 | EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); | ||
542 | |||
543 | der = NULL; | ||
544 | if ((der_len = i2d_ECPKParameters(group, &der)) <= 0) { | ||
545 | fprintf(stderr, "FAIL: %s i2d_ECPKParameters (named)\n", __func__); | ||
546 | ERR_print_errors_fp(stderr); | ||
547 | goto err; | ||
548 | } | ||
549 | |||
550 | if (compare_data("Weierstrass 25519 named curve", der, der_len, | ||
551 | ec_wei25519_pkparameters_named_curve, | ||
552 | sizeof(ec_wei25519_pkparameters_named_curve)) == -1) | ||
553 | goto err; | ||
554 | |||
555 | freezero(der, der_len); | ||
556 | der = NULL; | ||
557 | |||
558 | /* At this point we should have no error on the stack. */ | ||
559 | if (ERR_peek_last_error() != 0) { | ||
560 | fprintf(stderr, "FAIL: %s unexpected error %lu\n", __func__, | ||
561 | ERR_peek_last_error()); | ||
562 | goto err; | ||
563 | } | ||
564 | |||
565 | pder = ec_wei25519_pkparameters_named_curve; | ||
566 | der_len = sizeof(ec_wei25519_pkparameters_named_curve); | ||
567 | if ((new_group = d2i_ECPKParameters(NULL, &pder, der_len)) != NULL) { | ||
568 | fprintf(stderr, "FAIL: %s managed to decode unknown named curve\n", | ||
569 | __func__); | ||
570 | goto err; | ||
571 | } | ||
572 | |||
573 | error = ERR_get_error(); | ||
574 | if (ERR_GET_REASON(error) != EC_R_UNKNOWN_GROUP) { | ||
575 | fprintf(stderr, "FAIL: %s unexpected error: want %d, got %d\n", | ||
576 | __func__, EC_R_UNKNOWN_GROUP, ERR_GET_REASON(error)); | ||
577 | goto err; | ||
578 | } | ||
579 | |||
580 | ERR_clear_error(); | ||
581 | pder = ec_wei25519_pkparameters_parameters; | ||
582 | der_len = sizeof(ec_wei25519_pkparameters_parameters); | ||
583 | |||
584 | #if 0 | ||
585 | if ((new_group = d2i_ECPKParameters(NULL, &pder, der_len)) != NULL) { | ||
586 | fprintf(stderr, "FAIL: %s managed to decode non-builtin parameters\n", | ||
587 | __func__); | ||
588 | goto err; | ||
589 | } | ||
590 | |||
591 | error = ERR_peek_last_error(); | ||
592 | if (ERR_GET_REASON(error) != EC_R_PKPARAMETERS2GROUP_FAILURE) { | ||
593 | fprintf(stderr, "FAIL: %s unexpected error: want %d, got %d\n", | ||
594 | __func__, EC_R_UNKNOWN_GROUP, ERR_GET_REASON(error)); | ||
595 | goto err; | ||
596 | } | ||
597 | #else | ||
598 | if ((new_group = d2i_ECPKParameters(NULL, &pder, der_len)) == NULL) { | ||
599 | fprintf(stderr, "FAIL: %s d2i_ECPKParameters(Wei25519)\n", __func__); | ||
600 | goto err; | ||
601 | } | ||
602 | if (EC_GROUP_cmp(group, new_group, ctx) != 0) { | ||
603 | fprintf(stderr, "FAIL: %s Weierstrass groups do not match!\n", | ||
604 | __func__); | ||
605 | goto err; | ||
606 | } | ||
607 | #endif | ||
608 | |||
609 | failed = 0; | ||
610 | |||
611 | err: | ||
612 | BN_CTX_end(ctx); | ||
613 | BN_CTX_free(ctx); | ||
614 | |||
615 | EC_GROUP_free(group); | ||
616 | EC_GROUP_free(new_group); | ||
617 | EC_POINT_free(generator); | ||
618 | |||
619 | freezero(der, der_len); | ||
620 | |||
621 | return failed; | ||
622 | } | ||
623 | |||
342 | int | 624 | int |
343 | main(int argc, char **argv) | 625 | main(int argc, char **argv) |
344 | { | 626 | { |
@@ -348,6 +630,7 @@ main(int argc, char **argv) | |||
348 | failed |= ec_group_pkparameters_parameters_test(); | 630 | failed |= ec_group_pkparameters_parameters_test(); |
349 | failed |= ec_group_pkparameters_correct_padding_test(); | 631 | failed |= ec_group_pkparameters_correct_padding_test(); |
350 | failed |= ec_group_roundtrip_builtin_curves(); | 632 | failed |= ec_group_roundtrip_builtin_curves(); |
633 | failed |= ec_weierstrass25519(); | ||
351 | 634 | ||
352 | return (failed); | 635 | return (failed); |
353 | } | 636 | } |