summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2014-04-20 13:47:45 +1000
committerColin Watson <cjwatson@debian.org>2014-04-21 21:22:36 +0100
commit02883061577ec43ff8d0e8f0cf486bc5131db507 (patch)
treecff56a0039ff84648c22cb1fabc141844ee4d1ac
parent08a63152deb5deda168aaef870bdb9f56425acb3 (diff)
bad bignum encoding for curve25519-sha256@libssh.org
Hi, So I screwed up when writing the support for the curve25519 KEX method that doesn't depend on OpenSSL's BIGNUM type - a bug in my code left leading zero bytes where they should have been skipped. The impact of this is that OpenSSH 6.5 and 6.6 will fail during key exchange with a peer that implements curve25519-sha256@libssh.org properly about 0.2% of the time (one in every 512ish connections). We've fixed this for OpenSSH 6.7 by avoiding the curve25519-sha256 key exchange for previous versions, but I'd recommend distributors of OpenSSH apply this patch so the affected code doesn't become too entrenched in LTS releases. The patch fixes the bug and makes OpenSSH identify itself as 6.6.1 so as to distinguish itself from the incorrect versions so the compatibility code to disable the affected KEX isn't activated. I've committed this on the 6.6 branch too. Apologies for the hassle. -d Origin: upstream, https://lists.mindrot.org/pipermail/openssh-unix-dev/2014-April/032494.html Forwarded: not-needed Last-Update: 2014-04-21 Patch-Name: curve25519-sha256-bignum-encoding.patch
-rw-r--r--bufaux.c5
-rw-r--r--compat.c17
-rw-r--r--compat.h2
-rw-r--r--sshconnect2.c2
-rw-r--r--sshd.c3
-rw-r--r--version.h2
6 files changed, 28 insertions, 3 deletions
diff --git a/bufaux.c b/bufaux.c
index e24b5fc0a..f6a6f2ab2 100644
--- a/bufaux.c
+++ b/bufaux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bufaux.c,v 1.56 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: bufaux.c,v 1.57 2014/04/16 23:22:45 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * 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)
372 372
373 if (l > 8 * 1024) 373 if (l > 8 * 1024)
374 fatal("%s: length %u too long", __func__, l); 374 fatal("%s: length %u too long", __func__, l);
375 /* Skip leading zero bytes */
376 for (; l > 0 && *s == 0; l--, s++)
377 ;
375 p = buf = xmalloc(l + 1); 378 p = buf = xmalloc(l + 1);
376 /* 379 /*
377 * If most significant bit is set then prepend a zero byte to 380 * If most significant bit is set then prepend a zero byte to
diff --git a/compat.c b/compat.c
index 9d9fabef3..2709dc5cf 100644
--- a/compat.c
+++ b/compat.c
@@ -95,6 +95,9 @@ compat_datafellows(const char *version)
95 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 95 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
96 { "OpenSSH_4*", 0 }, 96 { "OpenSSH_4*", 0 },
97 { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT}, 97 { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT},
98 { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH},
99 { "OpenSSH_6.5*,"
100 "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD},
98 { "OpenSSH*", SSH_NEW_OPENSSH }, 101 { "OpenSSH*", SSH_NEW_OPENSSH },
99 { "*MindTerm*", 0 }, 102 { "*MindTerm*", 0 },
100 { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 103 { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
@@ -251,7 +254,6 @@ compat_cipher_proposal(char *cipher_prop)
251 return cipher_prop; 254 return cipher_prop;
252} 255}
253 256
254
255char * 257char *
256compat_pkalg_proposal(char *pkalg_prop) 258compat_pkalg_proposal(char *pkalg_prop)
257{ 259{
@@ -265,3 +267,16 @@ compat_pkalg_proposal(char *pkalg_prop)
265 return pkalg_prop; 267 return pkalg_prop;
266} 268}
267 269
270char *
271compat_kex_proposal(char *kex_prop)
272{
273 if (!(datafellows & SSH_BUG_CURVE25519PAD))
274 return kex_prop;
275 debug2("%s: original KEX proposal: %s", __func__, kex_prop);
276 kex_prop = filter_proposal(kex_prop, "curve25519-sha256@libssh.org");
277 debug2("%s: compat KEX proposal: %s", __func__, kex_prop);
278 if (*kex_prop == '\0')
279 fatal("No supported key exchange algorithms found");
280 return kex_prop;
281}
282
diff --git a/compat.h b/compat.h
index b174fa171..a6c3f3d7a 100644
--- a/compat.h
+++ b/compat.h
@@ -59,6 +59,7 @@
59#define SSH_BUG_RFWD_ADDR 0x02000000 59#define SSH_BUG_RFWD_ADDR 0x02000000
60#define SSH_NEW_OPENSSH 0x04000000 60#define SSH_NEW_OPENSSH 0x04000000
61#define SSH_BUG_DYNAMIC_RPORT 0x08000000 61#define SSH_BUG_DYNAMIC_RPORT 0x08000000
62#define SSH_BUG_CURVE25519PAD 0x10000000
62 63
63void enable_compat13(void); 64void enable_compat13(void);
64void enable_compat20(void); 65void enable_compat20(void);
@@ -66,6 +67,7 @@ void compat_datafellows(const char *);
66int proto_spec(const char *); 67int proto_spec(const char *);
67char *compat_cipher_proposal(char *); 68char *compat_cipher_proposal(char *);
68char *compat_pkalg_proposal(char *); 69char *compat_pkalg_proposal(char *);
70char *compat_kex_proposal(char *);
69 71
70extern int compat13; 72extern int compat13;
71extern int compat20; 73extern int compat20;
diff --git a/sshconnect2.c b/sshconnect2.c
index 66cb03527..1a4e55179 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -220,6 +220,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
220 } 220 }
221 if (options.kex_algorithms != NULL) 221 if (options.kex_algorithms != NULL)
222 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; 222 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
223 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
224 myproposal[PROPOSAL_KEX_ALGS]);
223 225
224#ifdef GSSAPI 226#ifdef GSSAPI
225 /* If we've got GSSAPI algorithms, then we also support the 227 /* If we've got GSSAPI algorithms, then we also support the
diff --git a/sshd.c b/sshd.c
index 09644914c..fe78d7b66 100644
--- a/sshd.c
+++ b/sshd.c
@@ -2534,6 +2534,9 @@ do_ssh2_kex(void)
2534 if (options.kex_algorithms != NULL) 2534 if (options.kex_algorithms != NULL)
2535 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; 2535 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
2536 2536
2537 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
2538 myproposal[PROPOSAL_KEX_ALGS]);
2539
2537 if (options.rekey_limit || options.rekey_interval) 2540 if (options.rekey_limit || options.rekey_interval)
2538 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 2541 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
2539 (time_t)options.rekey_interval); 2542 (time_t)options.rekey_interval);
diff --git a/version.h b/version.h
index a97c337a3..065957661 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
1/* $OpenBSD: version.h,v 1.70 2014/02/27 22:57:40 djm Exp $ */ 1/* $OpenBSD: version.h,v 1.70 2014/02/27 22:57:40 djm Exp $ */
2 2
3#define SSH_VERSION "OpenSSH_6.6" 3#define SSH_VERSION "OpenSSH_6.6.1"
4 4
5#define SSH_PORTABLE "p1" 5#define SSH_PORTABLE "p1"
6#define SSH_RELEASE_MINIMUM SSH_VERSION SSH_PORTABLE 6#define SSH_RELEASE_MINIMUM SSH_VERSION SSH_PORTABLE