diff --git a/SOURCES/openssh-6.7p1-coverity.patch b/SOURCES/openssh-6.7p1-coverity.patch
index 6852384..e372f09 100644
--- a/SOURCES/openssh-6.7p1-coverity.patch
+++ b/SOURCES/openssh-6.7p1-coverity.patch
@@ -101,22 +101,6 @@ diff -up openssh-7.4p1/channels.c.coverity openssh-7.4p1/channels.c
  	return idx;
  }
  
-diff -up openssh-8.5p1/compat.c.coverity openssh-8.5p1/compat.c
---- openssh-8.5p1/compat.c.coverity	2021-03-24 12:03:33.768968062 +0100
-+++ openssh-8.5p1/compat.c	2021-03-24 12:03:33.783968166 +0100
-@@ -191,10 +191,12 @@ compat_kex_proposal(struct ssh *ssh, cha
- 		return p;
- 	debug2_f("original KEX proposal: %s", p);
- 	if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
-+		/* coverity[overwrite_var : FALSE] */
- 		if ((p = match_filter_denylist(p,
- 		    "curve25519-sha256@libssh.org")) == NULL)
- 			fatal("match_filter_denylist failed");
- 	if ((ssh->compat & SSH_OLD_DHGEX) != 0) {
-+		/* coverity[overwrite_var : FALSE] */
- 		if ((p = match_filter_denylist(p,
- 		    "diffie-hellman-group-exchange-sha256,"
- 		    "diffie-hellman-group-exchange-sha1")) == NULL)
 diff -up openssh-8.5p1/dns.c.coverity openssh-8.5p1/dns.c
 --- openssh-8.5p1/dns.c.coverity	2021-03-02 11:31:47.000000000 +0100
 +++ openssh-8.5p1/dns.c	2021-03-24 12:03:33.783968166 +0100
@@ -392,10 +376,9 @@ diff -up openssh-8.5p1/session.c.coverity openssh-8.5p1/session.c
  	}
  
  	/* SSH_CLIENT deprecated */
-diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c
---- openssh-7.4p1/sftp.c.coverity	2016-12-19 05:59:41.000000000 +0100
-+++ openssh-7.4p1/sftp.c	2016-12-23 16:40:26.903788691 +0100
-@@ -224,7 +224,7 @@ killchild(int signo)
+--- a/sftp.c	2022-06-30 10:43:13.914058913 +0200
++++ b/sftp.c	2022-06-30 10:48:17.243997888 +0200
+@@ -222,7 +222,7 @@ killchild(int signo)
  	pid = sshpid;
  	if (pid > 1) {
  		kill(pid, SIGTERM);
@@ -404,8 +387,8 @@ diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c
  	}
  
  	_exit(1);
-@@ -762,6 +762,8 @@ process_put(struct sftp_conn *conn, cons
- 			    fflag || global_fflag) == -1)
+@@ -768,6 +768,8 @@ process_put(struct sftp_conn *conn, cons
+ 			    fflag || global_fflag, 0) == -1)
  				err = -1;
  		}
 +		free(abs_dst);
@@ -413,7 +396,7 @@ diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c
  	}
  
  out:
