From ed29a9dcff3272b8a14247b52c1146b4b2f0f604 Mon Sep 17 00:00:00 2001 From: hwx1054416 Date: Mon, 13 Sep 2021 17:00:31 +0800 Subject: [PATCH] fix CVE-2021-3634 --- CVE-2021-3634.patch | 213 ++++++++++++++++++++++++++++++++++++++++++++ libssh.spec | 10 ++- 2 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 CVE-2021-3634.patch diff --git a/CVE-2021-3634.patch b/CVE-2021-3634.patch new file mode 100644 index 0000000..791ea74 --- /dev/null +++ b/CVE-2021-3634.patch @@ -0,0 +1,213 @@ +From ebd18d65b725948e816be992d1649e7b18e67272 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Wed, 23 Jun 2021 13:16:33 +0200 +Subject: [PATCH] CVE-2021-3634:Create a sepatate length for session_id + +Normally,the length of session_id and secret_hash is the same, +but if we will get into rekeying with a peer that changes preference +of key exchange algorithm,the new secret hash can be larger or +smaller than the previous session_id causing invalid reads or writes. + +Resolves https://bugs.chromium.org/p/oss-fuzz/issues/datail?id=35485 + +Signed-off-by: Jakub Jelen +--- + include/libssh/crypto.h | 3 ++- + src/gssapi.c | 4 ++-- + src/kdf.c | 2 +- + src/kex.c | 4 +++- + src/libcrypto.c | 2 +- + src/messages.c | 4 ++-- + src/packet.c | 9 +++++---- + src/pki.c | 8 ++++---- + src/wrapper.c | 2 +- + tests/unittests/torture_session_keys.c | 3 ++- + 10 files changed, 23 insertions(+), 18 deletions(-) + +diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h +index ede7166..671cf91 100644 +--- a/include/libssh/crypto.h ++++ b/include/libssh/crypto.h +@@ -126,8 +126,9 @@ struct ssh_crypto_struct { + ssh_curve25519_pubkey curve25519_server_pubkey; + #endif + ssh_string dh_server_signature; /* information used by dh_handshake. */ +- size_t digest_len; /* len of the two fields below */ ++ size_t session_id_len; + unsigned char *session_id; ++ size_t digest_len; /* len of the two secret hash */ + unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */ + unsigned char *encryptIV; + unsigned char *decryptIV; +diff --git a/src/gssapi.c b/src/gssapi.c +index 488df58..1d0fb6a 100644 +--- a/src/gssapi.c ++++ b/src/gssapi.c +@@ -465,8 +465,8 @@ static ssh_buffer ssh_gssapi_build_mic(ssh_session session) + + rc = ssh_buffer_pack(mic_buffer, + "dPbsss", +- crypto->digest_len, +- (size_t)crypto->digest_len, crypto->session_id, ++ crypto->session_id_len, ++ crypto->session_id_len, crypto->session_id, + SSH2_MSG_USERAUTH_REQUEST, + session->gssapi->user, + "ssh-connection", +diff --git a/src/kdf.c b/src/kdf.c +index 0e90e18..0964473 100644 +--- a/src/kdf.c ++++ b/src/kdf.c +@@ -138,7 +138,7 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, + ssh_mac_update(ctx, key, key_len); + ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); + ssh_mac_update(ctx, &letter, 1); +- ssh_mac_update(ctx, crypto->session_id, crypto->digest_len); ++ ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len); + ssh_mac_final(digest, ctx); + + if (requested_len < output_len) { +diff --git a/src/kex.c b/src/kex.c +index 80b6e8a..602de1c 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -1197,11 +1197,13 @@ int ssh_make_sessionid(ssh_session session) + } + memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash, + session->next_crypto->digest_len); ++ /* Initial length is the same as secret hash */ ++ session->next_crypto->session_id_len = session->next_crypto->digest_len; + } + #ifdef DEBUG_CRYPTO + printf("Session hash: \n"); + ssh_log_hexdump("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len); +- ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->digest_len); ++ ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->session_id_len); + #endif + + rc = SSH_OK; +diff --git a/src/libcrypto.c b/src/libcrypto.c +index 8ff8a02..3db75df 100644 +--- a/src/libcrypto.c ++++ b/src/libcrypto.c +@@ -392,7 +392,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto, + goto out; + } + rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, +- crypto->session_id, crypto->digest_len); ++ crypto->session_id, crypto->session_id_len); + if (rc != 1) { + goto out; + } +diff --git a/src/messages.c b/src/messages.c +index 25683b2..2891218 100644 +--- a/src/messages.c ++++ b/src/messages.c +@@ -708,8 +708,8 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session, + + rc = ssh_buffer_pack(buffer, + "dPbsssbsS", +- crypto->digest_len, /* session ID string */ +- (size_t)crypto->digest_len, crypto->session_id, ++ crypto->session_id_len, /* session ID string */ ++ crypto->session_id_len, crypto->session_id, + SSH2_MSG_USERAUTH_REQUEST, /* type */ + msg->auth_request.username, + service, +diff --git a/src/packet.c b/src/packet.c +index e9ae564..9824fca 100644 +--- a/src/packet.c ++++ b/src/packet.c +@@ -1899,7 +1899,7 @@ ssh_packet_set_newkeys(ssh_session session, + + /* Both sides switched: do the actual switch now */ + if (session->next_crypto->used == SSH_DIRECTION_BOTH) { +- size_t digest_len; ++ size_t session_id_len; + + if (session->current_crypto != NULL) { + crypto_free(session->current_crypto); +@@ -1916,8 +1916,8 @@ ssh_packet_set_newkeys(ssh_session session, + return SSH_ERROR; + } + +- digest_len = session->current_crypto->digest_len; +- session->next_crypto->session_id = malloc(digest_len); ++ session_id_len = session->current_crypto->session_id_len; ++ session->next_crypto->session_id = malloc(session_id_len); + if (session->next_crypto->session_id == NULL) { + ssh_set_error_oom(session); + return SSH_ERROR; +@@ -1925,7 +1925,8 @@ ssh_packet_set_newkeys(ssh_session session, + + memcpy(session->next_crypto->session_id, + session->current_crypto->session_id, +- digest_len); ++ session_id_len); ++ session->next_crypto->session_id_len = session_id_len; + + return SSH_OK; + } +diff --git a/src/pki.c b/src/pki.c +index 6dcb120..dba305c 100644 +--- a/src/pki.c ++++ b/src/pki.c +@@ -2328,11 +2328,11 @@ ssh_string ssh_pki_do_sign(ssh_session session, + } + + /* Get the session ID */ +- session_id = ssh_string_new(crypto->digest_len); ++ session_id = ssh_string_new(crypto->session_id_len); + if (session_id == NULL) { + return NULL; + } +- ssh_string_fill(session_id, crypto->session_id, crypto->digest_len); ++ ssh_string_fill(session_id, crypto->session_id, crypto->session_id_len); + + /* Fill the input */ + sign_input = ssh_buffer_new(); +@@ -2389,11 +2389,11 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session, + } + + /* prepend session identifier */ +- session_id = ssh_string_new(crypto->digest_len); ++ session_id = ssh_string_new(crypto->session_id_len); + if (session_id == NULL) { + return NULL; + } +- ssh_string_fill(session_id, crypto->session_id, crypto->digest_len); ++ ssh_string_fill(session_id, crypto->session_id, crypto->session_id_len); + + sig_buf = ssh_buffer_new(); + if (sig_buf == NULL) { +diff --git a/src/wrapper.c b/src/wrapper.c +index 7e57ab5..36dc39c 100644 +--- a/src/wrapper.c ++++ b/src/wrapper.c +@@ -183,7 +183,7 @@ void crypto_free(struct ssh_crypto_struct *crypto) + } + #endif + if (crypto->session_id != NULL) { +- explicit_bzero(crypto->session_id, crypto->digest_len); ++ explicit_bzero(crypto->session_id, crypto->session_id_len); + SAFE_FREE(crypto->session_id); + } + if (crypto->secret_hash != NULL) { +diff --git a/tests/unittests/torture_session_keys.c b/tests/unittests/torture_session_keys.c +index f220e01..7a4e7ce 100644 +--- a/tests/unittests/torture_session_keys.c ++++ b/tests/unittests/torture_session_keys.c +@@ -48,8 +48,9 @@ struct ssh_cipher_struct fake_out_cipher = { + }; + + struct ssh_crypto_struct test_crypto = { +- .digest_len = 32, ++ .session_id_len = 32, + .session_id = secret, ++ .digest_len = 32, + .secret_hash = secret, + .in_cipher = &fake_in_cipher, + .out_cipher = &fake_out_cipher, +-- +1.8.3.1 + diff --git a/libssh.spec b/libssh.spec index 9fec48e..c3b92fc 100644 --- a/libssh.spec +++ b/libssh.spec @@ -1,6 +1,6 @@ Name: libssh Version: 0.9.5 -Release: 1 +Release: 2 Summary: A library implementing the SSH protocol License: LGPLv2+ URL: http://www.libssh.org @@ -9,6 +9,8 @@ Source0: https://www.libssh.org/files/0.9/%{name}-%{version}.tar.xz Source1: https://www.libssh.org/files/0.9/%{name}-%{version}.tar.xz.asc Source2: https://cryptomilk.org/gpgkey-8DFF53E18F2ABC8D8F3C92237EE0FC4DCC014E3D.gpg#/%{name}.keyring +Patch6000: CVE-2021-3634.patch + BuildRequires: cmake gcc-c++ gnupg2 openssl-devel pkgconfig zlib-devel BuildRequires: krb5-devel libcmocka-devel openssh-clients openssh-server BuildRequires: nmap-ncat libssh @@ -94,6 +96,12 @@ popd %doc ChangeLog README %changelog +* Mon Sep 13 2021 heyaohua - 0.9.5-2 +- Type:CVE +- Id:CVE-2021-3634 +- SUG:NA +- DESC:fix CVE-2021-3634 + * Fri Jan 29 2021 xihaochen - 0.9.5-1 - Type:requirements - Id:NA -- Gitee