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

« back to all changes in this revision

Viewing changes to .pc/CVE-2013-1619.patch/lib/gnutls_cipher.c

  • 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
/*
 
2
 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010
 
3
 * Free Software Foundation, Inc.
 
4
 *
 
5
 * Author: Nikos Mavrogiannopoulos
 
6
 *
 
7
 * This file is part of GnuTLS.
 
8
 *
 
9
 * The GnuTLS is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU Lesser General Public License
 
11
 * as published by the Free Software Foundation; either version 2.1 of
 
12
 * the License, or (at your option) any later version.
 
13
 *
 
14
 * This library is distributed in the hope that it will be useful, but
 
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 * Lesser General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Lesser General Public
 
20
 * License along with this library; if not, write to the Free Software
 
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
22
 * USA
 
23
 *
 
24
 */
 
25
 
 
26
/* Some high level functions to be used in the record encryption are
 
27
 * included here.
 
28
 */
 
29
 
 
30
#include "gnutls_int.h"
 
31
#include "gnutls_errors.h"
 
32
#include "gnutls_compress.h"
 
33
#include "gnutls_cipher.h"
 
34
#include "gnutls_algorithms.h"
 
35
#include "gnutls_hash_int.h"
 
36
#include "gnutls_cipher_int.h"
 
37
#include "debug.h"
 
38
#include "gnutls_num.h"
 
39
#include "gnutls_datum.h"
 
40
#include "gnutls_kx.h"
 
41
#include "gnutls_record.h"
 
42
#include "gnutls_constate.h"
 
43
#include <random.h>
 
44
 
 
45
inline static int
 
46
is_write_comp_null (gnutls_session_t session)
 
47
{
 
48
  if (session->security_parameters.write_compression_algorithm ==
 
49
      GNUTLS_COMP_NULL)
 
50
    return 0;
 
51
 
 
52
  return 1;
 
53
}
 
54
 
 
55
inline static int
 
56
is_read_comp_null (gnutls_session_t session)
 
57
{
 
58
  if (session->security_parameters.read_compression_algorithm ==
 
59
      GNUTLS_COMP_NULL)
 
60
    return 0;
 
61
 
 
62
  return 1;
 
63
}
 
64
 
 
65
 
 
66
/* returns ciphertext which contains the headers too. This also
 
67
 * calculates the size in the header field.
 
68
 * 
 
69
 * If random pad != 0 then the random pad data will be appended.
 
70
 */
 
71
int
 
72
_gnutls_encrypt (gnutls_session_t session, const opaque * headers,
 
73
                 size_t headers_size, const opaque * data,
 
74
                 size_t data_size, opaque * ciphertext,
 
75
                 size_t ciphertext_size, content_type_t type, int random_pad)
 
76
{
 
77
  gnutls_datum_t plain;
 
78
  gnutls_datum_t comp;
 
79
  int ret;
 
80
  int free_comp = 1;
 
81
 
 
82
  plain.data = (opaque *) data;
 
83
  plain.size = data_size;
 
84
 
 
85
  if (plain.size == 0 || is_write_comp_null (session) == 0)
 
86
    {
 
87
      comp = plain;
 
88
      free_comp = 0;
 
89
    }
 
90
  else
 
91
    {
 
92
      /* Here comp is allocated and must be 
 
93
       * freed.
 
94
       */
 
95
      ret = _gnutls_m_plaintext2compressed (session, &comp, &plain);
 
96
      if (ret < 0)
 
97
        {
 
98
          gnutls_assert ();
 
99
          return ret;
 
100
        }
 
101
    }
 
102
 
 
103
  ret = _gnutls_compressed2ciphertext (session, &ciphertext[headers_size],
 
104
                                       ciphertext_size - headers_size,
 
105
                                       comp, type, random_pad);
 
106
 
 
107
  if (free_comp)
 
108
    _gnutls_free_datum (&comp);
 
109
 
 
110
  if (ret < 0)
 
111
    {
 
112
      gnutls_assert ();
 
113
      return ret;
 
114
    }
 
115
 
 
116
 
 
117
  /* copy the headers */
 
118
  memcpy (ciphertext, headers, headers_size);
 
119
  _gnutls_write_uint16 (ret, &ciphertext[3]);
 
120
 
 
121
  return ret + headers_size;
 
122
}
 
