aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/dh-gex.h35
-rw-r--r--include/libssh/session.h1
-rw-r--r--src/dh-gex.c127
-rw-r--r--src/kex.c2
4 files changed, 164 insertions, 1 deletions
diff --git a/include/libssh/dh-gex.h b/include/libssh/dh-gex.h
new file mode 100644
index 00000000..2963c297
--- /dev/null
+++ b/include/libssh/dh-gex.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2016 by Aris Adamantiadis <aris@0xbadc0de.be>
+ *
+ * The SSH Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The SSH Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the SSH Library; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#ifndef SRC_DH_GEX_H_
+#define SRC_DH_GEX_H_
+
+#include "config.h"
+
+int ssh_client_dhgex_init(ssh_session session);
+
+#ifdef WITH_SERVER
+void ssh_server_dhgex_init(ssh_session session);
+#endif /* WITH_SERVER */
+
+
+#endif /* SRC_DH_GEX_H_ */
diff --git a/include/libssh/session.h b/include/libssh/session.h
index 60d78578..a97d9bda 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_REQUEST_SENT,
DH_STATE_INIT_SENT,
DH_STATE_NEWKEYS_SENT,
DH_STATE_FINISHED
diff --git a/src/dh-gex.c b/src/dh-gex.c
new file mode 100644
index 00000000..f72684e6
--- /dev/null
+++ b/src/dh-gex.c
@@ -0,0 +1,127 @@
+/*
+ * dh-gex.c - diffie-hellman group exchange
+ *
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2016 by Aris Adamantiadis <aris@0xbadc0de.be>
+ *
+ * The SSH Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The SSH Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the SSH Library; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#include "libssh/dh-gex.h"
+#include "libssh/libssh.h"
+#include "libssh/ssh2.h"
+#include "libssh/callbacks.h"
+#include "libssh/dh.h"
+
+static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group);
+static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply);
+
+static ssh_packet_callback dhgex_client_callbacks[]= {
+ ssh_packet_client_dhgex_group, /* SSH_MSG_KEX_DH_GEX_GROUP */
+ NULL, /* SSH_MSG_KEX_DH_GEX_INIT */
+ ssh_packet_client_dhgex_reply /* SSH_MSG_KEX_DH_GEX_REPLY */
+};
+
+static struct ssh_packet_callbacks_struct ssh_dh_client_callbacks = {
+ .start = SSH2_MSG_KEX_DH_GEX_GROUP,
+ .n_callbacks = 3,
+ .callbacks = dhgex_client_callbacks,
+ .user = NULL
+};
+
+/** @internal
+ * @brief initiates a diffie-hellman-group-exchange kex
+ */
+int ssh_client_dhgex_init(ssh_session session){
+ int rc;
+
+ rc = ssh_dh_init_common(session);
+ if (rc != SSH_OK){
+ return rc;
+ }
+
+ /* Minimum group size, preferred group size, maximum group size */
+ rc = ssh_buffer_pack(session->out_buffer, "bddd",
+ SSH2_MSG_KEX_DH_GEX_REQUEST, 1534, 2048, 8192);
+ /* register the packet callbacks */
+ ssh_packet_set_callbacks(session, &ssh_dh_client_callbacks);
+ session->dh_handshake_state = DH_STATE_REQUEST_SENT;
+ rc = packet_send(session);
+ return rc;
+error:
+ ssh_dh_cleanup(session);
+ return SSH_ERROR;
+}
+
+/** @internal
+ * @brief handle a DH_GEX_GROUP packet, client side. This packet contains
+ * the group parameters.
+ */
+SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group){
+ int rc;
+ int blen;
+ bignum pmin1=NULL, one=NULL;
+
+ if (session->dh_handshake_state != DH_STATE_REQUEST_SENT){
+ ssh_set_error(session, SSH_FATAL, "Received DH_GEX_GROUP in invalid state");
+ goto error;
+ }
+ one = bignum_new();
+ pmin1 = bignum_new();
+ if (one == NULL || pmin1 == NULL){
+ ssh_error_oom(session);
+ goto error;
+ }
+ session->next_crypto->dh_group_is_mutable = 1;
+ rc = ssh_buffer_unpack(packet, "BB", &session->next_crypto->p, &session->next_crypto->g);
+ if (rc != SSH_OK){
+ ssh_set_error(session, SSH_FATAL, "Invalid DH_GEX_GROUP packet");
+ goto error;
+ }
+ /* basic checks */
+ bignum_set_word(one, 1);
+ blen = bignum_num_bits(session->next_crypto->p);
+ if (blen < 1024 || blen > 8192){
+ ssh_set_error(session, SSH_FATAL, "Invalid dh group parameter p: %d not in [1024:8192]", blen);
+ goto error;
+ }
+ if (bignum_cmp(session->next_crypto->p, one) <= 0){
+ /* p must be positive and preferably bigger than one */
+ ssh_set_error(session, SSH_FATAL, "Invalid dh group parameter p");
+ }
+ if (!bignum_is_bit_set(session->next_crypto->p, 0)){
+ /* p must be a prime and therefore not divisible by 2 */
+ ssh_set_error(session, SSH_FATAL, "Invalid dh group parameter p");
+ goto error;
+ }
+ bignum_sub(pmin1, session->next_crypto->p, one);
+ if (bignum_cmp(session->next_crypto->g, one) <= 0 ||
+ bignum_cmp(session->next_crypto->g, pmin1) > 0){
+ /* generator must be at least 2 and smaller than p-1*/
+ ssh_set_error(session, SSH_FATAL, "Invalid dh group parameter g");
+ goto error;
+ }
+
+ session->dh_handshake_state = DH_STATE_INIT_SENT;
+ return SSH_PACKET_USED;
+error:
+ bignum_safe_free(one);
+ bignum_safe_free(pmin1);
+ ssh_dh_cleanup(session);
+ session->session_state=SSH_SESSION_STATE_ERROR;
+ return SSH_PACKET_USED;
+}
diff --git a/src/kex.c b/src/kex.c
index 8ffa7007..4025eba7 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -86,7 +86,7 @@
#define ECDH ""
#endif
-#define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
+#define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
#define KEX_METHODS_SIZE 10
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */