Skip to content
This repository was archived by the owner on Jan 26, 2026. It is now read-only.

Commit b759ae5

Browse files
Jakujecryptomilk
authored andcommitted
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>
1 parent 6df2dae commit b759ae5

9 files changed

Lines changed: 66 additions & 4 deletions

File tree

include/libssh/curve25519.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
5252

5353

5454
int ssh_client_curve25519_init(ssh_session session);
55+
void ssh_client_curve25519_remove_callbacks(ssh_session session);
5556

5657
#ifdef WITH_SERVER
5758
void ssh_server_curve25519_init(ssh_session session);

include/libssh/dh-gex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extern "C" {
2828
#endif
2929

3030
int ssh_client_dhgex_init(ssh_session session);
31+
void ssh_client_dhgex_remove_callbacks(ssh_session session);
3132

3233
#ifdef WITH_SERVER
3334
void ssh_server_dhgex_init(ssh_session session);

include/libssh/dh.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ int ssh_dh_get_next_server_publickey_blob(ssh_session session,
7979
ssh_string *pubkey_blob);
8080

8181
int ssh_client_dh_init(ssh_session session);
82+
void ssh_client_dh_remove_callbacks(ssh_session session);
8283
#ifdef WITH_SERVER
8384
void ssh_server_dh_init(ssh_session session);
8485
#endif /* WITH_SERVER */

include/libssh/ecdh.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ extern "C" {
4949
extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks;
5050
/* Backend-specific functions. */
5151
int ssh_client_ecdh_init(ssh_session session);
52+
void ssh_client_ecdh_remove_callbacks(ssh_session session);
5253
int ecdh_build_k(ssh_session session);
5354

5455
#ifdef WITH_SERVER

src/curve25519.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ int ssh_client_curve25519_init(ssh_session session)
172172
return rc;
173173
}
174174

175+
void ssh_client_curve25519_remove_callbacks(ssh_session session)
176+
{
177+
ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks);
178+
}
179+
175180
static int ssh_curve25519_build_k(ssh_session session)
176181
{
177182
ssh_curve25519_pubkey k;
@@ -285,7 +290,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
285290
(void)type;
286291
(void)user;
287292

288-
ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks);
293+
ssh_client_curve25519_remove_callbacks(session);
289294

290295
pubkey_blob = ssh_buffer_get_ssh_string(packet);
291296
if (pubkey_blob == NULL) {

src/dh-gex.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group)
248248
return SSH_PACKET_USED;
249249
}
250250

251+
void ssh_client_dhgex_remove_callbacks(ssh_session session)
252+
{
253+
ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks);
254+
}
255+
251256
static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
252257
{
253258
struct ssh_crypto_struct *crypto=session->next_crypto;
@@ -258,7 +263,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply)
258263
(void)user;
259264
SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_DH_GEX_REPLY received");
260265

261-
ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks);
266+
ssh_client_dhgex_remove_callbacks(session);
262267
rc = ssh_buffer_unpack(packet,
263268
"SBS",
264269
&pubkey_blob, &server_pubkey,

src/dh.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,11 @@ int ssh_client_dh_init(ssh_session session){
354354
return SSH_ERROR;
355355
}
356356

357+
void ssh_client_dh_remove_callbacks(ssh_session session)
358+
{
359+
ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
360+
}
361+
357362
SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
358363
struct ssh_crypto_struct *crypto=session->next_crypto;
359364
ssh_string pubkey_blob = NULL;
@@ -363,7 +368,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
363368
(void)type;
364369
(void)user;
365370

366-
ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
371+
ssh_client_dh_remove_callbacks(session);
367372

368373
rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey,
369374
&crypto->dh_server_signature);

src/ecdh.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks = {
4343
.user = NULL
4444
};
4545

46+
void ssh_client_ecdh_remove_callbacks(ssh_session session)
47+
{
48+
ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks);
49+
}
50+
4651
/** @internal
4752
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
4853
* a SSH_MSG_NEWKEYS
@@ -55,7 +60,7 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){
5560
(void)type;
5661
(void)user;
5762

58-
ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks);
63+
ssh_client_ecdh_remove_callbacks(session);
5964
pubkey_blob = ssh_buffer_get_ssh_string(packet);
6065
if (pubkey_blob == NULL) {
6166
ssh_set_error(session,SSH_FATAL, "No public key in packet");

src/kex.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,44 @@ kex_select_kex_type(const char *kex)
818818
return 0;
819819
}
820820

821+
822+
/** @internal
823+
* @brief Reverts guessed callbacks set during the dh_handshake()
824+
* @param session session handle
825+
* @returns void
826+
*/
827+
static void revert_kex_callbacks(ssh_session session)
828+
{
829+
switch (session->next_crypto->kex_type) {
830+
case SSH_KEX_DH_GROUP1_SHA1:
831+
case SSH_KEX_DH_GROUP14_SHA1:
832+
case SSH_KEX_DH_GROUP14_SHA256:
833+
case SSH_KEX_DH_GROUP16_SHA512:
834+
case SSH_KEX_DH_GROUP18_SHA512:
835+
ssh_client_dh_remove_callbacks(session);
836+
break;
837+
#ifdef WITH_GEX
838+
case SSH_KEX_DH_GEX_SHA1:
839+
case SSH_KEX_DH_GEX_SHA256:
840+
ssh_client_dhgex_remove_callbacks(session);
841+
break;
842+
#endif /* WITH_GEX */
843+
#ifdef HAVE_ECDH
844+
case SSH_KEX_ECDH_SHA2_NISTP256:
845+
case SSH_KEX_ECDH_SHA2_NISTP384:
846+
case SSH_KEX_ECDH_SHA2_NISTP521:
847+
ssh_client_ecdh_remove_callbacks(session);
848+
break;
849+
#endif
850+
#ifdef HAVE_CURVE25519
851+
case SSH_KEX_CURVE25519_SHA256:
852+
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
853+
ssh_client_curve25519_remove_callbacks(session);
854+
break;
855+
#endif
856+
}
857+
}
858+
821859
/** @brief Select the different methods on basis of client's and
822860
* server's kex messages, and watches out if a match is possible.
823861
*/

0 commit comments

Comments
 (0)