diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch
index 05b2907..704de05 100644
--- a/openssh-7.7p1-fips.patch
+++ b/openssh-7.7p1-fips.patch
@@ -81,7 +81,7 @@ diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c
  #include <openssl/crypto.h>
 +#include <openssl/fips.h>
  #include <openssl/dh.h>
- # ifdef HAVE_EVP_KDF_CTX_NEW_ID
+ # ifdef HAVE_EVP_KDF_CTX_NEW
  # include <openssl/kdf.h>
 @@ -203,7 +203,10 @@ kex_names_valid(const char *names)
  	for ((p = strsep(&cp, ",")); p && *p != '\0';
diff --git a/openssh-8.0p1-openssl-kdf.patch b/openssh-8.0p1-openssl-kdf.patch
index 5d76a4f..e190472 100644
--- a/openssh-8.0p1-openssl-kdf.patch
+++ b/openssh-8.0p1-openssl-kdf.patch
@@ -12,7 +12,7 @@ index 2a455e4e..e01c3d43 100644
  		HMAC_CTX_init \
  		RSA_generate_key_ex \
  		RSA_get_default_method \
-+		EVP_KDF_CTX_new_id \
++		EVP_KDF_CTX_new \
  	])
  
  	# OpenSSL_add_all_algorithms may be a macro.
@@ -20,33 +20,35 @@ diff --git a/kex.c b/kex.c
 index b6f041f4..1fbce2bb 100644
 --- a/kex.c
 +++ b/kex.c
-@@ -38,6 +38,9 @@
+@@ -38,6 +38,11 @@
  #ifdef WITH_OPENSSL
  #include <openssl/crypto.h>
  #include <openssl/dh.h>
-+# ifdef HAVE_EVP_KDF_CTX_NEW_ID
++# ifdef HAVE_EVP_KDF_CTX_NEW
 +# include <openssl/kdf.h>
++# include <openssl/param_build.h>
++# include <openssl/core_names.h>
 +# endif
  #endif
  
  #include "ssh.h"
-@@ -942,6 +945,95 @@ kex_choose_conf(struct ssh *ssh)
+@@ -942,6 +945,112 @@ kex_choose_conf(struct ssh *ssh)
  	return r;
  }
  
-+#ifdef HAVE_EVP_KDF_CTX_NEW_ID
-+static const EVP_MD *
++#ifdef HAVE_EVP_KDF_CTX_NEW
++static const char *
 +digest_to_md(int digest_type)
 +{
 +	switch (digest_type) {
 +	case SSH_DIGEST_SHA1:
-+		return EVP_sha1();
++		return SN_sha1;
 +	case SSH_DIGEST_SHA256:
-+		return EVP_sha256();
++		return SN_sha256;
 +	case SSH_DIGEST_SHA384:
-+		return EVP_sha384();
++		return SN_sha384;
 +	case SSH_DIGEST_SHA512:
-+		return EVP_sha512();
++		return SN_sha512;
 +	}
 +	return NULL;
 +}
@@ -56,52 +58,67 @@ index b6f041f4..1fbce2bb 100644
 +    const struct sshbuf *shared_secret, u_char **keyp)
 +{
 +	struct kex *kex = ssh->kex;
-+	EVP_KDF_CTX *ctx = NULL;
 +	u_char *key = NULL;
 +	int r, key_len;
 +
-+	if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0)
-+		return SSH_ERR_INVALID_ARGUMENT;
-+	key_len = ROUNDUP(need, key_len);
-+	if ((key = calloc(1, key_len)) == NULL) {
-+		r = SSH_ERR_ALLOC_FAIL;
++	EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL);
++	EVP_KDF_CTX *ctx = NULL;
++	OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new();
++	OSSL_PARAM *params = NULL;
++       const char *md = digest_to_md(kex->hash_alg);
++       char keytype = (char)id;
++
++	if (!kdf) {
++		r = SSH_ERR_LIBCRYPTO_ERROR;
 +		goto out;
 +	}
