From a0d0cbee7654ad7582400efaa92d493cd8e669e9 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 27 Jul 2017 13:56:38 +0200 Subject: [PATCH] gpg,sm: Fix compliance checking for decryption. * common/compliance.c (gnupg_pk_is_compliant): Remove the Elgamal signing check. We don't support Elgamal signing at all. (gnupg_pk_is_allowed) : Revert encryption/decryption for RSA. Check the curvenames for ECDH. * g10/pubkey-enc.c (get_session_key): Print only a warning if the key is not compliant. * sm/decrypt.c (gpgsm_decrypt): Ditto. Use the same string as in gpg so that we have only one translation. -- We always allow decryption and print only a note if the key was not complaint at the encryption site. GnuPG-bug-id: 3308 Signed-off-by: Werner Koch --- common/compliance.c | 46 +++++++++++++++++++++++++++++++-------------- g10/pubkey-enc.c | 42 ++++++++++++++++++----------------------- sm/decrypt.c | 22 ++++++++++++---------- 3 files changed, 62 insertions(+), 48 deletions(-) diff --git a/common/compliance.c b/common/compliance.c index 268ea4dbf..951172415 100644 --- a/common/compliance.c +++ b/common/compliance.c @@ -99,7 +99,7 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo, gcry_mpi_t key[], unsigned int keylength, const char *curvename) { - enum { is_rsa, is_dsa, is_pgp5, is_elg_sign, is_ecc } algotype; + enum { is_rsa, is_dsa, is_elg, is_ecc } algotype; int result = 0; if (! initialized) @@ -118,7 +118,7 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo, break; case PUBKEY_ALGO_ELGAMAL_E: - algotype = is_pgp5; + algotype = is_elg; break; case PUBKEY_ALGO_ECDH: @@ -128,8 +128,7 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo, break; case PUBKEY_ALGO_ELGAMAL: - algotype = is_elg_sign; - break; + return 0; /* Signing with Elgamal is not at all supported. */ default: /* Unknown. */ return 0; @@ -141,7 +140,7 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo, switch (algotype) { - case is_pgp5: + case is_elg: result = 0; break; @@ -183,11 +182,6 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo, } xfree (curve); } - else if (algotype == is_elg_sign) - { - /* An Elgamal signing key is only RFC-2440 compliant. */ - result = (compliance == CO_RFC2440); - } else { result = 1; /* Assume compliance. */ @@ -219,9 +213,9 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance, case PUBKEY_ALGO_RSA_S: switch (use) { - case PK_USE_ENCRYPTION: - return 1; case PK_USE_DECRYPTION: + return 1; + case PK_USE_ENCRYPTION: case PK_USE_SIGNING: return (keylength == 2048 || keylength == 3072 @@ -253,10 +247,34 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance, case PUBKEY_ALGO_ELGAMAL: case PUBKEY_ALGO_ELGAMAL_E: - return use == PK_USE_ENCRYPTION; + return use == PK_USE_DECRYPTION; case PUBKEY_ALGO_ECDH: - return use == PK_USE_ENCRYPTION; + if (use == PK_USE_DECRYPTION) + return 1; + else if (use == PK_USE_ENCRYPTION) + { + int result = 0; + char *curve = NULL; + + if (!curvename && key) + { + curve = openpgp_oid_to_str (key[0]); + curvename = openpgp_oid_to_curve (curve, 0); + if (!curvename) + curvename = curve; + } + + result = (curvename + && (!strcmp (curvename, "brainpoolP256r1") + || !strcmp (curvename, "brainpoolP384r1") + || !strcmp (curvename, "brainpoolP512r1"))); + + xfree (curve); + return result; + } + else + return 0; case PUBKEY_ALGO_ECDSA: { diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 0ddb8d7bb..013fd2f1b 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -90,19 +90,16 @@ get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek) sk->pubkey_algo = k->pubkey_algo; /* We want a pubkey with this algo. */ if (!(rc = get_seckey (ctrl, sk, k->keyid))) { - /* Check compliance. */ - if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION, - sk->pubkey_algo, - sk->pkey, nbits_from_pk (sk), NULL)) - { - log_info (_("key %s not suitable for decryption" - " while in %s mode\n"), - keystr_from_pk (sk), - gnupg_compliance_option_string (opt.compliance)); - rc = gpg_error (GPG_ERR_PUBKEY_ALGO); - } - else - rc = get_it (ctrl, k, dek, sk, k->keyid); + /* Print compliance warning. */ + if (!gnupg_pk_is_compliant (opt.compliance, + sk->pubkey_algo, + sk->pkey, nbits_from_pk (sk), NULL)) + log_info (_("Note: key %s was not suitable for encryption" + " in %s mode\n"), + keystr_from_pk (sk), + gnupg_compliance_option_string (opt.compliance)); + + rc = get_it (ctrl, k, dek, sk, k->keyid); } } else if (opt.skip_hidden_recipients) @@ -131,17 +128,14 @@ get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek) log_info (_("anonymous recipient; trying secret key %s ...\n"), keystr (keyid)); - /* Check compliance. */ - if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION, - sk->pubkey_algo, - sk->pkey, nbits_from_pk (sk), NULL)) - { - log_info (_("key %s not suitable for decryption" - " while in %s mode\n"), - keystr_from_pk (sk), - gnupg_compliance_option_string (opt.compliance)); - continue; - } + /* Print compliance warning. */ + if (!gnupg_pk_is_compliant (opt.compliance, + sk->pubkey_algo, + sk->pkey, nbits_from_pk (sk), NULL)) + log_info (_("Note: key %s was not suitable for encryption" + " in %s mode\n"), + keystr_from_pk (sk), + gnupg_compliance_option_string (opt.compliance)); rc = get_it (ctrl, k, dek, sk, keyid); if (!rc) diff --git a/sm/decrypt.c b/sm/decrypt.c index 170ad5ad3..3de742a25 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -480,17 +480,19 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp) unsigned int nbits; int pk_algo = gpgsm_get_key_algo_info (cert, &nbits); - /* Check compliance. */ - if (! gnupg_pk_is_allowed (opt.compliance, - PK_USE_DECRYPTION, - pk_algo, NULL, nbits, NULL)) + /* Print compliance warning. */ + if (! gnupg_pk_is_compliant (opt.compliance, + pk_algo, NULL, nbits, NULL)) { - log_error ("certificate ID 0x%08lX not suitable for " - "decryption while in %s mode\n", - gpgsm_get_short_fingerprint (cert, NULL), - gnupg_compliance_option_string (opt.compliance)); - rc = gpg_error (GPG_ERR_PUBKEY_ALGO); - goto oops; + char kidstr[10+1]; + + snprintf (kidstr, sizeof kidstr, "0x%08lX", + gpgsm_get_short_fingerprint (cert, NULL)); + log_info + (_("Note: key %s was not suitable for encryption" + " in %s mode\n"), + kidstr, + gnupg_compliance_option_string (opt.compliance)); } /* Check that all certs are compliant with CO_DE_VS. */