diff --git a/cli-kex.c b/cli-kex.c
index 833529ac04221464acd6db61e90f63b69f73df71..1158aa66b5e16d291a08001b019044eecd3c9d51 100644
--- a/cli-kex.c
+++ b/cli-kex.c
@@ -43,11 +43,19 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen);
 
 void send_msg_kexdh_init() {
 	TRACE(("send_msg_kexdh_init()"))	
-	cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int));
-	cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int));
-	m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
+	if ((cli_ses.dh_e && cli_ses.dh_x 
+				&& cli_ses.dh_val_algo == ses.newkeys->algo_kex)) {
+		TRACE(("reusing existing dh_e from first_kex_packet_follows"))
+	} else {
+		if (!cli_ses.dh_e || !cli_ses.dh_e) {
+			cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int));
+			cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int));
+			m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
+		}
 
-	gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x);
+		gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x);
+		cli_ses.dh_val_algo = ses.newkeys->algo_kex;
+	}
 
 	CHECKCLEARTOWRITE();
 	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
@@ -99,6 +107,7 @@ void recv_msg_kexdh_reply() {
 	mp_clear_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);
 	m_free(cli_ses.dh_e);
 	m_free(cli_ses.dh_x);
+	cli_ses.dh_val_algo = DROPBEAR_KEX_NONE;
 
 	if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE) 
 			!= DROPBEAR_SUCCESS) {
diff --git a/cli-session.c b/cli-session.c
index 600827fab974c98a5c68b98eb85818a8e4e319c7..9e642813aa1022947533b18f0b9366e4d5bf9849 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -182,6 +182,11 @@ static void cli_sessionloop() {
 
 	TRACE2(("enter cli_sessionloop"))
 
+	if (ses.lastpacket == 0) {
+		TRACE2(("exit cli_sessionloop: no real packets yet"))
+		return;
+	}
+
 	if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
 		/* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT
 		 * negotiation would have failed. */
@@ -206,10 +211,9 @@ static void cli_sessionloop() {
 		return;
 	}
 
-	/* We should exit if we haven't donefirstkex: we shouldn't reach here
-	 * in normal operation */
 	if (ses.kexstate.donefirstkex == 0) {
-		TRACE(("XXX XXX might be bad! leave cli_sessionloop: haven't donefirstkex"))
+		/* We might reach here if we have partial packet reads or have
+		 * received SSG_MSG_IGNORE etc. Just skip it */
 		return;
 	}
 
diff --git a/common-algo.c b/common-algo.c
index 8267852c5b56d34f9592e20b390b9a83129da944..b698611e404fe38faa2e5c54ba79abc500a73205 100644
--- a/common-algo.c
+++ b/common-algo.c
@@ -214,8 +214,8 @@ algo_type sshhostkey[] = {
 };
 
 algo_type sshkex[] = {
-	{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL},
 	{"diffie-hellman-group14-sha1", DROPBEAR_KEX_DH_GROUP14, NULL, 1, NULL},
+	{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL},
 	{KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL},
 	{NULL, 0, NULL, 0, NULL}
 };
diff --git a/session.h b/session.h
index 33c153994be270ccedbd24fb6e121a17ac3db4c3..9bbeac413c9c75e4485ddb20826b9e8ea4eaa55f 100644
--- a/session.h
+++ b/session.h
@@ -241,6 +241,7 @@ typedef enum {
 struct clientsession {
 
 	mp_int *dh_e, *dh_x; /* Used during KEX */
+	int dh_val_algo; /* KEX algorithm corresponding to current dh_e and dh_x */
 	cli_kex_state kex_state; /* Used for progressing KEX */
 	cli_state state; /* Used to progress auth/channelsession etc */
 	unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */
diff --git a/sysoptions.h b/sysoptions.h
index 6e6029471143869119e97612b5a24974af010721..4d648c131b1666e3b837b5ebd12a355845ccc518 100644
--- a/sysoptions.h
+++ b/sysoptions.h
@@ -61,8 +61,9 @@
 #define DROPBEAR_FAILURE -1
 
 /* various algorithm identifiers */
-#define DROPBEAR_KEX_DH_GROUP1 0
-#define DROPBEAR_KEX_DH_GROUP14 1
+#define DROPBEAR_KEX_NONE 0
+#define DROPBEAR_KEX_DH_GROUP1 1
+#define DROPBEAR_KEX_DH_GROUP14 2
 
 #define DROPBEAR_SIGNKEY_ANY 0
 #define DROPBEAR_SIGNKEY_RSA 1