diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index 08b374d5..93594a70 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -51,6 +51,7 @@ static const struct { "Curve25519", "1.3.6.1.4.1.3029.1.5.1" }, /* OpenPGP */ { "Curve25519", "1.3.101.110" }, /* rfc8410 */ { "Curve25519", "X25519" }, /* rfc8410 */ + { "ietf25" }, /* rfc9580 */ { "Ed448", "1.3.101.113" }, /* rfc8410 */ { "X448", "1.3.101.111" }, /* rfc8410 */ @@ -177,6 +178,18 @@ static const ecc_domain_parms_t domain_parms[] = * the function _gcry_ecc_fill_in_curve. See bug #4712. */ }, + { + /* (y^2 = x^3 + 486662*x^2 + x) */ + "ietf25", 255, 0, + MPI_EC_MONTGOMERY, ECC_DIALECT_SAFECURVE, + "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED", + "0x01DB41", + "0x01", + "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED", + "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14", + 8 + }, { /* (x^2 + y^2 = 1 + dx^2y^2) */ "Ed448", 448, 1, @@ -596,7 +609,8 @@ find_domain_parms_idx (const char *name) if (!domain_parms[idx].desc) { for (aliasno = 0; curve_aliases[aliasno].name; aliasno++) - if (!strcmp (name, curve_aliases[aliasno].other)) + if (curve_aliases[aliasno].other + && !strcmp (name, curve_aliases[aliasno].other)) break; if (curve_aliases[aliasno].name) { diff --git a/tests/curves.c b/tests/curves.c index 3cd74422..c50cb6dd 100644 --- a/tests/curves.c +++ b/tests/curves.c @@ -33,7 +33,7 @@ #include "t-common.h" /* Number of curves defined in ../cipher/ecc-curves.c */ -#define N_CURVES 27 +#define N_CURVES 28 /* A real world sample public key. */ static char const sample_key_1[] = diff --git a/tests/t-cv25519.c b/tests/t-cv25519.c index 14a6719b..2902b434 100644 --- a/tests/t-cv25519.c +++ b/tests/t-cv25519.c @@ -241,6 +241,117 @@ test_cv_hl (int testno, const char *k_str, const char *u_str, xfree (buffer); } +static void +test_cv_hl25 (int testno, const char *k_str, const char *u_str, + const char *result_str) +{ + gpg_error_t err; + void *buffer = NULL; + size_t buflen; + gcry_sexp_t s_pk = NULL; + gcry_mpi_t mpi_k = NULL; + gcry_sexp_t s_data = NULL; + gcry_sexp_t s_result = NULL; + gcry_sexp_t s_tmp = NULL; + unsigned char *res = NULL; + size_t res_len; + + if (verbose > 1) + info ("Running test %d\n", testno); + + if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) + { + fail ("error building s-exp for test %d, %s: %s", + testno, "k", "invalid hex string"); + goto leave; + } + + mpi_k = gcry_mpi_set_opaque (NULL, buffer, buflen*8); + if ((err = gcry_sexp_build (&s_data, NULL, "%m", mpi_k))) + { + fail ("error building s-exp for test %d, %s: %s", + testno, "data", gpg_strerror (err)); + goto leave; + } + + if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 32) + { + fail ("error building s-exp for test %d, %s: %s", + testno, "u", "invalid hex string"); + goto leave; + } + + /* + * The procedure of decodeUCoordinate will be done internally + * by _gcry_ecc_mont_decodepoint. So, we just put the little-endian + * binary to build S-exp. + */ + if ((err = gcry_sexp_build (&s_pk, NULL, + "(public-key" + " (ecc" + " (curve \"ietf25\")" + " (q%b)))", (int)buflen, buffer))) + { + fail ("error building s-exp for test %d, %s: %s", + testno, "pk", gpg_strerror (err)); + goto leave; + } + + xfree (buffer); + buffer = NULL; + + err = gcry_pk_encrypt (&s_result, s_data, s_pk); + if (in_fips_mode) + { + if (!err) + fail ("gcry_pk_encrypt is not expected to work in FIPS mode for test %d", + testno); + if (verbose > 1) + info ("not executed in FIPS mode\n"); + goto leave; + } + if (err) + fail ("gcry_pk_encrypt failed for test %d: %s", testno, + gpg_strerror (err)); + + s_tmp = gcry_sexp_find_token (s_result, "s", 0); + if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len))) + fail ("gcry_pk_encrypt failed for test %d: %s", testno, "missing value"); + else + { + char *r, *r0; + int i; + + r0 = r = xmalloc (2*(res_len)+1); + if (!r0) + { + fail ("memory allocation for test %d", testno); + goto leave; + } + + for (i=0; i < res_len; i++, r += 2) + snprintf (r, 3, "%02x", res[i]); + if (strcmp (result_str, r0)) + { + fail ("gcry_pk_encrypt failed for test %d: %s", + testno, "wrong value returned"); + info (" expected: '%s'", result_str); + info (" got: '%s'", r0); + } + xfree (r0); + } + + leave: + xfree (res); + gcry_mpi_release (mpi_k); + gcry_sexp_release (s_tmp); + gcry_sexp_release (s_result); + gcry_sexp_release (s_data); + gcry_sexp_release (s_pk); + xfree (buffer); +} + + /* * Test X25519 functionality through the API for X25519. * @@ -327,6 +438,7 @@ test_cv (int testno, const char *k_str, const char *u_str, const char *result_str) { test_cv_hl (testno, k_str, u_str, result_str); + test_cv_hl25 (testno, k_str, u_str, result_str); test_cv_x25519 (testno, k_str, u_str, result_str); }