-@@ -985,6 +987,7 @@ do_globbed_ls(struct sftp_conn *conn, co
+@@ -991,6 +993,7 @@ do_globbed_ls(struct sftp_conn *conn, co
  		if (lflag & LS_LONG_VIEW) {
  			if (g.gl_statv[i] == NULL) {
  				error("no stat information for %s", fname);
@@ -514,15 +497,6 @@ diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c
  }
  
  /*
-@@ -2474,7 +2479,7 @@ do_ssh2_kex(struct ssh *ssh)
- 	if (options.rekey_limit || options.rekey_interval)
- 		ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
- 		    options.rekey_interval);
--
-+	/* coverity[leaked_storage : FALSE]*/
- 	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
- 	    ssh, list_hostkey_types());
- 
 @@ -2519,8 +2524,11 @@ do_ssh2_kex(struct ssh *ssh)
  
  	if (newstr)
diff --git a/SOURCES/openssh-7.7p1-fips.patch b/SOURCES/openssh-7.7p1-fips.patch
index 6e72d04..1466b40 100644
--- a/SOURCES/openssh-7.7p1-fips.patch
+++ b/SOURCES/openssh-7.7p1-fips.patch
@@ -1,16 +1,3 @@
-diff -up openssh-8.6p1/cipher-ctr.c.fips openssh-8.6p1/cipher-ctr.c
---- openssh-8.6p1/cipher-ctr.c.fips	2021-05-06 12:08:36.423926297 +0200
-+++ openssh-8.6p1/cipher-ctr.c	2021-05-06 12:08:36.497926869 +0200
-@@ -179,7 +179,8 @@ evp_aes_128_ctr(void)
- 	aes_ctr.do_cipher = ssh_aes_ctr;
- #ifndef SSH_OLD_EVP
- 	aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
--	    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
-+	    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV |
-+	    EVP_CIPH_FLAG_FIPS;
- #endif
- 	return (&aes_ctr);
- }
 diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c
 --- openssh-8.6p1/dh.c.fips	2021-04-16 05:55:25.000000000 +0200
 +++ openssh-8.6p1/dh.c	2021-05-06 12:12:10.107634472 +0200
@@ -19,7 +6,7 @@ diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c
  	struct dhgroup dhg;
  
 +	if (FIPS_mode()) {
-+		logit("Using arbitrary primes is not allowed in FIPS mode."
++		verbose("Using arbitrary primes is not allowed in FIPS mode."
 +		    " Falling back to known groups.");
 +		return (dh_new_group_fallback(max));
 +	}
@@ -117,7 +104,7 @@ diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c
 diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h
 --- openssh-8.6p1/myproposal.h.fips	2021-04-16 05:55:25.000000000 +0200
 +++ openssh-8.6p1/myproposal.h	2021-05-06 12:08:36.498926877 +0200
-@@ -57,6 +57,20 @@
+@@ -57,6 +57,18 @@
  	"rsa-sha2-256," \
  	"ssh-rsa"
  
@@ -127,13 +114,11 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h
 +	"ecdsa-sha2-nistp521-cert-v01@openssh.com," \
 +	"rsa-sha2-512-cert-v01@openssh.com," \
 +	"rsa-sha2-256-cert-v01@openssh.com," \
-+	"ssh-rsa-cert-v01@openssh.com," \
 +	"ecdsa-sha2-nistp256," \
 +	"ecdsa-sha2-nistp384," \
 +	"ecdsa-sha2-nistp521," \
 +	"rsa-sha2-512," \
-+	"rsa-sha2-256," \
-+	"ssh-rsa"
++	"rsa-sha2-256"
 +
  #define	KEX_SERVER_ENCRYPT \
  	"chacha20-poly1305@openssh.com," \
@@ -359,6 +344,20 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c
  	/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
  	saved_argc = ac;
  	rexec_argc = ac;
+@@ -1931,6 +1931,13 @@ main(int ac, char **av)
+ 		    &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
+ 			do_log2_r(r, ll, "Unable to load host key \"%s\"",
+ 			    options.host_key_files[i]);
++		if (FIPS_mode() && key != NULL && (sshkey_type_plain(key->type) == KEY_ED25519_SK
++				||  sshkey_type_plain(key->type) == KEY_ED25519)) {
++		    logit_f("sshd: Ed25519 keys are not allowed in FIPS mode, skipping %s", options.host_key_files[i]);
++		    sshkey_free(key);
++		    key = NULL;
++		    continue;
++		}
+ 		if (sshkey_is_sk(key) &&
+ 		    key->sk_flags & SSH_SK_USER_PRESENCE_REQD) {
+ 			debug("host key %s requires user presence, ignoring",
 @@ -2110,6 +2113,10 @@ main(int ac, char **av)
  	/* Reinitialize the log (because of the fork above). */
  	log_init(__progname, options.log_level, options.log_facility, log_stderr);
@@ -408,15 +407,78 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c
  #include "ssh-sk.h"
  
  #ifdef WITH_XMSS
-@@ -1705,6 +1707,8 @@ rsa_generate_private_key(u_int bits, RSA
+@@ -285,6 +285,18 @@ sshkey_alg_list(int certs_only, int plai
+ 	for (kt = keytypes; kt->type != -1; kt++) {
+ 		if (kt->name == NULL || kt->type == KEY_NULL)
+ 			continue;
++		if (FIPS_mode()) {
++			switch (kt->type) {
++			case KEY_ED25519:
++			case KEY_ED25519_SK:
++			case KEY_ED25519_CERT:
++			case KEY_ED25519_SK_CERT:
++			     continue;
++			     break;
++			default:
++			     break;
++			}
++		}
+ 		if (!include_sigonly && kt->sigonly)
+ 			continue;
+ 		if ((certs_only && !kt->cert) || (plain_only && kt->cert))
+@@ -1503,6 +1503,20 @@ sshkey_read(struct sshkey *ret, char **c
+ 		return SSH_ERR_EC_CURVE_MISMATCH;
  	}
- 	if (!BN_set_word(f4, RSA_F4) ||
- 	    !RSA_generate_key_ex(private, bits, f4, NULL)) {
-+			if (FIPS_mode())
-+				logit_f("the key length might be unsupported by FIPS mode approved key generation method");
+ 
++	switch (type) {
++	case KEY_ED25519:
++	case KEY_ED25519_SK:
++	case KEY_ED25519_CERT:
++	case KEY_ED25519_SK_CERT:
++		if (FIPS_mode()) {
++		    sshkey_free(k);
++		    logit_f("Ed25519 keys are not allowed in FIPS mode");
++		    return SSH_ERR_INVALID_ARGUMENT;
++		}
++		break;
++	default:
++		break;
++	}
+ 	/* Fill in ret from parsed key */
+ 	ret->type = type;
+ 	if (sshkey_is_cert(ret)) {
+@@ -1705,6 +1707,8 @@ rsa_generate_private_key(u_int bits, RSA
+		goto out;
+
+	if (EVP_PKEY_keygen(ctx, &res) <= 0) {
++		if (FIPS_mode())
++			logit_f("the key length might be unsupported by FIPS mode approved key generation method");
  		ret = SSH_ERR_LIBCRYPTO_ERROR;
  		goto out;
  	}
+@@ -2916,6 +2916,11 @@ sshkey_sign(struct sshkey *key,
+ 		break;
+ 	case KEY_ED25519_SK:
+ 	case KEY_ED25519_SK_CERT:
++		if (FIPS_mode()) {
++		    logit_f("Ed25519 keys are not allowed in FIPS mode");
++		    return SSH_ERR_INVALID_ARGUMENT;
++		}
++		/* Fallthrough */
+ 	case KEY_ECDSA_SK_CERT:
+ 	case KEY_ECDSA_SK:
+ 		r = sshsk_sign(sk_provider, key, sigp, lenp, data,
+@@ -2973,6 +2978,10 @@ sshkey_verify(const struct sshkey *key,
+ 		return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
+ 	case KEY_ED25519_SK:
+ 	case KEY_ED25519_SK_CERT:
++		if (FIPS_mode()) {
++		    logit_f("Ed25519 keys are not allowed in FIPS mode");
++		    return SSH_ERR_INVALID_ARGUMENT;
++		}
+ 		return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen,
+ 		    compat, detailsp);
+ #ifdef WITH_XMSS
 diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c
 --- openssh-8.6p1/ssh-keygen.c.fips	2021-05-06 12:08:36.467926637 +0200
 +++ openssh-8.6p1/ssh-keygen.c	2021-05-06 12:08:36.503926916 +0200
@@ -427,7 +489,7 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c
 +	if (FIPS_mode()) {
 +		if (type == KEY_DSA)
 +			fatal("DSA keys are not allowed in FIPS mode");
-+		if (type == KEY_ED25519)
++		if (type == KEY_ED25519 || type == KEY_ED25519_SK)
 +			fatal("ED25519 keys are not allowed in FIPS mode");
 +	}
  	switch (type) {
@@ -452,3 +514,122 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c
  		if ((fd = mkstemp(prv_tmp)) == -1) {
  			error("Could not save your private key in %s: %s",
  			    prv_tmp, strerror(errno));
+diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c
+--- openssh-8.7p1/kexgen.c.fips3	2022-07-11 16:11:21.973519913 +0200
++++ openssh-8.7p1/kexgen.c	2022-07-11 16:25:31.172187365 +0200
+@@ -31,6 +31,7 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <signal.h>
++#include <openssl/crypto.h>
+ 
+ #include "sshkey.h"
+ #include "kex.h"
+@@ -115,10 +116,20 @@ kex_gen_client(struct ssh *ssh)
+ 		break;
+ #endif
+ 	case KEX_C25519_SHA256:
+-		r = kex_c25519_keypair(kex);
++		if (FIPS_mode()) {
++		    logit_f("Key exchange type c25519 is not allowed in FIPS mode");
++		    r = SSH_ERR_INVALID_ARGUMENT;
++		} else {
++		    r = kex_c25519_keypair(kex);
++		}
+ 		break;
+ 	case KEX_KEM_SNTRUP761X25519_SHA512:
+-		r = kex_kem_sntrup761x25519_keypair(kex);
++		if (FIPS_mode()) {
++		    logit_f("Key exchange type sntrup761 is not allowed in FIPS mode");
++		    r = SSH_ERR_INVALID_ARGUMENT;
++		} else {
++		    r = kex_kem_sntrup761x25519_keypair(kex);
++		}
+ 		break;
+ 	default:
+ 		r = SSH_ERR_INVALID_ARGUMENT;
+@@ -186,11 +197,21 @@ input_kex_gen_reply(int type, u_int32_t
+ 		break;
+ #endif
+ 	case KEX_C25519_SHA256:
+-		r = kex_c25519_dec(kex, server_blob, &shared_secret);
++		if (FIPS_mode()) {
++		    logit_f("Key exchange type c25519 is not allowed in FIPS mode");
++		    r = SSH_ERR_INVALID_ARGUMENT;
++		} else {
++		    r = kex_c25519_dec(kex, server_blob, &shared_secret);
++		}
+ 		break;
+ 	case KEX_KEM_SNTRUP761X25519_SHA512:
+-		r = kex_kem_sntrup761x25519_dec(kex, server_blob,
+-		    &shared_secret);
++		if (FIPS_mode()) {
++		    logit_f("Key exchange type sntrup761 is not allowed in FIPS mode");
++		    r = SSH_ERR_INVALID_ARGUMENT;
++		} else {
++		    r = kex_kem_sntrup761x25519_dec(kex, server_blob,
++		        &shared_secret);
++		}
+ 		break;
+ 	default:
+ 		r = SSH_ERR_INVALID_ARGUMENT;
+@@ -285,12 +306,22 @@ input_kex_gen_init(int type, u_int32_t s
+ 		break;
+ #endif
+ 	case KEX_C25519_SHA256:
+-		r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
+-		    &shared_secret);
++		if (FIPS_mode()) {
++		    logit_f("Key exchange type c25519 is not allowed in FIPS mode");
++		    r = SSH_ERR_INVALID_ARGUMENT;
++		} else {
++		    r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
++		        &shared_secret);
++		}
+ 		break;
+ 	case KEX_KEM_SNTRUP761X25519_SHA512:
+-		r = kex_kem_sntrup761x25519_enc(kex, client_pubkey,
+-		    &server_pubkey, &shared_secret);
++		if (FIPS_mode()) {
++		    logit_f("Key exchange type sntrup761 is not allowed in FIPS mode");
++		    r = SSH_ERR_INVALID_ARGUMENT;
++		} else {
++		    r = kex_kem_sntrup761x25519_enc(kex, client_pubkey,
++		        &server_pubkey, &shared_secret);
++		}
+ 		break;
+ 	default:
+ 		r = SSH_ERR_INVALID_ARGUMENT;
+diff -up openssh-8.7p1/ssh-ed25519.c.fips3 openssh-8.7p1/ssh-ed25519.c
+--- openssh-8.7p1/ssh-ed25519.c.fips3	2022-07-11 16:53:41.428343304 +0200
++++ openssh-8.7p1/ssh-ed25519.c	2022-07-11 16:56:09.284663661 +0200
+@@ -24,6 +24,7 @@
+ 
+ #include <string.h>
+ #include <stdarg.h>
++#include <openssl/crypto.h>
+ 
+ #include "log.h"
+ #include "sshbuf.h"
+@@ -52,6 +53,10 @@ ssh_ed25519_sign(const struct sshkey *ke
+ 	    key->ed25519_sk == NULL ||
+ 	    datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
+ 		return SSH_ERR_INVALID_ARGUMENT;
++	if (FIPS_mode()) {
++	    logit_f("Ed25519 keys are not allowed in FIPS mode");
++	    return SSH_ERR_INVALID_ARGUMENT;
++	}
+ 	smlen = slen = datalen + crypto_sign_ed25519_BYTES;
+ 	if ((sig = malloc(slen)) == NULL)
+ 		return SSH_ERR_ALLOC_FAIL;
+@@ -108,6 +113,10 @@ ssh_ed25519_verify(const struct sshkey *
+ 	    datalen >= INT_MAX - crypto_sign_ed25519_BYTES ||
+ 	    signature == NULL || signaturelen == 0)
+ 		return SSH_ERR_INVALID_ARGUMENT;
++	if (FIPS_mode()) {
++	    logit_f("Ed25519 keys are not allowed in FIPS mode");
++	    return SSH_ERR_INVALID_ARGUMENT;
++	}
+ 
+ 	if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+ 		return SSH_ERR_ALLOC_FAIL;
diff --git a/SOURCES/openssh-7.8p1-UsePAM-warning.patch b/SOURCES/openssh-7.8p1-UsePAM-warning.patch
index 8560c9f..feedcba 100644
--- a/SOURCES/openssh-7.8p1-UsePAM-warning.patch
+++ b/SOURCES/openssh-7.8p1-UsePAM-warning.patch
@@ -5,9 +5,9 @@ diff -up openssh-8.6p1/sshd.c.log-usepam-no openssh-8.6p1/sshd.c
  	parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
  	    cfg, &includes, NULL);
  
-+	/* 'UsePAM no' is not supported in Fedora */
++	/* 'UsePAM no' is not supported in RHEL */
 +	if (! options.use_pam)
-+		logit("WARNING: 'UsePAM no' is not supported in Fedora and may cause several problems.");
++		logit("WARNING: 'UsePAM no' is not supported in RHEL and may cause several problems.");
 +
  #ifdef WITH_OPENSSL
  	if (options.moduli_file != NULL)
@@ -19,7 +19,7 @@ diff -up openssh-8.6p1/sshd_config.log-usepam-no openssh-8.6p1/sshd_config
  # If you just want the PAM account and session checks to run without
  # PAM authentication, then enable this but set PasswordAuthentication
  # and KbdInteractiveAuthentication to 'no'.
-+# WARNING: 'UsePAM no' is not supported in Fedora and may cause several
++# WARNING: 'UsePAM no' is not supported in RHEL and may cause several
 +# problems.
  #UsePAM no
  
diff --git a/SOURCES/openssh-8.0p1-crypto-policies.patch b/SOURCES/openssh-8.0p1-crypto-policies.patch
index 762825e..502e1de 100644
--- a/SOURCES/openssh-8.0p1-crypto-policies.patch
+++ b/SOURCES/openssh-8.0p1-crypto-policies.patch
@@ -1,13 +1,13 @@
-diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5
---- openssh-8.7p1/ssh_config.5.crypto-policies	2021-08-30 13:29:00.174292872 +0200
-+++ openssh-8.7p1/ssh_config.5	2021-08-30 13:31:32.009548808 +0200
-@@ -373,17 +373,13 @@ or
+diff --color -ru a/ssh_config.5 b/ssh_config.5
+--- a/ssh_config.5	2022-07-12 15:05:22.550013071 +0200
++++ b/ssh_config.5	2022-07-12 15:17:20.016704545 +0200
+@@ -373,17 +373,13 @@
  .Qq *.c.example.com
  domains.
  .It Cm CASignatureAlgorithms
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies which algorithms are allowed for signing of certificates
@@ -24,13 +24,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5
  If the specified list begins with a
  .Sq +
  character, then the specified algorithms will be appended to the default set
-@@ -445,20 +441,25 @@ If the option is set to
+@@ -445,20 +441,25 @@
  (the default),
  the check will not be executed.
  .It Cm Ciphers
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies the ciphers allowed and their order of preference.
@@ -54,7 +54,7 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5
  .Pp
  The supported ciphers are:
  .Bd -literal -offset indent
-@@ -474,13 +475,6 @@ aes256-gcm@openssh.com
+@@ -474,13 +475,6 @@
  chacha20-poly1305@openssh.com
  .Ed
  .Pp
@@ -68,19 +68,19 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5
  The list of available ciphers may also be obtained using
  .Qq ssh -Q cipher .
  .It Cm ClearAllForwardings
-@@ -874,6 +868,11 @@ command line will be passed untouched to
+@@ -874,6 +868,11 @@
  The default is
  .Dq no .
  .It Cm GSSAPIKexAlgorithms
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  The list of key exchange algorithms that are offered for GSSAPI
  key exchange. Possible values are
  .Bd -literal -offset 3n
-@@ -886,10 +885,8 @@ gss-nistp256-sha256-,
+@@ -886,10 +885,8 @@
  gss-curve25519-sha256-
  .Ed
  .Pp
@@ -92,13 +92,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5
  .It Cm HashKnownHosts
  Indicates that
  .Xr ssh 1
-@@ -1219,29 +1216,25 @@ it may be zero or more of:
+@@ -1219,29 +1216,25 @@
  and
  .Cm pam .
  .It Cm KexAlgorithms
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies the available KEX (Key Exchange) algorithms.
@@ -131,13 +131,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5
  .Pp
  The list of available key exchange algorithms may also be obtained using
  .Qq ssh -Q kex .
-@@ -1351,37 +1344,33 @@ function, and all code in the
+@@ -1351,37 +1344,33 @@
  file.
  This option is intended for debugging and no overrides are enabled by default.
  .It Cm MACs
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies the MAC (message authentication code) algorithms
@@ -178,13 +178,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5
  The list of available MAC algorithms may also be obtained using
  .Qq ssh -Q mac .
  .It Cm NoHostAuthenticationForLocalhost
-@@ -1553,37 +1542,25 @@ instead of continuing to execute and pas
+@@ -1553,37 +1542,25 @@
  The default is
  .Cm no .
  .It Cm PubkeyAcceptedAlgorithms
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies the signature algorithms that will be used for public key
@@ -225,16 +225,16 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5
  .Pp
  The list of available signature algorithms may also be obtained using
  .Qq ssh -Q PubkeyAcceptedAlgorithms .
-diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
---- openssh-8.7p1/sshd_config.5.crypto-policies	2021-08-30 13:29:00.157292731 +0200
-+++ openssh-8.7p1/sshd_config.5	2021-08-30 13:32:16.263918533 +0200
-@@ -373,17 +373,13 @@ If the argument is
+diff --color -ru a/sshd_config.5 b/sshd_config.5
+--- a/sshd_config.5	2022-07-12 15:05:22.535012771 +0200
++++ b/sshd_config.5	2022-07-12 15:15:33.394809258 +0200
+@@ -373,17 +373,13 @@
  then no banner is displayed.
  By default, no banner is displayed.
  .It Cm CASignatureAlgorithms
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies which algorithms are allowed for signing of certificates
@@ -251,13 +251,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
  If the specified list begins with a
  .Sq +
  character, then the specified algorithms will be appended to the default set
-@@ -450,20 +446,25 @@ The default is
+@@ -450,20 +446,25 @@
  indicating not to
  .Xr chroot 2 .
  .It Cm Ciphers
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies the ciphers allowed.
@@ -281,7 +281,7 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
  .Pp
  The supported ciphers are:
  .Pp
-@@ -490,13 +491,6 @@ aes256-gcm@openssh.com
+@@ -490,13 +491,6 @@
  chacha20-poly1305@openssh.com
  .El
  .Pp
@@ -295,13 +295,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
  The list of available ciphers may also be obtained using
  .Qq ssh -Q cipher .
  .It Cm ClientAliveCountMax
-@@ -685,21 +679,22 @@ For this to work
+@@ -685,21 +679,22 @@
  .Cm GSSAPIKeyExchange
  needs to be enabled in the server and also used by the client.
  .It Cm GSSAPIKexAlgorithms
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  The list of key exchange algorithms that are accepted by GSSAPI
@@ -328,13 +328,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
  This option only applies to connections using GSSAPI.
  .It Cm HostbasedAcceptedAlgorithms
  Specifies the signature algorithms that will be accepted for hostbased
-@@ -799,26 +794,13 @@ is specified, the location of the socket
+@@ -799,26 +794,13 @@
  .Ev SSH_AUTH_SOCK
  environment variable.
  .It Cm HostKeyAlgorithms
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies the host key signature algorithms
@@ -360,13 +360,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
  The list of available signature algorithms may also be obtained using
  .Qq ssh -Q HostKeyAlgorithms .
  .It Cm IgnoreRhosts
-@@ -965,20 +947,25 @@ Specifies whether to look at .k5login fi
+@@ -965,20 +947,25 @@
  The default is
  .Cm yes .
  .It Cm KexAlgorithms
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies the available KEX (Key Exchange) algorithms.
@@ -390,7 +390,7 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
  The supported algorithms are:
  .Pp
  .Bl -item -compact -offset indent
-@@ -1010,15 +997,6 @@ ecdh-sha2-nistp521
+@@ -1010,15 +997,6 @@
  sntrup761x25519-sha512@openssh.com
  .El
  .Pp
@@ -406,13 +406,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
  The list of available key exchange algorithms may also be obtained using
  .Qq ssh -Q KexAlgorithms .
  .It Cm ListenAddress
-@@ -1104,21 +1082,26 @@ function, and all code in the
+@@ -1104,21 +1082,26 @@
  file.
  This option is intended for debugging and no overrides are enabled by default.
  .It Cm MACs
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies the available MAC (message authentication code) algorithms.
@@ -437,7 +437,7 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
  .Pp
  The algorithms that contain
  .Qq -etm
-@@ -1161,15 +1144,6 @@ umac-64-etm@openssh.com
+@@ -1161,15 +1144,6 @@
  umac-128-etm@openssh.com
  .El
  .Pp
@@ -453,13 +453,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5
  The list of available MAC algorithms may also be obtained using
  .Qq ssh -Q mac .
  .It Cm Match
-@@ -1548,37 +1522,25 @@ or equivalent.)
+@@ -1548,37 +1522,25 @@
  The default is
  .Cm yes .
  .It Cm PubkeyAcceptedAlgorithms
 +The default is handled system-wide by
 +.Xr crypto-policies 7 .
-+To see the defaults and how to modify this default, see manual page
++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
 +.Xr update-crypto-policies 8 .
 +.Pp
  Specifies the signature algorithms that will be accepted for public key
diff --git a/SOURCES/openssh-8.7p1-evpgenkey.patch b/SOURCES/openssh-8.7p1-evpgenkey.patch
new file mode 100644
index 0000000..1af9b49
--- /dev/null
+++ b/SOURCES/openssh-8.7p1-evpgenkey.patch
@@ -0,0 +1,110 @@
+diff -up openssh-8.7p1/sshkey.c.evpgenrsa openssh-8.7p1/sshkey.c
+--- openssh-8.7p1/sshkey.c.evpgenrsa	2022-06-30 15:14:58.200518353 +0200
++++ openssh-8.7p1/sshkey.c	2022-06-30 15:24:31.499641196 +0200
+@@ -1657,7 +1657,8 @@ sshkey_cert_type(const struct sshkey *k)
+ static int
+ rsa_generate_private_key(u_int bits, RSA **rsap)
+ {
+-	RSA *private = NULL;
++	EVP_PKEY_CTX *ctx = NULL;
++	EVP_PKEY *res = NULL;
+ 	BIGNUM *f4 = NULL;
+ 	int ret = SSH_ERR_INTERNAL_ERROR;
+ 
+@@ -1667,20 +1668,42 @@ rsa_generate_private_key(u_int bits, RSA
+ 	    bits > SSHBUF_MAX_BIGNUM * 8)
+ 		return SSH_ERR_KEY_LENGTH;
+ 	*rsap = NULL;
+-	if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
++
++	if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL
++		|| (f4 = BN_new()) == NULL || !BN_set_word(f4, RSA_F4)) {
+ 		ret = SSH_ERR_ALLOC_FAIL;
+ 		goto out;
+ 	}
+-	if (!BN_set_word(f4, RSA_F4) ||
+-	    !RSA_generate_key_ex(private, bits, f4, NULL)) {
++
++	if (EVP_PKEY_keygen_init(ctx) <= 0) {
++		ret = SSH_ERR_LIBCRYPTO_ERROR;
++		goto out;
++	}
++
++	if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) {
++		ret = SSH_ERR_KEY_LENGTH;
++		goto out;
++	}
++
++	if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, f4) <= 0)
++		goto out;
++
++	if (EVP_PKEY_keygen(ctx, &res) <= 0) {
++		ret = SSH_ERR_LIBCRYPTO_ERROR;
++		goto out;
++	}
++
++	/* This function is deprecated in OpenSSL 3.0 but OpenSSH doesn't worry about it*/
++	*rsap = EVP_PKEY_get1_RSA(res);
++	if (*rsap) {
++		ret = 0;
++	} else {
+ 		ret = SSH_ERR_LIBCRYPTO_ERROR;
+ 		goto out;
+ 	}
+-	*rsap = private;
+-	private = NULL;
+-	ret = 0;
+  out:
+-	RSA_free(private);
++	EVP_PKEY_CTX_free(ctx);
++	EVP_PKEY_free(res);
+ 	BN_free(f4);
+ 	return ret;
+ }
+@@ -1820,7 +1820,8 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k)
+ static int
+ ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
+ {
+-	EC_KEY *private;
++	EVP_PKEY_CTX *ctx = NULL;
++	EVP_PKEY *res = NULL;
+ 	int ret = SSH_ERR_INTERNAL_ERROR;
+ 
+ 	if (nid == NULL || ecdsap == NULL)
+@@ -1828,20 +1829,29 @@ ecdsa_generate_private_key(u_int bits, i
+ 	if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
+ 		return SSH_ERR_KEY_LENGTH;
+ 	*ecdsap = NULL;
+-	if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
++
++	if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL) {
+ 		ret = SSH_ERR_ALLOC_FAIL;
+ 		goto out;
+ 	}
+-	if (EC_KEY_generate_key(private) != 1) {
++
++	if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_CTX_set_group_name(ctx, OBJ_nid2sn(*nid)) <= 0
++	   || EVP_PKEY_keygen(ctx, &res) <= 0) {
++		ret = SSH_ERR_LIBCRYPTO_ERROR;
++		goto out;
++	}
++	/* This function is deprecated in OpenSSL 3.0 but OpenSSH doesn't worry about it*/
++	*ecdsap = EVP_PKEY_get1_EC_KEY(res);
++	if (*ecdsap) {
++		EC_KEY_set_asn1_flag(*ecdsap, OPENSSL_EC_NAMED_CURVE);
++		ret = 0;
++	} else {
+ 		ret = SSH_ERR_LIBCRYPTO_ERROR;
+ 		goto out;
+ 	}
+-	EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
+-	*ecdsap = private;
+-	private = NULL;
+-	ret = 0;
+  out:
+-	EC_KEY_free(private);
++	EVP_PKEY_CTX_free(ctx);
++	EVP_PKEY_free(res);
+ 	return ret;
+ }
+ # endif /* OPENSSL_HAS_ECC */
diff --git a/SOURCES/openssh-8.7p1-gssapi-auth.patch b/SOURCES/openssh-8.7p1-gssapi-auth.patch
new file mode 100644
index 0000000..6908cad
--- /dev/null
+++ b/SOURCES/openssh-8.7p1-gssapi-auth.patch
@@ -0,0 +1,20 @@
+diff --color -rup a/monitor.c b/monitor.c
+--- a/monitor.c	2022-07-11 15:11:28.146863144 +0200
++++ b/monitor.c	2022-07-11 15:15:35.726655877 +0200
+@@ -376,8 +376,15 @@ monitor_child_preauth(struct ssh *ssh, s
+ 		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
+ 			auth_log(ssh, authenticated, partial,
+ 			    auth_method, auth_submethod);
+-			if (!partial && !authenticated)
++			if (!partial && !authenticated) {
++#ifdef GSSAPI
++				/* If gssapi-with-mic failed, MONITOR_REQ_GSSCHECKMIC is disabled.
++				 * We have to reenable it to try again for gssapi-keyex */
++				if (strcmp(auth_method, "gssapi-with-mic") == 0 && options.gss_keyex)
++					monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
++#endif
+ 				authctxt->failures++;
++			}
+ 			if (authenticated || partial) {
+ 				auth2_update_session_info(authctxt,
+ 				    auth_method, auth_submethod);
diff --git a/SOURCES/openssh-8.7p1-host-based-auth.patch b/SOURCES/openssh-8.7p1-host-based-auth.patch
new file mode 100644
index 0000000..23efe91
--- /dev/null
+++ b/SOURCES/openssh-8.7p1-host-based-auth.patch
@@ -0,0 +1,151 @@
+diff --color -rup a/sshconnect2.c b/sshconnect2.c
+--- a/sshconnect2.c	2022-07-11 17:00:02.618575727 +0200
++++ b/sshconnect2.c	2022-07-11 17:03:05.096085690 +0200
+@@ -2288,9 +2288,9 @@ userauth_hostbased(struct ssh *ssh)
+ 			if (authctxt->sensitive->keys[i] == NULL ||
+ 			    authctxt->sensitive->keys[i]->type == KEY_UNSPEC)
+ 				continue;
+-			if (match_pattern_list(
++			if (!sshkey_match_keyname_to_sigalgs(
+ 			    sshkey_ssh_name(authctxt->sensitive->keys[i]),
+-			    authctxt->active_ktype, 0) != 1)
++			    authctxt->active_ktype))
+ 				continue;
+ 			/* we take and free the key */
+ 			private = authctxt->sensitive->keys[i];
+@@ -2316,7 +2316,8 @@ userauth_hostbased(struct ssh *ssh)
+ 		error_f("sshkey_fingerprint failed");
+ 		goto out;
+ 	}
+-	debug_f("trying hostkey %s %s", sshkey_ssh_name(private), fp);
++	debug_f("trying hostkey %s %s using sigalg %s",
++		sshkey_ssh_name(private), fp, authctxt->active_ktype);
+ 
+ 	/* figure out a name for the client host */
+ 	lname = get_local_name(ssh_packet_get_connection_in(ssh));
+diff --color -rup a/sshkey.c b/sshkey.c
+--- a/sshkey.c	2022-07-11 17:00:02.609575554 +0200
++++ b/sshkey.c	2022-07-11 17:12:30.905976443 +0200
+@@ -252,6 +252,29 @@ sshkey_ecdsa_nid_from_name(const char *n
+ 	return -1;
+ }
+ 
++int
++sshkey_match_keyname_to_sigalgs(const char *keyname, const char *sigalgs)
++{
++	int ktype;
++
++	if (sigalgs == NULL || *sigalgs == '\0' ||
++	    (ktype = sshkey_type_from_name(keyname)) == KEY_UNSPEC)
++		return 0;
++	else if (ktype == KEY_RSA) {
++		return match_pattern_list("ssh-rsa", sigalgs, 0) == 1 ||
++		    match_pattern_list("rsa-sha2-256", sigalgs, 0) == 1 ||
++		    match_pattern_list("rsa-sha2-512", sigalgs, 0) == 1;
++	} else if (ktype == KEY_RSA_CERT) {
++		return match_pattern_list("ssh-rsa-cert-v01@openssh.com",
++		    sigalgs, 0) == 1 ||
++		    match_pattern_list("rsa-sha2-256-cert-v01@openssh.com",
++		    sigalgs, 0) == 1 ||
++		    match_pattern_list("rsa-sha2-512-cert-v01@openssh.com",
++		    sigalgs, 0) == 1;
++	} else
++		return match_pattern_list(keyname, sigalgs, 0) == 1;
++}
++
+ char *
+ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
+ {
+diff --color -rup a/sshkey.h b/sshkey.h
+--- a/sshkey.h	2022-07-11 17:00:02.603575438 +0200
++++ b/sshkey.h	2022-07-11 17:13:01.052556879 +0200
+@@ -194,6 +194,10 @@ int	 sshkey_is_cert(const struct sshkey
+ int	 sshkey_is_sk(const struct sshkey *);
+ int	 sshkey_type_is_cert(int);
+ int	 sshkey_type_plain(int);
++
++/* Returns non-zero if key name match sigalgs pattern list. (handles RSA) */
++int	 sshkey_match_keyname_to_sigalgs(const char *, const char *);
++
+ int	 sshkey_to_certified(struct sshkey *);
+ int	 sshkey_drop_cert(struct sshkey *);
+ int	 sshkey_cert_copy(const struct sshkey *, struct sshkey *);
+diff --color -rup a/ssh-keysign.c b/ssh-keysign.c
+--- a/ssh-keysign.c	2021-08-20 06:03:49.000000000 +0200
++++ b/ssh-keysign.c	2022-07-11 17:00:23.306973667 +0200
+@@ -62,7 +62,7 @@
+ extern char *__progname;
+ 
+ static int
+-valid_request(struct passwd *pw, char *host, struct sshkey **ret,
++valid_request(struct passwd *pw, char *host, struct sshkey **ret, char **pkalgp,
+     u_char *data, size_t datalen)
+ {
+ 	struct sshbuf *b;
+@@ -75,6 +75,8 @@ valid_request(struct passwd *pw, char *h
+ 
+ 	if (ret != NULL)
+ 		*ret = NULL;
++	if (pkalgp != NULL)
++		*pkalgp = NULL;
+ 	fail = 0;
+ 
+ 	if ((b = sshbuf_from(data, datalen)) == NULL)
+@@ -122,8 +124,6 @@ valid_request(struct passwd *pw, char *h
+ 		fail++;
+ 	} else if (key->type != pktype)
+ 		fail++;
+-	free(pkalg);
+-	free(pkblob);
+ 
+ 	/* client host name, handle trailing dot */
+ 	if ((r = sshbuf_get_cstring(b, &p, &len)) != 0)
+@@ -154,8 +154,19 @@ valid_request(struct passwd *pw, char *h
+ 
+ 	if (fail)
+ 		sshkey_free(key);
+-	else if (ret != NULL)
+-		*ret = key;
++	else {
++		if (ret != NULL) {
++			*ret = key;
++			key = NULL;
++		}
++		if (pkalgp != NULL) {
++			*pkalgp = pkalg;
++			pkalg = NULL;
++		}
++	}
++	sshkey_free(key);
++	free(pkalg);
++	free(pkblob);
+ 
+ 	return (fail ? -1 : 0);
+ }
+@@ -170,7 +181,7 @@ main(int argc, char **argv)
+ 	struct passwd *pw;
+ 	int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
+ 	u_char *signature, *data, rver;
+-	char *host, *fp;
++	char *host, *fp, *pkalg;
+ 	size_t slen, dlen;
+ 
+ 	if (pledge("stdio rpath getpw dns id", NULL) != 0)
+@@ -258,7 +269,7 @@ main(int argc, char **argv)
+ 
+ 	if ((r = sshbuf_get_string(b, &data, &dlen)) != 0)
+ 		fatal_r(r, "%s: buffer error", __progname);
+-	if (valid_request(pw, host, &key, data, dlen) < 0)
++	if (valid_request(pw, host, &key, &pkalg, data, dlen) < 0)
+ 		fatal("%s: not a valid request", __progname);
+ 	free(host);
+ 
+@@ -279,7 +290,7 @@ main(int argc, char **argv)
+ 	}
+ 
+ 	if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen,
+-	    NULL, NULL, NULL, 0)) != 0)
++	    pkalg, NULL, NULL, 0)) != 0)
+ 		fatal_r(r, "%s: sshkey_sign failed", __progname);
+ 	free(data);
+ 
diff --git a/SOURCES/openssh-8.7p1-ibmca.patch b/SOURCES/openssh-8.7p1-ibmca.patch
new file mode 100644
index 0000000..c9c12ee
--- /dev/null
+++ b/SOURCES/openssh-8.7p1-ibmca.patch
@@ -0,0 +1,12 @@
+--- openssh-8.7p1/openbsd-compat/bsd-closefrom.c.orig	2022-04-12 15:47:03.815044607 +0200
++++ openssh-8.7p1/openbsd-compat/bsd-closefrom.c	2022-04-12 15:48:12.464963511 +0200
+@@ -16,7 +16,7 @@
+ 
+ #include "includes.h"
+ 
+-#ifndef HAVE_CLOSEFROM
++#if (!defined HAVE_CLOSEFROM) || (defined __s390__)
+ 
+ #include <sys/types.h>
+ #include <sys/param.h>
+
diff --git a/SOURCES/openssh-8.7p1-mem-leak.patch b/SOURCES/openssh-8.7p1-mem-leak.patch
new file mode 100644
index 0000000..8c9ac80
--- /dev/null
+++ b/SOURCES/openssh-8.7p1-mem-leak.patch
@@ -0,0 +1,156 @@
+diff --color -rup a/compat.c b/compat.c
+--- a/compat.c	2021-08-20 06:03:49.000000000 +0200
++++ b/compat.c	2022-07-14 17:39:23.770268440 +0200
+@@ -157,11 +157,12 @@ compat_banner(struct ssh *ssh, const cha
+ 	debug_f("no match: %s", version);
+ }
+ 
++/* Always returns pointer to allocated memory, caller must free. */
+ char *
+ compat_cipher_proposal(struct ssh *ssh, char *cipher_prop)
+ {
+ 	if (!(ssh->compat & SSH_BUG_BIGENDIANAES))
+-		return cipher_prop;
++		return xstrdup(cipher_prop);
+ 	debug2_f("original cipher proposal: %s", cipher_prop);
+ 	if ((cipher_prop = match_filter_denylist(cipher_prop, "aes*")) == NULL)
+ 		fatal("match_filter_denylist failed");
+@@ -171,11 +172,12 @@ compat_cipher_proposal(struct ssh *ssh,
+ 	return cipher_prop;
+ }
+ 
++/* Always returns pointer to allocated memory, caller must free. */
+ char *
+ compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop)
+ {
+ 	if (!(ssh->compat & SSH_BUG_RSASIGMD5))
+-		return pkalg_prop;
++		return xstrdup(pkalg_prop);
+ 	debug2_f("original public key proposal: %s", pkalg_prop);
+ 	if ((pkalg_prop = match_filter_denylist(pkalg_prop, "ssh-rsa")) == NULL)
+ 		fatal("match_filter_denylist failed");
+@@ -185,21 +187,26 @@ compat_pkalg_proposal(struct ssh *ssh, c
+ 	return pkalg_prop;
+ }
+ 
++/* Always returns pointer to allocated memory, caller must free. */
+ char *
+ compat_kex_proposal(struct ssh *ssh, char *p)
+ {
++	char *cp = NULL;
++
+ 	if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
+-		return p;
++		return xstrdup(p);
+ 	debug2_f("original KEX proposal: %s", p);
+ 	if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
+ 		if ((p = match_filter_denylist(p,
+ 		    "curve25519-sha256@libssh.org")) == NULL)
+ 			fatal("match_filter_denylist failed");
+ 	if ((ssh->compat & SSH_OLD_DHGEX) != 0) {
++		cp = p;
+ 		if ((p = match_filter_denylist(p,
+ 		    "diffie-hellman-group-exchange-sha256,"
+ 		    "diffie-hellman-group-exchange-sha1")) == NULL)
+ 			fatal("match_filter_denylist failed");
++		free(cp);
+ 	}
+ 	debug2_f("compat KEX proposal: %s", p);
+ 	if (*p == '\0')
+diff --color -rup a/sshconnect2.c b/sshconnect2.c
+--- a/sshconnect2.c	2022-07-14 17:38:43.241496549 +0200
++++ b/sshconnect2.c	2022-07-14 17:39:23.772268479 +0200
+@@ -222,6 +222,7 @@ ssh_kex2(struct ssh *ssh, char *host, st
+ {
+ 	char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
+ 	char *s, *all_key;
++	char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL;
+ 	int r, use_known_hosts_order = 0;
+ 
+ #if defined(GSSAPI) && defined(WITH_OPENSSL)
+@@ -252,10 +253,9 @@ ssh_kex2(struct ssh *ssh, char *host, st
+ 
+ 	if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
+ 		fatal_f("kex_names_cat");
+-	myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, s);
++	myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, s);
+ 	myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+-	    compat_cipher_proposal(ssh, options.ciphers);
+-	myproposal[PROPOSAL_ENC_ALGS_STOC] =
++	    myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc =
+ 	    compat_cipher_proposal(ssh, options.ciphers);
+ 	myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+ 	    myproposal[PROPOSAL_COMP_ALGS_STOC] =
+@@ -264,12 +264,12 @@ ssh_kex2(struct ssh *ssh, char *host, st
+ 	    myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+ 	if (use_known_hosts_order) {
+ 		/* Query known_hosts and prefer algorithms that appear there */
+-		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
++		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
+ 		    compat_pkalg_proposal(ssh,
+ 		    order_hostkeyalgs(host, hostaddr, port, cinfo));
+ 	} else {
+ 		/* Use specified HostkeyAlgorithms exactly */
+-		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
++		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
+ 		    compat_pkalg_proposal(ssh, options.hostkeyalgorithms);
+ 	}
+ 
+@@ -383,6 +383,10 @@ ssh_kex2(struct ssh *ssh, char *host, st
+ 	    (r = ssh_packet_write_wait(ssh)) != 0)
+ 		fatal_fr(r, "send packet");
+ #endif
++	/* Free only parts of proposal that were dynamically allocated here. */
++	free(prop_kex);
++	free(prop_enc);
++	free(prop_hostkey);
+ }
+ 
+ /*
+diff --color -rup a/sshd.c b/sshd.c
+--- a/sshd.c	2022-07-14 17:38:43.242496568 +0200
++++ b/sshd.c	2022-07-14 17:42:07.616388978 +0200
+@@ -2493,14 +2493,15 @@ do_ssh2_kex(struct ssh *ssh)
+ {
+ 	char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
+ 	struct kex *kex;
++	char *hostkey_types = NULL;
++	char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL;
+ 	int r;
+ 
+-	myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh,
++	myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh,
+ 	    options.kex_algorithms);
+-	myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(ssh,
+-	    options.ciphers);
+-	myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(ssh,
+-	    options.ciphers);
++	myproposal[PROPOSAL_ENC_ALGS_CTOS] =
++	    myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc =
++	    compat_cipher_proposal(ssh, options.ciphers);
+ 	myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+ 	    myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+ 
+@@ -2513,8 +2514,10 @@ do_ssh2_kex(struct ssh *ssh)
+ 		ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
+ 		    options.rekey_interval);
+ 
+-	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
+-	    ssh, list_hostkey_types());
++	hostkey_types = list_hostkey_types();
++	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
++	    compat_pkalg_proposal(ssh, hostkey_types);
++	free(hostkey_types);
+ 
+ #if defined(GSSAPI) && defined(WITH_OPENSSL)
+ 	{
+@@ -2606,6 +2609,9 @@ do_ssh2_kex(struct ssh *ssh)
+ 	    (r = ssh_packet_write_wait(ssh)) != 0)
+ 		fatal_fr(r, "send test");
+ #endif
++	free(prop_kex);
++	free(prop_enc);
++	free(prop_hostkey);
+ 	debug("KEX done");
+ }
+ 
diff --git a/SOURCES/openssh-8.7p1-minimize-sha1-use.patch b/SOURCES/openssh-8.7p1-minimize-sha1-use.patch
index 519b8f4..fc517da 100644
--- a/SOURCES/openssh-8.7p1-minimize-sha1-use.patch
+++ b/SOURCES/openssh-8.7p1-minimize-sha1-use.patch
@@ -1,102 +1,207 @@
-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 --git a/hostfile.c b/hostfile.c
+index a035b381..bd49e3ac 100644
+--- a/hostfile.c
++++ b/hostfile.c
+@@ -642,7 +642,7 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
+ 	/* Re-add the requested keys */
+ 	want = HKF_MATCH_HOST | (ip == NULL ? 0 : HKF_MATCH_IP);
+ 	for (i = 0; i < nkeys; i++) {
+-		if ((want & ctx.match_keys[i]) == want)
++		if (keys[i] == NULL || (want & ctx.match_keys[i]) == want)
+ 			continue;
+ 		if ((fp = sshkey_fingerprint(keys[i], hash_alg,
+ 		    SSH_FP_DEFAULT)) == NULL) {
+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/SOURCES/openssh-8.7p1-minrsabits.patch b/SOURCES/openssh-8.7p1-minrsabits.patch
new file mode 100644
index 0000000..107fe70
--- /dev/null
+++ b/SOURCES/openssh-8.7p1-minrsabits.patch
@@ -0,0 +1,437 @@
+diff --git a/auth2-hostbased.c b/auth2-hostbased.c
+index 2ab222ed6..4e9437912 100644
+--- a/auth2-hostbased.c
++++ b/auth2-hostbased.c
+@@ -118,6 +118,10 @@ userauth_hostbased(struct ssh *ssh, const char *method)
+ 		    "(null)" : key->cert->signature_type);
+ 		goto done;
+ 	}
++	if ((r = sshkey_check_rsa_length(key, options.rsa_min_size)) != 0) {
++		logit("refusing %s key", sshkey_type(key));
++		goto done;
++	}
+ 
+ 	if (!authctxt->valid || authctxt->user == NULL) {
+ 		debug2_f("disabled because of invalid user");
+diff --git a/auth2-pubkey.c b/auth2-pubkey.c
+index daa756a01..68e7dea1f 100644
+--- a/auth2-pubkey.c
++++ b/auth2-pubkey.c
+@@ -172,6 +172,10 @@ userauth_pubkey(struct ssh *ssh, const char *method)
+ 		    "(null)" : key->cert->signature_type);
+ 		goto done;
+ 	}
++	if ((r = sshkey_check_rsa_length(key, options.rsa_min_size)) != 0) {
++		logit("refusing %s key", sshkey_type(key));
++		goto done;
++	}
+ 	key_s = format_key(key);
+ 	if (sshkey_is_cert(key))
+ 		ca_s = format_key(key->cert->signature_key);
+diff --git a/readconf.c b/readconf.c
+index 5b5afa8e3..5e17abd41 100644
+--- a/readconf.c
++++ b/readconf.c
+@@ -160,7 +160,7 @@ typedef enum {
+ 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
+ 	oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
+ 	oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
+-	oSecurityKeyProvider, oKnownHostsCommand,
++	oSecurityKeyProvider, oKnownHostsCommand, oRSAMinSize,
+ 	oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
+ } OpCodes;
+ 
+@@ -306,6 +306,7 @@ static struct {
+ 	{ "proxyjump", oProxyJump },
+ 	{ "securitykeyprovider", oSecurityKeyProvider },
+ 	{ "knownhostscommand", oKnownHostsCommand },
++	{ "rsaminsize", oRSAMinSize },
+ 
+ 	{ NULL, oBadOption }
+ };
+@@ -2162,6 +2163,10 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
+ 			*charptr = xstrdup(arg);
+ 		break;
+ 
++	case oRSAMinSize:
++		intptr = &options->rsa_min_size;
++		goto parse_int;
++
+ 	case oDeprecated:
+ 		debug("%s line %d: Deprecated option \"%s\"",
+ 		    filename, linenum, keyword);
+@@ -2409,6 +2414,7 @@ initialize_options(Options * options)
+ 	options->hostbased_accepted_algos = NULL;
+ 	options->pubkey_accepted_algos = NULL;
+ 	options->known_hosts_command = NULL;
++	options->rsa_min_size = -1;
+ }
+ 
+ /*
+@@ -2598,6 +2604,8 @@ fill_default_options(Options * options)
+ 	if (options->sk_provider == NULL)
+ 		options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
+ #endif
++	if (options->rsa_min_size == -1)
++		options->rsa_min_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
+ 
+ 	/* Expand KEX name lists */
+ 	all_cipher = cipher_alg_list(',', 0);
+@@ -3287,6 +3295,7 @@ dump_client_config(Options *o, const char *host)
+ 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
+ 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
+ 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
++	dump_cfg_int(oRSAMinSize, o->rsa_min_size);
+ 
+ 	/* String options */
+ 	dump_cfg_string(oBindAddress, o->bind_address);
+diff --git a/readconf.h b/readconf.h
+index f647bd42a..29db353ab 100644
+--- a/readconf.h
++++ b/readconf.h
+@@ -176,6 +176,8 @@ typedef struct {
+ 
+ 	char   *known_hosts_command;
+ 
++	int	rsa_min_size;	/* minimum size of RSA keys */
++
+ 	char	*ignored_unknown; /* Pattern list of unknown tokens to ignore */
+ }       Options;
+ 
+diff --git a/servconf.c b/servconf.c
+index f7317a5cb..362ff5b67 100644
+--- a/servconf.c
++++ b/servconf.c
+@@ -177,6 +177,7 @@ initialize_server_options(ServerOptions *options)
+ 	options->fingerprint_hash = -1;
+ 	options->disable_forwarding = -1;
+ 	options->expose_userauth_info = -1;
++	options->rsa_min_size = -1;
+ }
+ 
+ /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
+@@ -416,6 +417,8 @@ fill_default_server_options(ServerOptions *options)
+ 		options->expose_userauth_info = 0;
+ 	if (options->sk_provider == NULL)
+ 		options->sk_provider = xstrdup("internal");
++	if (options->rsa_min_size == -1)
++		options->rsa_min_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
+ 
+ 	assemble_algorithms(options);
+ 
+@@ -489,6 +492,7 @@ typedef enum {
+ 	sStreamLocalBindMask, sStreamLocalBindUnlink,
+ 	sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
+ 	sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
++	sRSAMinSize,
+ 	sDeprecated, sIgnore, sUnsupported
+ } ServerOpCodes;
+ 
+@@ -632,6 +636,7 @@ static struct {
+ 	{ "rdomain", sRDomain, SSHCFG_ALL },
+ 	{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
+ 	{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
++	{ "rsaminsize", sRSAMinSize, SSHCFG_ALL },
+ 	{ NULL, sBadOption, 0 }
+ };
+ 
+@@ -2377,6 +2382,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
+ 			*charptr = xstrdup(arg);
+ 		break;
+ 
++	case sRSAMinSize:
++		intptr = &options->rsa_min_size;
++		goto parse_int;
++
+ 	case sDeprecated:
+ 	case sIgnore:
+ 	case sUnsupported:
+@@ -2549,6 +2558,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
+ 	M_CP_INTOPT(rekey_limit);
+ 	M_CP_INTOPT(rekey_interval);
+ 	M_CP_INTOPT(log_level);
++	M_CP_INTOPT(rsa_min_size);
+ 
+ 	/*
+ 	 * The bind_mask is a mode_t that may be unsigned, so we can't use
+@@ -2810,6 +2820,7 @@ dump_config(ServerOptions *o)
+ 	dump_cfg_int(sMaxSessions, o->max_sessions);
+ 	dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
+ 	dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
++	dump_cfg_int(sRSAMinSize, o->rsa_min_size);
+ 	dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
+ 
+ 	/* formatted integer arguments */
+diff --git a/servconf.h b/servconf.h
+index 115db1e79..2e3486906 100644
+--- a/servconf.h
++++ b/servconf.h
+@@ -227,6 +227,7 @@ typedef struct {
+ 	int	expose_userauth_info;
+ 	u_int64_t timing_secret;
+ 	char   *sk_provider;
++	int	rsa_min_size;	/* minimum size of RSA keys */
+ }       ServerOptions;
+ 
+ /* Information about the incoming connection as used by Match */
+diff --git a/ssh.c b/ssh.c
+index a926cc007..cd13fb879 100644
+--- a/ssh.c
++++ b/ssh.c
+@@ -500,14 +500,22 @@ resolve_canonicalize(char **hostp, int port)
+ }
+ 
+ /*
+- * Check the result of hostkey loading, ignoring some errors and
+- * fatal()ing for others.
++ * Check the result of hostkey loading, ignoring some errors and either
++ * discarding the key or fatal()ing for others.
+  */
+ static void
+-check_load(int r, const char *path, const char *message)
++check_load(int r, struct sshkey **k, const char *path, const char *message)
+ {
+ 	switch (r) {
+ 	case 0:
++		/* Check RSA keys size and discard if undersized */
++		if (k != NULL && *k != NULL &&
++		    (r = sshkey_check_rsa_length(*k,
++		    options.rsa_min_size)) != 0) {
++			error_r(r, "load %s \"%s\"", message, path);
++			free(*k);
++			*k = NULL;
++		}
+ 		break;
+ 	case SSH_ERR_INTERNAL_ERROR:
+ 	case SSH_ERR_ALLOC_FAIL:
+@@ -1557,12 +1565,13 @@ main(int ac, char **av)
+ 	if ((o) >= sensitive_data.nkeys) \
+ 		fatal_f("pubkey out of array bounds"); \
+ 	check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
+-	    p, "pubkey"); \
++	    &(sensitive_data.keys[o]), p, "pubkey"); \
+ } while (0)
+ #define L_CERT(p,o) do { \
+ 	if ((o) >= sensitive_data.nkeys) \
+ 		fatal_f("cert out of array bounds"); \
+-	check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \
++	check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \
++	    &(sensitive_data.keys[o]), p, "cert"); \
+ } while (0)
+ 
+ 		if (options.hostbased_authentication == 1) {
+@@ -2244,7 +2253,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
+ 		filename = default_client_percent_dollar_expand(cp, cinfo);
+ 		free(cp);
+ 		check_load(sshkey_load_public(filename, &public, NULL),
+-		    filename, "pubkey");
++		    &public, filename, "pubkey");
+ 		debug("identity file %s type %d", filename,
+ 		    public ? public->type : -1);
+ 		free(options.identity_files[i]);
+@@ -2263,7 +2272,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
+ 			continue;
+ 		xasprintf(&cp, "%s-cert", filename);
+ 		check_load(sshkey_load_public(cp, &public, NULL),
+-		    filename, "pubkey");
++		    &public, filename, "pubkey");
+ 		debug("identity file %s type %d", cp,
+ 		    public ? public->type : -1);
+ 		if (public == NULL) {
+@@ -2294,7 +2303,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
+ 		free(cp);
+ 
+ 		check_load(sshkey_load_public(filename, &public, NULL),
+-		    filename, "certificate");
++		    &public, filename, "certificate");
+ 		debug("certificate file %s type %d", filename,
+ 		    public ? public->type : -1);
+ 		free(options.certificate_files[i]);
+diff --git a/sshconnect2.c b/sshconnect2.c
+index 67f8e0309..d050c1656 100644
+--- a/sshconnect2.c
++++ b/sshconnect2.c
+@@ -91,6 +91,10 @@ static const struct ssh_conn_info *xxx_conn_info;
+ static int
+ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
+ {
++	int r;
++
++	if ((r = sshkey_check_rsa_length(hostkey, options.rsa_min_size)) != 0)
++		fatal_r(r, "Bad server host key");
+ 	if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
+ 	    xxx_conn_info) == -1)
+ 		fatal("Host key verification failed.");
+@@ -1762,6 +1762,12 @@ load_identity_file(Identity *id)
+ 			private = NULL;
+ 			quit = 1;
+ 		}
++		if (r = sshkey_check_rsa_length(private, options.rsa_min_size) != 0) {
++			debug_fr(r, "Skipping key %s", id->filename);
++			sshkey_free(private);
++			private = NULL;
++			quit = 1;
++		}
+ 		if (!quit && private != NULL && id->agent_fd == -1 &&
+ 		    !(id->key && id->isprivate))
+ 			maybe_add_key_to_agent(id->filename, private, comment,
+@@ -1747,6 +1751,12 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt)
+		close(agent_fd);
+	} else {
+ 		for (j = 0; j < idlist->nkeys; j++) {
++			if ((r = sshkey_check_rsa_length(idlist->keys[j],
++			    options.rsa_min_size)) != 0) {
++				debug_fr(r, "ignoring %s agent key",
++				    sshkey_ssh_name(idlist->keys[j]));
++				continue;
++			}
+ 			found = 0;
+ 			TAILQ_FOREACH(id, &files, next) {
+ 				/*
+diff --git a/sshd.c b/sshd.c
+index d26eb86ae..5f36905a1 100644
+--- a/sshd.c
++++ b/sshd.c
+@@ -1746,6 +1746,13 @@ main(int ac, char **av)
+ 				fatal_r(r, "Could not demote key: \"%s\"",
+ 				    options.host_key_files[i]);
+ 		}
++		if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey,
++		    options.rsa_min_size)) != 0) {
++			error_fr(r, "Host key %s", options.host_key_files[i]);
++			sshkey_free(pubkey);
++			sshkey_free(key);
++			continue;
++		}
+ 		sensitive_data.host_keys[i] = key;
+ 		sensitive_data.host_pubkeys[i] = pubkey;
+ 
+diff --git a/sshkey.c b/sshkey.c
+index 47864e6d8..8bad6bd99 100644
+--- a/sshkey.c
++++ b/sshkey.c
+@@ -2319,18 +2319,24 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
+ 	return ret;
+ }
+ 
+-#ifdef WITH_OPENSSL
+-static int
+-check_rsa_length(const RSA *rsa)
++int
++sshkey_check_rsa_length(const struct sshkey *k, int min_size)
+ {
++#ifdef WITH_OPENSSL
+ 	const BIGNUM *rsa_n;
++	int nbits;
+ 
+-	RSA_get0_key(rsa, &rsa_n, NULL, NULL);
+-	if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
++	if (k == NULL || k->rsa == NULL ||
++	    (k->type != KEY_RSA && k->type != KEY_RSA_CERT))
++		return 0;
++	RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
++	nbits = BN_num_bits(rsa_n);
++	if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
++	    (min_size > 0 && nbits < min_size))
+ 		return SSH_ERR_KEY_LENGTH;
++#endif /* WITH_OPENSSL */
+ 	return 0;
+ }
+-#endif
+ 
+ static int
+ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
+@@ -2391,7 +2397,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
+ 			goto out;
+ 		}
+ 		rsa_n = rsa_e = NULL; /* transferred */
+-		if ((ret = check_rsa_length(key->rsa)) != 0)
++		if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
+ 			goto out;
+ #ifdef DEBUG_PK
+ 		RSA_print_fp(stderr, key->rsa, 8);
+@@ -3580,7 +3586,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
+ 			goto out;
+ 		}
+ 		rsa_p = rsa_q = NULL; /* transferred */
+-		if ((r = check_rsa_length(k->rsa)) != 0)
++		if ((r = sshkey_check_rsa_length(k, 0)) != 0)
+ 			goto out;
+ 		if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
+ 			goto out;
+@@ -4566,7 +4572,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
+ 			r = SSH_ERR_LIBCRYPTO_ERROR;
+ 			goto out;
+ 		}
+-		if ((r = check_rsa_length(prv->rsa)) != 0)
++		if ((r = sshkey_check_rsa_length(prv, 0)) != 0)
+ 			goto out;
+ 	} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
+ 	    (type == KEY_UNSPEC || type == KEY_DSA)) {
+diff --git a/sshkey.h b/sshkey.h
+index 125cadb64..52e879456 100644
+--- a/sshkey.h
++++ b/sshkey.h
+@@ -267,6 +267,7 @@ int	sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
+ int	sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
+     int type, struct sshkey **pubkeyp);
+ 
++int sshkey_check_rsa_length(const struct sshkey *, int);
+ /* XXX should be internal, but used by ssh-keygen */
+ int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
+ 
+diff --git a/ssh.1 b/ssh.1
+index b4956aec..b1a40ebd 100644
+--- a/ssh.1
++++ b/ssh.1
+@@ -554,6 +554,7 @@ For full details of the options listed below, and their possible values, see
+ .It LogLevel
+ .It MACs
+ .It Match
++.It RSAMinSize
+ .It NoHostAuthenticationForLocalhost
+ .It NumberOfPasswordPrompts
+ .It PasswordAuthentication
+diff --git a/ssh_config.5 b/ssh_config.5
+index 24a46460..68771e4b 100644
+--- a/ssh_config.5
++++ b/ssh_config.5
+@@ -1322,6 +1322,10 @@ The argument to this keyword must be
+ or
+ .Cm no
+ (the default).
++.It Cm RSAMinSize
++Provides a minimal bits requirement for RSA keys when used for signature and
++verification but not for the key generation. The default value is 1024 and
++can't be reduced.
+ .It Cm NumberOfPasswordPrompts
+ Specifies the number of password prompts before giving up.
+ The argument to this keyword must be an integer.
+diff --git a/sshd_config.5 b/sshd_config.5
+index 867a747d..e08811ca 100644
+--- a/sshd_config.5
++++ b/sshd_config.5
+@@ -1266,6 +1266,10 @@ will refuse connection attempts with a probability of rate/100 (30%)
+ if there are currently start (10) unauthenticated connections.
+ The probability increases linearly and all connection attempts
+ are refused if the number of unauthenticated connections reaches full (60).
++.It Cm RSAMinSize
++Provides a minimal bits requirement for RSA keys when used for signature and
++verification but not for the key generation. The default value is 1024 and
++can't be reduced.
+ .It Cm ModuliFile
+ Specifies the
+ .Xr moduli 5
+diff --git a/sshkey.h b/sshkey.h
+index 094815e0..2bb8cb90 100644
+--- a/sshkey.h
++++ b/sshkey.h
+@@ -286,6 +286,8 @@ int	 sshkey_private_serialize_maxsign(struct sshkey *key,
+ 
+ void	 sshkey_sig_details_free(struct sshkey_sig_details *);
+ 
++int ssh_set_rsa_min_bits(int minbits);
++
+ #ifdef SSHKEY_INTERNAL
+ int ssh_rsa_sign(const struct sshkey *key,
+     u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
diff --git a/SOURCES/openssh-8.7p1-negotiate-supported-algs.patch b/SOURCES/openssh-8.7p1-negotiate-supported-algs.patch
new file mode 100644
index 0000000..2fb9297
--- /dev/null
+++ b/SOURCES/openssh-8.7p1-negotiate-supported-algs.patch
@@ -0,0 +1,63 @@
+diff --color -rup a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh
+--- a/regress/hostkey-agent.sh	2021-08-20 06:03:49.000000000 +0200
++++ b/regress/hostkey-agent.sh	2022-07-14 11:58:12.172786060 +0200
+@@ -13,8 +13,12 @@ r=$?
+ grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
+ echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig
+ 
++PUBKEY_ACCEPTED_ALGOS=`$SSH -G "example.com" | \
++    grep -i "PubkeyAcceptedAlgorithms" | cut -d ' ' -f2- | tr "," "|"`
++SSH_ACCEPTED_KEYTYPES=`echo "$SSH_KEYTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"`
++
+ trace "load hostkeys"
+-for k in $SSH_KEYTYPES ; do
++for k in $SSH_ACCEPTED_KEYTYPES ; do
+ 	${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k"
+ 	(
+ 		printf 'localhost-with-alias,127.0.0.1,::1 '
+@@ -31,7 +35,7 @@ cp $OBJ/known_hosts.orig $OBJ/known_host
+ unset SSH_AUTH_SOCK
+ 
+ for ps in yes; do
+-	for k in $SSH_KEYTYPES ; do
++	for k in $SSH_ACCEPTED_KEYTYPES ; do
+ 		verbose "key type $k privsep=$ps"
+ 		cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
+ 		echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
+diff --color -rup a/sshconnect2.c b/sshconnect2.c
+--- a/sshconnect2.c	2022-07-14 10:10:07.262975710 +0200
++++ b/sshconnect2.c	2022-07-14 10:10:32.068452067 +0200
+@@ -222,6 +222,7 @@ ssh_kex2(struct ssh *ssh, char *host, st
+ {
+ 	char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
+ 	char *s, *all_key;
++	char *hostkeyalgs = NULL, *pkalg = NULL;
+ 	char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL;
+ 	int r, use_known_hosts_order = 0;
+ 
+@@ -264,14 +265,19 @@ ssh_kex2(struct ssh *ssh, char *host, st
+ 	    myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+ 	if (use_known_hosts_order) {
+ 		/* Query known_hosts and prefer algorithms that appear there */
+-		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
+-		    compat_pkalg_proposal(ssh,
+-		    order_hostkeyalgs(host, hostaddr, port, cinfo));
++		if ((hostkeyalgs = order_hostkeyalgs(host, hostaddr, port, cinfo)) == NULL)
++			fatal_f("order_hostkeyalgs");
++		pkalg = match_filter_allowlist(hostkeyalgs, options.pubkey_accepted_algos);
++		free(hostkeyalgs);
+ 	} else {
+-		/* Use specified HostkeyAlgorithms exactly */
+-		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
+-		    compat_pkalg_proposal(ssh, options.hostkeyalgorithms);
++		/* Use specified HostkeyAlgorithms */
++		pkalg = match_filter_allowlist(options.hostkeyalgorithms, options.pubkey_accepted_algos);
+ 	}
++	if (pkalg == NULL)
++		fatal_f("match_filter_allowlist");
++	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
++	    compat_pkalg_proposal(ssh, pkalg);
++	free(pkalg);
+ 
+ #if defined(GSSAPI) && defined(WITH_OPENSSL)
+ 	if (options.gss_keyex) {
diff --git a/SOURCES/openssh-8.7p1-scp-clears-file.patch b/SOURCES/openssh-8.7p1-scp-clears-file.patch
new file mode 100644
index 0000000..4c033da
--- /dev/null
+++ b/SOURCES/openssh-8.7p1-scp-clears-file.patch
@@ -0,0 +1,304 @@
+diff --color -rup a/scp.c b/scp.c
+--- a/scp.c	2022-07-26 14:51:40.560120817 +0200
++++ b/scp.c	2022-07-26 14:52:37.118213004 +0200
+@@ -1324,12 +1324,12 @@ source_sftp(int argc, char *src, char *t
+ 
+ 	if (src_is_dir && iamrecursive) {
+ 		if (upload_dir(conn, src, abs_dst, pflag,
+-		    SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
++		    SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) {
+ 			error("failed to upload directory %s to %s",
+ 				src, abs_dst);
+ 			errs = 1;
+ 		}
+-	} else if (do_upload(conn, src, abs_dst, pflag, 0, 0) != 0) {
++	} else if (do_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) {
+ 		error("failed to upload file %s to %s", src, abs_dst);
+ 		errs = 1;
+ 	}
+@@ -1566,11 +1566,11 @@ sink_sftp(int argc, char *dst, const cha
+ 		debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
+ 		if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
+ 			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
+-			    pflag, SFTP_PROGRESS_ONLY, 0, 0, 1) == -1)
++			    pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1)
+ 				err = -1;
+ 		} else {
+ 			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
+-			    pflag, 0, 0) == -1)
++			    pflag, 0, 0, 1) == -1)
+ 				err = -1;
+ 		}
+ 		free(abs_dst);
+diff --color -rup a/sftp.c b/sftp.c
+--- a/sftp.c	2022-07-26 14:51:40.561120836 +0200
++++ b/sftp.c	2022-07-26 14:52:37.119213023 +0200
+@@ -666,12 +666,12 @@ process_get(struct sftp_conn *conn, cons
+ 		if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
+ 			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
+ 			    pflag || global_pflag, 1, resume,
+-			    fflag || global_fflag, 0) == -1)
++			    fflag || global_fflag, 0, 0) == -1)
+ 				err = -1;
+ 		} else {
+ 			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
+ 			    pflag || global_pflag, resume,
+-			    fflag || global_fflag) == -1)
++			    fflag || global_fflag, 0) == -1)
+ 				err = -1;
+ 		}
+ 		free(abs_dst);
+@@ -760,12 +760,12 @@ process_put(struct sftp_conn *conn, cons
+ 		if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
+ 			if (upload_dir(conn, g.gl_pathv[i], abs_dst,
+ 			    pflag || global_pflag, 1, resume,
+-			    fflag || global_fflag, 0, 0) == -1)
++			    fflag || global_fflag, 0, 0, 0) == -1)
+ 				err = -1;
+ 		} else {
+ 			if (do_upload(conn, g.gl_pathv[i], abs_dst,
+ 			    pflag || global_pflag, resume,
+-			    fflag || global_fflag) == -1)
++			    fflag || global_fflag, 0) == -1)
+ 				err = -1;
+ 		}
+ 	}
+diff --color -rup a/sftp-client.c b/sftp-client.c
+--- a/sftp-client.c	2022-07-26 14:51:40.561120836 +0200
++++ b/sftp-client.c	2022-07-26 15:09:54.825295533 +0200
+@@ -1454,7 +1454,7 @@ progress_meter_path(const char *path)
+ int
+ do_download(struct sftp_conn *conn, const char *remote_path,
+     const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
+-    int fsync_flag)
++    int fsync_flag, int inplace_flag)
+ {
+ 	struct sshbuf *msg;
+ 	u_char *handle;
+@@ -1498,8 +1498,8 @@ do_download(struct sftp_conn *conn, cons
+ 	    &handle, &handle_len) != 0)
+ 		return -1;
+ 
+-	local_fd = open(local_path,
+-	    O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR);
++	local_fd = open(local_path, O_WRONLY | O_CREAT |
++	((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR);
+ 	if (local_fd == -1) {
+ 		error("Couldn't open local file \"%s\" for writing: %s",
+ 		    local_path, strerror(errno));
+@@ -1661,8 +1661,11 @@ do_download(struct sftp_conn *conn, cons
+ 	/* Sanity check */
+ 	if (TAILQ_FIRST(&requests) != NULL)
+ 		fatal("Transfer complete, but requests still in queue");
+-	/* Truncate at highest contiguous point to avoid holes on interrupt */
+-	if (read_error || write_error || interrupted) {
++	/*
++	 * Truncate at highest contiguous point to avoid holes on interrupt,
++	 * or unconditionally if writing in place.
++	 */
++	if (inplace_flag || read_error || write_error || interrupted) {
+ 		if (reordered && resume_flag) {
+ 			error("Unable to resume download of \"%s\": "
+ 			    "server reordered requests", local_path);
+@@ -1724,7 +1727,7 @@ do_download(struct sftp_conn *conn, cons
+ static int
+ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
+     int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
+-    int resume_flag, int fsync_flag, int follow_link_flag)
++    int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag)
+ {
+ 	int i, ret = 0;
+ 	SFTP_DIRENT **dir_entries;
+@@ -1781,7 +1784,7 @@ download_dir_internal(struct sftp_conn *
+ 			if (download_dir_internal(conn, new_src, new_dst,
+ 			    depth + 1, &(dir_entries[i]->a), preserve_flag,
+ 			    print_flag, resume_flag,
+-			    fsync_flag, follow_link_flag) == -1)
++			    fsync_flag, follow_link_flag, inplace_flag) == -1)
+ 				ret = -1;
+ 		} else if (S_ISREG(dir_entries[i]->a.perm) ||
+ 		    (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) {
+@@ -1793,7 +1796,8 @@ download_dir_internal(struct sftp_conn *
+ 			if (do_download(conn, new_src, new_dst,
+ 			    S_ISLNK(dir_entries[i]->a.perm) ? NULL :
+ 			    &(dir_entries[i]->a),
+-			    preserve_flag, resume_flag, fsync_flag) == -1) {
++			    preserve_flag, resume_flag, fsync_flag,
++			    inplace_flag) == -1) {
+ 				error("Download of file %s to %s failed",
+ 				    new_src, new_dst);
+ 				ret = -1;
+@@ -1831,7 +1835,7 @@ download_dir_internal(struct sftp_conn *
+ int
+ download_dir(struct sftp_conn *conn, const char *src, const char *dst,
+     Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
+-    int fsync_flag, int follow_link_flag)
++    int fsync_flag, int follow_link_flag, int inplace_flag)
+ {
+ 	char *src_canon;
+ 	int ret;
+@@ -1843,26 +1847,25 @@ download_dir(struct sftp_conn *conn, con
+ 
+ 	ret = download_dir_internal(conn, src_canon, dst, 0,
+ 	    dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag,
+-	    follow_link_flag);
++	    follow_link_flag, inplace_flag);
+ 	free(src_canon);
+ 	return ret;
+ }
+ 
+ int
+ do_upload(struct sftp_conn *conn, const char *local_path,
+-    const char *remote_path, int preserve_flag, int resume, int fsync_flag)
++    const char *remote_path, int preserve_flag, int resume,
++    int fsync_flag, int inplace_flag)
+ {
+ 	int r, local_fd;
+-	u_int status = SSH2_FX_OK;
+-	u_int id;
+-	u_char type;
++	u_int openmode, id, status = SSH2_FX_OK, reordered = 0;
+ 	off_t offset, progress_counter;
+-	u_char *handle, *data;
++	u_char type, *handle, *data;
+ 	struct sshbuf *msg;
+ 	struct stat sb;
+-	Attrib a, *c = NULL;
+-	u_int32_t startid;
+-	u_int32_t ackid;
++	Attrib a, t, *c = NULL;
++	u_int32_t startid, ackid;
++	u_int64_t highwater = 0;
+ 	struct request *ack = NULL;
+ 	struct requests acks;
+ 	size_t handle_len;
+@@ -1913,10 +1916,15 @@ do_upload(struct sftp_conn *conn, const
+ 		}
+ 	}
+ 
++	openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT;
++	if (resume)
++		openmode |= SSH2_FXF_APPEND;
++	else if (!inplace_flag)
++		openmode |= SSH2_FXF_TRUNC;
++
+ 	/* Send open request */
+-	if (send_open(conn, remote_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT|
+-	    (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC),
+-	    &a, &handle, &handle_len) != 0) {
++	if (send_open(conn, remote_path, "dest", openmode, &a,
++	    &handle, &handle_len) != 0) {
+ 		close(local_fd);
+ 		return -1;
+ 	}
+@@ -1999,6 +2007,12 @@ do_upload(struct sftp_conn *conn, const
+ 			    ack->id, ack->len, (unsigned long long)ack->offset);
+ 			++ackid;
+ 			progress_counter += ack->len;
++			if (!reordered && ack->offset <= highwater)
++				highwater = ack->offset + ack->len;
++			else if (!reordered && ack->offset > highwater) {
++				debug3_f("server reordered ACKs");
++				reordered = 1;
++			}
+ 			free(ack);
+ 		}
+ 		offset += len;
+@@ -2017,6 +2031,14 @@ do_upload(struct sftp_conn *conn, const
+ 		status = SSH2_FX_FAILURE;
+ 	}
+ 
++	if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) {
++		debug("truncating at %llu", (unsigned long long)highwater);
++		attrib_clear(&t);
++		t.flags = SSH2_FILEXFER_ATTR_SIZE;
++		t.size = highwater;
++		do_fsetstat(conn, handle, handle_len, &t);
++	}
++
+ 	if (close(local_fd) == -1) {
+ 		error("Couldn't close local file \"%s\": %s", local_path,
+ 		    strerror(errno));
+@@ -2041,7 +2063,7 @@ do_upload(struct sftp_conn *conn, const
+ static int
+ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
+     int depth, int preserve_flag, int print_flag, int resume, int fsync_flag,
+-    int follow_link_flag)
++    int follow_link_flag, int inplace_flag)
+ {
+ 	int ret = 0;
+ 	DIR *dirp;
+@@ -2119,12 +2141,13 @@ upload_dir_internal(struct sftp_conn *co
+ 
+ 			if (upload_dir_internal(conn, new_src, new_dst,
+ 			    depth + 1, preserve_flag, print_flag, resume,
+-			    fsync_flag, follow_link_flag) == -1)
++			    fsync_flag, follow_link_flag, inplace_flag) == -1)
+ 				ret = -1;
+ 		} else if (S_ISREG(sb.st_mode) ||
+ 		    (follow_link_flag && S_ISLNK(sb.st_mode))) {
+ 			if (do_upload(conn, new_src, new_dst,
+-			    preserve_flag, resume, fsync_flag) == -1) {
++			    preserve_flag, resume, fsync_flag,
++			    inplace_flag) == -1) {
+ 				error("Uploading of file %s to %s failed!",
+ 				    new_src, new_dst);
+ 				ret = -1;
+@@ -2144,7 +2167,7 @@ upload_dir_internal(struct sftp_conn *co
+ int
+ upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
+     int preserve_flag, int print_flag, int resume, int fsync_flag,
+-    int follow_link_flag, int create_dir)
++    int follow_link_flag, int create_dir, int inplace_flag)
+ {
+ 	char *dst_canon;
+ 	int ret;
+@@ -2155,7 +2178,7 @@ upload_dir(struct sftp_conn *conn, const
+ 	}
+ 
+ 	ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
+-	    print_flag, resume, fsync_flag, follow_link_flag);
++	    print_flag, resume, fsync_flag, follow_link_flag, inplace_flag);
+ 
+ 	free(dst_canon);
+ 	return ret;
+diff --color -rup a/sftp-client.h b/sftp-client.h
+--- a/sftp-client.h	2022-07-26 14:51:40.561120836 +0200
++++ b/sftp-client.h	2022-07-26 14:52:37.120213042 +0200
+@@ -138,28 +138,29 @@ int do_fsync(struct sftp_conn *conn, u_c
+  * Download 'remote_path' to 'local_path'. Preserve permissions and times
+  * if 'pflag' is set
+  */
+-int do_download(struct sftp_conn *, const char *, const char *,
+-    Attrib *, int, int, int);
++int do_download(struct sftp_conn *, const char *, const char *, Attrib *,
++    int, int, int, int);
+ 
+ /*
+  * Recursively download 'remote_directory' to 'local_directory'. Preserve
+  * times if 'pflag' is set
+  */
+-int download_dir(struct sftp_conn *, const char *, const char *,
+-    Attrib *, int, int, int, int, int);
++int download_dir(struct sftp_conn *, const char *, const char *, Attrib *,
++    int, int, int, int, int, int);
+ 
+ /*
+  * Upload 'local_path' to 'remote_path'. Preserve permissions and times
+  * if 'pflag' is set
+  */
+-int do_upload(struct sftp_conn *, const char *, const char *, int, int, int);
++int do_upload(struct sftp_conn *, const char *, const char *,
++    int, int, int, int);
+ 
+ /*
+  * Recursively upload 'local_directory' to 'remote_directory'. Preserve
+  * times if 'pflag' is set
+  */
+-int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int,
+-    int, int, int);
++int upload_dir(struct sftp_conn *, const char *, const char *,
++    int, int, int, int, int, int, int);
+ 
+ /*
+  * Download a 'from_path' from the 'from' connection and upload it to
diff --git a/SOURCES/openssh-8.7p1-ssh-manpage.patch b/SOURCES/openssh-8.7p1-ssh-manpage.patch
new file mode 100644
index 0000000..bd0bdb7
--- /dev/null
+++ b/SOURCES/openssh-8.7p1-ssh-manpage.patch
@@ -0,0 +1,53 @@
+diff --color -ru a/ssh.1 b/ssh.1
+--- a/ssh.1	2022-07-12 11:47:51.307295880 +0200
++++ b/ssh.1	2022-07-12 11:50:28.793363263 +0200
+@@ -493,6 +493,7 @@
+ .It AddressFamily
+ .It BatchMode
+ .It BindAddress
++.It BindInterface
+ .It CanonicalDomains
+ .It CanonicalizeFallbackLocal
+ .It CanonicalizeHostname
+@@ -510,6 +511,7 @@
+ .It ControlPath
+ .It ControlPersist
+ .It DynamicForward
++.It EnableSSHKeysign
+ .It EscapeChar
+ .It ExitOnForwardFailure
+ .It FingerprintHash
+@@ -538,6 +540,8 @@
+ .It IdentitiesOnly
+ .It IdentityAgent
+ .It IdentityFile
++.It IgnoreUnknown
++.It Include
+ .It IPQoS
+ .It KbdInteractiveAuthentication
+ .It KbdInteractiveDevices
+@@ -546,6 +550,7 @@
+ .It LocalCommand
+ .It LocalForward
+ .It LogLevel
++.It LogVerbose
+ .It MACs
+ .It Match
+ .It RSAMinSize
+@@ -566,6 +571,8 @@
+ .It RemoteCommand
+ .It RemoteForward
+ .It RequestTTY
++.It RevokedHostKeys
++.It SecurityKeyProvider
+ .It SendEnv
+ .It ServerAliveInterval
+ .It ServerAliveCountMax
+@@ -575,6 +582,7 @@
+ .It StreamLocalBindMask
+ .It StreamLocalBindUnlink
+ .It StrictHostKeyChecking
++.It SyslogFacility
+ .It TCPKeepAlive
+ .It Tunnel
+ .It TunnelDevice
diff --git a/SOURCES/pam_ssh_agent_auth-0.10.4-rsasha2.patch b/SOURCES/pam_ssh_agent_auth-0.10.4-rsasha2.patch
new file mode 100644
index 0000000..c8815bb
--- /dev/null
+++ b/SOURCES/pam_ssh_agent_auth-0.10.4-rsasha2.patch
@@ -0,0 +1,19 @@
+diff -up openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.rsasha2 openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c
+--- openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.rsasha2	2022-07-15 15:08:12.865585410 +0200
++++ openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c	2022-07-15 15:16:25.164282372 +0200
+@@ -87,8 +87,13 @@ userauth_pubkey_from_id(const char *ruse
+         (r = sshbuf_put_string(b, pkblob, blen)) != 0)
+         fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ 
+-    if (ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) != 0)
+-        goto user_auth_clean_exit;
++    if (sshkey_type_plain(id->key->type) == KEY_RSA
++	&& ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), "rsa-sha2-256", 0) == 0) {
++	/* Do nothing */
++    } else {
++        if (ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) != 0)
++            goto user_auth_clean_exit;
++    }
+ 
+     /* test for correct signature */
+     if (sshkey_verify(id->key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0, NULL) == 0)
diff --git a/SPECS/openssh.spec b/SPECS/openssh.spec
index 6f6e971..4ce3542 100644
--- a/SPECS/openssh.spec
+++ b/SPECS/openssh.spec
@@ -51,9 +51,9 @@
 
 # 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 22
 %global pam_ssh_agent_ver 0.10.4
-%global pam_ssh_agent_rel 4
+%global pam_ssh_agent_rel 5
 
 Summary: An open source implementation of SSH protocol version 2
 Name: openssh
@@ -102,6 +102,8 @@ Patch306: pam_ssh_agent_auth-0.10.2-compat.patch
 # Fix NULL dereference from getpwuid() return value
 # https://sourceforge.net/p/pamsshagentauth/bugs/22/
 Patch307: pam_ssh_agent_auth-0.10.2-dereference.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=2070113
+Patch308: pam_ssh_agent_auth-0.10.4-rsasha2.patch
 
 #https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX)
 Patch400: openssh-7.8p1-role-mls.patch
@@ -212,8 +214,49 @@ 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
+# https://github.com/djmdjm/openssh-wip/pull/13
+Patch982: openssh-8.7p1-minrsabits.patch
+# downstream only
+Patch983: openssh-8.7p1-evpgenkey.patch
+# downstream only, IBMCA tentative fix
+# From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14
+Patch984: openssh-8.7p1-ibmca.patch
 
+# Minimize the use of SHA1 as a proof of possession for RSA key (#2031868)
+# upstream commits:
+# 291721bc7c840d113a49518f3fca70e86248b8e8
+# 0fa33683223c76289470a954404047bc762be84c
+# Avoid dubious diagnostics on update known hosts (#2115246)
+# 8832402bd500d1661ccc80a476fd563335ef6cdc
 Patch1000: openssh-8.7p1-minimize-sha1-use.patch
+# Fix for scp clearing file when src and dest are the same (#2056884)
+# upstream commits:
+# 7b1cbcb7599d9f6a3bbad79d412604aa1203b5ee
+Patch1001: openssh-8.7p1-scp-clears-file.patch
+# Add missing options from ssh_config into ssh manpage
+# upstream bug:
+# https://bugzilla.mindrot.org/show_bug.cgi?id=3455
+Patch1002: openssh-8.7p1-ssh-manpage.patch
+# Always return allocated strings from the kex filtering so that we can free them
+# upstream commits:
+# 486c4dc3b83b4b67d663fb0fa62bc24138ec3946
+# 6c31ba10e97b6953c4f325f526f3e846dfea647a
+# 322964f8f2e9c321e77ebae1e4d2cd0ccc5c5a0b
+Patch1003: openssh-8.7p1-mem-leak.patch
+# Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures
+# upstream MR:
+# https://github.com/openssh-gsskex/openssh-gsskex/pull/21
+Patch1004: openssh-8.7p1-gssapi-auth.patch
+# Fix host-based authentication with rsa keys
+# upstream commits:
+# 7aa7b096cf2bafe2777085abdeed5ce00581f641
+# d9dbb5d9a0326e252d3c7bc13beb9c2434f59409
+# fdb1d58d0d3888b042e5a500f6ce524486aaf782
+Patch1005: openssh-8.7p1-host-based-auth.patch
+# Don't propose disallowed algorithms during hostkey negotiation
+# upstream MR:
+# https://github.com/openssh/openssh-portable/pull/323
+Patch1006: openssh-8.7p1-negotiate-supported-algs.patch
 
 License: BSD
 Requires: /sbin/nologin
@@ -341,6 +384,7 @@ pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}
 %patch306 -p2 -b .psaa-compat
 %patch305 -p2 -b .psaa-agent
 %patch307 -p2 -b .psaa-deref
+%patch308 -p2 -b .rsasha2
 # Remove duplicate headers and library files
 rm -f $(cat %{SOURCE5})
 popd
@@ -395,12 +439,21 @@ popd
 %patch979 -p1 -b .find-principals
 %patch980 -p1 -b .sftpdirs
 %patch981 -p1 -b .scp-sftpdirs
+%patch982 -p1 -b .minrsabits
+%patch983 -p1 -b .evpgenrsa
+%patch984 -p1 -b .ibmca
 
 %patch200 -p1 -b .audit
 %patch201 -p1 -b .audit-race
 %patch700 -p1 -b .fips
 
-%patch1000 -p1 -b .minsha1
+%patch1000 -p1 -b .minimize-sha1-use
+%patch1001 -p1 -b .scp-clears-file
+%patch1002 -p1 -b .ssh-manpage
+%patch1003 -p1 -b .mem-leak
+%patch1004 -p1 -b .gssapi-auth
+%patch1005 -p1 -b .host-based-auth
+%patch1006 -p1 -b .negotiate-supported-algs
 
 %patch100 -p1 -b .coverity
 
@@ -681,6 +734,80 @@ test -f %{sysconfig_anaconda} && \
 %endif
 
 %changelog
+* Tue Aug 16 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-22
+- Avoid spirous message on connecting to the machine with ssh-rsa keys
+  Related: rhbz#2115246
+- Set minimal value of RSA key length via configuration option
+  Related: rhbz#2066882
+
+* Thu Aug 04 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-21
+- IBMCA workaround
+  Related: rhbz#1976202
+
+* Tue Jul 26 2022 Zoltan Fridrich <zfridric@redhat.com> - 8.7p1-20 + 0.10.4-5
+- Fix openssh-8.7p1-scp-clears-file.patch
+  Related: rhbz#2056884
+
+* Fri Jul 15 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-19 + 0.10.4-5
+- FIX pam_ssh_agent_auth auth for RSA keys
+  Related: rhbz#2070113
+
+* Thu Jul 14 2022 Zoltan Fridrich <zfridric@redhat.com> - 8.7p1-18
+- Fix new coverity issues
+  Related: rhbz#2068423
+
+* Thu Jul 14 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-17
+- Disable ed25519 and ed25519-sk keys in FIPS mode
+  Related: rhbz#2087915
+
+* Thu Jul 14 2022 Zoltan Fridrich <zfridric@redhat.com> - 8.7p1-16
+- Don't propose disallowed algorithms during hostkey negotiation
+  Resolves: rhbz#2068423
+
+* Thu Jul 14 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-15
+- Disable ed25519 and ed25519-sk keys in FIPS mode
+  Related: rhbz#2087915
+
+* Wed Jul 13 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-14
+- Disable ed25519 and ed25519-sk keys in FIPS mode
+  Related: rhbz#2087915
+
+* Tue Jul 12 2022 Zoltan Fridrich <zfridric@redhat.com> - 8.7p1-13
+- Add reference for policy customization in ssh/sshd_config manpages
+  Resolves: rhbz#1984575
+
+* Mon Jul 11 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-12
+- Disable sntrup761x25519-sha512 in FIPS mode
+  Related: rhbz#2070628
+- Disable ed25519 and ed25519-sk keys in FIPS mode
+  Related: rhbz#2087915
+
+* Mon Jul 11 2022 Zoltan Fridrich <zfridric@redhat.com> - 8.7p1-11
+- Fix scp clearing file when src and dest are the same
+  Resolves: rhbz#2056884
+- Add missing options from ssh_config into ssh manpage
+  Resolves: rhbz#2033372
+- Fix several memory leaks
+  Related: rhbz#2068423
+- Fix gssapi authentication failures
+  Resolves: rhbz#2091023
+- Fix host-based authentication with rsa keys
+  Resolves: rhbz#2088916
+
+* Wed Jun 29 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-10
+- Set minimal value of RSA key length via configuration option
+  Related: rhbz#2066882
+- Use EVP functions for RSA key generation
+  Related: rhbz#2087121
+
+* Wed Jun 29 2022 Zoltan Fridrich <zfridric@redhat.com> - 8.7p1-9
+- Update minimize-sha1-use.patch to use upstream code
+  Related: rhbz#2031868
+- Change product name from Fedora to RHEL in openssh-7.8p1-UsePAM-warning.patch
+  Resolves: rhbz#2064338
+- Change log level of FIPS specific log message to verbose
+  Resolves: rhbz#2102201
+
 * Mon Feb 21 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-8
 - Workaround for RHEL 8 incompatibility in scp utility in SFTP mode
   Related: rhbz#2038854