From 9d7154fdc40585a48c9a7c3a540c280977f2104b Mon Sep 17 00:00:00 2001 From: Anakin Zhang Date: Wed, 22 Apr 2020 15:26:34 +0800 Subject: [PATCH] fix CVE-2019-14855 --- ...0-Ignore-all-SHA-1-3rd-party-key-sig.patch | 99 ++++++++++ ...Add-option-allow-weak-key-signatures.patch | 178 ++++++++++++++++++ ...-creation-of-SHA-1-3rd-party-key-sig.patch | 162 ++++++++++++++++ gnupg2.spec | 10 +- 4 files changed, 447 insertions(+), 2 deletions(-) create mode 100644 fix-CVE-2019-14855-0-Ignore-all-SHA-1-3rd-party-key-sig.patch create mode 100644 fix-CVE-2019-14855-1-Add-option-allow-weak-key-signatures.patch create mode 100644 fix-CVE-2019-14855-2-Forbid-creation-of-SHA-1-3rd-party-key-sig.patch diff --git a/fix-CVE-2019-14855-0-Ignore-all-SHA-1-3rd-party-key-sig.patch b/fix-CVE-2019-14855-0-Ignore-all-SHA-1-3rd-party-key-sig.patch new file mode 100644 index 0000000..cd463c4 --- /dev/null +++ b/fix-CVE-2019-14855-0-Ignore-all-SHA-1-3rd-party-key-sig.patch @@ -0,0 +1,99 @@ +From 7d9aad63c4f1aefe97da61baf5acd96c12c0278e Mon Sep 17 00:00:00 2001 +From: Werner Koch +Date: Thu, 3 Oct 2019 18:20:59 +0200 +Subject: [PATCH] gpg: Ignore all SHA-1 signatures in 3rd party key signatures. + +* g10/sig-check.c (check_signature_over_key_or_uid): No cut-off date +and remove debug output. +-- + +With 2.2 we do not not support SHA-1 key signatures anymore even if +that means that the WoT shrinks. + +Signed-off-by: Werner Koch +--- + g10/sig-check.c | 40 +++++++++++++++++++++++++--------------- + 1 file changed, 25 insertions(+), 15 deletions(-) + +diff --git a/g10/sig-check.c b/g10/sig-check.c +index a93b496..c1498ef 100644 +--- a/g10/sig-check.c ++++ b/g10/sig-check.c +@@ -824,6 +824,10 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer, + PKT_public_key *pripk = kb->pkt->pkt.public_key; + gcry_md_hd_t md; + int signer_alloced = 0; ++ int stub_is_selfsig; ++ ++ if (!is_selfsig) ++ is_selfsig = &stub_is_selfsig; + + rc = openpgp_pk_test_algo (sig->pubkey_algo); + if (rc) +@@ -857,14 +861,11 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer, + + if (signer) + { +- if (is_selfsig) +- { +- if (signer->keyid[0] == pripk->keyid[0] +- && signer->keyid[1] == pripk->keyid[1]) +- *is_selfsig = 1; +- else +- *is_selfsig = 0; +- } ++ if (signer->keyid[0] == pripk->keyid[0] ++ && signer->keyid[1] == pripk->keyid[1]) ++ *is_selfsig = 1; ++ else ++ *is_selfsig = 0; + } + else + { +@@ -874,8 +875,7 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer, + { + /* Issued by the primary key. */ + signer = pripk; +- if (is_selfsig) +- *is_selfsig = 1; ++ *is_selfsig = 1; + } + else + { +@@ -904,8 +904,7 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer, + if (! signer) + { + /* Signer by some other key. */ +- if (is_selfsig) +- *is_selfsig = 0; ++ *is_selfsig = 0; + if (ret_pk) + { + signer = ret_pk; +@@ -966,9 +965,20 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer, + else if (IS_UID_SIG (sig) || IS_UID_REV (sig)) + { + log_assert (packet->pkttype == PKT_USER_ID); +- hash_public_key (md, pripk); +- hash_uid_packet (packet->pkt.user_id, md, sig); +- rc = check_signature_end_simple (signer, sig, md); ++ if (sig->digest_algo == DIGEST_ALGO_SHA1 && !*is_selfsig) ++ { ++ /* If the signature was created using SHA-1 we consider this ++ * signature invalid because it makes it possible to mount a ++ * chosen-prefix collision. We don't do this for ++ * self-signatures, though. */ ++ rc = gpg_error (GPG_ERR_DIGEST_ALGO); ++ } ++ else ++ { ++ hash_public_key (md, pripk); ++ hash_uid_packet (packet->pkt.user_id, md, sig); ++ rc = check_signature_end_simple (signer, sig, md); ++ } + } + else + { +-- +2.19.1 + diff --git a/fix-CVE-2019-14855-1-Add-option-allow-weak-key-signatures.patch b/fix-CVE-2019-14855-1-Add-option-allow-weak-key-signatures.patch new file mode 100644 index 0000000..cda2dee --- /dev/null +++ b/fix-CVE-2019-14855-1-Add-option-allow-weak-key-signatures.patch @@ -0,0 +1,178 @@ +From e624c41dbafd33af82c1153188d14de72fcc7cd8 Mon Sep 17 00:00:00 2001 +From: Werner Koch +Date: Thu, 7 Nov 2019 10:36:17 +0100 +Subject: [PATCH] gpg: Add option --allow-weak-key-signatures. + +* g10/gpg.c (oAllowWeakKeySignatures): New. +(opts): Add --allow-weak-key-signatures. +(main): Set it. +* g10/options.h (struct opt): Add flags.allow_weak_key_signatures. +* g10/misc.c (print_sha1_keysig_rejected_note): New. +* g10/sig-check.c (check_signature_over_key_or_uid): Print note and +act on new option. + +Signed-off-by: Werner Koch +--- + doc/gpg.texi | 19 ++++++++++++++----- + g10/gpg.c | 8 ++++++++ + g10/main.h | 1 + + g10/misc.c | 18 ++++++++++++++++++ + g10/options.h | 1 + + g10/sig-check.c | 4 +++- + 6 files changed, 45 insertions(+), 6 deletions(-) + +diff --git a/doc/gpg.texi b/doc/gpg.texi +index 8a88b11..093c309 100644 +--- a/doc/gpg.texi ++++ b/doc/gpg.texi +@@ -113,9 +113,12 @@ only one command is allowed. Generally speaking, irrelevant options + are silently ignored, and may not be checked for correctness. + + @command{@gpgname} may be run with no commands. In this case it will +-perform a reasonable action depending on the type of file it is given +-as input (an encrypted message is decrypted, a signature is verified, +-a file containing keys is listed, etc.). ++print a warning perform a reasonable action depending on the type of ++file it is given as input (an encrypted message is decrypted, a ++signature is verified, a file containing keys is listed, etc.). ++ ++If you run into any problems, please add the option @option{--verbose} ++to the invocation to see more diagnostics. + + + @menu +@@ -2355,10 +2358,10 @@ opposite meaning. The options are: + + @item self-sigs-only + Accept only self-signatures while importing a key. All other +- key-signatures are skipped at an early import stage. This option ++ key signatures are skipped at an early import stage. This option + can be used with @code{keyserver-options} to mitigate attempts to + flood a key with bogus signatures from a keyserver. The drawback is +- that all other valid key-signatures, as required by the Web of Trust ++ that all other valid key signatures, as required by the Web of Trust + are also not imported. + + @item repair-keys +@@ -3262,6 +3265,12 @@ weak. See also @option{--allow-weak-digest-algos} to disable + rejection of weak digests. MD5 is always considered weak, and does + not need to be listed explicitly. + ++@item --allow-weak-key-signatures ++@opindex allow-weak-key-signatures ++To avoid a minor risk of collision attacks on third-party key ++signatures made using SHA-1, those key signatures are considered ++invalid. This options allows to override this restriction. ++ + @item --no-default-keyring + @opindex no-default-keyring + Do not add the default keyrings to the list of keyrings. Note that +diff --git a/g10/gpg.c b/g10/gpg.c +index 2c784d4..03540a1 100644 +--- a/g10/gpg.c ++++ b/g10/gpg.c +@@ -407,6 +407,7 @@ enum cmd_and_opt_values + oAllowMultipleMessages, + oNoAllowMultipleMessages, + oAllowWeakDigestAlgos, ++ oAllowWeakKeySignatures, + oFakedSystemTime, + oNoAutostart, + oPrintPKARecords, +@@ -867,6 +868,9 @@ static ARGPARSE_OPTS opts[] = { + ARGPARSE_s_n (oNoAllowMultipleMessages, "no-allow-multiple-messages", "@"), + ARGPARSE_s_n (oAllowWeakDigestAlgos, "allow-weak-digest-algos", "@"), + ++ /* Options to override new security defaults. */ ++ ARGPARSE_s_n (oAllowWeakKeySignatures, "allow-weak-key-signatures", "@"), ++ + ARGPARSE_s_s (oDefaultNewKeyAlgo, "default-new-key-algo", "@"), + + /* These two are aliases to help users of the PGP command line +@@ -3550,6 +3554,10 @@ main (int argc, char **argv) + opt.flags.allow_weak_digest_algos = 1; + break; + ++ case oAllowWeakKeySignatures: ++ opt.flags.allow_weak_key_signatures = 1; ++ break; ++ + case oFakedSystemTime: + { + size_t len = strlen (pargs.r.ret_str); +diff --git a/g10/main.h b/g10/main.h +index 9136e4c..90e164f 100644 +--- a/g10/main.h ++++ b/g10/main.h +@@ -91,6 +91,7 @@ void print_pubkey_algo_note (pubkey_algo_t algo); + void print_cipher_algo_note (cipher_algo_t algo); + void print_digest_algo_note (digest_algo_t algo); + void print_digest_rejected_note (enum gcry_md_algos algo); ++void print_sha1_keysig_rejected_note (void); + void print_reported_error (gpg_error_t err, gpg_err_code_t skip_if_ec); + void print_further_info (const char *format, ...) GPGRT_ATTR_PRINTF(1,2); + void additional_weak_digest (const char* digestname); +diff --git a/g10/misc.c b/g10/misc.c +index 6d525a8..291d36f 100644 +--- a/g10/misc.c ++++ b/g10/misc.c +@@ -357,6 +357,24 @@ print_digest_rejected_note (enum gcry_md_algos algo) + } + + ++void ++print_sha1_keysig_rejected_note (void) ++{ ++ static int shown; ++ ++ if (shown) ++ return; ++ ++ shown = 1; ++ es_fflush (es_stdout); ++ log_info (_("Note: third-party key signatures using" ++ " the %s algorithm are rejected\n"), ++ gcry_md_algo_name (GCRY_MD_SHA1)); ++ print_further_info ("use option \"%s\" to override", ++ "--allow-weak-key-signatures"); ++} ++ ++ + /* Print a message + * "(reported error: %s)\n + * in verbose mode to further explain an error. If the error code has +diff --git a/g10/options.h b/g10/options.h +index 0f007c1..ffeecaa 100644 +--- a/g10/options.h ++++ b/g10/options.h +@@ -237,6 +237,7 @@ struct + unsigned int dsa2:1; + unsigned int allow_multiple_messages:1; + unsigned int allow_weak_digest_algos:1; ++ unsigned int allow_weak_key_signatures:1; + unsigned int large_rsa:1; + unsigned int disable_signer_uid:1; + /* Flag to enable experimental features from RFC4880bis. */ +diff --git a/g10/sig-check.c b/g10/sig-check.c +index a4e0df1..f48f0cd 100644 +--- a/g10/sig-check.c ++++ b/g10/sig-check.c +@@ -965,12 +965,14 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer, + else if (IS_UID_SIG (sig) || IS_UID_REV (sig)) + { + log_assert (packet->pkttype == PKT_USER_ID); +- if (sig->digest_algo == DIGEST_ALGO_SHA1 && !*is_selfsig) ++ if (sig->digest_algo == DIGEST_ALGO_SHA1 && !*is_selfsig ++ && !opt.flags.allow_weak_key_signatures) + { + /* If the signature was created using SHA-1 we consider this + * signature invalid because it makes it possible to mount a + * chosen-prefix collision. We don't do this for + * self-signatures, though. */ ++ print_sha1_keysig_rejected_note (); + rc = gpg_error (GPG_ERR_DIGEST_ALGO); + } + else +-- +1.8.3.1 + diff --git a/fix-CVE-2019-14855-2-Forbid-creation-of-SHA-1-3rd-party-key-sig.patch b/fix-CVE-2019-14855-2-Forbid-creation-of-SHA-1-3rd-party-key-sig.patch new file mode 100644 index 0000000..bd2530e --- /dev/null +++ b/fix-CVE-2019-14855-2-Forbid-creation-of-SHA-1-3rd-party-key-sig.patch @@ -0,0 +1,162 @@ +From 754a03f5a279964af62025d11d92391e650fddb7 Mon Sep 17 00:00:00 2001 +From: Werner Koch +Date: Mon, 11 Nov 2019 11:41:00 +0100 +Subject: [PATCH] gpg: Forbid the creation of SHA-1 third-party key +signatures. + +* g10/sign.c (SIGNHINT_KEYSIG, SIGNHINT_SELFSIG): New. +(do_sign): Add arg signhints and inhibit SHA-1 signatures. Change +callers to pass 0. +(complete_sig): Add arg signhints and pass on. +(make_keysig_packet, update_keysig_packet): Set signhints. +-- + +Signed-off-by: Werner Koch +--- + g10/sign.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 45 insertions(+), 7 deletions(-) + +diff --git a/g10/sign.c b/g10/sign.c +index 92ff361..543e1a7 100644 +--- a/g10/sign.c ++++ b/g10/sign.c +@@ -49,8 +49,15 @@ + #define LF "\n" + #endif + ++/* Bitflags to convey hints on what kind of signayire is created. */ ++#define SIGNHINT_KEYSIG 1 ++#define SIGNHINT_SELFSIG 2 ++ ++ ++/* Hack */ + static int recipient_digest_algo=0; + ++ + /**************** + * Create notations and other stuff. It is assumed that the stings in + * STRLIST are already checked to contain only printable data and have +@@ -252,10 +259,12 @@ hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig) + + + /* Perform the sign operation. If CACHE_NONCE is given the agent is +- advised to use that cached passphrase for the key. */ ++ * advised to use that cached passphrase for the key. SIGNHINTS has ++ * hints so that we can do some additional checks. */ + static int + do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig, +- gcry_md_hd_t md, int mdalgo, const char *cache_nonce) ++ gcry_md_hd_t md, int mdalgo, ++ const char *cache_nonce, unsigned int signhints) + { + gpg_error_t err; + byte *dp; +@@ -278,6 +287,19 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig, + if (!mdalgo) + mdalgo = gcry_md_get_algo (md); + ++ if ((signhints & SIGNHINT_KEYSIG) && !(signhints & SIGNHINT_SELFSIG) ++ && mdalgo == GCRY_MD_SHA1 ++ && !opt.flags.allow_weak_key_signatures) ++ { ++ /* We do not allow the creation of third-party key signatures ++ * using SHA-1 because we also reject them when verifying. Note ++ * that this will render dsa1024 keys unsuitable for such ++ * keysigs and in turn the WoT. */ ++ print_sha1_keysig_rejected_note (); ++ err = gpg_error (GPG_ERR_DIGEST_ALGO); ++ goto leave; ++ } ++ + /* Check compliance. */ + if (! gnupg_digest_is_allowed (opt.compliance, 1, mdalgo)) + { +@@ -374,12 +396,12 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig, + static int + complete_sig (ctrl_t ctrl, + PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md, +- const char *cache_nonce) ++ const char *cache_nonce, unsigned int signhints) + { + int rc; + + /* if (!(rc = check_secret_key (pksk, 0))) */ +- rc = do_sign (ctrl, pksk, sig, md, 0, cache_nonce); ++ rc = do_sign (ctrl, pksk, sig, md, 0, cache_nonce, signhints); + return rc; + } + +@@ -753,7 +775,7 @@ write_signature_packets (ctrl_t ctrl, + hash_sigversion_to_magic (md, sig); + gcry_md_final (md); + +- rc = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce); ++ rc = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce, 0); + gcry_md_close (md); + if (!rc) + { +@@ -1468,6 +1490,8 @@ make_keysig_packet (ctrl_t ctrl, + int rc=0; + int sigversion; + gcry_md_hd_t md; ++ u32 pk_keyid[2], pksk_keyid[2]; ++ unsigned int signhints; + + log_assert ((sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F + || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19 +@@ -1504,6 +1528,12 @@ make_keysig_packet (ctrl_t ctrl, + digest_algo = DEFAULT_DIGEST_ALGO; + } + ++ signhints = SIGNHINT_KEYSIG; ++ keyid_from_pk (pk, pk_keyid); ++ keyid_from_pk (pksk, pksk_keyid); ++ if (pk_keyid[0] == pksk_keyid[0] && pk_keyid[1] == pksk_keyid[1]) ++ signhints |= SIGNHINT_SELFSIG; ++ + if ( gcry_md_open (&md, digest_algo, 0 ) ) + BUG (); + +@@ -1549,7 +1579,7 @@ make_keysig_packet (ctrl_t ctrl, + hash_sigversion_to_magic (md, sig); + gcry_md_final (md); + +- rc = complete_sig (ctrl, sig, pksk, md, cache_nonce); ++ rc = complete_sig (ctrl, sig, pksk, md, cache_nonce, signhints); + } + + gcry_md_close (md); +@@ -1585,6 +1615,8 @@ update_keysig_packet (ctrl_t ctrl, + gpg_error_t rc = 0; + int digest_algo; + gcry_md_hd_t md; ++ u32 pk_keyid[2], pksk_keyid[2]; ++ unsigned int signhints; + + if ((!orig_sig || !pk || !pksk) + || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid) +@@ -1603,6 +1635,12 @@ update_keysig_packet (ctrl_t ctrl, + else + digest_algo = orig_sig->digest_algo; + ++ signhints = SIGNHINT_KEYSIG; ++ keyid_from_pk (pk, pk_keyid); ++ keyid_from_pk (pksk, pksk_keyid); ++ if (pk_keyid[0] == pksk_keyid[0] && pk_keyid[1] == pksk_keyid[1]) ++ signhints |= SIGNHINT_SELFSIG; ++ + if ( gcry_md_open (&md, digest_algo, 0 ) ) + BUG (); + +@@ -1656,7 +1694,7 @@ update_keysig_packet (ctrl_t ctrl, + hash_sigversion_to_magic (md, sig); + gcry_md_final (md); + +- rc = complete_sig (ctrl, sig, pksk, md, NULL); ++ rc = complete_sig (ctrl, sig, pksk, md, NULL, signhints); + } + + leave: +-- +1.8.3.1 + diff --git a/gnupg2.spec b/gnupg2.spec index c0f1620..e635251 100644 --- a/gnupg2.spec +++ b/gnupg2.spec @@ -1,14 +1,17 @@ Name: gnupg2 Version: 2.2.17 -Release: 5 +Release: 5.h1 Summary: Utility for secure communication and data storage License: GPLv3+ URL: https://gnupg.org/ Source0: https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-%{version}.tar.bz2 Source1: https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-%{version}.tar.bz2.sig +Patch0: fix-CVE-2019-14855-0-Ignore-all-SHA-1-3rd-party-key-sig.patch +Patch1: fix-CVE-2019-14855-1-Add-option-allow-weak-key-signatures.patch +Patch2: fix-CVE-2019-14855-2-Forbid-creation-of-SHA-1-3rd-party-key-sig.patch -BuildRequires: zlib-devel, npth-devel gdb +BuildRequires: zlib-devel, npth-devel, gdb, texinfo BuildRequires: libgpg-error-devel >= 1.31 BuildRequires: libgcrypt-devel >= 1.7.0 BuildRequires: libksba-devel >= 1.3.0 @@ -101,6 +104,9 @@ make check %changelog +* Wed Apr 22 2020 Anakin Zhang - 2.2.17-5.h1 +- fix CVE-2019-14855 + * Sat Mar 14 2020 openEuler Buildteam - 2.2.17-5 - Add build requires of gdb -- Gitee