diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2013-04-11 13:10:14 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2013-04-11 13:28:14 +0000 |
commit | 47656f3ce258fd3968b8f4dc2c27c2fa4e71a70d (patch) | |
tree | 1a7e73b6231545f5a2d492ec887cb4ac3dbab03d /main/gnutls/CVE-2013-1619.patch | |
parent | ce3adccd9865fd634d89940731b9c81c178a9b4c (diff) |
main/gnutls: security fix (CVE-2013-1619)
Patch from ubuntu:
https://launchpadlibrarian.net/132499561/gnutls26_2.10.5-1ubuntu3.2_2.10.5-1ubuntu3.3.diff.gz
fixes #1657
Diffstat (limited to 'main/gnutls/CVE-2013-1619.patch')
-rw-r--r-- | main/gnutls/CVE-2013-1619.patch | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/main/gnutls/CVE-2013-1619.patch b/main/gnutls/CVE-2013-1619.patch new file mode 100644 index 00000000000..7b9938c600a --- /dev/null +++ b/main/gnutls/CVE-2013-1619.patch @@ -0,0 +1,178 @@ +Description: fix "Lucky Thirteen" timing side-channel TLS attack +Origin: backport, https://gitorious.org/gnutls/gnutls/commit/7b65049a81ea02a92fef934318a680afd55e98d2 +Origin: backport, https://gitorious.org/gnutls/gnutls/commit/458c67cf98740e7b12404f6c30e0d5317d56fd30 +Origin: backport, https://gitorious.org/gnutls/gnutls/commit/93b7fcfa3297a9123630704668b2946f602b910e + +Index: gnutls26-2.10.5/lib/gnutls_cipher.c +=================================================================== +--- gnutls26-2.10.5.orig/lib/gnutls_cipher.c 2013-02-25 11:52:27.670965684 -0500 ++++ gnutls26-2.10.5/lib/gnutls_cipher.c 2013-02-25 12:04:38.642984400 -0500 +@@ -447,6 +447,49 @@ + return length; + } + ++static void dummy_wait(gnutls_session_t session, gnutls_datum_t* plaintext, ++ unsigned pad_failed, unsigned int pad, unsigned total, int ver) ++{ ++ /* this hack is only needed on CBC ciphers */ ++ if (_gnutls_cipher_is_block (session->security_parameters.read_bulk_cipher_algorithm) == CIPHER_BLOCK) ++ { ++ uint8_t MAC[MAX_HASH_SIZE]; ++ unsigned len; ++ digest_hd_st td; ++ int ret; ++ ++ ret = mac_init (&td, session->security_parameters.read_mac_algorithm, ++ session->connection_state.read_mac_secret.data, ++ session->connection_state.read_mac_secret.size, ver); ++ ++ if (ret < 0) ++ return; ++ ++ /* force an additional hash compression function evaluation to prevent timing ++ * attacks that distinguish between wrong-mac + correct pad, from wrong-mac + incorrect pad. ++ */ ++ if (pad_failed == 0 && pad > 0) ++ { ++ len = _gnutls_get_hash_block_len(session->security_parameters.read_mac_algorithm); ++ if (len > 0) ++ { ++ /* This is really specific to the current hash functions. ++ * It should be removed once a protocol fix is in place. ++ */ ++ if ((pad+total) % len > len-9 && total % len <= len-9) ++ { ++ if (len < plaintext->size) ++ mac_hash (&td, plaintext->data, len, ver); ++ else ++ mac_hash (&td, plaintext->data, plaintext->size, ver); ++ } ++ } ++ } ++ ++ mac_deinit (&td, MAC, ver); ++ } ++} ++ + /* Deciphers the ciphertext packet, and puts the result to compress_data, of compress_size. + * Returns the actual compressed packet size. + */ +@@ -458,12 +501,12 @@ + { + uint8_t MAC[MAX_HASH_SIZE]; + uint16_t c_length; +- uint8_t pad; ++ unsigned int pad = 0; + int length; + uint16_t blocksize; + int ret, i, pad_failed = 0; + opaque preamble[PREAMBLE_SIZE]; +- int preamble_size; ++ int preamble_size = 0; + int ver = gnutls_protocol_get_version (session); + int hash_size = + _gnutls_hash_get_algo_len (session-> +@@ -522,31 +565,23 @@ + gnutls_assert (); + return GNUTLS_E_DECRYPTION_FAILED; + } +- pad = ciphertext.data[ciphertext.size - 1] + 1; /* pad */ ++ pad = ciphertext.data[ciphertext.size - 1]; /* pad */ + +- if ((int) pad > (int) ciphertext.size - hash_size) +- { +- gnutls_assert (); +- _gnutls_record_log +- ("REC[%p]: Short record length %d > %d - %d (under attack?)\n", +- session, pad, ciphertext.size, hash_size); +- /* We do not fail here. We check below for the +- * the pad_failed. If zero means success. +- */ +- pad_failed = GNUTLS_E_DECRYPTION_FAILED; +- } +- +- length = ciphertext.size - hash_size - pad; +- +- /* Check the pading bytes (TLS 1.x) ++ /* Check the pading bytes (TLS 1.x). ++ * Note that we access all 256 bytes of ciphertext for padding check ++ * because there is a timing channel in that memory access (in certain CPUs). + */ + if (_gnutls_version_has_variable_padding (ver) && pad_failed == 0) +- for (i = 2; i < pad; i++) ++ for (i = 2; i <= pad; i++) + { +- if (ciphertext.data[ciphertext.size - i] != +- ciphertext.data[ciphertext.size - 1]) ++ if (ciphertext.data[ciphertext.size - i] != pad) + pad_failed = GNUTLS_E_DECRYPTION_FAILED; + } ++ ++ if (pad_failed) ++ pad = 0; ++ length = ciphertext.size - hash_size - pad - 1; ++ + break; + default: + gnutls_assert (); +@@ -585,24 +620,19 @@ + mac_deinit (&td, MAC, ver); + } + +- /* This one was introduced to avoid a timing attack against the TLS +- * 1.0 protocol. +- */ +- if (pad_failed != 0) +- { +- gnutls_assert (); +- return pad_failed; +- } +- + /* HMAC was not the same. + */ +- if (memcmp (MAC, &ciphertext.data[length], hash_size) != 0) ++ if (memcmp (MAC, &ciphertext.data[length], hash_size) != 0 || pad_failed != 0) + { ++ gnutls_datum_t compressed = {compress_data, compress_size}; ++ /* HMAC was not the same. */ ++ dummy_wait(session, &compressed, pad_failed, pad, length+preamble_size, ver); ++ + gnutls_assert (); + return GNUTLS_E_DECRYPTION_FAILED; + } + +- /* copy the decrypted stuff to compress_data. ++ /* copy the decrypted stuff to compressed_data. + */ + if (compress_size < length) + { +Index: gnutls26-2.10.5/lib/gnutls_hash_int.h +=================================================================== +--- gnutls26-2.10.5.orig/lib/gnutls_hash_int.h 2013-02-25 11:52:27.670965684 -0500 ++++ gnutls26-2.10.5/lib/gnutls_hash_int.h 2013-02-25 11:52:27.666965683 -0500 +@@ -98,4 +98,25 @@ + + int _gnutls_hash_copy (digest_hd_st * dst_handle, digest_hd_st * src_handle); + ++/* We shouldn't need to know that, but a work-around in decoding ++ * TLS record padding requires that. ++ */ ++inline static size_t ++_gnutls_get_hash_block_len (gnutls_digest_algorithm_t algo) ++{ ++ switch (algo) ++ { ++ case GNUTLS_DIG_MD5: ++ case GNUTLS_DIG_SHA1: ++ case GNUTLS_DIG_RMD160: ++ case GNUTLS_DIG_SHA256: ++ case GNUTLS_DIG_SHA384: ++ case GNUTLS_DIG_SHA512: ++ case GNUTLS_DIG_SHA224: ++ return 64; ++ default: ++ return 0; ++ } ++} ++ + #endif /* GNUTLS_HASH_INT_H */ |