aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2017-06-11 11:57:25 +0200
committerAris Adamantiadis <aris@0xbadc0de.be>2017-06-11 11:57:25 +0200
commit3bd1b80c85d6657f47031b10211265fa216da37c (patch)
treee0e820ef7aa2b9dfe3d4f8c01413512edbcb789e
parent6f8ec3062c8b7f21a6995d498c3aae8f106bda8f (diff)
downloadlibssh-3bd1b80c85d6657f47031b10211265fa216da37c.tar.gz
libssh-3bd1b80c85d6657f47031b10211265fa216da37c.tar.xz
libssh-3bd1b80c85d6657f47031b10211265fa216da37c.zip
dh: WIP
-rw-r--r--include/libssh/crypto.h2
-rw-r--r--include/libssh/dh.h1
-rw-r--r--include/libssh/session.h1
-rw-r--r--src/dh.c60
-rw-r--r--src/kex.c4
-rw-r--r--src/server.c1
6 files changed, 47 insertions, 22 deletions
diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index 201feaf2..805873ea 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -81,7 +81,7 @@ struct ssh_crypto_struct {
bignum g, p;
int dh_group_is_mutable; /* do free group parameters */
int dh_group_bits; /* size of p in bits */
- int pmin; int pn; int pmax; /* preferred group parameters */
+ int dh_pmin; int dh_pn; int dh_pmax; /* preferred group parameters */
#ifdef HAVE_ECDH
#ifdef HAVE_OPENSSL_ECC
EC_KEY *ecdh_privkey;
diff --git a/include/libssh/dh.h b/include/libssh/dh.h
index b270abf5..3a613cb9 100644
--- a/include/libssh/dh.h
+++ b/include/libssh/dh.h
@@ -38,5 +38,6 @@ void ssh_server_dh_init(ssh_session session);
int ssh_dh_init_common(ssh_session session);
void ssh_dh_cleanup(struct ssh_crypto_struct *crypto);
int ssh_dh_generate_secret(ssh_session session, bignum dest);
+int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet);
#endif /* DH_H_ */
diff --git a/include/libssh/session.h b/include/libssh/session.h
index a97d9bda..bcf02c3d 100644
--- a/include/libssh/session.h
+++ b/include/libssh/session.h
@@ -45,6 +45,7 @@ enum ssh_session_state_e {
enum ssh_dh_state_e {
DH_STATE_INIT=0,
+ DH_STATE_GROUP_SENT,
DH_STATE_REQUEST_SENT,
DH_STATE_INIT_SENT,
DH_STATE_NEWKEYS_SENT,
diff --git a/src/dh.c b/src/dh.c
index 6845b396..5b1d748b 100644
--- a/src/dh.c
+++ b/src/dh.c
@@ -371,23 +371,19 @@ void ssh_server_dh_init(ssh_session session){
}
/** @internal
- * @brief parse an incoming SSH_MSG_KEXDH_INIT packet and complete
- * Diffie-Hellman key exchange
- **/
-static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init){
+ * @brief processes a SSH_MSG_KEXDH_INIT or SSH_MSG_KEX_DH_GEX_INIT packet and send
+ * the appropriate SSH_MSG_KEXDH_REPLY or SSH_MSG_KEXDEH_GEX_REPLY
+ */
+int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet){
ssh_key privkey;
ssh_string sig_blob;
- bignum_CTX ctx = bignum_ctx_new();
int rc;
-
- (void)type;
- (void)user;
+ int packet_type;
+ bignum_CTX ctx = bignum_ctx_new();
if (bignum_ctx_invalid(ctx)) {
goto error;
}
- ssh_packet_remove_callbacks(session, &ssh_dh_server_callbacks);
-
rc = ssh_buffer_unpack(packet, "B", &session->next_crypto->e);
if (rc == SSH_ERROR) {
ssh_set_error(session, SSH_FATAL, "No e number in client request");
@@ -428,10 +424,22 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init){
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
goto error;
}
-
+ switch (session->next_crypto->kex_type){
+ case SSH_KEX_DH_GROUP1_SHA1:
+ case SSH_KEX_DH_GROUP14_SHA1:
+ packet_type = SSH2_MSG_KEXDH_REPLY;
+ break;
+ case SSH_KEX_DH_GEX_SHA1:
+ case SSH_KEX_DH_GEX_SHA256:
+ packet_type = SSH2_MSG_KEX_DH_GEX_REPLY;
+ break;
+ default:
+ ssh_set_error(session, SSH_FATAL, "Invalid kex type");
+ goto error;
+ }
rc = ssh_buffer_pack(session->out_buffer,
"bSBS",
- SSH2_MSG_KEXDH_REPLY,
+ packet_type,
session->next_crypto->server_pubkey,
session->next_crypto->f,
sig_blob);
@@ -442,28 +450,40 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init){
goto error;
}
- if (ssh_packet_send(session) == SSH_ERROR) {
+ if (ssh_packet_send(session) == SSH_ERROR) {
goto error;
}
-
- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
+ SSH_LOG(SSH_LOG_DEBUG, "Sent KEX_DH_[GEX]_REPLY");
+ if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
ssh_buffer_reinit(session->out_buffer);
goto error;
}
+ session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
- if (ssh_packet_send(session) == SSH_ERROR) {
+ if (ssh_packet_send(session) == SSH_ERROR) {
goto error;
}
SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");
- session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
- ssh_dh_cleanup(session);
- return SSH_PACKET_USED;
+ return SSH_OK;
error:
- ssh_dh_cleanup(session);
if (!bignum_ctx_invalid(ctx)){
bignum_ctx_free(ctx);
}
session->session_state=SSH_SESSION_STATE_ERROR;
+ ssh_dh_cleanup(session->next_crypto);
+ return SSH_ERROR;
+}
+
+/** @internal
+ * @brief parse an incoming SSH_MSG_KEXDH_INIT packet and complete
+ * Diffie-Hellman key exchange
+ **/
+static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init){
+ (void)type;
+ (void)user;
+ SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_KEXDH_INIT");
+ ssh_packet_remove_callbacks(session, &ssh_dh_server_callbacks);
+ ssh_server_dh_process_init(session, packet);
return SSH_PACKET_USED;
}
diff --git a/src/kex.c b/src/kex.c
index 64d9a369..fea7f940 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -768,7 +768,9 @@ int ssh_make_sessionid(ssh_session session) {
case SSH_KEX_DH_GEX_SHA256:
rc = ssh_buffer_pack(buf,
"dddBBBB",
- 1534, 2048, 8192,
+ session->next_crypto->dh_pmin,
+ session->next_crypto->dh_pn,
+ session->next_crypto->dh_pmax,
session->next_crypto->p,
session->next_crypto->g,
session->next_crypto->e,
diff --git a/src/server.c b/src/server.c
index e6c51d30..683488c9 100644
--- a/src/server.c
+++ b/src/server.c
@@ -165,6 +165,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
session->first_kex_follows_guess_wrong = 0;
return SSH_PACKET_USED;
}
+ SSH_LOG(SSH_LOG_DEBUG, "Calling next KEXDH handler");
return SSH_PACKET_NOT_USED;
}