forked from rpms/openssh
		
	Use FIPS-compatible API for key derivation
Resolves: RHEL-32809
This commit is contained in:
		
							parent
							
								
									2c2ea1d489
								
							
						
					
					
						commit
						03eff3f0f1
					
				| @ -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'; | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user