123
 
 
124
/* Decrypts the given data.
 
125
 * Returns the decrypted data length.
 
126
 */
 
127
int
 
128
_gnutls_decrypt (gnutls_session_t session, opaque * ciphertext,
 
129
                 size_t ciphertext_size, uint8_t * data,
 
130
                 size_t max_data_size, content_type_t type)
 
131
{
 
132
  gnutls_datum_t gtxt;
 
133
  gnutls_datum_t gcipher;
 
134
  int ret;
 
135
 
 
136
  if (ciphertext_size == 0)
 
137
    return 0;
 
138
 
 
139
  gcipher.size = ciphertext_size;
 
140
  gcipher.data = ciphertext;
 
141
 
 
142
  ret =
 
143
    _gnutls_ciphertext2compressed (session, data, max_data_size,
 
144
                                   gcipher, type);
 
145
  if (ret < 0)
 
146
    {
 
147
      return ret;
 
148
    }
 
149
 
 
150
  if (ret == 0 || is_read_comp_null (session) == 0)
 
151
    {
 
152
      /* ret == ret */
 
153
 
 
154
    }
 
155
  else
 
156
    {
 
157
      gnutls_datum_t gcomp;
 
158
 
 
159
      /* compression has this malloc overhead.
 
160
       */
 
161
 
 
162
      gcomp.data = data;
 
163
      gcomp.size = ret;
 
164
      ret = _gnutls_m_compressed2plaintext (session, &gtxt, &gcomp);
 
165
      if (ret < 0)
 
166
        {
 
167
          return ret;
 
168
        }
 
169
 
 
170
      if (gtxt.size > MAX_RECORD_RECV_SIZE)
 
171
        {
 
172
          gnutls_assert ();
 
173
          _gnutls_free_datum (&gtxt);
 
174
          /* This shouldn't have happen and
 
175
           * is a TLS fatal error.
 
176
           */
 
177
          return GNUTLS_E_DECOMPRESSION_FAILED;
 
178
        }
 
179
 
 
180
      /* This check is not really needed */
 
181
      if (max_data_size < MAX_RECORD_RECV_SIZE)
 
182
        {
 
183
          gnutls_assert ();
 
184
          _gnutls_free_datum (&gtxt);
 
185
          return GNUTLS_E_INTERNAL_ERROR;
 
186
        }
 
187
 
 
188
      memcpy (data, gtxt.data, gtxt.size);
 
189
      ret = gtxt.size;
 
190
 
 
191
      _gnutls_free_datum (&gtxt);
 
192
    }
 
193
 
 
194
  return ret;
 
195
}
 
196
 
 
197
static inline int
 
198
mac_init (digest_hd_st * td, gnutls_mac_algorithm_t mac, opaque * secret,
 
199
          int secret_size, int ver)
 
200
{
 
201
  int ret = 0;
 
202
 
 
203
  if (mac == GNUTLS_MAC_NULL)
 
204
    {
 
205
      return GNUTLS_E_HASH_FAILED;
 
206
    }
 
207
 
 
208
  if (ver == GNUTLS_SSL3)
 
209
    {                           /* SSL 3.0 */
 
210
      ret = _gnutls_mac_init_ssl3 (td, mac, secret, secret_size);
 
211
    }
 
212
  else
 
213
    {                           /* TLS 1.x */
 
214
      ret = _gnutls_hmac_init (td, mac, secret, secret_size);
 
215
    }
 
216
 
 
217
  return ret;
 
218
}
 
