diff --git a/include/libssh/curve25519.h b/include/libssh/curve25519.h index 0406b9ee..96018000 100644 --- a/include/libssh/curve25519.h +++ b/include/libssh/curve25519.h @@ -48,7 +48,6 @@ typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE]; int ssh_client_curve25519_init(ssh_session session); -int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet); #ifdef WITH_SERVER int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet); diff --git a/include/libssh/dh.h b/include/libssh/dh.h index cfdcfeec..2198a9fa 100644 --- a/include/libssh/dh.h +++ b/include/libssh/dh.h @@ -43,7 +43,6 @@ int ssh_dh_import_next_pubkey_blob(ssh_session session, ssh_string pubkey_blob); int ssh_dh_build_k(ssh_session session); int ssh_client_dh_init(ssh_session session); -int ssh_client_dh_reply(ssh_session session, ssh_buffer packet); ssh_key ssh_dh_get_current_server_publickey(ssh_session session); int ssh_dh_get_current_server_publickey_blob(ssh_session session, diff --git a/include/libssh/ecdh.h b/include/libssh/ecdh.h index 66659b85..c5212bc7 100644 --- a/include/libssh/ecdh.h +++ b/include/libssh/ecdh.h @@ -41,8 +41,7 @@ #define HAVE_ECDH 1 #endif -/* Common functions. */ -int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet); +extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks; /* Backend-specific functions. */ int ssh_client_ecdh_init(ssh_session session); diff --git a/src/curve25519.c b/src/curve25519.c index 167209f4..6738da61 100644 --- a/src/curve25519.c +++ b/src/curve25519.c @@ -39,6 +39,19 @@ #include "libssh/pki.h" #include "libssh/bignum.h" +static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply); + +static ssh_packet_callback dh_client_callbacks[] = { + ssh_packet_client_curve25519_reply +}; + +static struct ssh_packet_callbacks_struct ssh_curve25519_client_callbacks = { + .start = SSH2_MSG_KEX_ECDH_REPLY, + .n_callbacks = 1, + .callbacks = dh_client_callbacks, + .user = NULL +}; + /** @internal * @brief Starts curve25519-sha256@libssh.org / curve25519-sha256 key exchange */ @@ -64,7 +77,8 @@ int ssh_client_curve25519_init(ssh_session session){ ssh_set_error_oom(session); return SSH_ERROR; } - + /* register the packet callbacks */ + ssh_packet_set_callbacks(session, &ssh_curve25519_client_callbacks); rc = ssh_packet_send(session); return rc; @@ -117,11 +131,15 @@ static int ssh_curve25519_build_k(ssh_session session) { * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back * a SSH_MSG_NEWKEYS */ -int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet){ +static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){ ssh_string q_s_string = NULL; ssh_string pubkey_blob = NULL; ssh_string signature = NULL; int rc; + (void)type; + (void)user; + + ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks); pubkey_blob = ssh_buffer_get_ssh_string(packet); if (pubkey_blob == NULL) { @@ -171,10 +189,18 @@ int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet){ } rc=ssh_packet_send(session); + if (rc == SSH_ERROR) { + goto error; + } + SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); - return rc; + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; + error: - return SSH_ERROR; + session->session_state=SSH_SESSION_STATE_ERROR; + return SSH_PACKET_USED; } #ifdef WITH_SERVER diff --git a/src/dh.c b/src/dh.c index cc12fd46..474f52f3 100644 --- a/src/dh.c +++ b/src/dh.c @@ -652,6 +652,19 @@ int ssh_dh_build_k(ssh_session session) { return 0; } +static SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply); + +static ssh_packet_callback dh_client_callbacks[]= { + ssh_packet_client_dh_reply +}; + +static struct ssh_packet_callbacks_struct ssh_dh_client_callbacks = { + .start = SSH2_MSG_KEXDH_REPLY, + .n_callbacks = 1, + .callbacks = dh_client_callbacks, + .user = NULL +}; + /** @internal * @brief Starts diffie-hellman-group1 key exchange */ @@ -680,6 +693,9 @@ int ssh_client_dh_init(ssh_session session){ ssh_string_free(e); e=NULL; + /* register the packet callbacks */ + ssh_packet_set_callbacks(session, &ssh_dh_client_callbacks); + rc = ssh_packet_send(session); return rc; error: @@ -691,11 +707,15 @@ int ssh_client_dh_init(ssh_session session){ return SSH_ERROR; } -int ssh_client_dh_reply(ssh_session session, ssh_buffer packet){ +SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ ssh_string f; ssh_string pubkey_blob = NULL; ssh_string signature = NULL; int rc; + (void)type; + (void)user; + + ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks); pubkey_blob = ssh_buffer_get_ssh_string(packet); if (pubkey_blob == NULL){ @@ -740,10 +760,16 @@ int ssh_client_dh_reply(ssh_session session, ssh_buffer packet){ } rc=ssh_packet_send(session); + if (rc == SSH_ERROR) { + goto error; + } + SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); - return rc; + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + return SSH_PACKET_USED; error: - return SSH_ERROR; + session->session_state=SSH_SESSION_STATE_ERROR; + return SSH_PACKET_USED; } int ssh_make_sessionid(ssh_session session) { diff --git a/src/ecdh.c b/src/ecdh.c index f7fcaf13..71779da9 100644 --- a/src/ecdh.c +++ b/src/ecdh.c @@ -30,16 +30,32 @@ #ifdef HAVE_ECDH +static SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply); + +static ssh_packet_callback ecdh_client_callbacks[]= { + ssh_packet_client_ecdh_reply +}; + +struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks = { + .start = SSH2_MSG_KEX_ECDH_REPLY, + .n_callbacks = 1, + .callbacks = ecdh_client_callbacks, + .user = NULL +}; + /** @internal * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back * a SSH_MSG_NEWKEYS */ -int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet){ +SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){ ssh_string q_s_string = NULL; ssh_string pubkey_blob = NULL; ssh_string signature = NULL; int rc; + (void)type; + (void)user; + ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks); pubkey_blob = ssh_buffer_get_ssh_string(packet); if (pubkey_blob == NULL) { ssh_set_error(session,SSH_FATAL, "No public key in packet"); @@ -77,10 +93,18 @@ int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet){ } rc=ssh_packet_send(session); + if (rc == SSH_ERROR) { + goto error; + } + SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); - return rc; + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; + error: - return SSH_ERROR; + session->session_state=SSH_SESSION_STATE_ERROR; + return SSH_PACKET_USED; } #endif /* HAVE_ECDH */ diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c index 24f21c03..10cc6a5f 100644 --- a/src/ecdh_crypto.c +++ b/src/ecdh_crypto.c @@ -108,6 +108,10 @@ int ssh_client_ecdh_init(ssh_session session){ session->next_crypto->ecdh_privkey = key; session->next_crypto->ecdh_client_pubkey = client_pubkey; + /* register the packet callbacks */ + ssh_packet_set_callbacks(session, &ssh_ecdh_client_callbacks); + session->dh_handshake_state = DH_STATE_INIT_SENT; + rc = ssh_packet_send(session); return rc; diff --git a/src/ecdh_gcrypt.c b/src/ecdh_gcrypt.c index e43cacea..96dbd1a0 100644 --- a/src/ecdh_gcrypt.c +++ b/src/ecdh_gcrypt.c @@ -106,6 +106,10 @@ int ssh_client_ecdh_init(ssh_session session) session->next_crypto->ecdh_client_pubkey = client_pubkey; client_pubkey = NULL; + /* register the packet callbacks */ + ssh_packet_set_callbacks(session, &ssh_ecdh_client_callbacks); + session->dh_handshake_state = DH_STATE_INIT_SENT; + rc = ssh_packet_send(session); out: diff --git a/src/ecdh_mbedcrypto.c b/src/ecdh_mbedcrypto.c index fa350028..3ff93ee8 100644 --- a/src/ecdh_mbedcrypto.c +++ b/src/ecdh_mbedcrypto.c @@ -106,6 +106,9 @@ int ssh_client_ecdh_init(ssh_session session) session->next_crypto->ecdh_client_pubkey = client_pubkey; client_pubkey = NULL; + /* register the packet callbacks */ + ssh_packet_set_callbacks(session, &ssh_ecdh_client_callbacks); + session->dh_handshake_state = DH_STATE_INIT_SENT; rc = ssh_packet_send(session); out: diff --git a/src/packet.c b/src/packet.c index 030a29a1..8fa10283 100644 --- a/src/packet.c +++ b/src/packet.c @@ -74,7 +74,7 @@ static ssh_packet_callback default_packet_handlers[]= { #else NULL, #endif - ssh_packet_dh_reply, // SSH2_MSG_KEXDH_REPLY 31 + NULL, // SSH2_MSG_KEXDH_REPLY 31 // SSH2_MSG_KEX_DH_GEX_GROUP 31 NULL, // SSH2_MSG_KEX_DH_GEX_INIT 32 NULL, // SSH2_MSG_KEX_DH_GEX_REPLY 33 diff --git a/src/packet_cb.c b/src/packet_cb.c index 43dae481..22051c5d 100644 --- a/src/packet_cb.c +++ b/src/packet_cb.c @@ -92,50 +92,6 @@ SSH_PACKET_CALLBACK(ssh_packet_ignore_callback){ return SSH_PACKET_USED; } -SSH_PACKET_CALLBACK(ssh_packet_dh_reply){ - int rc; - (void)type; - (void)user; - SSH_LOG(SSH_LOG_PROTOCOL,"Received SSH_KEXDH_REPLY"); - if (session->session_state != SSH_SESSION_STATE_DH || - session->dh_handshake_state != DH_STATE_INIT_SENT){ - ssh_set_error(session,SSH_FATAL,"ssh_packet_dh_reply called in wrong state : %d:%d", - session->session_state,session->dh_handshake_state); - goto error; - } - switch(session->next_crypto->kex_type){ - case SSH_KEX_DH_GROUP1_SHA1: - case SSH_KEX_DH_GROUP14_SHA1: - case SSH_KEX_DH_GROUP16_SHA512: - case SSH_KEX_DH_GROUP18_SHA512: - rc=ssh_client_dh_reply(session, packet); - break; -#ifdef HAVE_ECDH - case SSH_KEX_ECDH_SHA2_NISTP256: - case SSH_KEX_ECDH_SHA2_NISTP384: - case SSH_KEX_ECDH_SHA2_NISTP521: - rc = ssh_client_ecdh_reply(session, packet); - break; -#endif -#ifdef HAVE_CURVE25519 - case SSH_KEX_CURVE25519_SHA256: - case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: - rc = ssh_client_curve25519_reply(session, packet); - break; -#endif - default: - ssh_set_error(session,SSH_FATAL,"Wrong kex type in ssh_packet_dh_reply"); - goto error; - } - if(rc==SSH_OK) { - session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; - return SSH_PACKET_USED; - } -error: - session->session_state=SSH_SESSION_STATE_ERROR; - return SSH_PACKET_USED; -} - SSH_PACKET_CALLBACK(ssh_packet_newkeys){ ssh_string sig_blob = NULL; ssh_signature sig = NULL;