From 194b9aa8d269ef29e51249b3c39352f630125514 Mon Sep 17 00:00:00 2001 From: tb Date: Fri, 18 Oct 2024 09:01:44 +0000 Subject: [PATCH] ec_asn1_test: clean up & refactor; test Wei25519 with simple method --- regress/lib/libcrypto/ec/ec_asn1_test.c | 298 +++++++++++++++--------- 1 file changed, 189 insertions(+), 109 deletions(-) diff --git a/regress/lib/libcrypto/ec/ec_asn1_test.c b/regress/lib/libcrypto/ec/ec_asn1_test.c index 171014bda7e..c53864cadd4 100644 --- a/regress/lib/libcrypto/ec/ec_asn1_test.c +++ b/regress/lib/libcrypto/ec/ec_asn1_test.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_asn1_test.c,v 1.6 2024/10/16 23:58:25 tb Exp $ */ +/* $OpenBSD: ec_asn1_test.c,v 1.7 2024/10/18 09:01:44 tb Exp $ */ /* * Copyright (c) 2017, 2021 Joel Sing * Copyright (c) 2024 Theo Buehler @@ -344,35 +344,6 @@ ec_group_roundtrip_builtin_curves(void) * From draft-ietf-lwig-curve-representation-23, Appendix E.3 */ -static const struct { - 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; -} wei25519 = { - .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", -}; - const uint8_t ec_wei25519_pkparameters_named_curve[] = { 0x06, 0x03, 0x2b, 0x65, 0x6c, }; @@ -409,100 +380,163 @@ const uint8_t ec_wei25519_pkparameters_parameters[] = { 0x08, }; -static int -ec_weierstrass25519(void) +struct curve { + 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; + const char *named; + size_t named_len; + const char *param; + size_t param_len; +}; + +static const struct curve wei25519 = { + .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 EC_GROUP * +ec_group_from_curve_method(const struct curve *curve, const EC_METHOD *method, + BN_CTX *ctx) { - EC_GROUP *group = NULL, *new_group = NULL; + EC_GROUP *group; EC_POINT *generator = NULL; - BN_CTX *ctx = NULL; BIGNUM *p, *a, *b; - BIGNUM *order, *cofactor, *guessed_cofactor, *x, *y; - const unsigned char *pder; - unsigned char *der = NULL; - long error; - int der_len = 0; - int nid; - int failed = 1; + BIGNUM *order, *x, *y; - ERR_clear_error(); - if ((ctx = BN_CTX_new()) == NULL) - goto err; BN_CTX_start(ctx); - if ((nid = OBJ_create(wei25519.oid, wei25519.sn, NULL)) == NID_undef) { - fprintf(stderr, "FAIL: %s OBJ_create(wei25519)\n", __func__); - goto err; - } - 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 ((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 ((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, wei25519.p) == 0) + if (BN_hex2bn(&p, curve->p) == 0) errx(1, "BN_hex2bn(p)"); - if (BN_hex2bn(&a, wei25519.a) == 0) + if (BN_hex2bn(&a, curve->a) == 0) errx(1, "BN_hex2bn(a)"); - if (BN_hex2bn(&b, wei25519.b) == 0) + if (BN_hex2bn(&b, curve->b) == 0) errx(1, "BN_hex2bn(b)"); - /* - * XXX - this uses the Montgomery method. Consider exercising the - * simple method as well. - */ - if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { - fprintf(stderr, "FAIL: %s EC_GROUP_new_curve_GFp", __func__); - goto err; - } + 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, wei25519.x) == 0) + if (BN_hex2bn(&x, curve->x) == 0) errx(1, "BN_hex2bn(x)"); - if (BN_hex2bn(&x, wei25519.x) == 0) + if (BN_hex2bn(&x, curve->x) == 0) errx(1, "BN_hex2bn(x)"); - if (BN_hex2bn(&y, wei25519.y) == 0) + 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", __func__); + fprintf(stderr, "FAIL: %s EC_POINT_set_affine_coordinates", + curve->sn); ERR_print_errors_fp(stderr); goto err; } - if (BN_hex2bn(&order, wei25519.order) == 0) + if (BN_hex2bn(&order, curve->order) == 0) errx(1, "BN_hex2bn(order)"); - if (BN_hex2bn(&cofactor, wei25519.cofactor) == 0) - errx(1, "BN_hex2bn(cofactor)"); /* Don't set cofactor to exercise the cofactor guessing code. */ if (!EC_GROUP_set_generator(group, generator, order, NULL)) { - fprintf(stderr, "FAIL: %s EC_GROUP_set_generator\n", __func__); + fprintf(stderr, "FAIL: %s EC_GROUP_set_generator\n", curve->sn); + 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->sn); + 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->sn); 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", __func__); + fprintf(stderr, "FAIL: %s EC_GROUP_get_cofactor\n", curve->sn); ERR_print_errors_fp(stderr); goto err; } if (BN_cmp(cofactor, guessed_cofactor) != 0) { - fprintf(stderr, "FAIL: %s cofactor: want ", __func__); + fprintf(stderr, "FAIL: %s cofactor: want ", curve->sn); BN_print_fp(stderr, cofactor); fprintf(stderr, ", got "); BN_print_fp(stderr, guessed_cofactor); @@ -511,49 +545,80 @@ ec_weierstrass25519(void) } if (!EC_GROUP_check(group, ctx)) { - fprintf(stderr, "FAIL: %s EC_GROUP_check\n", __func__); + fprintf(stderr, "FAIL: %s EC_GROUP_check\n", curve->sn); ERR_print_errors_fp(stderr); goto err; } - /* Explicit curve parameter encoding should work without NID set. */ - if (EC_GROUP_get_curve_name(group) != NID_undef) { - fprintf(stderr, "FAIL: %s unexpected curve name %d\n", __func__, - EC_GROUP_get_curve_name(group)); - ERR_print_errors_fp(stderr); + 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; + long error; + int der_len = 0; + int nid; + int failed = 1; + + ERR_clear_error(); + BN_CTX_start(ctx); + + if ((group = ec_group_new(curve, method, ctx)) == NULL) + goto err; + + if ((nid = EC_GROUP_get_curve_name(group)) == NID_undef) { + fprintf(stderr, "FAIL: no curve name set for %s\n", curve->sn); goto err; } - EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE); + 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 (explicit)\n", __func__); + fprintf(stderr, "FAIL: %s i2d_ECPKParameters (named)\n", + curve->sn); ERR_print_errors_fp(stderr); goto err; } - if (compare_data("Weierstrass 25519 explicit", der, der_len, - ec_wei25519_pkparameters_parameters, - sizeof(ec_wei25519_pkparameters_parameters)) == -1) + if (compare_data("Weierstrass 25519 named curve", der, der_len, + ec_wei25519_pkparameters_named_curve, + sizeof(ec_wei25519_pkparameters_named_curve)) == -1) goto err; freezero(der, der_len); der = NULL; - EC_GROUP_set_curve_name(group, nid); - EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); + /* Explicit curve parameter encoding should work without NID set. */ + 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: %s i2d_ECPKParameters (named)\n", __func__); + fprintf(stderr, "FAIL: i2d_ECPKParameters (explicit) %s\n", + curve->sn); ERR_print_errors_fp(stderr); goto err; } - if (compare_data("Weierstrass 25519 named curve", der, der_len, - ec_wei25519_pkparameters_named_curve, - sizeof(ec_wei25519_pkparameters_named_curve)) == -1) + if (compare_data(curve->sn, der, der_len, + curve->param, curve->param_len) == -1) goto err; freezero(der, der_len); @@ -561,51 +626,51 @@ ec_weierstrass25519(void) /* At this point we should have no error on the stack. */ if (ERR_peek_last_error() != 0) { - fprintf(stderr, "FAIL: %s unexpected error %lu\n", __func__, + fprintf(stderr, "FAIL: %s unexpected error %lu\n", curve->sn, ERR_peek_last_error()); goto err; } - pder = ec_wei25519_pkparameters_named_curve; - der_len = sizeof(ec_wei25519_pkparameters_named_curve); + pder = curve->named; + der_len = curve->named_len; if ((new_group = d2i_ECPKParameters(NULL, &pder, der_len)) != NULL) { - fprintf(stderr, "FAIL: %s managed to decode unknown named curve\n", - __func__); + fprintf(stderr, "FAIL: managed to decode unknown named curve %s\n", + curve->sn); goto err; } error = ERR_get_error(); if (ERR_GET_REASON(error) != EC_R_UNKNOWN_GROUP) { fprintf(stderr, "FAIL: %s unexpected error: want %d, got %d\n", - __func__, EC_R_UNKNOWN_GROUP, ERR_GET_REASON(error)); + curve->sn, EC_R_UNKNOWN_GROUP, ERR_GET_REASON(error)); goto err; } ERR_clear_error(); - pder = ec_wei25519_pkparameters_parameters; - der_len = sizeof(ec_wei25519_pkparameters_parameters); - + pder = curve->param; + der_len = curve->param_len; #if 0 if ((new_group = d2i_ECPKParameters(NULL, &pder, der_len)) != NULL) { - fprintf(stderr, "FAIL: %s managed to decode non-builtin parameters\n", - __func__); + fprintf(stderr, "FAIL: managed to decode non-builtin parameters %s\n", + curve->sn); goto err; } 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", - __func__, EC_R_UNKNOWN_GROUP, ERR_GET_REASON(error)); + curve->sn, EC_R_UNKNOWN_GROUP, ERR_GET_REASON(error)); goto err; } #else if ((new_group = d2i_ECPKParameters(NULL, &pder, der_len)) == NULL) { - fprintf(stderr, "FAIL: %s d2i_ECPKParameters(Wei25519)\n", __func__); + fprintf(stderr, "FAIL: d2i_ECPKParameters(%s)\n", curve->sn); goto err; } - if (EC_GROUP_cmp(group, new_group, ctx) != 0) { + if (method == EC_GFp_mont_method() && + EC_GROUP_cmp(group, new_group, ctx) != 0) { fprintf(stderr, "FAIL: %s Weierstrass groups do not match!\n", - __func__); + curve->sn); goto err; } #endif @@ -614,17 +679,32 @@ ec_weierstrass25519(void) err: BN_CTX_end(ctx); - BN_CTX_free(ctx); EC_GROUP_free(group); EC_GROUP_free(new_group); - EC_POINT_free(generator); 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); + + BN_CTX_free(ctx); + + return failed; +} + int main(int argc, char **argv) { @@ -634,7 +714,7 @@ main(int argc, char **argv) failed |= ec_group_pkparameters_parameters_test(); failed |= ec_group_pkparameters_correct_padding_test(); failed |= ec_group_roundtrip_builtin_curves(); - failed |= ec_weierstrass25519(); + failed |= ec_group_non_builtin_curves(); return (failed); } -- 2.20.1