219
 
 
220
static inline void
 
221
mac_hash (digest_hd_st * td, void *data, int data_size, int ver)
 
222
{
 
223
  if (ver == GNUTLS_SSL3)
 
224
    {                           /* SSL 3.0 */
 
225
      _gnutls_hash (td, data, data_size);
 
226
    }
 
227
  else
 
228
    {
 
229
      _gnutls_hmac (td, data, data_size);
 
230
    }
 
231
}
 
232
 
 
233
static inline void
 
234
mac_deinit (digest_hd_st * td, opaque * res, int ver)
 
235
{
 
236
  if (ver == GNUTLS_SSL3)
 
237
    {                           /* SSL 3.0 */
 
238
      _gnutls_mac_deinit_ssl3 (td, res);
 
239
    }
 
240
  else
 
241
    {
 
242
      _gnutls_hmac_deinit (td, res);
 
243
    }
 
244
}
 
245
 
 
246
inline static int
 
247
calc_enc_length (gnutls_session_t session, int data_size,
 
248
                 int hash_size, uint8_t * pad, int random_pad,
 
249
                 cipher_type_t block_algo, uint16_t blocksize)
 
250
{
 
251
  uint8_t rnd;
 
252
  int length, ret;
 
253
 
 
254
  *pad = 0;
 
255
 
 
256
  switch (block_algo)
 
257
    {
 
258
    case CIPHER_STREAM:
 
259
      length = data_size + hash_size;
 
260
 
 
261
      break;
 
262
    case CIPHER_BLOCK:
 
263
      ret = _gnutls_rnd (GNUTLS_RND_NONCE, &rnd, 1);
 
264
      if (ret < 0)
 
265
        {
 
266
          gnutls_assert ();
 
267
          return ret;
 
268
        }
 
269
 
 
270
      /* make rnd a multiple of blocksize */
 
271
      if (session->security_parameters.version == GNUTLS_SSL3 ||
 
272
          random_pad == 0)
 
273
        {
 
274
          rnd = 0;
 
275
        }
 
276
      else
 
277
        {
 
278
          rnd = (rnd / blocksize) * blocksize;
 
279
          /* added to avoid the case of pad calculated 0
 
280
           * seen below for pad calculation.
 
281
           */
 
282
          if (rnd > blocksize)
 
283
            rnd -= blocksize;
 
284
        }
 
285
 
 
286
      length = data_size + hash_size;
 
287
 
 
288
      *pad = (uint8_t) (blocksize - (length % blocksize)) + rnd;
 
289
 
 
290
      length += *pad;
 
291
      if (_gnutls_version_has_explicit_iv
 
292
          (session->security_parameters.version))
 
293
        length += blocksize;    /* for the IV */
 
294
 
 
295
      break;
 
296
    default:
 
297
      gnutls_assert ();
 
298
      return GNUTLS_E_INTERNAL_ERROR;
 
299
    }
 
300
 
 
301
  return length;
 
302
}
 
303
 
 
304
#define PREAMBLE_SIZE 16
 
305
static inline int
 
306
make_preamble (opaque * uint64_data, opaque type, uint16_t c_length,
 
307
               opaque ver, opaque * preamble)
 
308
{
 
309
  opaque minor = _gnutls_version_get_minor (ver);
 
310
  opaque major = _gnutls_version_get_major (ver);
 
311
  opaque *p = preamble;
 
312
 
 
313
  memcpy (p, uint64_data, 8);
 
314
  p += 8;
 
315
  *p = type;
 
316
  p++;
 
317
  if (_gnutls_version_has_variable_padding (ver))
 
318
    {                           /* TLS 1.0 or higher */
 
319
      *p = major;
 
320
      p++;
 
321
      *p = minor;
 
322
      p++;
 
323
    }
 
324
  memcpy (p, &c_length, 2);
 
325
  p += 2;
 
326
  return p - preamble;
 
327
}
 
