diff --git a/openssh-8.7p1-minimize-sha1-use.patch b/openssh-8.7p1-minimize-sha1-use.patch index 519b8f4..cbaba49 100644 --- a/openssh-8.7p1-minimize-sha1-use.patch +++ b/openssh-8.7p1-minimize-sha1-use.patch @@ -1,102 +1,194 @@ -diff -up openssh-8.7p1/kex.c.minsha1 openssh-8.7p1/kex.c ---- openssh-8.7p1/kex.c.minsha1 2021-12-20 17:38:51.438294309 +0100 -+++ openssh-8.7p1/kex.c 2021-12-21 11:02:48.379991319 +0100 -@@ -994,6 +994,35 @@ kex_choose_conf(struct ssh *ssh) - free(ext); - } +diff --color -ru a/clientloop.c b/clientloop.c +--- a/clientloop.c 2022-06-29 16:35:06.677597259 +0200 ++++ b/clientloop.c 2022-06-29 16:40:29.737926205 +0200 +@@ -116,6 +116,9 @@ + #include "ssh-gss.h" + #endif -+ /* Check whether client supports rsa-sha2 algorithms */ -+ if (kex->server && (kex->flags & KEX_INITIAL)) { -+ char *ext; ++/* Permitted RSA signature algorithms for UpdateHostkeys proofs */ ++#define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" + -+ ext = match_list("rsa-sha2-256", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); -+ if (ext) { -+ kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; -+ free(ext); + /* import options */ + extern Options options; + +@@ -2110,8 +2113,10 @@ + struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; + size_t i, ndone; + struct sshbuf *signdata; +- int r, kexsigtype, use_kexsigtype; ++ int r, plaintype; + const u_char *sig; ++ const char *rsa_kexalg = NULL; ++ char *alg = NULL; + size_t siglen; + + if (ctx->nnew == 0) +@@ -2122,9 +2127,9 @@ + hostkeys_update_ctx_free(ctx); + return; + } +- kexsigtype = sshkey_type_plain( +- sshkey_type_from_name(ssh->kex->hostkey_alg)); +- ++ if (sshkey_type_plain(sshkey_type_from_name( ++ ssh->kex->hostkey_alg)) == KEY_RSA) ++ rsa_kexalg = ssh->kex->hostkey_alg; + if ((signdata = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + /* +@@ -2135,6 +2140,7 @@ + for (ndone = i = 0; i < ctx->nkeys; i++) { + if (ctx->keys_match[i]) + continue; ++ plaintype = sshkey_type_plain(ctx->keys[i]->type); + /* Prepare data to be signed: session ID, unique string, key */ + sshbuf_reset(signdata); + if ( (r = sshbuf_put_cstring(signdata, +@@ -2148,19 +2154,33 @@ + error_fr(r, "parse sig"); + goto out; + } ++ if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) { ++ error_fr(r, "server gave unintelligible signature " ++ "for %s key %zu", sshkey_type(ctx->keys[i]), i); ++ goto out; + } -+ -+ ext = match_list("rsa-sha2-512", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); -+ if (ext) { -+ kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; -+ free(ext); + /* +- * For RSA keys, prefer to use the signature type negotiated +- * during KEX to the default (SHA1). ++ * Special case for RSA keys: if a RSA hostkey was negotiated, ++ * then use its signature type for verification of RSA hostkey ++ * proofs. Otherwise, accept only RSA-SHA256/512 signatures. + */ +- use_kexsigtype = kexsigtype == KEY_RSA && +- sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA; +- debug3_f("verify %s key %zu using %s sigalg", +- sshkey_type(ctx->keys[i]), i, +- use_kexsigtype ? ssh->kex->hostkey_alg : "default"); ++ if (plaintype == KEY_RSA && rsa_kexalg == NULL && ++ match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS, 0) != 1) { ++ debug_f("server used untrusted RSA signature algorithm " ++ "%s for key %zu, disregarding", alg, i); ++ free(alg); ++ /* zap the key from the list */ ++ sshkey_free(ctx->keys[i]); ++ ctx->keys[i] = NULL; ++ ndone++; ++ continue; + } ++ debug3_f("verify %s key %zu using sigalg %s", ++ sshkey_type(ctx->keys[i]), i, alg); ++ free(alg); + if ((r = sshkey_verify(ctx->keys[i], sig, siglen, + sshbuf_ptr(signdata), sshbuf_len(signdata), +- use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0, +- NULL)) != 0) { ++ plaintype == KEY_RSA ? rsa_kexalg : NULL, 0, NULL)) != 0) { + error_fr(r, "server gave bad signature for %s key %zu", + sshkey_type(ctx->keys[i]), i); + goto out; +diff --color -ru a/kex.c b/kex.c +--- a/kex.c 2022-06-29 16:35:06.775599179 +0200 ++++ b/kex.c 2022-06-29 16:42:00.839710940 +0200 +@@ -959,6 +959,18 @@ + return (1); + } + ++/* returns non-zero if proposal contains any algorithm from algs */ ++static int ++has_any_alg(const char *proposal, const char *algs) ++{ ++ char *cp; + -+ ext = match_list("rsa-sha2-256-cert-v01@openssh.com", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); -+ if (ext) { -+ kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; -+ free(ext); -+ } ++ if ((cp = match_list(proposal, algs, NULL)) == NULL) ++ return 0; ++ free(cp); ++ return 1; ++} + -+ ext = match_list("rsa-sha2-512-cert-v01@openssh.com", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); -+ if (ext) { + static int + kex_choose_conf(struct ssh *ssh) + { +@@ -994,6 +1006,16 @@ + free(ext); + } + ++ /* Check whether client supports rsa-sha2 algorithms */ ++ if (kex->server && (kex->flags & KEX_INITIAL)) { ++ if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com")) ++ kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; ++ if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com")) + kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; -+ free(ext); -+ } + } + /* Algorithm Negotiation */ if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS])) != 0) { -diff -up openssh-8.7p1/kex.h.minsha1 openssh-8.7p1/kex.h ---- openssh-8.7p1/kex.h.minsha1 2021-12-20 17:38:51.430294240 +0100 -+++ openssh-8.7p1/kex.h 2021-12-21 10:56:29.066735608 +0100 -@@ -116,6 +116,8 @@ enum kex_exchange { +diff --color -ru a/kex.h b/kex.h +--- a/kex.h 2022-06-29 16:35:06.766599003 +0200 ++++ b/kex.h 2022-06-29 16:42:24.199168567 +0200 +@@ -116,6 +116,8 @@ #define KEX_INIT_SENT 0x0001 #define KEX_INITIAL 0x0002 -+#define KEX_RSA_SHA2_256_SUPPORTED 0x0004 -+#define KEX_RSA_SHA2_512_SUPPORTED 0x0008 ++#define KEX_RSA_SHA2_256_SUPPORTED 0x0008 /* only set in server for now */ ++#define KEX_RSA_SHA2_512_SUPPORTED 0x0010 /* only set in server for now */ struct sshenc { char *name; -diff -up openssh-8.7p1/serverloop.c.minsha1 openssh-8.7p1/serverloop.c ---- openssh-8.7p1/serverloop.c.minsha1 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/serverloop.c 2021-12-21 11:01:00.594047538 +0100 -@@ -684,7 +685,7 @@ server_input_hostkeys_prove(struct ssh * +diff --color -ru a/serverloop.c b/serverloop.c +--- a/serverloop.c 2021-08-20 06:03:49.000000000 +0200 ++++ b/serverloop.c 2022-06-29 16:45:05.902336428 +0200 +@@ -684,16 +684,18 @@ struct sshbuf *resp = NULL; struct sshbuf *sigbuf = NULL; struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; - int r, ndx, kexsigtype, use_kexsigtype, success = 0; + int r, ndx, success = 0; const u_char *blob; ++ const char *sigalg, *kex_rsa_sigalg = NULL; u_char *sig = 0; size_t blen, slen; -@@ -692,9 +693,11 @@ server_input_hostkeys_prove(struct ssh * + if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); - kexsigtype = sshkey_type_plain( - sshkey_type_from_name(ssh->kex->hostkey_alg)); ++ if (sshkey_type_plain(sshkey_type_from_name( ++ ssh->kex->hostkey_alg)) == KEY_RSA) ++ kex_rsa_sigalg = ssh->kex->hostkey_alg; while (ssh_packet_remaining(ssh) > 0) { -+ const char *pkexstr = NULL; -+ const char *rsa_sha2_256 = "rsa-sha2-256"; -+ const char *rsa_sha2_512 = "rsa-sha2-512"; -+ sshkey_free(key); key = NULL; - if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 || -@@ -726,8 +729,13 @@ server_input_hostkeys_prove(struct ssh * +@@ -726,16 +728,24 @@ * For RSA keys, prefer to use the signature type negotiated * during KEX to the default (SHA1). */ - use_kexsigtype = kexsigtype == KEY_RSA && - sshkey_type_plain(key->type) == KEY_RSA; ++ sigalg = NULL; + if (sshkey_type_plain(key->type) == KEY_RSA) { -+ if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) -+ pkexstr = rsa_sha2_512; -+ else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) -+ pkexstr = rsa_sha2_256; ++ if (kex_rsa_sigalg != NULL) ++ sigalg = kex_rsa_sigalg; ++ else if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) ++ sigalg = "rsa-sha2-512"; ++ else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) ++ sigalg = "rsa-sha2-256"; + } -+ ++ debug3_f("sign %s key (index %d) using sigalg %s", ++ sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); if ((r = sshbuf_put_cstring(sigbuf, "hostkeys-prove-00@openssh.com")) != 0 || (r = sshbuf_put_stringb(sigbuf, -@@ -735,7 +743,7 @@ server_input_hostkeys_prove(struct ssh * + ssh->kex->session_id)) != 0 || (r = sshkey_puts(key, sigbuf)) != 0 || (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen, - sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), +- sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), - use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 || -+ pkexstr)) != 0 || ++ sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), sigalg)) != 0 || (r = sshbuf_put_string(resp, sig, slen)) != 0) { error_fr(r, "assemble signature"); goto out; diff --git a/openssh.spec b/openssh.spec index 6f6e971..22f4854 100644 --- a/openssh.spec +++ b/openssh.spec @@ -51,7 +51,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 8.7p1 -%global openssh_rel 8 +%global openssh_rel 9 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 4 @@ -212,7 +212,10 @@ Patch980: openssh-8.7p1-sftpscp-dir-create.patch # https://github.com/openssh/openssh-portable/pull/299 # downstream only Patch981: openssh-8.7p1-recursive-scp.patch - +# Minimize the use of SHA1 as a proof of possession for RSA key (#2031868) +# upstream commits: +# 291721bc7c840d113a49518f3fca70e86248b8e8 +# 0fa33683223c76289470a954404047bc762be84c Patch1000: openssh-8.7p1-minimize-sha1-use.patch License: BSD @@ -400,7 +403,7 @@ popd %patch201 -p1 -b .audit-race %patch700 -p1 -b .fips -%patch1000 -p1 -b .minsha1 +%patch1000 -p1 -b .minimize-sha1-use %patch100 -p1 -b .coverity @@ -681,6 +684,10 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Wed Jun 29 2022 Zoltan Fridrich - 8.7p1-9 +- Update minimize-sha1-use.patch to use upstream code + Related: rhbz#2031868 + * Mon Feb 21 2022 Dmitry Belyavskiy - 8.7p1-8 - Workaround for RHEL 8 incompatibility in scp utility in SFTP mode Related: rhbz#2038854