~ubuntu-branches/ubuntu/oneiric/gnutls26/oneiric-security

« back to all changes in this revision

Viewing changes to debian/patches/CVE-2013-1619.patch

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2013-02-25 11:52:02 UTC
  • mfrom: (29.1.1 oneiric-proposed)
  • Revision ID: package-import@ubuntu.com-20130225115202-wrc28soy4vuj1m09
Tags: 2.10.5-1ubuntu3.3
* SECURITY UPDATE: "Lucky Thirteen" timing side-channel TLS attack
  - debian/patches/CVE-2013-1619.patch: avoid timing attacks in
    lib/gnutls_cipher.c, lib/gnutls_hash_int.h.
  - CVE-2013-1619

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Description: fix "Lucky Thirteen" timing side-channel TLS attack
 
2
Origin: backport, https://gitorious.org/gnutls/gnutls/commit/7b65049a81ea02a92fef934318a680afd55e98d2
 
3
Origin: backport, https://gitorious.org/gnutls/gnutls/commit/458c67cf98740e7b12404f6c30e0d5317d56fd30
 
4
Origin: backport, https://gitorious.org/gnutls/gnutls/commit/93b7fcfa3297a9123630704668b2946f602b910e
 
5
 
 
6
Index: gnutls26-2.10.5/lib/gnutls_cipher.c
 
7
===================================================================
 
8
--- gnutls26-2.10.5.orig/lib/gnutls_cipher.c    2013-02-25 11:52:27.670965684 -0500
 
9
+++ gnutls26-2.10.5/lib/gnutls_cipher.c 2013-02-25 12:04:38.642984400 -0500
 
10
@@ -447,6 +447,49 @@
 
11
   return length;
 
12
 }
 
13
 
 
14
+static void dummy_wait(gnutls_session_t session, gnutls_datum_t* plaintext, 
 
15
+                       unsigned pad_failed, unsigned int pad, unsigned total, int ver)
 
16
+{
 
17
+  /* this hack is only needed on CBC ciphers */
 
18
+  if (_gnutls_cipher_is_block (session->security_parameters.read_bulk_cipher_algorithm) == CIPHER_BLOCK)
 
19
+    {
 
20
+      uint8_t MAC[MAX_HASH_SIZE];
 
21
+      unsigned len;
 
22
+      digest_hd_st td;
 
23
+      int ret;
 
24
+
 
25
+      ret = mac_init (&td, session->security_parameters.read_mac_algorithm,
 
26
+                      session->connection_state.read_mac_secret.data,
 
27
+                      session->connection_state.read_mac_secret.size, ver);
 
28
+
 
29
+      if (ret < 0)
 
30
+        return;
 
31
+
 
32
+      /* force an additional hash compression function evaluation to prevent timing 
 
33
+       * attacks that distinguish between wrong-mac + correct pad, from wrong-mac + incorrect pad.
 
34
+       */
 
35
+      if (pad_failed == 0 && pad > 0) 
 
36
+        {
 
37
+          len = _gnutls_get_hash_block_len(session->security_parameters.read_mac_algorithm);
 
38
+          if (len > 0)
 
39
+            {
 
40
+              /* This is really specific to the current hash functions.
 
41
+               * It should be removed once a protocol fix is in place.
 
42
+               */
 
43
+             if ((pad+total) % len > len-9 && total % len <= len-9) 
 
44
+               {
 
45
+                 if (len < plaintext->size)
 
46
+                    mac_hash (&td, plaintext->data, len, ver);
 
47
+                  else
 
48
+                    mac_hash (&td, plaintext->data, plaintext->size, ver);
 
49
+                }
 
50
+            }
 
51
+        }
 
52
+
 
53
+      mac_deinit (&td, MAC, ver);
 
54
+    }
 
55
+}
 
56
+
 
57
 /* Deciphers the ciphertext packet, and puts the result to compress_data, of compress_size.
 
58
  * Returns the actual compressed packet size.
 
59
  */
 
60
@@ -458,12 +501,12 @@
 
