Package: putty / 0.62-9+deb7u3

enforce-dh-range.patch Patch series | download
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
Description: Enforce acceptable range for Diffie-Hellman server value
 Florent Daigniere of Matta points out that RFC 4253 actually
 _requires_ us to refuse to accept out-of-range values, though it isn't
 completely clear to me why this should be a MUST on the receiving end.
 .
 Matta considers this to be a security vulnerability, on the grounds
 that if a server should accidentally send an obviously useless value
 such as 1 then we will fail to reject it and agree a key that an
 eavesdropper could also figure out. Their id for this vulnerability is
 MATTA-2015-002.
Origin: backport, http://tartarus.org/~simon-git/gitweb/?p=putty.git;a=commitdiff;h=174476813f0ed94337aecc3e2d13a202a1dc2fa8
Last-Update: 2015-03-01

Index: b/ssh.c
===================================================================
--- a/ssh.c
+++ b/ssh.c
@@ -6007,6 +6007,13 @@
         }
         ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen);
 
+        {
+            const char *err = dh_validate_f(ssh->kex_ctx, s->f);
+            if (err) {
+                bombout(("key exchange reply failed validation: %s", err));
+                crStop(0);
+            }
+        }
         s->K = dh_find_K(ssh->kex_ctx, s->f);
 
         /* We assume everything from now on will be quick, and it might
Index: b/ssh.h
===================================================================
--- a/ssh.h
+++ b/ssh.h
@@ -470,6 +470,7 @@
 void *dh_setup_gex(Bignum pval, Bignum gval);
 void dh_cleanup(void *);
 Bignum dh_create_e(void *, int nbits);
+const char *dh_validate_f(void *handle, Bignum f);
 Bignum dh_find_K(void *, Bignum f);
 
 int loadrsakey(const Filename *filename, struct RSAKey *key,
Index: b/sshdh.c
===================================================================
--- a/sshdh.c
+++ b/sshdh.c
@@ -219,6 +219,29 @@
 }
 
 /*
+ * DH stage 2-epsilon: given a number f, validate it to ensure it's in
+ * range. (RFC 4253 section 8: "Values of 'e' or 'f' that are not in
+ * the range [1, p-1] MUST NOT be sent or accepted by either side."
+ * Also, we rule out 1 and p-1 too, since that's easy to do and since
+ * they lead to obviously weak keys that even a passive eavesdropper
+ * can figure out.)
+ */
+const char *dh_validate_f(void *handle, Bignum f)
+{
+    struct dh_ctx *ctx = (struct dh_ctx *)handle;
+    if (bignum_cmp(f, One) <= 0) {
+        return "f value received is too small";
+    } else {
+        Bignum pm1 = bigsub(ctx->p, One);
+        int cmp = bignum_cmp(f, pm1);
+        freebn(pm1);
+        if (cmp >= 0)
+            return "f value received is too large";
+    }
+    return NULL;
+}
+
+/*
  * DH stage 2: given a number f, compute K = f^x mod p.
  */
 Bignum dh_find_K(void *handle, Bignum f)