328
 
 
329
/* This is the actual encryption 
 
330
 * Encrypts the given compressed datum, and puts the result to cipher_data,
 
331
 * which has cipher_size size.
 
332
 * return the actual encrypted data length.
 
333
 */
 
334
int
 
335
_gnutls_compressed2ciphertext (gnutls_session_t session,
 
336
                               opaque * cipher_data, int cipher_size,
 
337
                               gnutls_datum_t compressed,
 
338
                               content_type_t _type, int random_pad)
 
339
{
 
340
  uint8_t MAC[MAX_HASH_SIZE];
 
341
  uint16_t c_length;
 
342
  uint8_t pad;
 
343
  int length, ret;
 
344
  uint8_t type = _type;
 
345
  opaque preamble[PREAMBLE_SIZE];
 
346
  int preamble_size;
 
347
  int hash_size =
 
348
    _gnutls_hash_get_algo_len (session->
 
349
                               security_parameters.write_mac_algorithm);
 
350
  int blocksize =
 
351
    gnutls_cipher_get_block_size (session->
 
352
                                  security_parameters.write_bulk_cipher_algorithm);
 
353
  cipher_type_t block_algo =
 
354
    _gnutls_cipher_is_block (session->
 
355
                             security_parameters.write_bulk_cipher_algorithm);
 
356
  opaque *data_ptr;
 
357
  int ver = gnutls_protocol_get_version (session);
 
358
 
 
359
 
 
360
  /* Initialize MAC */
 
361
 
 
362
  c_length = _gnutls_conv_uint16 (compressed.size);
 
363
 
 
364
  if (session->security_parameters.write_mac_algorithm != GNUTLS_MAC_NULL)
 
365
    {                           /* actually when the algorithm in not the NULL one */
 
366
      digest_hd_st td;
 
367
 
 
368
      ret = mac_init (&td, session->security_parameters.write_mac_algorithm,
 
369
                      session->connection_state.write_mac_secret.data,
 
370
                      session->connection_state.write_mac_secret.size, ver);
 
371
 
 
372
      if (ret < 0)
 
373
        {
 
374
          gnutls_assert ();
 
375
          return ret;
 
376
        }
 
377
      preamble_size =
 
378
        make_preamble (UINT64DATA
 
379
                       (session->connection_state.write_sequence_number),
 
380
                       type, c_length, ver, preamble);
 
381
      mac_hash (&td, preamble, preamble_size, ver);
 
382
      mac_hash (&td, compressed.data, compressed.size, ver);
 
383
      mac_deinit (&td, MAC, ver);
 
384
    }
 
385
 
 
386
 
 
387
  /* Calculate the encrypted length (padding etc.)
 
388
   */
 
389
  length =
 
390
    calc_enc_length (session, compressed.size, hash_size, &pad,
 
391
                     random_pad, block_algo, blocksize);
 
392
  if (length < 0)
 
393
    {
 
394
      gnutls_assert ();
 
395
      return length;
 
396
    }
 
397
 
 
398
  /* copy the encrypted data to cipher_data.
 
399
   */
 
400
  if (cipher_size < length)
 
401
    {
 
402
      gnutls_assert ();
 
403
      return GNUTLS_E_MEMORY_ERROR;
 
404
    }
 
405
 
 
406
  data_ptr = cipher_data;
 
407
  if (block_algo == CIPHER_BLOCK &&
 
408
      _gnutls_version_has_explicit_iv (session->security_parameters.version))
 
409
    {
 
410
      /* copy the random IV.
 
411
       */
 
412
      ret = _gnutls_rnd (GNUTLS_RND_NONCE, data_ptr, blocksize);
 
413
      if (ret < 0)
 
414
        {
 
415
          gnutls_assert ();
 
416
          return ret;
 
417
        }
 
418
 
 
419
      data_ptr += blocksize;
 
420
    }
 
421
 
 
422
  memcpy (data_ptr, compressed.data, compressed.size);
 
423
  data_ptr += compressed.size;
 
424
 
 
425
  if (hash_size > 0)
 
426
    {
 
427
      memcpy (data_ptr, MAC, hash_size);
 
428
      data_ptr += hash_size;
 
429
    }
 
430
  if (block_algo == CIPHER_BLOCK && pad > 0)
 
431
    {
 
432
      memset (data_ptr, pad - 1, pad);
 
433
    }
 
434
 
 
435
 
 
436
  /* Actual encryption (inplace).
 
437
   */
 
438
  ret =
 
439
    _gnutls_cipher_encrypt (&session->connection_state.write_cipher_state,
 
440
                            cipher_data, length);
 
441
  if (ret < 0)
 
442
    {
 
443
      gnutls_assert ();
 
444
      return ret;
 
445
    }
 
446
 
 
447
  return length;
 
448
}
 
