CVE-2023-1667:dh: Expose the callback cleanup functions

These will be helpful when we already sent the first key exchange packet, but we
found out that our guess was wrong and we need to initiate different key
exchange method with different callbacks.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Norbert Pocs <npocs@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Jakub Jelen
2023-03-17 14:05:01 +01:00
committed by Andreas Schneider
parent f455ffe8b8
commit cd0aa0bd91
9 changed files with 66 additions and 4 deletions

View File

@@ -52,6 +52,7 @@ typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
int ssh_client_curve25519_init(ssh_session session);
void ssh_client_curve25519_remove_callbacks(ssh_session session);
#ifdef WITH_SERVER
void ssh_server_curve25519_init(ssh_session session);

View File

@@ -28,6 +28,7 @@ extern "C" {
#endif
int ssh_client_dhgex_init(ssh_session session);
void ssh_client_dhgex_remove_callbacks(ssh_session session);
#ifdef WITH_SERVER
void ssh_server_dhgex_init(ssh_session session);

View File

@@ -79,6 +79,7 @@ int ssh_dh_get_next_server_publickey_blob(ssh_session session,
ssh_string *pubkey_blob);
int ssh_client_dh_init(ssh_session session);
void ssh_client_dh_remove_callbacks(ssh_session session);
#ifdef WITH_SERVER
void ssh_server_dh_init(ssh_session session);
#endif /* WITH_SERVER */

View File

@@ -49,6 +49,7 @@ extern "C" {
extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks;
/* Backend-specific functions. */
int ssh_client_ecdh_init(ssh_session session);
void ssh_client_ecdh_remove_callbacks(ssh_session session);
int ecdh_build_k(ssh_session session);
#ifdef WITH_SERVER

View File

@@ -172,6 +172,11 @@ int ssh_client_curve25519_init(ssh_session session)
return rc;
}
void ssh_client_curve25519_remove_callbacks(ssh_session session)
{
ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks);
}
static int ssh_curve25519_build_k(ssh_session session)
{
ssh_curve25519_pubkey k;
@@ -285,7 +290,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
(void)type;
(void)user;
ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks);
ssh_client_curve25519_remove_callbacks(session);
pubkey_blob = ssh_buffer_get_ssh_string(packet);
if (pubkey_blob == NULL) {

View File

@@ -248,6 +248,11 @@ error:
return SSH_PACKET_USED;
}
void ssh_client_dhgex_remove_callbacks(ssh_session session)
{
ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks);
}
static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
{
struct ssh_crypto_struct *crypto=session->next_crypto;
@@ -258,7 +263,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
(void)user;
SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_KEX_DH_GEX_REPLY received");
ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks);
ssh_client_dhgex_remove_callbacks(session);
rc = ssh_buffer_unpack(packet,
"SBS",
&pubkey_blob, &server_pubkey,

View File

@@ -354,6 +354,11 @@ error:
return SSH_ERROR;
}
void ssh_client_dh_remove_callbacks(ssh_session session)
{
ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
}
SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
struct ssh_crypto_struct *crypto=session->next_crypto;
ssh_string pubkey_blob = NULL;
@@ -363,7 +368,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
(void)type;
(void)user;
ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
ssh_client_dh_remove_callbacks(session);
rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey,
&crypto->dh_server_signature);

View File

@@ -43,6 +43,11 @@ struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks = {
.user = NULL
};
void ssh_client_ecdh_remove_callbacks(ssh_session session)
{
ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks);
}
/** @internal
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
* a SSH_MSG_NEWKEYS
@@ -55,7 +60,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){
(void)type;
(void)user;
ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks);
ssh_client_ecdh_remove_callbacks(session);
pubkey_blob = ssh_buffer_get_ssh_string(packet);
if (pubkey_blob == NULL) {
ssh_set_error(session,SSH_FATAL, "No public key in packet");

View File

@@ -813,6 +813,44 @@ kex_select_kex_type(const char *kex)
return 0;
}
/** @internal
* @brief Reverts guessed callbacks set during the dh_handshake()
* @param session session handle
* @returns void
*/
static void revert_kex_callbacks(ssh_session session)
{
switch (session->next_crypto->kex_type) {
case SSH_KEX_DH_GROUP1_SHA1:
case SSH_KEX_DH_GROUP14_SHA1:
case SSH_KEX_DH_GROUP14_SHA256:
case SSH_KEX_DH_GROUP16_SHA512:
case SSH_KEX_DH_GROUP18_SHA512:
ssh_client_dh_remove_callbacks(session);
break;
#ifdef WITH_GEX
case SSH_KEX_DH_GEX_SHA1:
case SSH_KEX_DH_GEX_SHA256:
ssh_client_dhgex_remove_callbacks(session);
break;
#endif /* WITH_GEX */
#ifdef HAVE_ECDH
case SSH_KEX_ECDH_SHA2_NISTP256:
case SSH_KEX_ECDH_SHA2_NISTP384:
case SSH_KEX_ECDH_SHA2_NISTP521:
ssh_client_ecdh_remove_callbacks(session);
break;
#endif
#ifdef HAVE_CURVE25519
case SSH_KEX_CURVE25519_SHA256:
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
ssh_client_curve25519_remove_callbacks(session);
break;
#endif
}
}
/** @brief Select the different methods on basis of client's and
* server's kex messages, and watches out if a match is possible.
*/