diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch
index 8288ed2..1408e4d 100644
--- a/openssh-7.7p1-fips.patch
+++ b/openssh-7.7p1-fips.patch
@@ -409,9 +409,9 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c
  
  #ifdef WITH_XMSS
 @@ -1705,6 +1707,8 @@ rsa_generate_private_key(u_int bits, RSA
- 	}
- 	if (!BN_set_word(f4, RSA_F4) ||
- 	    !RSA_generate_key_ex(private, bits, f4, NULL)) {
+		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;
diff --git a/openssh-8.7p1-evpgenkey.patch b/openssh-8.7p1-evpgenkey.patch
new file mode 100644
index 0000000..1af9b49
--- /dev/null
+++ b/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/openssh.spec b/openssh.spec
index eb5904b..e5dd43c 100644
--- a/openssh.spec
+++ b/openssh.spec
@@ -214,6 +214,8 @@ Patch980: openssh-8.7p1-sftpscp-dir-create.patch
 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
 
 # Minimize the use of SHA1 as a proof of possession for RSA key (#2031868)
 # upstream commits:
@@ -402,6 +404,7 @@ popd
 %patch980 -p1 -b .sftpdirs
 %patch981 -p1 -b .scp-sftpdirs
 %patch982 -p1 -b .minrsabits
+%patch983 -p1 -b .evpgenrsa
 
 %patch200 -p1 -b .audit
 %patch201 -p1 -b .audit-race
@@ -691,6 +694,8 @@ test -f %{sysconfig_anaconda} && \
 * 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