diff options
author | Damien Miller <djm@mindrot.org> | 2014-04-20 13:47:45 +1000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2014-04-21 21:22:36 +0100 |
commit | 02883061577ec43ff8d0e8f0cf486bc5131db507 (patch) | |
tree | cff56a0039ff84648c22cb1fabc141844ee4d1ac | |
parent | 08a63152deb5deda168aaef870bdb9f56425acb3 (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.c | 5 | ||||
-rw-r--r-- | compat.c | 17 | ||||
-rw-r--r-- | compat.h | 2 | ||||
-rw-r--r-- | sshconnect2.c | 2 | ||||
-rw-r--r-- | sshd.c | 3 | ||||
-rw-r--r-- | version.h | 2 |
6 files changed, 28 insertions, 3 deletions
@@ -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 |
@@ -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 | |||
255 | char * | 257 | char * |
256 | compat_pkalg_proposal(char *pkalg_prop) | 258 | compat_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 | ||
270 | char * | ||
271 | compat_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 | |||
@@ -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 | ||
63 | void enable_compat13(void); | 64 | void enable_compat13(void); |
64 | void enable_compat20(void); | 65 | void enable_compat20(void); |
@@ -66,6 +67,7 @@ void compat_datafellows(const char *); | |||
66 | int proto_spec(const char *); | 67 | int proto_spec(const char *); |
67 | char *compat_cipher_proposal(char *); | 68 | char *compat_cipher_proposal(char *); |
68 | char *compat_pkalg_proposal(char *); | 69 | char *compat_pkalg_proposal(char *); |
70 | char *compat_kex_proposal(char *); | ||
69 | 71 | ||
70 | extern int compat13; | 72 | extern int compat13; |
71 | extern int compat20; | 73 | extern 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 |
@@ -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); |
@@ -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 |