61
 {
 
62
   uint8_t MAC[MAX_HASH_SIZE];
 
63
   uint16_t c_length;
 
64
-  uint8_t pad;
 
65
+  unsigned int pad = 0;
 
66
   int length;
 
67
   uint16_t blocksize;
 
68
   int ret, i, pad_failed = 0;
 
69
   opaque preamble[PREAMBLE_SIZE];
 
70
-  int preamble_size;
 
71
+  int preamble_size = 0;
 
72
   int ver = gnutls_protocol_get_version (session);
 
73
   int hash_size =
 
74
     _gnutls_hash_get_algo_len (session->
 
75
@@ -522,31 +565,23 @@
 
76
          gnutls_assert ();
 
77
          return GNUTLS_E_DECRYPTION_FAILED;
 
78
        }
 
79
-      pad = ciphertext.data[ciphertext.size - 1] + 1;  /* pad */
 
80
+      pad = ciphertext.data[ciphertext.size - 1];   /* pad */
 
81
 
 
82
-      if ((int) pad > (int) ciphertext.size - hash_size)
 
83
-       {
 
84
-         gnutls_assert ();
 
85
-         _gnutls_record_log
 
86
-           ("REC[%p]: Short record length %d > %d - %d (under attack?)\n",
 
87
-            session, pad, ciphertext.size, hash_size);
 
88
-         /* We do not fail here. We check below for the
 
89
-          * the pad_failed. If zero means success.
 
90
-          */
 
91
-         pad_failed = GNUTLS_E_DECRYPTION_FAILED;
 
92
-       }
 
93
-
 
94
-      length = ciphertext.size - hash_size - pad;
 
95
-
 
96
-      /* Check the pading bytes (TLS 1.x)
 
97
+      /* Check the pading bytes (TLS 1.x). 
 
98
+       * Note that we access all 256 bytes of ciphertext for padding check
 
99
+       * because there is a timing channel in that memory access (in certain CPUs).
 
100
        */
 
101
       if (_gnutls_version_has_variable_padding (ver) && pad_failed == 0)
 
102
-       for (i = 2; i < pad; i++)
 
103
+       for (i = 2; i <= pad; i++)
 
104
          {
 
105
-           if (ciphertext.data[ciphertext.size - i] !=
 
106
-               ciphertext.data[ciphertext.size - 1])
 
107
+            if (ciphertext.data[ciphertext.size - i] != pad)
 
108
              pad_failed = GNUTLS_E_DECRYPTION_FAILED;
 
109
          }
 
110
+          
 
111
+      if (pad_failed)
 
112
+        pad = 0;
 
113
+      length = ciphertext.size - hash_size - pad - 1;
 
114
+
 
115
       break;
 
116
     default:
 
117
       gnutls_assert ();
 
118
@@ -585,24 +620,19 @@
 
119
       mac_deinit (&td, MAC, ver);
 
120
     }
 
121
 
 
122
-  /* This one was introduced to avoid a timing attack against the TLS
 
123
-   * 1.0 protocol.
 
124
-   */
 
125
-  if (pad_failed != 0)
 
126
-    {
 
127
-      gnutls_assert ();
 
128
-      return pad_failed;
 
129
-    }
 
130
-
 
131
   /* HMAC was not the same. 
 
132
    */
 
133
-  if (memcmp (MAC, &ciphertext.data[length], hash_size) != 0)
 
134
+  if (memcmp (MAC, &ciphertext.data[length], hash_size) != 0 || pad_failed != 0)
 
135
     {
 
136
+      gnutls_datum_t compressed = {compress_data, compress_size};
 
137
+      /* HMAC was not the same. */
 
138
+      dummy_wait(session, &compressed, pad_failed, pad, length+preamble_size, ver);
 
139
+
 
140
       gnutls_assert ();
 
141
       return GNUTLS_E_DECRYPTION_FAILED;
 
142
     }
 
143
 
 
144
-  /* copy the decrypted stuff to compress_data.
 
145
+  /* copy the decrypted stuff to compressed_data.
 
146
    */
 
147
   if (compress_size < length)
 
148
     {
 
149
Index: gnutls26-2.10.5/lib/gnutls_hash_int.h
 
150
===================================================================
 
151
--- gnutls26-2.10.5.orig/lib/gnutls_hash_int.h  2013-02-25 11:52:27.670965684 -0500
 
152
+++ gnutls26-2.10.5/lib/gnutls_hash_int.h       2013-02-25 11:52:27.666965683 -0500
 
153
@@ -98,4 +98,25 @@
 
154
 
 
155
 int _gnutls_hash_copy (digest_hd_st * dst_handle, digest_hd_st * src_handle);
 
156
 
 
157
+/* We shouldn't need to know that, but a work-around in decoding
 
158
+ * TLS record padding requires that.
 
159
+ */
 
160
+inline static size_t
 
161
+_gnutls_get_hash_block_len (gnutls_digest_algorithm_t algo)
 
162
+{
 
163
+  switch (algo)
 
164
+    {
 
165
+    case GNUTLS_DIG_MD5:
 
166
+    case GNUTLS_DIG_SHA1:
 
167
+    case GNUTLS_DIG_RMD160:
 
168
+    case GNUTLS_DIG_SHA256:
 
169
+    case GNUTLS_DIG_SHA384:
 
170
+    case GNUTLS_DIG_SHA512:
 
171
+    case GNUTLS_DIG_SHA224:
 
172
+      return 64;
 
173
+    default:
 
174
+      return 0;
 
175
+    }
 
176
+}
 
177
+
 
178
 #endif /* GNUTLS_HASH_INT_H */