summaryrefslogtreecommitdiff
path: root/debian/patches/curve25519-sha256-bignum-encoding.patch
blob: ccb66048dd4eeb13faf984f3749a16800f44d99b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
From 02883061577ec43ff8d0e8f0cf486bc5131db507 Mon Sep 17 00:00:00 2001
From: Damien Miller <djm@mindrot.org>
Date: Sun, 20 Apr 2014 13:47:45 +1000
Subject: 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
---
 bufaux.c      |  5 ++++-
 compat.c      | 17 ++++++++++++++++-
 compat.h      |  2 ++
 sshconnect2.c |  2 ++
 sshd.c        |  3 +++
 version.h     |  2 +-
 6 files changed, 28 insertions(+), 3 deletions(-)

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 66cb035..1a4e551 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 0964491..fe78d7b 100644
--- a/sshd.c
+++ b/sshd.c
@@ -2534,6 +2534,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 a97c337..0659576 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_MINIMUM	SSH_VERSION SSH_PORTABLE