449
 
 
450
/* Deciphers the ciphertext packet, and puts the result to compress_data, of compress_size.
 
451
 * Returns the actual compressed packet size.
 
452
 */
 
453
int
 
454
_gnutls_ciphertext2compressed (gnutls_session_t session,
 
455
                               opaque * compress_data,
 
456
                               int compress_size,
 
457
                               gnutls_datum_t ciphertext, uint8_t type)
 
458
{
 
459
  uint8_t MAC[MAX_HASH_SIZE];
 
460
  uint16_t c_length;
 
461
  uint8_t pad;
 
462
  int length;
 
463
  uint16_t blocksize;
 
464
  int ret, i, pad_failed = 0;
 
465
  opaque preamble[PREAMBLE_SIZE];
 
466
  int preamble_size;
 
467
  int ver = gnutls_protocol_get_version (session);
 
468
  int hash_size =
 
469
    _gnutls_hash_get_algo_len (session->
 
470
                               security_parameters.read_mac_algorithm);
 
471
 
 
472
  blocksize =
 
473
    gnutls_cipher_get_block_size (session->
 
474
                                  security_parameters.read_bulk_cipher_algorithm);
 
475
 
 
476
 
 
477
  /* actual decryption (inplace)
 
478
   */
 
479
  switch (_gnutls_cipher_is_block
 
480
          (session->security_parameters.read_bulk_cipher_algorithm))
 
481
    {
 
482
    case CIPHER_STREAM:
 
483
      if ((ret =
 
484
           _gnutls_cipher_decrypt (&session->
 
485
                                   connection_state.read_cipher_state,
 
486
                                   ciphertext.data, ciphertext.size)) < 0)
 
487
        {
 
488
          gnutls_assert ();
 
489
          return ret;
 
490
        }
 
491
 
 
492
      length = ciphertext.size - hash_size;
 
493
 
 
494
      break;
 
495
    case CIPHER_BLOCK:
 
496
      if ((ciphertext.size < blocksize) || (ciphertext.size % blocksize != 0))
 
497
        {
 
498
          gnutls_assert ();
 
499
          return GNUTLS_E_DECRYPTION_FAILED;
 
500
        }
 
501
 
 
502
      if ((ret =
 
503
           _gnutls_cipher_decrypt (&session->
 
504
                                   connection_state.read_cipher_state,
 
505
                                   ciphertext.data, ciphertext.size)) < 0)
 
506
        {
 
507
          gnutls_assert ();
 
508
          return ret;
 
509
        }
 
510
 
 
511
      /* ignore the IV in TLS 1.1.
 
512
       */
 
513
      if (_gnutls_version_has_explicit_iv
 
514
          (session->security_parameters.version))
 
515
        {
 
516
          ciphertext.size -= blocksize;
 
517
          ciphertext.data += blocksize;
 
518
        }
 
519
 
 
520
      if (ciphertext.size < hash_size)
 
521
        {
 
522
          gnutls_assert ();
 
523
          return GNUTLS_E_DECRYPTION_FAILED;
 
524
        }
 
525
      pad = ciphertext.data[ciphertext.size - 1] + 1;   /* pad */
 
526
 
 
527
      if ((int) pad > (int) ciphertext.size - hash_size)
 
528
        {
 
529
          gnutls_assert ();
 
530
          _gnutls_record_log
 
531
            ("REC[%p]: Short record length %d > %d - %d (under attack?)\n",
 
532
             session, pad, ciphertext.size, hash_size);
 
533
          /* We do not fail here. We check below for the
 
534
           * the pad_failed. If zero means success.
 
535
           */
 
536
          pad_failed = GNUTLS_E_DECRYPTION_FAILED;
 
537
        }
 
538
 
 
539
      length = ciphertext.size - hash_size - pad;
 
540
 
 
541
      /* Check the pading bytes (TLS 1.x)
 
542
       */
 
543
      if (_gnutls_version_has_variable_padding (ver) && pad_failed == 0)
 
544
        for (i = 2; i < pad; i++)
 
545
          {
 
546
            if (ciphertext.data[ciphertext.size - i] !=
 
547
                ciphertext.data[ciphertext.size - 1])
 
548
              pad_failed = GNUTLS_E_DECRYPTION_FAILED;
 
549
          }
 
550
      break;
 
551
    default:
 
552
      gnutls_assert ();
 
553
      return GNUTLS_E_INTERNAL_ERROR;
 
554
    }
 
555
 
 
556
  if (length < 0)
 
557
    length = 0;
 
558
  c_length = _gnutls_conv_uint16 ((uint16_t) length);
 
559
 
 
560
  /* Pass the type, version, length and compressed through
 
561
   * MAC.
 
562
   */
 
563
  if (session->security_parameters.read_mac_algorithm != GNUTLS_MAC_NULL)
 
564
    {
 
565
      digest_hd_st td;
 
566
 
 
567
      ret = mac_init (&td, session->security_parameters.read_mac_algorithm,
 
568
                      session->connection_state.read_mac_secret.data,
 
569
                      session->connection_state.read_mac_secret.size, ver);
 
570
 
 
571
      if (ret < 0)
 
572
        {
 
573
          gnutls_assert ();
 
574
          return GNUTLS_E_INTERNAL_ERROR;
 
575
        }
 
576
 
 
577
      preamble_size =
 
578
        make_preamble (UINT64DATA
 
579
                       (session->connection_state.read_sequence_number), type,
 
580
                       c_length, ver, preamble);
 
581
      mac_hash (&td, preamble, preamble_size, ver);
 
582
      if (length > 0)
 
583
        mac_hash (&td, ciphertext.data, length, ver);
 
584
 
 
585
      mac_deinit (&td, MAC, ver);
 
586
    }
 
587
 
 
588
  /* This one was introduced to avoid a timing attack against the TLS
 
589
   * 1.0 protocol.
 
590
   */
 
591
  if (pad_failed != 0)
 
592
    {
 
593
      gnutls_assert ();
 
594
      return pad_failed;
 
595
    }
 
596
 
 
597
  /* HMAC was not the same. 
 
598
   */
 
599
  if (memcmp (MAC, &ciphertext.data[length], hash_size) != 0)
 
600
    {
 
601
      gnutls_assert ();
 
602
      return GNUTLS_E_DECRYPTION_FAILED;
 
603
    }
 
604
 
 
605
  /* copy the decrypted stuff to compress_data.
 
606
   */
 
607
  if (compress_size < length)
 
608
    {
 
609
      gnutls_assert ();
 
610
      return GNUTLS_E_DECOMPRESSION_FAILED;
 
611
    }
 
612
  memcpy (compress_data, ciphertext.data, length);
 
613
 
 
614
  return length;
 
615
}