From 266a6602f0c93c541acb4e5aad0a475f985f1e3f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 14 Nov 2022 17:10:26 +0100 Subject: [PATCH] gpgsm: Some more ECC support backported. * sm/certcheck.c (gpgsm_check_cert_sig): Map ECDSA OIDs. * sm/misc.c (transform_sigval): Add ECC support. -- GnuPG-bug-id: 6253 --- sm/certcheck.c | 10 +++++ sm/misc.c | 109 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 94 insertions(+), 25 deletions(-) diff --git a/sm/certcheck.c b/sm/certcheck.c index d6b967c8a..17cce4405 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -357,9 +357,19 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) int use_pss = 0; unsigned int saltlen; + /* Note that we map the 4 algos which current Libgcrypt versions are + * not aware of the OID. */ algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert))); if (!algo && algoid && !strcmp (algoid, "1.2.840.113549.1.1.10")) use_pss = 1; + else if (!algo && algoid && !strcmp (algoid, "1.2.840.10045.4.3.1")) + algo = GCRY_MD_SHA224; /* ecdsa-with-sha224 */ + else if (!algo && algoid && !strcmp (algoid, "1.2.840.10045.4.3.2")) + algo = GCRY_MD_SHA256; /* ecdsa-with-sha256 */ + else if (!algo && algoid && !strcmp (algoid, "1.2.840.10045.4.3.3")) + algo = GCRY_MD_SHA384; /* ecdsa-with-sha384 */ + else if (!algo && algoid && !strcmp (algoid, "1.2.840.10045.4.3.4")) + algo = GCRY_MD_SHA512; /* ecdsa-with-sha512 */ else if (!algo) { log_error ("unknown digest algorithm '%s' used certificate\n", diff --git a/sm/misc.c b/sm/misc.c index 66d928c6b..1c28293aa 100644 --- a/sm/misc.c +++ b/sm/misc.c @@ -101,7 +101,7 @@ setup_pinentry_env (void) function ignores missing parameters so that it can also be used to create an siginfo value as expected by ksba_certreq_set_siginfo. To create a siginfo s-expression a public-key s-expression may be - used instead of a sig-val. We only support RSA for now. */ + used instead of a sig-val. */ gpg_error_t transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo, unsigned char **r_newsigval, size_t *r_newsigvallen) @@ -111,11 +111,15 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo, size_t buflen, toklen; int depth, last_depth1, last_depth2; int is_pubkey = 0; - const unsigned char *rsa_s = NULL; - size_t rsa_s_len = 0; + int pkalgo; + const unsigned char *rsa_s, *ecc_r, *ecc_s; + size_t rsa_s_len, ecc_r_len, ecc_s_len; const char *oid; gcry_sexp_t sexp; + rsa_s = ecc_r = ecc_s = NULL; + rsa_s_len = ecc_r_len = ecc_s_len = 0; + *r_newsigval = NULL; if (r_newsigvallen) *r_newsigvallen = 0; @@ -137,7 +141,15 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo, return err; if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) return err; - if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen)) + if (!tok) + return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); + if (toklen == 3 && !memcmp ("rsa", tok, 3)) + pkalgo = GCRY_PK_RSA; + else if (toklen == 3 && !memcmp ("ecc", tok, 3)) + pkalgo = GCRY_PK_ECC; + else if (toklen == 5 && !memcmp ("ecdsa", tok, 5)) + pkalgo = GCRY_PK_ECC; + else return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); last_depth1 = depth; @@ -150,8 +162,8 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo, return err; if (tok && toklen == 1) { - const unsigned char **mpi; - size_t *mpi_len; + const unsigned char **mpi = NULL; + size_t *mpi_len = NULL; switch (*tok) { @@ -161,6 +173,25 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo, if (mpi && *mpi) return gpg_error (GPG_ERR_DUP_VALUE); + switch (*tok) + { + case 's': + if (pkalgo == GCRY_PK_RSA) + { + mpi = &rsa_s; + mpi_len = &rsa_s_len; + } + else if (pkalgo == GCRY_PK_ECC || pkalgo == GCRY_PK_EDDSA) + { + mpi = &ecc_s; + mpi_len = &ecc_s_len; + } + break; + + case 'r': mpi = &ecc_r; mpi_len = &ecc_r_len; break; + default: mpi = NULL; mpi_len = NULL; break; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) return err; if (tok && mpi) @@ -181,34 +212,62 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo, if (err) return err; - /* Map the hash algorithm to an OID. */ - switch (mdalgo) + if (0) + ; /* Just to align it with the code in 2.3. */ + else { - case GCRY_MD_SHA1: - oid = "1.2.840.113549.1.1.5"; /* sha1WithRSAEncryption */ - break; + /* Map the hash algorithm to an OID. */ + if (mdalgo < 0 || mdalgo > (1<<15) || pkalgo < 0 || pkalgo > (1<<15)) + return gpg_error (GPG_ERR_DIGEST_ALGO); - case GCRY_MD_SHA256: - oid = "1.2.840.113549.1.1.11"; /* sha256WithRSAEncryption */ - break; + switch (mdalgo | (pkalgo << 16)) + { + case GCRY_MD_SHA1 | (GCRY_PK_RSA << 16): + oid = "1.2.840.113549.1.1.5"; /* sha1WithRSAEncryption */ + break; - case GCRY_MD_SHA384: - oid = "1.2.840.113549.1.1.12"; /* sha384WithRSAEncryption */ - break; + case GCRY_MD_SHA256 | (GCRY_PK_RSA << 16): + oid = "1.2.840.113549.1.1.11"; /* sha256WithRSAEncryption */ + break; - case GCRY_MD_SHA512: - oid = "1.2.840.113549.1.1.13"; /* sha512WithRSAEncryption */ - break; + case GCRY_MD_SHA384 | (GCRY_PK_RSA << 16): + oid = "1.2.840.113549.1.1.12"; /* sha384WithRSAEncryption */ + break; - default: - return gpg_error (GPG_ERR_DIGEST_ALGO); + case GCRY_MD_SHA512 | (GCRY_PK_RSA << 16): + oid = "1.2.840.113549.1.1.13"; /* sha512WithRSAEncryption */ + break; + + case GCRY_MD_SHA224 | (GCRY_PK_ECC << 16): + oid = "1.2.840.10045.4.3.1"; /* ecdsa-with-sha224 */ + break; + + case GCRY_MD_SHA256 | (GCRY_PK_ECC << 16): + oid = "1.2.840.10045.4.3.2"; /* ecdsa-with-sha256 */ + break; + + case GCRY_MD_SHA384 | (GCRY_PK_ECC << 16): + oid = "1.2.840.10045.4.3.3"; /* ecdsa-with-sha384 */ + break; + + case GCRY_MD_SHA512 | (GCRY_PK_ECC << 16): + oid = "1.2.840.10045.4.3.4"; /* ecdsa-with-sha512 */ + break; + + default: + return gpg_error (GPG_ERR_DIGEST_ALGO); + } } - if (rsa_s && !is_pubkey) + if (is_pubkey) + err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s))", oid); + else if (pkalgo == GCRY_PK_RSA) err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s(s%b)))", oid, (int)rsa_s_len, rsa_s); - else - err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s))", oid); + else if (pkalgo == GCRY_PK_ECC || pkalgo == GCRY_PK_EDDSA) + err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s(r%b)(s%b)))", oid, + (int)ecc_r_len, ecc_r, (int)ecc_s_len, ecc_s); + if (err) return err; err = make_canon_sexp (sexp, r_newsigval, r_newsigvallen);