From 57dce1ee62c2b900b852877c1c9754126b87ed0f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 8 Oct 2024 15:25:41 +0900 Subject: [PATCH] common,gpg,scd,sm: Fix for Curve25519 OID supporting new and old. * common/util.h (openpgp_curve_to_oid): Add new argument to select OID by OpenPGP version. * common/openpgp-oid.c (openpgp_curve_to_oid): Implement returning selected OID for Curve25519. * common/openpgp-fpr.c (compute_openpgp_fpr_ecc): Follow the change, selecting by the version. * g10/export.c (match_curve_skey_pk): Likewise. (transfer_format_to_openpgp): Likewise. * g10/gpg.c (list_config): Likewise, print new OID. * g10/keygen.c (ecckey_from_sexp): Likewise, selecting by the version. * sm/encrypt.c (ecdh_encrypt): Likewise, don't care. * sm/minip12.c (build_ecc_key_sequence): Likewise, new OID. * scd/app-openpgp.c (ecdh_params, gen_challenge): Likewise, don't care. (ecc_read_pubkey, change_keyattr_from_string, ecc_writekey): Likewise, old OID. -- GnuPG-bug-id: 7316 Signed-off-by: NIIBE Yutaka --- common/openpgp-fpr.c | 3 ++- common/openpgp-oid.c | 14 ++++++++++++-- common/util.h | 3 ++- g10/export.c | 4 ++-- g10/gpg.c | 2 +- g10/keygen.c | 5 +---- scd/app-openpgp.c | 12 ++++++------ sm/encrypt.c | 2 +- sm/minip12.c | 2 +- 9 files changed, 28 insertions(+), 19 deletions(-) diff --git a/common/openpgp-fpr.c b/common/openpgp-fpr.c index 7860d3872..699eee9ee 100644 --- a/common/openpgp-fpr.c +++ b/common/openpgp-fpr.c @@ -231,7 +231,8 @@ compute_openpgp_fpr_ecc (int keyversion, unsigned long timestamp, unsigned char nbits_q[2]; unsigned int n; - curveoidstr = openpgp_curve_to_oid (curvename, &curvebits, &pgpalgo); + curveoidstr = openpgp_curve_to_oid (curvename, &curvebits, &pgpalgo, + (keyversion > 4)); err = openpgp_oid_from_str (curveoidstr, &curveoid); if (err) goto leave; diff --git a/common/openpgp-oid.c b/common/openpgp-oid.c index 0a7aae000..c4161ece1 100644 --- a/common/openpgp-oid.c +++ b/common/openpgp-oid.c @@ -443,9 +443,11 @@ openpgp_oid_is_cv448 (gcry_mpi_t a) curve names. If R_ALGO is not NULL and a specific ECC algorithm is required for this curve its OpenPGP algorithm number is stored there; otherwise 0 is stored which indicates that ECDSA or ECDH can - be used. */ + be used. SELECTOR specifies which OID should be returned: -1 for + don't care, 0 for old OID, 1 for new OID. */ const char * -openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo) +openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo, + int selector) { int i; unsigned int nbits = 0; @@ -479,6 +481,14 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo) } } + /* Special handling for Curve25519, where we have two valid OIDs. */ + if (algo && i == 0) + { + /* Select new OID, if wanted. */ + if (selector > 0) + oidstr = oidtable[2].oidstr; + } + if (r_nbits) *r_nbits = nbits; if (r_algo) diff --git a/common/util.h b/common/util.h index 671ffbcb7..acda2646e 100644 --- a/common/util.h +++ b/common/util.h @@ -230,7 +230,8 @@ int openpgp_oid_is_cv448 (gcry_mpi_t a); int openpgp_oid_is_ed448 (gcry_mpi_t a); enum gcry_kem_algos openpgp_oid_to_kem_algo (const char *oidname); const char *openpgp_curve_to_oid (const char *name, - unsigned int *r_nbits, int *r_algo); + unsigned int *r_nbits, int *r_algo, + int selector); const char *openpgp_oid_to_curve (const char *oid, int mode); const char *openpgp_oid_or_name_to_curve (const char *oidname, int canon); const char *openpgp_enum_curves (int *idxp); diff --git a/g10/export.c b/g10/export.c index 5d3ffffa4..2aafe8ee7 100644 --- a/g10/export.c +++ b/g10/export.c @@ -585,7 +585,7 @@ match_curve_skey_pk (gcry_sexp_t s_key, PKT_public_key *pk) } if (!strcmp (curve_str, "Ed448")) is_eddsa = 1; - oidstr = openpgp_curve_to_oid (curve_str, NULL, NULL); + oidstr = openpgp_curve_to_oid (curve_str, NULL, NULL, (pk->version > 4)); if (!oidstr) { log_error ("no OID known for curve '%s'\n", curve_str); @@ -1280,7 +1280,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk) goto leave; } - oidstr = openpgp_curve_to_oid (curve, NULL, NULL); + oidstr = openpgp_curve_to_oid (curve, NULL, NULL, (pk->version > 4)); if (!oidstr) { log_error ("no OID known for curve '%s'\n", curve); diff --git a/g10/gpg.c b/g10/gpg.c index d8b1051d5..694364b3d 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1983,7 +1983,7 @@ list_config(char *items) es_printf ("cfg:curveoid:"); for (iter=0, first=1; (s = openpgp_enum_curves (&iter)); first = 0) { - s = openpgp_curve_to_oid (s, NULL, NULL); + s = openpgp_curve_to_oid (s, NULL, NULL, 1); es_printf ("%s%s", first?"":";", s? s:"[?]"); } es_printf ("\n"); diff --git a/g10/keygen.c b/g10/keygen.c index dafac87b6..81f03fdfb 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1503,7 +1503,7 @@ ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, goto leave; } gcry_sexp_release (l2); - oidstr = openpgp_curve_to_oid (curve, &nbits, NULL); + oidstr = openpgp_curve_to_oid (curve, &nbits, NULL, pkversion > 4); if (!oidstr) { /* That can't happen because we used one of the curves @@ -1511,9 +1511,6 @@ ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, err = gpg_error (GPG_ERR_INV_OBJ); goto leave; } - /* For v5 keys we prefer the modern OID for cv25519. */ - if (pkversion > 4 && !strcmp (oidstr, "1.3.6.1.4.1.3029.1.5.1")) - oidstr = "1.3.101.110"; err = openpgp_oid_from_str (oidstr, &array[0]); if (err) diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 250c4142e..87ca46483 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1759,7 +1759,7 @@ ecdh_params (const char *curve) { unsigned int nbits; - openpgp_curve_to_oid (curve, &nbits, NULL); + openpgp_curve_to_oid (curve, &nbits, NULL, -1); /* See RFC-6637 for those constants. 0x03: Number of bytes @@ -1801,7 +1801,7 @@ ecc_read_pubkey (app_t app, ctrl_t ctrl, int meta_update, } curve = app->app_local->keyattr[keyno].ecc.curve; - oidstr = openpgp_curve_to_oid (curve, NULL, NULL); + oidstr = openpgp_curve_to_oid (curve, NULL, NULL, 0); err = openpgp_oid_from_str (oidstr, &oid); if (err) return err; @@ -4194,7 +4194,7 @@ change_keyattr_from_string (app_t app, ctrl_t ctrl, else { nbits = 0; - oidstr = openpgp_curve_to_oid (keyalgo, NULL, &algo); + oidstr = openpgp_curve_to_oid (keyalgo, NULL, &algo, 0); if (!oidstr) { err = gpg_error (GPG_ERR_INV_DATA); @@ -4244,7 +4244,7 @@ change_keyattr_from_string (app_t app, ctrl_t ctrl, else if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_EDDSA) { - oidstr = openpgp_curve_to_oid (string+n, NULL, NULL); + oidstr = openpgp_curve_to_oid (string+n, NULL, NULL, 0); if (!oidstr) { err = gpg_error (GPG_ERR_INV_DATA); @@ -4821,7 +4821,7 @@ ecc_writekey (app_t app, ctrl_t ctrl, ecdh_param_len = 4; } - oidstr = openpgp_curve_to_oid (curve, &n, NULL); + oidstr = openpgp_curve_to_oid (curve, &n, NULL, 0); ecc_d_fixed_len = (n+7)/8; err = openpgp_oid_from_str (oidstr, &oid); if (err) @@ -5552,7 +5552,7 @@ gen_challenge (app_t app, const void **r_data, size_t *r_datalen) { unsigned int n; - openpgp_curve_to_oid (app->app_local->keyattr[2].ecc.curve, &n, NULL); + openpgp_curve_to_oid (app->app_local->keyattr[2].ecc.curve, &n, NULL, -1); /* No hash algo header, and appropriate length of random octets, determined by field size of the curve. */ datalen = (n+7)/8; diff --git a/sm/encrypt.c b/sm/encrypt.c index 202bbb92f..98d3024ad 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -218,7 +218,7 @@ ecdh_encrypt (DEK dek, gcry_sexp_t s_pkey, gcry_sexp_t *r_encval) * canonical numerical OID. We also use this to get the size of the * curve which we need to figure out a suitable hash algo. We * should have a Libgcrypt function to do this; see bug report #4926. */ - curve = openpgp_curve_to_oid (curvebuf, &curvebits, NULL); + curve = openpgp_curve_to_oid (curvebuf, &curvebits, NULL, -1); if (!curve) { err = gpg_error (GPG_ERR_UNKNOWN_CURVE); diff --git a/sm/minip12.c b/sm/minip12.c index 00ba26d7d..34ba1a53b 100644 --- a/sm/minip12.c +++ b/sm/minip12.c @@ -2596,7 +2596,7 @@ build_ecc_key_sequence (gcry_mpi_t *kparms, int mode, size_t *r_length) /* We need to use our OpenPGP mapping to turn a curve name into its * canonical numerical OID. We should have a Libgcrypt function to * do this; see bug report #4926. */ - curve = openpgp_curve_to_oid (p, &curvebits, NULL); + curve = openpgp_curve_to_oid (p, &curvebits, NULL, 1); xfree (p); if (!curve) {