-+
-+	ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF);
++	ctx = EVP_KDF_CTX_new(kdf);
++	EVP_KDF_free(kdf);
 +	if (!ctx) {
 +		r = SSH_ERR_LIBCRYPTO_ERROR;
 +		goto out;
 +	}
-+
-+	r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest_to_md(kex->hash_alg));
-+	if (r != 1) {
-+		r = SSH_ERR_LIBCRYPTO_ERROR;
++	if (md == NULL) {
++		r = SSH_ERR_INVALID_ARGUMENT;
 +		goto out;
 +	}
-+	r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY,
-+	    sshbuf_ptr(shared_secret), sshbuf_len(shared_secret));
-+	if (r != 1) {
-+		r = SSH_ERR_LIBCRYPTO_ERROR;
++
++	if (param_bld == NULL) {
++		EVP_KDF_CTX_free(ctx);
++		return -1;
++	}
++	if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) {
++		r = SSH_ERR_INVALID_ARGUMENT;
 +		goto out;
 +	}
-+	r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, hash, hashlen);
-+	if (r != 1) {
-+		r = SSH_ERR_LIBCRYPTO_ERROR;
++
++	key_len = ROUNDUP(need, key_len);
++	if ((key = calloc(1, key_len)) == NULL) {
++		r = SSH_ERR_ALLOC_FAIL;
 +		goto out;
 +	}
-+	r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, id);
++
++	r =     OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_DIGEST,
++		                md, strlen(md)) && /* SN */
++		OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_KEY,
++				sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)) &&
++		OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_XCGHASH,
++				hash, hashlen) &&
++		OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_SESSION_ID,
++				sshbuf_ptr(kex->session_id), sshbuf_len(kex->session_id)) &&
++		OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_SSHKDF_TYPE,
++				&keytype, 1);
 +	if (r != 1) {
 +		r = SSH_ERR_LIBCRYPTO_ERROR;
 +		goto out;
 +	}
-+	r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
-+	    sshbuf_ptr(kex->session_id), sshbuf_len(kex->session_id));
-+	if (r != 1) {
++
++	params = OSSL_PARAM_BLD_to_param(param_bld);
++	if (params == NULL) {
 +		r = SSH_ERR_LIBCRYPTO_ERROR;
 +		goto out;
 +	}
-+	r = EVP_KDF_derive(ctx, key, key_len);
++	r = EVP_KDF_derive(ctx, key, key_len, params);
 +	if (r != 1) {
 +		r = SSH_ERR_LIBCRYPTO_ERROR;
 +		goto out;
@@ -115,6 +132,8 @@ index b6f041f4..1fbce2bb 100644
 +	r = 0;
 +
 +out:
++	OSSL_PARAM_BLD_free(param_bld);
++	OSSL_PARAM_free(params);
 +	free (key);
 +	EVP_KDF_CTX_free(ctx);
 +	if (r < 0) {
@@ -130,7 +149,7 @@ index b6f041f4..1fbce2bb 100644
  	ssh_digest_free(hashctx);
  	return r;
  }
-+#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */
++#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW */
  
  #define NKEYS	6
  int
diff --git a/openssh.spec b/openssh.spec
index 8a7a38e..de1e941 100644
--- a/openssh.spec
+++ b/openssh.spec
@@ -47,7 +47,7 @@
 
 # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1
 %global openssh_ver 8.7p1
-%global openssh_rel 38
+%global openssh_rel 39
 %global pam_ssh_agent_ver 0.10.4
 %global pam_ssh_agent_rel 5
 
@@ -798,6 +798,10 @@ test -f %{sysconfig_anaconda} && \
 %endif
 
 %changelog
+* Wed Apr 24 2024 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-39
+- Use FIPS-compatible API for key derivation
+  Resolves: RHEL-32809
+
 * Fri Jan 05 2024 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-38
 - Fix Terrapin attack
   Resolves: CVE-2023-48795