Blob Blame History Raw
From 5618210618256bbf5f4f71b2887ff186fd451736 Mon Sep 17 00:00:00 2001
From: Damien Miller <djm@mindrot.org>
Date: Sun, 20 Apr 2014 13:44:47 +1000
Subject: [PATCH]  - (djm) [bufaux.c compat.c compat.h sshconnect2.c sshd.c
 version.h]    OpenSSH 6.5 and 6.6 sometimes encode a value used in the
 curve25519    key exchange incorrectly, causing connection failures about
 0.2% of    the time when this method is used against a peer that implements  
  the method properly.

   Fix the problem and disable the curve25519 KEX when speaking to
   OpenSSH 6.5 or 6.6. This version will identify itself as 6.6.1
   to enable the compatability code.
---
 ChangeLog     | 11 +++++++++++
 bufaux.c      |  5 ++++-
 compat.c      | 17 ++++++++++++++++-
 compat.h      |  2 ++
 sshconnect2.c |  2 ++
 sshd.c        |  3 +++
 version.h     |  2 +-
 7 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1603a07..928999d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,13 +1,23 @@
 20140420
-   - djm@cvs.openbsd.org 2014/04/01 03:34:10
-     [sshconnect.c]
-     When using VerifyHostKeyDNS with a DNSSEC resolver, down-convert any
-     certificate keys to plain keys and attempt SSHFP resolution.
-     
-     Prevents a server from skipping SSHFP lookup and forcing a new-hostkey
-     dialog by offering only certificate keys.
-     
-     Reported by mcv21 AT cam.ac.uk
+ - (djm) [bufaux.c compat.c compat.h sshconnect2.c sshd.c version.h]
+   OpenSSH 6.5 and 6.6 sometimes encode a value used in the curve25519
+   key exchange incorrectly, causing connection failures about 0.2% of
+   the time when this method is used against a peer that implements
+   the method properly.
+
+   Fix the problem and disable the curve25519 KEX when speaking to
+   OpenSSH 6.5 or 6.6. This version will identify itself as 6.6.1
+   to enable the compatability code.
+
+ - djm@cvs.openbsd.org 2014/04/01 03:34:10
+   [sshconnect.c]
+   When using VerifyHostKeyDNS with a DNSSEC resolver, down-convert any
+   certificate keys to plain keys and attempt SSHFP resolution.
+   
+   Prevents a server from skipping SSHFP lookup and forcing a new-hostkey
+   dialog by offering only certificate keys.
+   
+   Reported by mcv21 AT cam.ac.uk
 
 20140313
  - (djm) Release OpenSSH 6.6
diff --git a/bufaux.c b/bufaux.c
index e24b5fc..f6a6f2a 100644
--- a/bufaux.c
+++ b/bufaux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bufaux.c,v 1.56 2014/02/02 03:44:31 djm Exp $ */
+/* $OpenBSD: bufaux.c,v 1.57 2014/04/16 23:22:45 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -372,6 +372,9 @@ buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
 
 	if (l > 8 * 1024)
 		fatal("%s: length %u too long", __func__, l);
+	/* Skip leading zero bytes */
+	for (; l > 0 && *s == 0; l--, s++)
+		;
 	p = buf = xmalloc(l + 1);
 	/*
 	 * If most significant bit is set then prepend a zero byte to
diff --git a/compat.c b/compat.c
index 9d9fabe..2709dc5 100644
--- a/compat.c
+++ b/compat.c
@@ -95,6 +95,9 @@ compat_datafellows(const char *version)
 		{ "Sun_SSH_1.0*",	SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
 		{ "OpenSSH_4*",		0 },
 		{ "OpenSSH_5*",		SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT},
+		{ "OpenSSH_6.6.1*",	SSH_NEW_OPENSSH},
+		{ "OpenSSH_6.5*,"
+		  "OpenSSH_6.6*",	SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD},
 		{ "OpenSSH*",		SSH_NEW_OPENSSH },
 		{ "*MindTerm*",		0 },
 		{ "2.1.0*",		SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
@@ -251,7 +254,6 @@ compat_cipher_proposal(char *cipher_prop)
 	return cipher_prop;
 }
 
-
 char *
 compat_pkalg_proposal(char *pkalg_prop)
 {
@@ -265,3 +267,16 @@ compat_pkalg_proposal(char *pkalg_prop)
 	return pkalg_prop;
 }
 
+char *
+compat_kex_proposal(char *kex_prop)
+{
+	if (!(datafellows & SSH_BUG_CURVE25519PAD))
+		return kex_prop;
+	debug2("%s: original KEX proposal: %s", __func__, kex_prop);
+	kex_prop = filter_proposal(kex_prop, "curve25519-sha256@libssh.org");
+	debug2("%s: compat KEX proposal: %s", __func__, kex_prop);
+	if (*kex_prop == '\0')
+		fatal("No supported key exchange algorithms found");
+	return kex_prop;
+}
+
diff --git a/compat.h b/compat.h
index b174fa1..a6c3f3d 100644
--- a/compat.h
+++ b/compat.h
@@ -59,6 +59,7 @@
 #define SSH_BUG_RFWD_ADDR	0x02000000
 #define SSH_NEW_OPENSSH		0x04000000
 #define SSH_BUG_DYNAMIC_RPORT	0x08000000
+#define SSH_BUG_CURVE25519PAD	0x10000000
 
 void     enable_compat13(void);
 void     enable_compat20(void);
@@ -66,6 +67,7 @@ void     compat_datafellows(const char *);
 int	 proto_spec(const char *);
 char	*compat_cipher_proposal(char *);
 char	*compat_pkalg_proposal(char *);
+char	*compat_kex_proposal(char *);
 
 extern int compat13;
 extern int compat20;
diff --git a/sshconnect2.c b/sshconnect2.c
index bb9292f..b00658b 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -220,6 +220,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
 	}
 	if (options.kex_algorithms != NULL)
 		myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+	myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
+	    myproposal[PROPOSAL_KEX_ALGS]);
 
 #ifdef GSSAPI
 	/* If we've got GSSAPI algorithms, then we also support the
diff --git a/sshd.c b/sshd.c
index e4e406e..512c7ed 100644
--- a/sshd.c
+++ b/sshd.c
@@ -2488,6 +2488,9 @@ do_ssh2_kex(void)
 	if (options.kex_algorithms != NULL)
 		myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
 
+	myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
+	    myproposal[PROPOSAL_KEX_ALGS]);
+
 	if (options.rekey_limit || options.rekey_interval)
 		packet_set_rekey_limits((u_int32_t)options.rekey_limit,
 		    (time_t)options.rekey_interval);
diff --git a/version.h b/version.h
index a1579ac..a33e77c 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
 /* $OpenBSD: version.h,v 1.70 2014/02/27 22:57:40 djm Exp $ */
 
-#define SSH_VERSION	"OpenSSH_6.6"
+#define SSH_VERSION	"OpenSSH_6.6.1"
 
 #define SSH_PORTABLE	"p1"
 #define SSH_RELEASE	SSH_VERSION SSH_PORTABLE