From 338a5ecaa1f11abf24514c8df994170bdb1018f4 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 12 Jan 2023 20:52:27 +0100 Subject: [PATCH] sm: Fix compliance checking for ECC signature verification. * common/compliance.c (gnupg_pk_is_compliant): Also consider the gcrypt vids for ECDSA et al. (gnupg_pk_is_allowed): Ditto. * sm/verify.c (gpgsm_verify): Consider the curve. Print a compliance notice for a non-compliant key. * sm/certchain.c (gpgsm_validate_chain): Silence the "switching to chain model". --- common/compliance.c | 16 ++++++++++++++-- common/compliance.h | 2 +- sm/certchain.c | 3 ++- sm/verify.c | 17 ++++++++++++++--- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/common/compliance.c b/common/compliance.c index 33a19fe06..315927575 100644 --- a/common/compliance.c +++ b/common/compliance.c @@ -83,7 +83,9 @@ gnupg_initialize_compliance (int gnupg_module_name) log_assert (! initialized); /* We accept both OpenPGP-style and gcrypt-style algorithm ids. - * Assert that they are compatible. */ + * Assert that they are compatible. At some places gcrypt ids are + * used which can't be encoded in an OpenPGP algo octet; we also + * assert this. */ log_assert ((int) GCRY_PK_RSA == (int) PUBKEY_ALGO_RSA); log_assert ((int) GCRY_PK_RSA_E == (int) PUBKEY_ALGO_RSA_E); log_assert ((int) GCRY_PK_RSA_S == (int) PUBKEY_ALGO_RSA_S); @@ -91,6 +93,9 @@ gnupg_initialize_compliance (int gnupg_module_name) log_assert ((int) GCRY_PK_DSA == (int) PUBKEY_ALGO_DSA); log_assert ((int) GCRY_PK_ECC == (int) PUBKEY_ALGO_ECDH); log_assert ((int) GCRY_PK_ELG == (int) PUBKEY_ALGO_ELGAMAL); + log_assert ((int) GCRY_PK_ECDSA > 255); + log_assert ((int) GCRY_PK_ECDH > 255); + log_assert ((int) GCRY_PK_EDDSA > 255); log_assert ((int) GCRY_CIPHER_NONE == (int) CIPHER_ALGO_NONE); log_assert ((int) GCRY_CIPHER_IDEA == (int) CIPHER_ALGO_IDEA); log_assert ((int) GCRY_CIPHER_3DES == (int) CIPHER_ALGO_3DES); @@ -159,6 +164,9 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo, case PUBKEY_ALGO_ECDH: case PUBKEY_ALGO_ECDSA: case PUBKEY_ALGO_EDDSA: + case GCRY_PK_ECDSA: + case GCRY_PK_ECDH: + case GCRY_PK_EDDSA: algotype = is_ecc; break; @@ -211,7 +219,9 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo, result = (curvename && (algo == PUBKEY_ALGO_ECDH - || algo == PUBKEY_ALGO_ECDSA) + || algo == PUBKEY_ALGO_ECDSA + || algo == GCRY_PK_ECDH + || algo == GCRY_PK_ECDSA) && (!strcmp (curvename, "brainpoolP256r1") || !strcmp (curvename, "brainpoolP384r1") || !strcmp (curvename, "brainpoolP512r1"))); @@ -292,6 +302,7 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance, break; case PUBKEY_ALGO_ECDH: + case GCRY_PK_ECDH: if (use == PK_USE_DECRYPTION) result = 1; else if (use == PK_USE_ENCRYPTION) @@ -316,6 +327,7 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance, break; case PUBKEY_ALGO_ECDSA: + case GCRY_PK_ECDSA: if (use == PK_USE_VERIFICATION) result = 1; else diff --git a/common/compliance.h b/common/compliance.h index 455efa544..ead11472c 100644 --- a/common/compliance.h +++ b/common/compliance.h @@ -45,7 +45,7 @@ enum gnupg_compliance_mode enum pk_use_case { PK_USE_ENCRYPTION, PK_USE_DECRYPTION, - PK_USE_SIGNING, PK_USE_VERIFICATION, + PK_USE_SIGNING, PK_USE_VERIFICATION }; /* Flags to distinguish public key algorithm variants. */ diff --git a/sm/certchain.c b/sm/certchain.c index 9813eca8c..cbb6e1127 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -2195,7 +2195,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime, /* The root CA indicated that the chain model is to be used but * we have not yet used it. Thus do the validation again using * the chain model. */ - do_list (0, listmode, listfp, _("switching to chain model")); + if (opt.verbose) + do_list (0, listmode, listfp, _("switching to chain model")); rc = do_validate_chain (ctrl, cert, checktime, r_exptime, listmode, listfp, (flags |= VALIDATE_FLAG_CHAIN_MODEL), diff --git a/sm/verify.c b/sm/verify.c index 2e40c021f..9f1216f83 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -299,6 +299,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp) unsigned int nbits; int pkalgo; char *pkalgostr = NULL; + char *pkcurve = NULL; char *pkfpr = NULL; unsigned int pkalgoflags, verifyflags; @@ -457,7 +458,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp) pkfpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); pkalgostr = gpgsm_pubkey_algo_string (cert, NULL); - pkalgo = gpgsm_get_key_algo_info (cert, &nbits); + pkalgo = gpgsm_get_key_algo_info2 (cert, &nbits, &pkcurve); /* Remap the ECC algo to the algo we use. Note that EdDSA has * already been mapped. */ if (pkalgo == GCRY_PK_ECC) @@ -513,9 +514,19 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp) goto next_signer; } + /* Print compliance warning for the key. */ + if (!opt.quiet + && !gnupg_pk_is_compliant (opt.compliance, pkalgo, pkalgoflags, + NULL, nbits, pkcurve)) + { + log_info (_("WARNING: This key is not suitable for signing" + " in %s mode\n"), + gnupg_compliance_option_string (opt.compliance)); + } + /* Check compliance with CO_DE_VS. */ if (gnupg_pk_is_compliant (CO_DE_VS, pkalgo, pkalgoflags, - NULL, nbits, NULL) + NULL, nbits, pkcurve) && gnupg_gcrypt_is_compliant (CO_DE_VS) && gnupg_digest_is_compliant (CO_DE_VS, sigval_hash_algo)) gpgsm_status (ctrl, STATUS_VERIFICATION_COMPLIANCE_MODE, @@ -528,7 +539,6 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp) gpgsm_errors_seen = 1; } - /* Now we can check the signature. */ if (msgdigest) { /* Signed attributes are available. */ @@ -715,6 +725,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp) gcry_sexp_release (sigval); xfree (msgdigest); xfree (pkalgostr); + xfree (pkcurve); xfree (pkfpr); ksba_cert_release (cert); cert = NULL;