Use FIPS-compatible API for key derivation

Resolves: RHEL-32809
This commit is contained in:
Dmitry Belyavskiy 2024-04-24 21:26:06 +02:00
parent 2c2ea1d489
commit 03eff3f0f1
3 changed files with 66 additions and 43 deletions

View File

@ -81,7 +81,7 @@ diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c
#include <openssl/crypto.h> #include <openssl/crypto.h>
+#include <openssl/fips.h> +#include <openssl/fips.h>
#include <openssl/dh.h> #include <openssl/dh.h>
# ifdef HAVE_EVP_KDF_CTX_NEW_ID # ifdef HAVE_EVP_KDF_CTX_NEW
# include <openssl/kdf.h> # include <openssl/kdf.h>
@@ -203,7 +203,10 @@ kex_names_valid(const char *names) @@ -203,7 +203,10 @@ kex_names_valid(const char *names)
for ((p = strsep(&cp, ",")); p && *p != '\0'; for ((p = strsep(&cp, ",")); p && *p != '\0';

View File

@ -12,7 +12,7 @@ index 2a455e4e..e01c3d43 100644
HMAC_CTX_init \ HMAC_CTX_init \
RSA_generate_key_ex \ RSA_generate_key_ex \
RSA_get_default_method \ RSA_get_default_method \
+ EVP_KDF_CTX_new_id \ + EVP_KDF_CTX_new \
]) ])
# OpenSSL_add_all_algorithms may be a macro. # OpenSSL_add_all_algorithms may be a macro.
@ -20,33 +20,35 @@ diff --git a/kex.c b/kex.c
index b6f041f4..1fbce2bb 100644 index b6f041f4..1fbce2bb 100644
--- a/kex.c --- a/kex.c
+++ b/kex.c +++ b/kex.c
@@ -38,6 +38,9 @@ @@ -38,6 +38,11 @@
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/dh.h> #include <openssl/dh.h>
+# ifdef HAVE_EVP_KDF_CTX_NEW_ID +# ifdef HAVE_EVP_KDF_CTX_NEW
+# include <openssl/kdf.h> +# include <openssl/kdf.h>
+# include <openssl/param_build.h>
+# include <openssl/core_names.h>
+# endif +# endif
#endif #endif
#include "ssh.h" #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; return r;
} }
+#ifdef HAVE_EVP_KDF_CTX_NEW_ID +#ifdef HAVE_EVP_KDF_CTX_NEW
+static const EVP_MD * +static const char *
+digest_to_md(int digest_type) +digest_to_md(int digest_type)
+{ +{
+ switch (digest_type) { + switch (digest_type) {
+ case SSH_DIGEST_SHA1: + case SSH_DIGEST_SHA1:
+ return EVP_sha1(); + return SN_sha1;
+ case SSH_DIGEST_SHA256: + case SSH_DIGEST_SHA256:
+ return EVP_sha256(); + return SN_sha256;
+ case SSH_DIGEST_SHA384: + case SSH_DIGEST_SHA384:
+ return EVP_sha384(); + return SN_sha384;
+ case SSH_DIGEST_SHA512: + case SSH_DIGEST_SHA512:
+ return EVP_sha512(); + return SN_sha512;
+ } + }
+ return NULL; + return NULL;
+} +}
@ -56,52 +58,67 @@ index b6f041f4..1fbce2bb 100644
+ const struct sshbuf *shared_secret, u_char **keyp) + const struct sshbuf *shared_secret, u_char **keyp)
+{ +{
+ struct kex *kex = ssh->kex; + struct kex *kex = ssh->kex;
+ EVP_KDF_CTX *ctx = NULL;
+ u_char *key = NULL; + u_char *key = NULL;
+ int r, key_len; + int r, key_len;
+ +
+ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) + EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL);
+ return SSH_ERR_INVALID_ARGUMENT; + 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(kdf);
+ EVP_KDF_free(kdf);
+ if (!ctx) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (md == NULL) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ 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;
+ }
+
+ key_len = ROUNDUP(need, key_len); + key_len = ROUNDUP(need, key_len);
+ if ((key = calloc(1, key_len)) == NULL) { + if ((key = calloc(1, key_len)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL; + r = SSH_ERR_ALLOC_FAIL;
+ goto out; + goto out;
+ } + }
+ +
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF); + r = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_DIGEST,
+ if (!ctx) { + 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; + r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out; + goto out;
+ } + }
+ +
+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest_to_md(kex->hash_alg)); + params = OSSL_PARAM_BLD_to_param(param_bld);
+ if (r != 1) { + if (params == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR; + r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out; + goto out;
+ } + }
+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, + r = EVP_KDF_derive(ctx, key, key_len, params);
+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret));
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, hash, hashlen);
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, id);
+ 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) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_derive(ctx, key, key_len);
+ if (r != 1) { + if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR; + r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out; + goto out;
@ -115,6 +132,8 @@ index b6f041f4..1fbce2bb 100644
+ r = 0; + r = 0;
+ +
+out: +out:
+ OSSL_PARAM_BLD_free(param_bld);
+ OSSL_PARAM_free(params);
+ free (key); + free (key);
+ EVP_KDF_CTX_free(ctx); + EVP_KDF_CTX_free(ctx);
+ if (r < 0) { + if (r < 0) {
@ -130,7 +149,7 @@ index b6f041f4..1fbce2bb 100644
ssh_digest_free(hashctx); ssh_digest_free(hashctx);
return r; return r;
} }
+#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */ +#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW */
#define NKEYS 6 #define NKEYS 6
int int

View File

@ -47,7 +47,7 @@
# Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 # 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_ver 8.7p1
%global openssh_rel 38 %global openssh_rel 39
%global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_ver 0.10.4
%global pam_ssh_agent_rel 5 %global pam_ssh_agent_rel 5
@ -798,6 +798,10 @@ test -f %{sysconfig_anaconda} && \
%endif %endif
%changelog %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 * Fri Jan 05 2024 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-38
- Fix Terrapin attack - Fix Terrapin attack
Resolves: CVE-2023-48795 Resolves: CVE-2023-48795