diff --git a/openssl-CVE-2013-0166.patch b/openssl-CVE-2013-0166.patch new file mode 100644 index 0000000..cde7ed7 --- /dev/null +++ b/openssl-CVE-2013-0166.patch @@ -0,0 +1,41 @@ +diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c +index cecdb13..097ec81 100644 +--- a/crypto/asn1/a_verify.c ++++ b/crypto/asn1/a_verify.c +@@ -136,6 +136,12 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signat + + int mdnid, pknid; + ++ if (!pkey) ++ { ++ ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER); ++ return -1; ++ } ++ + EVP_MD_CTX_init(&ctx); + + /* Convert signature OID into digest and public key OIDs */ +diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c +index 8a5e788..2767183 100644 +--- a/crypto/ocsp/ocsp_vfy.c ++++ b/crypto/ocsp/ocsp_vfy.c +@@ -91,9 +91,12 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + { + EVP_PKEY *skey; + skey = X509_get_pubkey(signer); +- ret = OCSP_BASICRESP_verify(bs, skey, 0); +- EVP_PKEY_free(skey); +- if(ret <= 0) ++ if (skey) ++ { ++ ret = OCSP_BASICRESP_verify(bs, skey, 0); ++ EVP_PKEY_free(skey); ++ } ++ if(!skey || ret <= 0) + { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE); + goto end; +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.1.patch b/openssl-CVE-2013-0169.1.patch new file mode 100644 index 0000000..8a95a18 --- /dev/null +++ b/openssl-CVE-2013-0169.1.patch @@ -0,0 +1,161 @@ +From 9c00a950604aca819cee977f1dcb4b45f2af3aa6 Mon Sep 17 00:00:00 2001 +From: Ben Laurie +Date: Mon, 28 Jan 2013 17:30:38 +0000 +Subject: [PATCH] Add and use a constant-time memcmp. + +This change adds CRYPTO_memcmp, which compares two vectors of bytes in +an amount of time that's independent of their contents. It also changes +several MAC compares in the code to use this over the standard memcmp, +which may leak information about the size of a matching prefix. +(cherry picked from commit 2ee798880a246d648ecddadc5b91367bee4a5d98) + +Conflicts: + crypto/crypto.h + ssl/t1_lib.c +--- + crypto/cryptlib.c | 13 +++++++++++++ + crypto/crypto.h | 7 +++++++ + crypto/rsa/rsa_oaep.c | 2 +- + ssl/d1_pkt.c | 2 +- + ssl/s2_clnt.c | 2 +- + ssl/s2_pkt.c | 3 +-- + ssl/s3_both.c | 2 +- + ssl/s3_pkt.c | 2 +- + ssl/t1_lib.c | 2 +- + 9 files changed, 27 insertions(+), 8 deletions(-) + +diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c +index 139bd12..fd6e3cc 100644 +--- a/crypto/cryptlib.c ++++ b/crypto/cryptlib.c +@@ -896,3 +896,16 @@ void OpenSSLDie(const char *file,int line,const char *assertion) + } + + void *OPENSSL_stderr(void) { return stderr; } ++ ++int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) ++ { ++ size_t i; ++ const unsigned char *a = in_a; ++ const unsigned char *b = in_b; ++ unsigned char x = 0; ++ ++ for (i = 0; i < len; i++) ++ x |= a[i] ^ b[i]; ++ ++ return x; ++ } +diff --git a/crypto/crypto.h b/crypto/crypto.h +index b0360ce..ab65f69 100644 +--- a/crypto/crypto.h ++++ b/crypto/crypto.h +@@ -547,6 +547,13 @@ unsigned long *OPENSSL_ia32cap_loc(void); + #define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc())) + int OPENSSL_isservice(void); + ++/* CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. It ++ * takes an amount of time dependent on |len|, but independent of the contents ++ * of |a| and |b|. Unlike memcmp, it cannot be used to put elements into a ++ * defined order as the return value when a != b is undefined, other than to be ++ * non-zero. */ ++int CRYPTO_memcmp(const void *a, const void *b, size_t len); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c +index 18d307e..9b9dba0 100644 +--- a/crypto/rsa/rsa_oaep.c ++++ b/crypto/rsa/rsa_oaep.c +@@ -147,7 +147,7 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, + + EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1(), NULL); + +- if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad) ++ if (CRYPTO_memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad) + goto decoding_err; + else + { +diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c +index 6d24573..46a1950 100644 +--- a/ssl/d1_pkt.c ++++ b/ssl/d1_pkt.c +@@ -455,7 +455,7 @@ printf("\n"); + else + rr->length = 0; + i=s->method->ssl3_enc->mac(s,md,0); +- if (i < 0 || mac == NULL || memcmp(md, mac, mac_size) != 0) ++ if (i < 0 || mac == NULL || CRYPTO_memcmp(md,mac,mac_size) != 0) + { + decryption_failed_or_bad_record_mac = 1; + } +diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c +index 76b690e..03b6cf9 100644 +--- a/ssl/s2_clnt.c ++++ b/ssl/s2_clnt.c +@@ -939,7 +939,7 @@ static int get_server_verify(SSL *s) + s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* SERVER-VERIFY */ + p += 1; + +- if (memcmp(p,s->s2->challenge,s->s2->challenge_length) != 0) ++ if (CRYPTO_memcmp(p,s->s2->challenge,s->s2->challenge_length) != 0) + { + ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_SERVER_VERIFY,SSL_R_CHALLENGE_IS_DIFFERENT); +diff --git a/ssl/s2_pkt.c b/ssl/s2_pkt.c +index ac963b2..8bb6ab8 100644 +--- a/ssl/s2_pkt.c ++++ b/ssl/s2_pkt.c +@@ -269,8 +269,7 @@ static int ssl2_read_internal(SSL *s, void *buf, int len, int peek) + s->s2->ract_data_length-=mac_size; + ssl2_mac(s,mac,0); + s->s2->ract_data_length-=s->s2->padding; +- if ( (memcmp(mac,s->s2->mac_data, +- (unsigned int)mac_size) != 0) || ++ if ( (CRYPTO_memcmp(mac,s->s2->mac_data,mac_size) != 0) || + (s->s2->rlength%EVP_CIPHER_CTX_block_size(s->enc_read_ctx) != 0)) + { + SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_MAC_DECODE); +diff --git a/ssl/s3_both.c b/ssl/s3_both.c +index a6d869d..4801dbf 100644 +--- a/ssl/s3_both.c ++++ b/ssl/s3_both.c +@@ -240,7 +240,7 @@ int ssl3_get_finished(SSL *s, int a, int b) + goto f_err; + } + +- if (memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) ++ if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) + { + al=SSL_AD_DECRYPT_ERROR; + SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED); +diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c +index f9b3629..85ff702 100644 +--- a/ssl/s3_pkt.c ++++ b/ssl/s3_pkt.c +@@ -462,7 +462,7 @@ printf("\n"); + #endif + } + i=s->method->ssl3_enc->mac(s,md,0); +- if (i < 0 || mac == NULL || memcmp(md, mac, (size_t)mac_size) != 0) ++ if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) + { + decryption_failed_or_bad_record_mac = 1; + } +diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c +index ffd5bf2..81d1a12 100644 +--- a/ssl/t1_lib.c ++++ b/ssl/t1_lib.c +@@ -1744,7 +1744,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, + HMAC_Update(&hctx, etick, eticklen); + HMAC_Final(&hctx, tick_hmac, NULL); + HMAC_CTX_cleanup(&hctx); +- if (memcmp(tick_hmac, etick + eticklen, mlen)) ++ if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) + goto tickerr; + /* Attempt to decrypt session data */ + /* Move p after IV to start of encrypted ticket, update length */ +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.10.patch b/openssl-CVE-2013-0169.10.patch new file mode 100644 index 0000000..6efb2b9 --- /dev/null +++ b/openssl-CVE-2013-0169.10.patch @@ -0,0 +1,122 @@ +From f306b87d766e6ecf30824635c7c395b67cff9dbc Mon Sep 17 00:00:00 2001 +From: Adam Langley +Date: Wed, 6 Feb 2013 16:05:40 +0000 +Subject: [PATCH] Fix for EXP-RC2-CBC-MD5 + +MD5 should use little endian order. Fortunately the only ciphersuite +affected is EXP-RC2-CBC-MD5 (TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5) which +is a rarely used export grade ciphersuite. +--- + ssl/s3_cbc.c | 39 ++++++++++++++++++++++++++++++--------- + test/testssl | 17 +++++++++++++++++ + 2 files changed, 47 insertions(+), 9 deletions(-) + +diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c +index 3c2c165..ce77acd 100644 +--- a/ssl/s3_cbc.c ++++ b/ssl/s3_cbc.c +@@ -328,16 +328,24 @@ void ssl3_cbc_copy_mac(unsigned char* out, + #endif + } + ++/* u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in ++ * little-endian order. The value of p is advanced by four. */ ++#define u32toLE(n, p) \ ++ (*((p)++)=(unsigned char)(n), \ ++ *((p)++)=(unsigned char)(n>>8), \ ++ *((p)++)=(unsigned char)(n>>16), \ ++ *((p)++)=(unsigned char)(n>>24)) ++ + /* These functions serialize the state of a hash and thus perform the standard + * "final" operation without adding the padding and length that such a function + * typically does. */ + static void tls1_md5_final_raw(void* ctx, unsigned char *md_out) + { + MD5_CTX *md5 = ctx; +- l2n(md5->A, md_out); +- l2n(md5->B, md_out); +- l2n(md5->C, md_out); +- l2n(md5->D, md_out); ++ u32toLE(md5->A, md_out); ++ u32toLE(md5->B, md_out); ++ u32toLE(md5->C, md_out); ++ u32toLE(md5->D, md_out); + } + + static void tls1_sha1_final_raw(void* ctx, unsigned char *md_out) +@@ -457,6 +465,7 @@ void ssl3_cbc_digest_record( + /* mdLengthSize is the number of bytes in the length field that terminates + * the hash. */ + unsigned md_length_size = 8; ++ char length_is_big_endian = 1; + + /* This is a, hopefully redundant, check that allows us to forget about + * many possible overflows later in this function. */ +@@ -470,6 +479,7 @@ void ssl3_cbc_digest_record( + md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform; + md_size = 16; + sslv3_pad_length = 48; ++ length_is_big_endian = 0; + break; + case NID_sha1: + SHA1_Init((SHA_CTX*)md_state.c); +@@ -610,11 +620,22 @@ void ssl3_cbc_digest_record( + md_transform(md_state.c, hmac_pad); + } + +- memset(length_bytes,0,md_length_size-4); +- length_bytes[md_length_size-4] = (unsigned char)(bits>>24); +- length_bytes[md_length_size-3] = (unsigned char)(bits>>16); +- length_bytes[md_length_size-2] = (unsigned char)(bits>>8); +- length_bytes[md_length_size-1] = (unsigned char)bits; ++ if (length_is_big_endian) ++ { ++ memset(length_bytes,0,md_length_size-4); ++ length_bytes[md_length_size-4] = (unsigned char)(bits>>24); ++ length_bytes[md_length_size-3] = (unsigned char)(bits>>16); ++ length_bytes[md_length_size-2] = (unsigned char)(bits>>8); ++ length_bytes[md_length_size-1] = (unsigned char)bits; ++ } ++ else ++ { ++ memset(length_bytes,0,md_length_size); ++ length_bytes[md_length_size-5] = (unsigned char)(bits>>24); ++ length_bytes[md_length_size-6] = (unsigned char)(bits>>16); ++ length_bytes[md_length_size-7] = (unsigned char)(bits>>8); ++ length_bytes[md_length_size-8] = (unsigned char)bits; ++ } + + if (k > 0) + { +diff --git a/test/testssl b/test/testssl +index 5ae4dc8..4e8542b 100644 +--- a/test/testssl ++++ b/test/testssl +@@ -119,6 +119,23 @@ $ssltest -bio_pair -server_auth -client_auth $CA $extra || exit 1 + echo test sslv2/sslv3 with both client and server authentication via BIO pair and app verify + $ssltest -bio_pair -server_auth -client_auth -app_verify $CA $extra || exit 1 + ++echo "Testing ciphersuites" ++for protocol in TLSv1.2 SSLv3; do ++ echo "Testing ciphersuites for $protocol" ++ for cipher in `../util/shlib_wrap.sh ../apps/openssl ciphers "RSA+$protocol" | tr ':' ' '`; do ++ echo "Testing $cipher" ++ prot="" ++ if [ $protocol = "SSLv3" ] ; then ++ prot="-ssl3" ++ fi ++ $ssltest -cipher $cipher $prot ++ if [ $? -ne 0 ] ; then ++ echo "Failed $cipher" ++ exit 1 ++ fi ++ done ++done ++ + ############################################################################# + + if ../util/shlib_wrap.sh ../apps/openssl no-dh; then +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.11.patch b/openssl-CVE-2013-0169.11.patch new file mode 100644 index 0000000..6aaa6d9 --- /dev/null +++ b/openssl-CVE-2013-0169.11.patch @@ -0,0 +1,89 @@ +From 47061af1062e36b87242810f7f5279ee7240b9e4 Mon Sep 17 00:00:00 2001 +From: Andy Polyakov +Date: Fri, 8 Feb 2013 16:59:26 +0100 +Subject: [PATCH] s3_cbc.c: get rid of expensive divisions [from master]. + (cherry picked from commit + e9baceab5a385e570706ca98dec768b2d89d1ac6) + +--- + ssl/s3_cbc.c | 35 +++++++++++++++++++++-------------- + 1 file changed, 21 insertions(+), 14 deletions(-) + +diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c +index 0f60507..f8d8ee8 100644 +--- a/ssl/s3_cbc.c ++++ b/ssl/s3_cbc.c +@@ -76,6 +76,13 @@ + #define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) ) + #define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x))) + ++/* constant_time_lt returns 0xff if a=b and 0x00 otherwise. */ + static unsigned constant_time_ge(unsigned a, unsigned b) + { +@@ -84,7 +91,7 @@ static unsigned constant_time_ge(unsigned a, unsigned b) + } + + /* constant_time_eq_8 returns 0xff if a==b and 0x00 otherwise. */ +-static unsigned char constant_time_eq_8(unsigned char a, unsigned char b) ++static unsigned char constant_time_eq_8(unsigned a, unsigned b) + { + unsigned c = a ^ b; + c--; +@@ -288,16 +295,13 @@ void ssl3_cbc_copy_mac(unsigned char* out, + rotate_offset = (div_spoiler + mac_start - scan_start) % md_size; + + memset(rotated_mac, 0, md_size); +- for (i = scan_start; i < rec->orig_len;) ++ for (i = scan_start, j = 0; i < rec->orig_len; i++) + { +- for (j = 0; j < md_size && i < rec->orig_len; i++, j++) +- { +- unsigned char mac_started = constant_time_ge(i, mac_start); +- unsigned char mac_ended = constant_time_ge(i, mac_end); +- unsigned char b = 0; +- b = rec->data[i]; +- rotated_mac[j] |= b & mac_started & ~mac_ended; +- } ++ unsigned char mac_started = constant_time_ge(i, mac_start); ++ unsigned char mac_ended = constant_time_ge(i, mac_end); ++ unsigned char b = rec->data[i]; ++ rotated_mac[j++] |= b & mac_started & ~mac_ended; ++ j &= constant_time_lt(j,md_size); + } + + /* Now rotate the MAC */ +@@ -305,16 +309,19 @@ void ssl3_cbc_copy_mac(unsigned char* out, + j = 0; + for (i = 0; i < md_size; i++) + { +- unsigned char offset = (div_spoiler + rotate_offset + i) % md_size; +- out[j++] = rotated_mac[offset]; ++ out[j++] = rotated_mac[rotate_offset++]; ++ rotate_offset &= constant_time_lt(rotate_offset,md_size); + } + #else + memset(out, 0, md_size); ++ rotate_offset = md_size - rotate_offset; ++ rotate_offset &= constant_time_lt(rotate_offset,md_size); + for (i = 0; i < md_size; i++) + { +- unsigned char offset = (div_spoiler + md_size - rotate_offset + i) % md_size; + for (j = 0; j < md_size; j++) +- out[j] |= rotated_mac[i] & constant_time_eq_8(j, offset); ++ out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset); ++ rotate_offset++; ++ rotate_offset &= constant_time_lt(rotate_offset,md_size); + } + #endif + } +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.12.patch b/openssl-CVE-2013-0169.12.patch new file mode 100644 index 0000000..7dd9014 --- /dev/null +++ b/openssl-CVE-2013-0169.12.patch @@ -0,0 +1,70 @@ +From 579f3a631ebeef5eb0135977640a835968d3ad6c Mon Sep 17 00:00:00 2001 +From: Andy Polyakov +Date: Fri, 8 Feb 2013 21:30:52 +0100 +Subject: [PATCH] s3_cbc.c: make CBC_MAC_ROTATE_IN_PLACE universal. (cherry + picked from commit + f93a41877d8d7a287debb7c63d7b646abaaf269c) + +--- + ssl/s3_cbc.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c +index f8d8ee8..02edf3f 100644 +--- a/ssl/s3_cbc.c ++++ b/ssl/s3_cbc.c +@@ -232,10 +232,6 @@ int tls1_cbc_remove_padding(const SSL* s, + return (int)((good & 1) | (~good & -1)); + } + +-#if defined(_M_AMD64) || defined(__x86_64__) +-#define CBC_MAC_ROTATE_IN_PLACE +-#endif +- + /* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in + * constant time (independent of the concrete value of rec->length, which may + * vary within a 256-byte window). +@@ -249,15 +245,18 @@ int tls1_cbc_remove_padding(const SSL* s, + * + * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with + * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into +- * a single cache-line, then the variable memory accesses don't actually affect +- * the timing. This has been tested to be true on Intel amd64 chips. ++ * a single or pair of cache-lines, then the variable memory accesses don't ++ * actually affect the timing. CPUs with smaller cache-lines [if any] are ++ * not multi-core and are not considered vulnerable to cache-timing attacks. + */ ++#define CBC_MAC_ROTATE_IN_PLACE ++ + void ssl3_cbc_copy_mac(unsigned char* out, + const SSL3_RECORD *rec, + unsigned md_size) + { + #if defined(CBC_MAC_ROTATE_IN_PLACE) +- unsigned char rotated_mac_buf[EVP_MAX_MD_SIZE*2]; ++ unsigned char rotated_mac_buf[64+EVP_MAX_MD_SIZE]; + unsigned char *rotated_mac; + #else + unsigned char rotated_mac[EVP_MAX_MD_SIZE]; +@@ -277,7 +276,7 @@ void ssl3_cbc_copy_mac(unsigned char* out, + OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE); + + #if defined(CBC_MAC_ROTATE_IN_PLACE) +- rotated_mac = (unsigned char*) (((intptr_t)(rotated_mac_buf + 64)) & ~63); ++ rotated_mac = rotated_mac_buf + ((0-(size_t)rotated_mac_buf)&63); + #endif + + /* This information is public so it's safe to branch based on it. */ +@@ -309,6 +308,8 @@ void ssl3_cbc_copy_mac(unsigned char* out, + j = 0; + for (i = 0; i < md_size; i++) + { ++ /* in case cache-line is 32 bytes, touch second line */ ++ ((volatile unsigned char *)rotated_mac)[rotate_offset^32]; + out[j++] = rotated_mac[rotate_offset++]; + rotate_offset &= constant_time_lt(rotate_offset,md_size); + } +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.2.patch b/openssl-CVE-2013-0169.2.patch new file mode 100644 index 0000000..a09fb58 --- /dev/null +++ b/openssl-CVE-2013-0169.2.patch @@ -0,0 +1,682 @@ +From e5420be6cd09af2550b128575a675490cfba0483 Mon Sep 17 00:00:00 2001 +From: Ben Laurie +Date: Mon, 28 Jan 2013 17:31:49 +0000 +Subject: [PATCH] Make CBC decoding constant time. + +This patch makes the decoding of SSLv3 and TLS CBC records constant +time. Without this, a timing side-channel can be used to build a padding +oracle and mount Vaudenay's attack. + +This patch also disables the stitched AESNI+SHA mode pending a similar +fix to that code. + +In order to be easy to backport, this change is implemented in ssl/, +rather than as a generic AEAD mode. In the future this should be changed +around so that HMAC isn't in ssl/, but crypto/ as FIPS expects. +(cherry picked from commit e130841bccfc0bb9da254dc84e23bc6a1c78a64e) + +Conflicts: + crypto/evp/c_allc.c + ssl/ssl_algs.c + ssl/ssl_locl.h + ssl/t1_enc.c +--- + crypto/evp/c_allc.c | 1 + + ssl/Makefile | 4 +- + ssl/d1_enc.c | 49 +++----------------- + ssl/s3_enc.c | 108 ++++++++++++++++++++++++++++---------------- + ssl/s3_pkt.c | 76 +++++++++++++++---------------- + ssl/ssl3.h | 4 ++ + ssl/ssl_algs.c | 2 + + ssl/ssl_locl.h | 34 ++++++++++++++ + ssl/t1_enc.c | 124 +++++++++++++++++++++++---------------------------- + 9 files changed, 214 insertions(+), 188 deletions(-) + +diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c +index c5f9268..e67022f 100644 +--- a/crypto/evp/c_allc.c ++++ b/crypto/evp/c_allc.c +@@ -194,6 +194,7 @@ void OpenSSL_add_all_ciphers(void) + EVP_add_cipher_alias(SN_aes_256_cbc,"AES256"); + EVP_add_cipher_alias(SN_aes_256_cbc,"aes256"); + #endif ++#endif + + #ifndef OPENSSL_NO_CAMELLIA + EVP_add_cipher(EVP_camellia_128_ecb()); +diff --git a/ssl/Makefile b/ssl/Makefile +index 2b275fa..79581e4 100644 +--- a/ssl/Makefile ++++ b/ssl/Makefile +@@ -22,7 +22,7 @@ LIB=$(TOP)/libssl.a + SHARED_LIB= libssl$(SHLIB_EXT) + LIBSRC= \ + s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ +- s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ ++ s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c s3_cbc.c \ + s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ + t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ + d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ +@@ -33,7 +33,7 @@ LIBSRC= \ + bio_ssl.c ssl_err.c kssl.c t1_reneg.c + LIBOBJ= \ + s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ +- s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ ++ s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o s3_cbc.o \ + s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ + t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ + d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ +diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c +index 07a5e97..c13b495 100644 +--- a/ssl/d1_enc.c ++++ b/ssl/d1_enc.c +@@ -131,15 +131,15 @@ int dtls1_enc(SSL *s, int send) + SSL3_RECORD *rec; + EVP_CIPHER_CTX *ds; + unsigned long l; +- int bs,i,ii,j,k,n=0; ++ int bs,i,j,k,mac_size=0; + const EVP_CIPHER *enc; + + if (send) + { + if (EVP_MD_CTX_md(s->write_hash)) + { +- n=EVP_MD_CTX_size(s->write_hash); +- if (n < 0) ++ mac_size=EVP_MD_CTX_size(s->write_hash); ++ if (mac_size < 0) + return -1; + } + ds=s->enc_write_ctx; +@@ -164,8 +164,8 @@ int dtls1_enc(SSL *s, int send) + { + if (EVP_MD_CTX_md(s->read_hash)) + { +- n=EVP_MD_CTX_size(s->read_hash); +- if (n < 0) ++ mac_size=EVP_MD_CTX_size(s->read_hash); ++ if (mac_size < 0) + return -1; + } + ds=s->enc_read_ctx; +@@ -245,44 +245,9 @@ int dtls1_enc(SSL *s, int send) + } + #endif /* KSSL_DEBUG */ + ++ rec->orig_len = rec->length; + if ((bs != 1) && !send) +- { +- ii=i=rec->data[l-1]; /* padding_length */ +- i++; +- if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) +- { +- /* First packet is even in size, so check */ +- if ((memcmp(s->s3->read_sequence, +- "\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) +- s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; +- if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) +- i--; +- } +- /* TLS 1.0 does not bound the number of padding bytes by the block size. +- * All of them must have value 'padding_length'. */ +- if (i + bs > (int)rec->length) +- { +- /* Incorrect padding. SSLerr() and ssl3_alert are done +- * by caller: we don't want to reveal whether this is +- * a decryption error or a MAC verification failure +- * (see http://www.openssl.org/~bodo/tls-cbc.txt) +- */ +- return -1; +- } +- for (j=(int)(l-i); j<(int)l; j++) +- { +- if (rec->data[j] != ii) +- { +- /* Incorrect padding */ +- return -1; +- } +- } +- rec->length-=i; +- +- rec->data += bs; /* skip the implicit IV */ +- rec->input += bs; +- rec->length -= bs; +- } ++ return tls1_cbc_remove_padding(s, rec, bs, mac_size); + } + return(1); + } +diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c +index b145970..de5354a 100644 +--- a/ssl/s3_enc.c ++++ b/ssl/s3_enc.c +@@ -470,7 +470,7 @@ int ssl3_enc(SSL *s, int send) + SSL3_RECORD *rec; + EVP_CIPHER_CTX *ds; + unsigned long l; +- int bs,i; ++ int bs,i,mac_size=0; + const EVP_CIPHER *enc; + + if (send) +@@ -531,22 +531,12 @@ int ssl3_enc(SSL *s, int send) + + EVP_Cipher(ds,rec->data,rec->input,l); + ++ rec->orig_len = rec->length; ++ ++ if (EVP_MD_CTX_md(s->read_hash) != NULL) ++ mac_size = EVP_MD_CTX_size(s->read_hash); + if ((bs != 1) && !send) +- { +- i=rec->data[l-1]+1; +- /* SSL 3.0 bounds the number of padding bytes by the block size; +- * padding bytes (except the last one) are arbitrary */ +- if (i > bs) +- { +- /* Incorrect padding. SSLerr() and ssl3_alert are done +- * by caller: we don't want to reveal whether this is +- * a decryption error or a MAC verification failure +- * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ +- return -1; +- } +- /* now i <= bs <= rec->length */ +- rec->length-=i; +- } ++ return ssl3_cbc_remove_padding(s, rec, bs, mac_size); + } + return(1); + } +@@ -704,7 +694,7 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send) + EVP_MD_CTX md_ctx; + const EVP_MD_CTX *hash; + unsigned char *p,rec_char; +- unsigned int md_size; ++ size_t md_size; + int npad; + int t; + +@@ -729,28 +719,68 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send) + md_size=t; + npad=(48/md_size)*md_size; + +- /* Chop the digest off the end :-) */ +- EVP_MD_CTX_init(&md_ctx); +- +- EVP_MD_CTX_copy_ex( &md_ctx,hash); +- EVP_DigestUpdate(&md_ctx,mac_sec,md_size); +- EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad); +- EVP_DigestUpdate(&md_ctx,seq,8); +- rec_char=rec->type; +- EVP_DigestUpdate(&md_ctx,&rec_char,1); +- p=md; +- s2n(rec->length,p); +- EVP_DigestUpdate(&md_ctx,md,2); +- EVP_DigestUpdate(&md_ctx,rec->input,rec->length); +- EVP_DigestFinal_ex( &md_ctx,md,NULL); +- +- EVP_MD_CTX_copy_ex( &md_ctx,hash); +- EVP_DigestUpdate(&md_ctx,mac_sec,md_size); +- EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad); +- EVP_DigestUpdate(&md_ctx,md,md_size); +- EVP_DigestFinal_ex( &md_ctx,md,&md_size); +- +- EVP_MD_CTX_cleanup(&md_ctx); ++ if (!send && ++ EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && ++ ssl3_cbc_record_digest_supported(hash)) ++ { ++ /* This is a CBC-encrypted record. We must avoid leaking any ++ * timing-side channel information about how many blocks of ++ * data we are hashing because that gives an attacker a ++ * timing-oracle. */ ++ ++ /* npad is, at most, 48 bytes and that's with MD5: ++ * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75. ++ * ++ * With SHA-1 (the largest hash speced for SSLv3) the hash size ++ * goes up 4, but npad goes down by 8, resulting in a smaller ++ * total size. */ ++ unsigned char header[75]; ++ unsigned j = 0; ++ memcpy(header+j, mac_sec, md_size); ++ j += md_size; ++ memcpy(header+j, ssl3_pad_1, npad); ++ j += npad; ++ memcpy(header+j, seq, 8); ++ j += 8; ++ header[j++] = rec->type; ++ header[j++] = rec->length >> 8; ++ header[j++] = rec->length & 0xff; ++ ++ ssl3_cbc_digest_record( ++ hash, ++ md, &md_size, ++ header, rec->input, ++ rec->length + md_size, rec->orig_len, ++ mac_sec, md_size, ++ 1 /* is SSLv3 */); ++ } ++ else ++ { ++ unsigned int md_size_u; ++ /* Chop the digest off the end :-) */ ++ EVP_MD_CTX_init(&md_ctx); ++ ++ EVP_MD_CTX_copy_ex( &md_ctx,hash); ++ EVP_DigestUpdate(&md_ctx,mac_sec,md_size); ++ EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad); ++ EVP_DigestUpdate(&md_ctx,seq,8); ++ rec_char=rec->type; ++ EVP_DigestUpdate(&md_ctx,&rec_char,1); ++ p=md; ++ s2n(rec->length,p); ++ EVP_DigestUpdate(&md_ctx,md,2); ++ EVP_DigestUpdate(&md_ctx,rec->input,rec->length); ++ EVP_DigestFinal_ex( &md_ctx,md,NULL); ++ ++ EVP_MD_CTX_copy_ex( &md_ctx,hash); ++ EVP_DigestUpdate(&md_ctx,mac_sec,md_size); ++ EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad); ++ EVP_DigestUpdate(&md_ctx,md,md_size); ++ EVP_DigestFinal_ex( &md_ctx,md,&md_size_u); ++ md_size = md_size_u; ++ ++ EVP_MD_CTX_cleanup(&md_ctx); ++ } + + ssl3_record_sequence_update(seq); + return(md_size); +diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c +index 85ff702..2e0c173 100644 +--- a/ssl/s3_pkt.c ++++ b/ssl/s3_pkt.c +@@ -289,11 +289,9 @@ static int ssl3_get_record(SSL *s) + unsigned char *p; + unsigned char md[EVP_MAX_MD_SIZE]; + short version; +- int mac_size; ++ unsigned mac_size; + int clear=0; + size_t extra; +- int decryption_failed_or_bad_record_mac = 0; +- unsigned char *mac = NULL; + + rr= &(s->s3->rrec); + sess=s->session; +@@ -402,17 +400,10 @@ fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); + rr->data=rr->input; + + enc_err = s->method->ssl3_enc->enc(s,0); +- if (enc_err <= 0) ++ if (enc_err == 0) + { +- if (enc_err == 0) +- /* SSLerr() and ssl3_send_alert() have been called */ +- goto err; +- +- /* Otherwise enc_err == -1, which indicates bad padding +- * (rec->length has not been changed in this case). +- * To minimize information leaked via timing, we will perform +- * the MAC computation anyway. */ +- decryption_failed_or_bad_record_mac = 1; ++ /* SSLerr() and ssl3_send_alert() have been called */ ++ goto err; + } + + #ifdef TLS_DEBUG +@@ -430,45 +421,54 @@ printf("\n"); + if (!clear) + { + /* !clear => s->read_hash != NULL => mac_size != -1 */ ++ unsigned char *mac = NULL; ++ unsigned char mac_tmp[EVP_MAX_MD_SIZE]; + mac_size=EVP_MD_CTX_size(s->read_hash); +- OPENSSL_assert(mac_size >= 0); ++ OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); + +- if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) ++ /* orig_len is the length of the record before any padding was ++ * removed. This is public information, as is the MAC in use, ++ * therefore we can safely process the record in a different ++ * amount of time if it's too short to possibly contain a MAC. ++ */ ++ if (rr->orig_len < mac_size || ++ /* CBC records must have a padding length byte too. */ ++ (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && ++ rr->orig_len < mac_size+1)) + { +-#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */ +- al=SSL_AD_RECORD_OVERFLOW; +- SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); ++ al=SSL_AD_DECODE_ERROR; ++ SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); + goto f_err; +-#else +- decryption_failed_or_bad_record_mac = 1; +-#endif + } +- /* check the MAC for rr->input (it's in mac_size bytes at the tail) */ +- if (rr->length >= (unsigned int)mac_size) ++ ++ if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) + { ++ /* We update the length so that the TLS header bytes ++ * can be constructed correctly but we need to extract ++ * the MAC in constant time from within the record, ++ * without leaking the contents of the padding bytes. ++ * */ ++ mac = mac_tmp; ++ ssl3_cbc_copy_mac(mac_tmp, rr, mac_size); + rr->length -= mac_size; +- mac = &rr->data[rr->length]; + } + else + { +- /* record (minus padding) is too short to contain a MAC */ +-#if 0 /* OK only for stream ciphers */ +- al=SSL_AD_DECODE_ERROR; +- SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); +- goto f_err; +-#else +- decryption_failed_or_bad_record_mac = 1; +- rr->length = 0; +-#endif ++ /* In this case there's no padding, so |rec->orig_len| ++ * equals |rec->length| and we checked that there's ++ * enough bytes for |mac_size| above. */ ++ rr->length -= mac_size; ++ mac = &rr->data[rr->length]; + } +- i=s->method->ssl3_enc->mac(s,md,0); ++ ++ i=s->method->ssl3_enc->mac(s,md,0 /* not send */); + if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) +- { +- decryption_failed_or_bad_record_mac = 1; +- } ++ enc_err = -1; ++ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) ++ enc_err = -1; + } + +- if (decryption_failed_or_bad_record_mac) ++ if (enc_err < 0) + { + /* A separate 'decryption_failed' alert was introduced with TLS 1.0, + * SSL 3.0 only has 'bad_record_mac'. But unless a decryption +diff --git a/ssl/ssl3.h b/ssl/ssl3.h +index 9c2c412..d3bd768 100644 +--- a/ssl/ssl3.h ++++ b/ssl/ssl3.h +@@ -349,6 +349,10 @@ typedef struct ssl3_record_st + /*r */ unsigned char *comp; /* only used with decompression - malloc()ed */ + /*r */ unsigned long epoch; /* epoch number, needed by DTLS1 */ + /*r */ unsigned char seq_num[8]; /* sequence number, needed by DTLS1 */ ++/*rw*/ unsigned int orig_len; /* How many bytes were available before padding ++ was removed? This is used to implement the ++ MAC check in constant time for CBC records. ++ */ + } SSL3_RECORD; + + typedef struct ssl3_buffer_st +diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c +index 0967b2d..7f1a042 100644 +--- a/ssl/ssl_algs.c ++++ b/ssl/ssl_algs.c +@@ -86,6 +86,8 @@ int SSL_library_init(void) + EVP_add_cipher(EVP_aes_192_cbc()); + EVP_add_cipher(EVP_aes_256_cbc()); + #endif ++ ++#endif + #ifndef OPENSSL_NO_CAMELLIA + EVP_add_cipher(EVP_camellia_128_cbc()); + EVP_add_cipher(EVP_camellia_256_cbc()); +diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h +index 7cf1d19..6a4f62a 100644 +--- a/ssl/ssl_locl.h ++++ b/ssl/ssl_locl.h +@@ -215,6 +215,15 @@ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + ++#define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>>48)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>>40)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>>32)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>>24)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>>16)&0xff), \ ++ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ ++ *((c)++)=(unsigned char)(((l) )&0xff)) ++ + #define n2l6(c,l) (l =((BN_ULLONG)(*((c)++)))<<40, \ + l|=((BN_ULLONG)(*((c)++)))<<32, \ + l|=((BN_ULLONG)(*((c)++)))<<24, \ +@@ -1079,4 +1088,29 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len, + int maxlen); + int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len, + int *al); ++/* s3_cbc.c */ ++void ssl3_cbc_copy_mac(unsigned char* out, ++ const SSL3_RECORD *rec, ++ unsigned md_size); ++int ssl3_cbc_remove_padding(const SSL* s, ++ SSL3_RECORD *rec, ++ unsigned block_size, ++ unsigned mac_size); ++int tls1_cbc_remove_padding(const SSL* s, ++ SSL3_RECORD *rec, ++ unsigned block_size, ++ unsigned mac_size); ++char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); ++void ssl3_cbc_digest_record( ++ const EVP_MD_CTX *ctx, ++ unsigned char* md_out, ++ size_t* md_out_size, ++ const unsigned char header[13], ++ const unsigned char *data, ++ size_t data_plus_mac_size, ++ size_t data_plus_mac_plus_padding_size, ++ const unsigned char *mac_secret, ++ unsigned mac_secret_length, ++ char is_sslv3); ++ + #endif +diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c +index 5a0bd66..3fcb77b 100644 +--- a/ssl/t1_enc.c ++++ b/ssl/t1_enc.c +@@ -640,7 +640,7 @@ int tls1_enc(SSL *s, int send) + SSL3_RECORD *rec; + EVP_CIPHER_CTX *ds; + unsigned long l; +- int bs,i,ii,j,k,n=0; ++ int bs,i,j,k,pad=0,ret,mac_size=0; + const EVP_CIPHER *enc; + + if (send) +@@ -676,11 +676,11 @@ int tls1_enc(SSL *s, int send) + printf("tls1_enc(%d)\n", send); + #endif /* KSSL_DEBUG */ + +- if ((s->session == NULL) || (ds == NULL) || +- (enc == NULL)) ++ if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) + { + memmove(rec->data,rec->input,rec->length); + rec->input=rec->data; ++ ret = 1; + } + else + { +@@ -708,13 +708,13 @@ int tls1_enc(SSL *s, int send) + + #ifdef KSSL_DEBUG + { +- unsigned long ui; ++ unsigned long ui; + printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", +- ds,rec->data,rec->input,l); ++ ds,rec->data,rec->input,l); + printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", +- ds->buf_len, ds->cipher->key_len, +- DES_KEY_SZ, DES_SCHEDULE_SZ, +- ds->cipher->iv_len); ++ ds->buf_len, ds->cipher->key_len, ++ DES_KEY_SZ, DES_SCHEDULE_SZ, ++ ds->cipher->iv_len); + printf("\t\tIV: "); + for (i=0; icipher->iv_len; i++) printf("%02X", ds->iv[i]); + printf("\n"); +@@ -738,57 +738,26 @@ int tls1_enc(SSL *s, int send) + + #ifdef KSSL_DEBUG + { +- unsigned long i; +- printf("\trec->data="); ++ unsigned long i; ++ printf("\trec->data="); + for (i=0; idata[i]); printf("\n"); +- } ++ printf(" %02x", rec->data[i]); printf("\n"); ++ } + #endif /* KSSL_DEBUG */ + ++ rec->orig_len = rec->length; ++ ++ ret = 1; ++ if (EVP_MD_CTX_md(s->read_hash) != NULL) ++ mac_size = EVP_MD_CTX_size(s->read_hash); + if ((bs != 1) && !send) +- { +- ii=i=rec->data[l-1]; /* padding_length */ +- i++; +- /* NB: if compression is in operation the first packet +- * may not be of even length so the padding bug check +- * cannot be performed. This bug workaround has been +- * around since SSLeay so hopefully it is either fixed +- * now or no buggy implementation supports compression +- * [steve] +- */ +- if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) +- && !s->expand) +- { +- /* First packet is even in size, so check */ +- if ((memcmp(s->s3->read_sequence, +- "\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) +- s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; +- if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) +- i--; +- } +- /* TLS 1.0 does not bound the number of padding bytes by the block size. +- * All of them must have value 'padding_length'. */ +- if (i > (int)rec->length) +- { +- /* Incorrect padding. SSLerr() and ssl3_alert are done +- * by caller: we don't want to reveal whether this is +- * a decryption error or a MAC verification failure +- * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ +- return -1; +- } +- for (j=(int)(l-i); j<(int)l; j++) +- { +- if (rec->data[j] != ii) +- { +- /* Incorrect padding */ +- return -1; +- } +- } +- rec->length-=i; +- } ++ ret = tls1_cbc_remove_padding(s, rec, bs, mac_size); ++ if (pad && !send) ++ rec->length -= pad; + } +- return(1); ++ return ret; + } ++ + int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out) + { + unsigned int ret; +@@ -881,7 +850,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) + size_t md_size; + int i; + EVP_MD_CTX hmac, *mac_ctx; +- unsigned char buf[5]; ++ unsigned char header[13]; + int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM)); + int t; + +@@ -902,12 +871,6 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) + OPENSSL_assert(t >= 0); + md_size=t; + +- buf[0]=rec->type; +- buf[1]=(unsigned char)(ssl->version>>8); +- buf[2]=(unsigned char)(ssl->version); +- buf[3]=rec->length>>8; +- buf[4]=rec->length&0xff; +- + /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ + if (stream_mac) + { +@@ -926,17 +889,44 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) + s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p); + memcpy (p,&seq[2],6); + +- EVP_DigestSignUpdate(mac_ctx,dtlsseq,8); ++ memcpy(header, dtlsseq, 8); + } + else +- EVP_DigestSignUpdate(mac_ctx,seq,8); ++ memcpy(header, seq, 8); ++ ++ header[8]=rec->type; ++ header[9]=(unsigned char)(ssl->version>>8); ++ header[10]=(unsigned char)(ssl->version); ++ header[11]=(rec->length)>>8; ++ header[12]=(rec->length)&0xff; + +- EVP_DigestSignUpdate(mac_ctx,buf,5); +- EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length); +- t=EVP_DigestSignFinal(mac_ctx,md,&md_size); +- OPENSSL_assert(t > 0); ++ if (!send && ++ EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && ++ ssl3_cbc_record_digest_supported(mac_ctx)) ++ { ++ /* This is a CBC-encrypted record. We must avoid leaking any ++ * timing-side channel information about how many blocks of ++ * data we are hashing because that gives an attacker a ++ * timing-oracle. */ ++ ssl3_cbc_digest_record( ++ mac_ctx, ++ md, &md_size, ++ header, rec->input, ++ rec->length + md_size, rec->orig_len, ++ ssl->s3->read_mac_secret, ++ ssl->s3->read_mac_secret_size, ++ 0 /* not SSLv3 */); ++ } ++ else ++ { ++ EVP_DigestSignUpdate(mac_ctx,header,sizeof(header)); ++ EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length); ++ t=EVP_DigestSignFinal(mac_ctx,md,&md_size); ++ OPENSSL_assert(t > 0); ++ } + +- if (!stream_mac) EVP_MD_CTX_cleanup(&hmac); ++ if (!stream_mac) ++ EVP_MD_CTX_cleanup(&hmac); + #ifdef TLS_DEBUG + printf("sec="); + {unsigned int z; for (z=0; z +Date: Mon, 28 Jan 2013 18:24:55 +0000 +Subject: [PATCH] Oops. Add missing file. (cherry picked from commit + 014265eb02e26f35c8db58e2ccbf100b0b2f0072) + +--- + ssl/s3_cbc.c | 696 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 696 insertions(+) + create mode 100644 ssl/s3_cbc.c + +diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c +new file mode 100644 +index 0000000..e9b112c +--- /dev/null ++++ b/ssl/s3_cbc.c +@@ -0,0 +1,696 @@ ++/* ssl/s3_cbc.c */ ++/* ==================================================================== ++ * Copyright (c) 2012 The OpenSSL Project. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. All advertising materials mentioning features or use of this ++ * software must display the following acknowledgment: ++ * "This product includes software developed by the OpenSSL Project ++ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" ++ * ++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to ++ * endorse or promote products derived from this software without ++ * prior written permission. For written permission, please contact ++ * openssl-core@openssl.org. ++ * ++ * 5. Products derived from this software may not be called "OpenSSL" ++ * nor may "OpenSSL" appear in their names without prior written ++ * permission of the OpenSSL Project. ++ * ++ * 6. Redistributions of any form whatsoever must retain the following ++ * acknowledgment: ++ * "This product includes software developed by the OpenSSL Project ++ * for use in the OpenSSL Toolkit (http://www.openssl.org/)" ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY ++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ++ * OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ==================================================================== ++ * ++ * This product includes cryptographic software written by Eric Young ++ * (eay@cryptsoft.com). This product includes software written by Tim ++ * Hudson (tjh@cryptsoft.com). ++ * ++ */ ++ ++#include ++ ++#include "ssl_locl.h" ++ ++#include ++#include ++ ++/* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's length ++ * field. (SHA-384/512 have 128-bit length.) */ ++#define MAX_HASH_BIT_COUNT_BYTES 16 ++ ++/* MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support. ++ * Currently SHA-384/512 has a 128-byte block size and that's the largest ++ * supported by TLS.) */ ++#define MAX_HASH_BLOCK_SIZE 128 ++ ++/* Some utility functions are needed: ++ * ++ * These macros return the given value with the MSB copied to all the other ++ * bits. They use the fact that arithmetic shift shifts-in the sign bit. ++ * However, this is not ensured by the C standard so you may need to replace ++ * them with something else on odd CPUs. */ ++#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) ) ++#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x))) ++ ++/* constant_time_ge returns 0xff if a>=b and 0x00 otherwise. */ ++static unsigned constant_time_ge(unsigned a, unsigned b) ++ { ++ a -= b; ++ return DUPLICATE_MSB_TO_ALL(~a); ++ } ++ ++/* constant_time_eq_8 returns 0xff if a==b and 0x00 otherwise. */ ++static unsigned char constant_time_eq_8(unsigned char a, unsigned char b) ++ { ++ unsigned c = a ^ b; ++ c--; ++ return DUPLICATE_MSB_TO_ALL_8(c); ++ } ++ ++/* ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC ++ * record in |rec| by updating |rec->length| in constant time. ++ * ++ * block_size: the block size of the cipher used to encrypt the record. ++ * returns: ++ * 0: (in non-constant time) if the record is publicly invalid. ++ * 1: if the padding was valid ++ * -1: otherwise. */ ++int ssl3_cbc_remove_padding(const SSL* s, ++ SSL3_RECORD *rec, ++ unsigned block_size, ++ unsigned mac_size) ++ { ++ unsigned padding_length, good; ++ const unsigned overhead = 1 /* padding length byte */ + mac_size; ++ ++ /* These lengths are all public so we can test them in non-constant ++ * time. */ ++ if (overhead > rec->length) ++ return 0; ++ ++ padding_length = rec->data[rec->length-1]; ++ good = constant_time_ge(rec->length, padding_length+overhead); ++ /* SSLv3 requires that the padding is minimal. */ ++ good &= constant_time_ge(block_size, padding_length+1); ++ rec->length -= good & (padding_length+1); ++ return (int)((good & 1) | (~good & -1)); ++} ++ ++/* tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC ++ * record in |rec| in constant time and returns 1 if the padding is valid and ++ * -1 otherwise. It also removes any explicit IV from the start of the record ++ * without leaking any timing about whether there was enough space after the ++ * padding was removed. ++ * ++ * block_size: the block size of the cipher used to encrypt the record. ++ * returns: ++ * 0: (in non-constant time) if the record is publicly invalid. ++ * 1: if the padding was valid ++ * -1: otherwise. */ ++int tls1_cbc_remove_padding(const SSL* s, ++ SSL3_RECORD *rec, ++ unsigned block_size, ++ unsigned mac_size) ++ { ++ unsigned padding_length, good, to_check, i; ++ const char has_explicit_iv = ++ s->version >= TLS1_1_VERSION || s->version == DTLS1_VERSION; ++ const unsigned overhead = 1 /* padding length byte */ + ++ mac_size + ++ (has_explicit_iv ? block_size : 0); ++ ++ /* These lengths are all public so we can test them in non-constant ++ * time. */ ++ if (overhead > rec->length) ++ return 0; ++ ++ padding_length = rec->data[rec->length-1]; ++ ++ /* NB: if compression is in operation the first packet may not be of ++ * even length so the padding bug check cannot be performed. This bug ++ * workaround has been around since SSLeay so hopefully it is either ++ * fixed now or no buggy implementation supports compression [steve] ++ */ ++ if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand) ++ { ++ /* First packet is even in size, so check */ ++ if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) && ++ !(padding_length & 1)) ++ { ++ s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; ++ } ++ if ((s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) && ++ padding_length > 0) ++ { ++ padding_length--; ++ } ++ } ++ ++ good = constant_time_ge(rec->length, overhead+padding_length); ++ /* The padding consists of a length byte at the end of the record and ++ * then that many bytes of padding, all with the same value as the ++ * length byte. Thus, with the length byte included, there are i+1 ++ * bytes of padding. ++ * ++ * We can't check just |padding_length+1| bytes because that leaks ++ * decrypted information. Therefore we always have to check the maximum ++ * amount of padding possible. (Again, the length of the record is ++ * public information so we can use it.) */ ++ to_check = 255; /* maximum amount of padding. */ ++ if (to_check > rec->length-1) ++ to_check = rec->length-1; ++ ++ for (i = 0; i < to_check; i++) ++ { ++ unsigned char mask = constant_time_ge(padding_length, i); ++ unsigned char b = rec->data[rec->length-1-i]; ++ /* The final |padding_length+1| bytes should all have the value ++ * |padding_length|. Therefore the XOR should be zero. */ ++ good &= ~(mask&(padding_length ^ b)); ++ } ++ ++ /* If any of the final |padding_length+1| bytes had the wrong value, ++ * one or more of the lower eight bits of |good| will be cleared. We ++ * AND the bottom 8 bits together and duplicate the result to all the ++ * bits. */ ++ good &= good >> 4; ++ good &= good >> 2; ++ good &= good >> 1; ++ good <<= sizeof(good)*8-1; ++ good = DUPLICATE_MSB_TO_ALL(good); ++ ++ rec->length -= good & (padding_length+1); ++ ++ /* We can always safely skip the explicit IV. We check at the beginning ++ * of this function that the record has at least enough space for the ++ * IV, MAC and padding length byte. (These can be checked in ++ * non-constant time because it's all public information.) So, if the ++ * padding was invalid, then we didn't change |rec->length| and this is ++ * safe. If the padding was valid then we know that we have at least ++ * overhead+padding_length bytes of space and so this is still safe ++ * because overhead accounts for the explicit IV. */ ++ if (has_explicit_iv) ++ { ++ rec->data += block_size; ++ rec->input += block_size; ++ rec->length -= block_size; ++ rec->orig_len -= block_size; ++ } ++ ++ return (int)((good & 1) | (~good & -1)); ++ } ++ ++#if defined(_M_AMD64) || defined(__x86_64__) ++#define CBC_MAC_ROTATE_IN_PLACE ++#endif ++ ++/* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in ++ * constant time (independent of the concrete value of rec->length, which may ++ * vary within a 256-byte window). ++ * ++ * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to ++ * this function. ++ * ++ * On entry: ++ * rec->orig_len >= md_size ++ * md_size <= EVP_MAX_MD_SIZE ++ * ++ * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with ++ * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into ++ * a single cache-line, then the variable memory accesses don't actually affect ++ * the timing. This has been tested to be true on Intel amd64 chips. ++ */ ++void ssl3_cbc_copy_mac(unsigned char* out, ++ const SSL3_RECORD *rec, ++ unsigned md_size) ++ { ++#if defined(CBC_MAC_ROTATE_IN_PLACE) ++ unsigned char rotated_mac_buf[EVP_MAX_MD_SIZE*2]; ++ unsigned char *rotated_mac; ++#else ++ unsigned char rotated_mac[EVP_MAX_MD_SIZE]; ++#endif ++ ++ /* mac_end is the index of |rec->data| just after the end of the MAC. */ ++ unsigned mac_end = rec->length; ++ unsigned mac_start = mac_end - md_size; ++ /* scan_start contains the number of bytes that we can ignore because ++ * the MAC's position can only vary by 255 bytes. */ ++ unsigned scan_start = 0; ++ unsigned i, j; ++ unsigned div_spoiler; ++ unsigned rotate_offset; ++ ++ OPENSSL_assert(rec->orig_len >= md_size); ++ OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE); ++ ++#if defined(CBC_MAC_ROTATE_IN_PLACE) ++ rotated_mac = (unsigned char*) (((intptr_t)(rotated_mac_buf + 64)) & ~63); ++#endif ++ ++ /* This information is public so it's safe to branch based on it. */ ++ if (rec->orig_len > md_size + 255 + 1) ++ scan_start = rec->orig_len - (md_size + 255 + 1); ++ /* div_spoiler contains a multiple of md_size that is used to cause the ++ * modulo operation to be constant time. Without this, the time varies ++ * based on the amount of padding when running on Intel chips at least. ++ * ++ * The aim of right-shifting md_size is so that the compiler doesn't ++ * figure out that it can remove div_spoiler as that would require it ++ * to prove that md_size is always even, which I hope is beyond it. */ ++ div_spoiler = md_size >> 1; ++ div_spoiler <<= (sizeof(div_spoiler)-1)*8; ++ rotate_offset = (div_spoiler + mac_start - scan_start) % md_size; ++ ++ memset(rotated_mac, 0, md_size); ++ for (i = scan_start; i < rec->orig_len;) ++ { ++ for (j = 0; j < md_size && i < rec->orig_len; i++, j++) ++ { ++ unsigned char mac_started = constant_time_ge(i, mac_start); ++ unsigned char mac_ended = constant_time_ge(i, mac_end); ++ unsigned char b = 0; ++ b = rec->data[i]; ++ rotated_mac[j] |= b & mac_started & ~mac_ended; ++ } ++ } ++ ++ /* Now rotate the MAC */ ++#if defined(CBC_MAC_ROTATE_IN_PLACE) ++ j = 0; ++ for (i = 0; i < md_size; i++) ++ { ++ unsigned char offset = (div_spoiler + rotate_offset + i) % md_size; ++ out[j++] = rotated_mac[offset]; ++ } ++#else ++ memset(out, 0, md_size); ++ for (i = 0; i < md_size; i++) ++ { ++ unsigned char offset = (div_spoiler + md_size - rotate_offset + i) % md_size; ++ for (j = 0; j < md_size; j++) ++ out[j] |= rotated_mac[i] & constant_time_eq_8(j, offset); ++ } ++#endif ++ } ++ ++/* These functions serialize the state of a hash and thus perform the standard ++ * "final" operation without adding the padding and length that such a function ++ * typically does. */ ++static void tls1_md5_final_raw(void* ctx, unsigned char *md_out) ++ { ++ MD5_CTX *md5 = ctx; ++ l2n(md5->A, md_out); ++ l2n(md5->B, md_out); ++ l2n(md5->C, md_out); ++ l2n(md5->D, md_out); ++ } ++ ++static void tls1_sha1_final_raw(void* ctx, unsigned char *md_out) ++ { ++ SHA_CTX *sha1 = ctx; ++ l2n(sha1->h0, md_out); ++ l2n(sha1->h1, md_out); ++ l2n(sha1->h2, md_out); ++ l2n(sha1->h3, md_out); ++ l2n(sha1->h4, md_out); ++ } ++ ++static void tls1_sha256_final_raw(void* ctx, unsigned char *md_out) ++ { ++ SHA256_CTX *sha256 = ctx; ++ unsigned i; ++ ++ for (i = 0; i < 8; i++) ++ { ++ l2n(sha256->h[i], md_out); ++ } ++ } ++ ++static void tls1_sha512_final_raw(void* ctx, unsigned char *md_out) ++ { ++ SHA512_CTX *sha512 = ctx; ++ unsigned i; ++ ++ for (i = 0; i < 8; i++) ++ { ++ l2n8(sha512->h[i], md_out); ++ } ++ } ++ ++/* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function ++ * which ssl3_cbc_digest_record supports. */ ++char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) ++ { ++ switch (ctx->digest->type) ++ { ++ case NID_md5: ++ case NID_sha1: ++ case NID_sha224: ++ case NID_sha256: ++ case NID_sha384: ++ case NID_sha512: ++ return 1; ++ default: ++ return 0; ++ } ++ } ++ ++/* ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS ++ * record. ++ * ++ * ctx: the EVP_MD_CTX from which we take the hash function. ++ * ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX. ++ * md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written. ++ * md_out_size: if non-NULL, the number of output bytes is written here. ++ * header: the 13-byte, TLS record header. ++ * data: the record data itself, less any preceeding explicit IV. ++ * data_plus_mac_size: the secret, reported length of the data and MAC ++ * once the padding has been removed. ++ * data_plus_mac_plus_padding_size: the public length of the whole ++ * record, including padding. ++ * is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS. ++ * ++ * On entry: by virtue of having been through one of the remove_padding ++ * functions, above, we know that data_plus_mac_size is large enough to contain ++ * a padding byte and MAC. (If the padding was invalid, it might contain the ++ * padding too. ) */ ++void ssl3_cbc_digest_record( ++ const EVP_MD_CTX *ctx, ++ unsigned char* md_out, ++ size_t* md_out_size, ++ const unsigned char header[13], ++ const unsigned char *data, ++ size_t data_plus_mac_size, ++ size_t data_plus_mac_plus_padding_size, ++ const unsigned char *mac_secret, ++ unsigned mac_secret_length, ++ char is_sslv3) ++ { ++ unsigned char md_state[sizeof(SHA512_CTX)]; ++ void (*md_final_raw)(void *ctx, unsigned char *md_out); ++ void (*md_transform)(void *ctx, const unsigned char *block); ++ unsigned md_size, md_block_size = 64; ++ unsigned sslv3_pad_length = 40, header_length, variance_blocks, ++ len, max_mac_bytes, num_blocks, ++ num_starting_blocks, k, mac_end_offset, c, index_a, index_b; ++ uint64_t bits; ++ unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES]; ++ /* hmac_pad is the masked HMAC key. */ ++ unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE]; ++ unsigned char first_block[MAX_HASH_BLOCK_SIZE]; ++ unsigned char mac_out[EVP_MAX_MD_SIZE]; ++ unsigned i, j, md_out_size_u; ++ EVP_MD_CTX md_ctx; ++ /* mdLengthSize is the number of bytes in the length field that terminates ++ * the hash. */ ++ unsigned md_length_size = 8; ++ ++ /* This is a, hopefully redundant, check that allows us to forget about ++ * many possible overflows later in this function. */ ++ OPENSSL_assert(data_plus_mac_plus_padding_size < 1024*1024); ++ ++ switch (ctx->digest->type) ++ { ++ case NID_md5: ++ MD5_Init((MD5_CTX*)md_state); ++ md_final_raw = tls1_md5_final_raw; ++ md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform; ++ md_size = 16; ++ sslv3_pad_length = 48; ++ break; ++ case NID_sha1: ++ SHA1_Init((SHA_CTX*)md_state); ++ md_final_raw = tls1_sha1_final_raw; ++ md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA1_Transform; ++ md_size = 20; ++ break; ++ case NID_sha224: ++ SHA224_Init((SHA256_CTX*)md_state); ++ md_final_raw = tls1_sha256_final_raw; ++ md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform; ++ md_size = 224/8; ++ break; ++ case NID_sha256: ++ SHA256_Init((SHA256_CTX*)md_state); ++ md_final_raw = tls1_sha256_final_raw; ++ md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform; ++ md_size = 32; ++ break; ++ case NID_sha384: ++ SHA384_Init((SHA512_CTX*)md_state); ++ md_final_raw = tls1_sha512_final_raw; ++ md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform; ++ md_size = 384/8; ++ md_block_size = 128; ++ md_length_size = 16; ++ break; ++ case NID_sha512: ++ SHA512_Init((SHA512_CTX*)md_state); ++ md_final_raw = tls1_sha512_final_raw; ++ md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform; ++ md_size = 64; ++ md_block_size = 128; ++ md_length_size = 16; ++ break; ++ default: ++ /* ssl3_cbc_record_digest_supported should have been ++ * called first to check that the hash function is ++ * supported. */ ++ OPENSSL_assert(0); ++ if (md_out_size) ++ *md_out_size = -1; ++ return; ++ } ++ ++ OPENSSL_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES); ++ OPENSSL_assert(md_block_size <= MAX_HASH_BLOCK_SIZE); ++ OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE); ++ ++ header_length = 13; ++ if (is_sslv3) ++ { ++ header_length = ++ mac_secret_length + ++ sslv3_pad_length + ++ 8 /* sequence number */ + ++ 1 /* record type */ + ++ 2 /* record length */; ++ } ++ ++ /* variance_blocks is the number of blocks of the hash that we have to ++ * calculate in constant time because they could be altered by the ++ * padding value. ++ * ++ * In SSLv3, the padding must be minimal so the end of the plaintext ++ * varies by, at most, 15+20 = 35 bytes. (We conservatively assume that ++ * the MAC size varies from 0..20 bytes.) In case the 9 bytes of hash ++ * termination (0x80 + 64-bit length) don't fit in the final block, we ++ * say that the final two blocks can vary based on the padding. ++ * ++ * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not ++ * required to be minimal. Therefore we say that the final six blocks ++ * can vary based on the padding. ++ * ++ * Later in the function, if the message is short and there obviously ++ * cannot be this many blocks then variance_blocks can be reduced. */ ++ variance_blocks = is_sslv3 ? 2 : 6; ++ /* From now on we're dealing with the MAC, which conceptually has 13 ++ * bytes of `header' before the start of the data (TLS) or 71/75 bytes ++ * (SSLv3) */ ++ len = data_plus_mac_plus_padding_size + header_length; ++ /* max_mac_bytes contains the maximum bytes of bytes in the MAC, including ++ * |header|, assuming that there's no padding. */ ++ max_mac_bytes = len - md_size - 1; ++ /* num_blocks is the maximum number of hash blocks. */ ++ num_blocks = (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size; ++ /* In order to calculate the MAC in constant time we have to handle ++ * the final blocks specially because the padding value could cause the ++ * end to appear somewhere in the final |variance_blocks| blocks and we ++ * can't leak where. However, |num_starting_blocks| worth of data can ++ * be hashed right away because no padding value can affect whether ++ * they are plaintext. */ ++ num_starting_blocks = 0; ++ /* k is the starting byte offset into the conceptual header||data where ++ * we start processing. */ ++ k = 0; ++ /* mac_end_offset is the index just past the end of the data to be ++ * MACed. */ ++ mac_end_offset = data_plus_mac_size + header_length - md_size; ++ /* c is the index of the 0x80 byte in the final hash block that ++ * contains application data. */ ++ c = mac_end_offset % md_block_size; ++ /* index_a is the hash block number that contains the 0x80 terminating ++ * value. */ ++ index_a = mac_end_offset / md_block_size; ++ /* index_b is the hash block number that contains the 64-bit hash ++ * length, in bits. */ ++ index_b = (mac_end_offset + md_length_size) / md_block_size; ++ /* bits is the hash-length in bits. It includes the additional hash ++ * block for the masked HMAC key, or whole of |header| in the case of ++ * SSLv3. */ ++ ++ /* For SSLv3, if we're going to have any starting blocks then we need ++ * at least two because the header is larger than a single block. */ ++ if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0)) ++ { ++ num_starting_blocks = num_blocks - variance_blocks; ++ k = md_block_size*num_starting_blocks; ++ } ++ ++ bits = 8*mac_end_offset; ++ if (!is_sslv3) ++ { ++ /* Compute the initial HMAC block. For SSLv3, the padding and ++ * secret bytes are included in |header| because they take more ++ * than a single block. */ ++ bits += 8*md_block_size; ++ memset(hmac_pad, 0, md_block_size); ++ OPENSSL_assert(mac_secret_length <= sizeof(hmac_pad)); ++ memcpy(hmac_pad, mac_secret, mac_secret_length); ++ for (i = 0; i < md_block_size; i++) ++ hmac_pad[i] ^= 0x36; ++ ++ md_transform(md_state, hmac_pad); ++ } ++ ++ j = 0; ++ if (md_length_size == 16) ++ { ++ memset(length_bytes, 0, 8); ++ j = 8; ++ } ++ for (i = 0; i < 8; i++) ++ length_bytes[i+j] = bits >> (8*(7-i)); ++ ++ if (k > 0) ++ { ++ if (is_sslv3) ++ { ++ /* The SSLv3 header is larger than a single block. ++ * overhang is the number of bytes beyond a single ++ * block that the header consumes: either 7 bytes ++ * (SHA1) or 11 bytes (MD5). */ ++ unsigned overhang = header_length-md_block_size; ++ md_transform(md_state, header); ++ memcpy(first_block, header + md_block_size, overhang); ++ memcpy(first_block + overhang, data, md_block_size-overhang); ++ md_transform(md_state, first_block); ++ for (i = 1; i < k/md_block_size - 1; i++) ++ md_transform(md_state, data + md_block_size*i - overhang); ++ } ++ else ++ { ++ /* k is a multiple of md_block_size. */ ++ memcpy(first_block, header, 13); ++ memcpy(first_block+13, data, md_block_size-13); ++ md_transform(md_state, first_block); ++ for (i = 1; i < k/md_block_size; i++) ++ md_transform(md_state, data + md_block_size*i - 13); ++ } ++ } ++ ++ memset(mac_out, 0, sizeof(mac_out)); ++ ++ /* We now process the final hash blocks. For each block, we construct ++ * it in constant time. If the |i==index_a| then we'll include the 0x80 ++ * bytes and zero pad etc. For each block we selectively copy it, in ++ * constant time, to |mac_out|. */ ++ for (i = num_starting_blocks; i <= num_starting_blocks+variance_blocks; i++) ++ { ++ unsigned char block[MAX_HASH_BLOCK_SIZE]; ++ unsigned char is_block_a = constant_time_eq_8(i, index_a); ++ unsigned char is_block_b = constant_time_eq_8(i, index_b); ++ for (j = 0; j < md_block_size; j++) ++ { ++ unsigned char b = 0, is_past_c, is_past_cp1; ++ if (k < header_length) ++ b = header[k]; ++ else if (k < data_plus_mac_plus_padding_size + header_length) ++ b = data[k-header_length]; ++ k++; ++ ++ is_past_c = is_block_a & constant_time_ge(j, c); ++ is_past_cp1 = is_block_a & constant_time_ge(j, c+1); ++ /* If this is the block containing the end of the ++ * application data, and we are at the offset for the ++ * 0x80 value, then overwrite b with 0x80. */ ++ b = (b&~is_past_c) | (0x80&is_past_c); ++ /* If this the the block containing the end of the ++ * application data and we're past the 0x80 value then ++ * just write zero. */ ++ b = b&~is_past_cp1; ++ /* If this is index_b (the final block), but not ++ * index_a (the end of the data), then the 64-bit ++ * length didn't fit into index_a and we're having to ++ * add an extra block of zeros. */ ++ b &= ~is_block_b | is_block_a; ++ ++ /* The final bytes of one of the blocks contains the ++ * length. */ ++ if (j >= md_block_size - md_length_size) ++ { ++ /* If this is index_b, write a length byte. */ ++ b = (b&~is_block_b) | (is_block_b&length_bytes[j-(md_block_size-md_length_size)]); ++ } ++ block[j] = b; ++ } ++ ++ md_transform(md_state, block); ++ md_final_raw(md_state, block); ++ /* If this is index_b, copy the hash value to |mac_out|. */ ++ for (j = 0; j < md_size; j++) ++ mac_out[j] |= block[j]&is_block_b; ++ } ++ ++ EVP_MD_CTX_init(&md_ctx); ++ EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */); ++ if (is_sslv3) ++ { ++ /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */ ++ memset(hmac_pad, 0x5c, sslv3_pad_length); ++ ++ EVP_DigestUpdate(&md_ctx, mac_secret, mac_secret_length); ++ EVP_DigestUpdate(&md_ctx, hmac_pad, sslv3_pad_length); ++ EVP_DigestUpdate(&md_ctx, mac_out, md_size); ++ } ++ else ++ { ++ /* Complete the HMAC in the standard manner. */ ++ for (i = 0; i < md_block_size; i++) ++ hmac_pad[i] ^= 0x6a; ++ ++ EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size); ++ EVP_DigestUpdate(&md_ctx, mac_out, md_size); ++ } ++ EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u); ++ if (md_out_size) ++ *md_out_size = md_out_size_u; ++ EVP_MD_CTX_cleanup(&md_ctx); ++ } +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.4.patch b/openssl-CVE-2013-0169.4.patch new file mode 100644 index 0000000..e1ce1eb --- /dev/null +++ b/openssl-CVE-2013-0169.4.patch @@ -0,0 +1,66 @@ +From 080f39539295d2c7c932e79dd670526b90a215a8 Mon Sep 17 00:00:00 2001 +From: Ben Laurie +Date: Tue, 29 Jan 2013 18:06:08 +0000 +Subject: [PATCH] Fixups from previous commit. + +--- + crypto/evp/c_allc.c | 1 - + ssl/s3_cbc.c | 3 +-- + ssl/ssl_algs.c | 1 - + ssl/t1_enc.c | 1 + + 4 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c +index e67022f..c5f9268 100644 +--- a/crypto/evp/c_allc.c ++++ b/crypto/evp/c_allc.c +@@ -194,7 +194,6 @@ void OpenSSL_add_all_ciphers(void) + EVP_add_cipher_alias(SN_aes_256_cbc,"AES256"); + EVP_add_cipher_alias(SN_aes_256_cbc,"aes256"); + #endif +-#endif + + #ifndef OPENSSL_NO_CAMELLIA + EVP_add_cipher(EVP_camellia_128_ecb()); +diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c +index e9b112c..6c5d43e 100644 +--- a/ssl/s3_cbc.c ++++ b/ssl/s3_cbc.c +@@ -139,8 +139,7 @@ int tls1_cbc_remove_padding(const SSL* s, + unsigned mac_size) + { + unsigned padding_length, good, to_check, i; +- const char has_explicit_iv = +- s->version >= TLS1_1_VERSION || s->version == DTLS1_VERSION; ++ const char has_explicit_iv = s->version == DTLS1_VERSION; + const unsigned overhead = 1 /* padding length byte */ + + mac_size + + (has_explicit_iv ? block_size : 0); +diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c +index 7f1a042..7de975d 100644 +--- a/ssl/ssl_algs.c ++++ b/ssl/ssl_algs.c +@@ -87,7 +87,6 @@ int SSL_library_init(void) + EVP_add_cipher(EVP_aes_256_cbc()); + #endif + +-#endif + #ifndef OPENSSL_NO_CAMELLIA + EVP_add_cipher(EVP_camellia_128_cbc()); + EVP_add_cipher(EVP_camellia_256_cbc()); +diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c +index 3fcb77b..0cb3c56 100644 +--- a/ssl/t1_enc.c ++++ b/ssl/t1_enc.c +@@ -641,6 +641,7 @@ int tls1_enc(SSL *s, int send) + EVP_CIPHER_CTX *ds; + unsigned long l; + int bs,i,j,k,pad=0,ret,mac_size=0; ++ int n; + const EVP_CIPHER *enc; + + if (send) +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.5.patch b/openssl-CVE-2013-0169.5.patch new file mode 100644 index 0000000..b924b8d --- /dev/null +++ b/openssl-CVE-2013-0169.5.patch @@ -0,0 +1,123 @@ +From 610dfc3ef4c4019394534023115226f4ed0e7204 Mon Sep 17 00:00:00 2001 +From: Ben Laurie +Date: Mon, 28 Jan 2013 17:33:18 +0000 +Subject: [PATCH] Don't crash when processing a zero-length, TLS >= 1.1 + record. + +The previous CBC patch was bugged in that there was a path through enc() +in s3_pkt.c/d1_pkt.c which didn't set orig_len. orig_len would be left +at the previous value which could suggest that the packet was a +sufficient length when it wasn't. +(cherry picked from commit 6cb19b7681f600b2f165e4adc57547b097b475fd) +--- + ssl/d1_enc.c | 1 - + ssl/d1_pkt.c | 1 + + ssl/s3_enc.c | 11 +++++++++-- + ssl/s3_pkt.c | 5 +++++ + ssl/t1_enc.c | 11 +++++++++-- + 5 files changed, 24 insertions(+), 5 deletions(-) + +diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c +index c13b495..da42348 100644 +--- a/ssl/d1_enc.c ++++ b/ssl/d1_enc.c +@@ -245,7 +245,6 @@ int dtls1_enc(SSL *s, int send) + } + #endif /* KSSL_DEBUG */ + +- rec->orig_len = rec->length; + if ((bs != 1) && !send) + return tls1_cbc_remove_padding(s, rec, bs, mac_size); + } +diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c +index 46a1950..5ee7c0d 100644 +--- a/ssl/d1_pkt.c ++++ b/ssl/d1_pkt.c +@@ -406,6 +406,7 @@ dtls1_process_record(SSL *s) + + /* decrypt in place in 'rr->input' */ + rr->data=rr->input; ++ rr->orig_len=rr->length; + + enc_err = s->method->ssl3_enc->enc(s,0); + if (enc_err <= 0) +diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c +index de5354a..a5829dc 100644 +--- a/ssl/s3_enc.c ++++ b/ssl/s3_enc.c +@@ -465,6 +465,15 @@ void ssl3_cleanup_key_block(SSL *s) + s->s3->tmp.key_block_length=0; + } + ++/* ssl3_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. ++ * ++ * Returns: ++ * 0: (in non-constant time) if the record is publically invalid (i.e. too ++ * short etc). ++ * 1: if the record's padding is valid / the encryption was successful. ++ * -1: if the record's padding is invalid or, if sending, an internal error ++ * occured. ++ */ + int ssl3_enc(SSL *s, int send) + { + SSL3_RECORD *rec; +@@ -531,8 +540,6 @@ int ssl3_enc(SSL *s, int send) + + EVP_Cipher(ds,rec->data,rec->input,l); + +- rec->orig_len = rec->length; +- + if (EVP_MD_CTX_md(s->read_hash) != NULL) + mac_size = EVP_MD_CTX_size(s->read_hash); + if ((bs != 1) && !send) +diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c +index 2e0c173..5bd0cd4 100644 +--- a/ssl/s3_pkt.c ++++ b/ssl/s3_pkt.c +@@ -398,8 +398,13 @@ fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); + + /* decrypt in place in 'rr->input' */ + rr->data=rr->input; ++ rr->orig_len=rr->length; + + enc_err = s->method->ssl3_enc->enc(s,0); ++ /* enc_err is: ++ * 0: (in non-constant time) if the record is publically invalid. ++ * 1: if the padding is valid ++ * -1: if the padding is invalid */ + if (enc_err == 0) + { + /* SSLerr() and ssl3_send_alert() have been called */ +diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c +index 0cb3c56..aaa4a5e 100644 +--- a/ssl/t1_enc.c ++++ b/ssl/t1_enc.c +@@ -635,6 +635,15 @@ err: + return(ret); + } + ++/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. ++ * ++ * Returns: ++ * 0: (in non-constant time) if the record is publically invalid (i.e. too ++ * short etc). ++ * 1: if the record's padding is valid / the encryption was successful. ++ * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, ++ * an internal error occured. ++ */ + int tls1_enc(SSL *s, int send) + { + SSL3_RECORD *rec; +@@ -746,8 +755,6 @@ int tls1_enc(SSL *s, int send) + } + #endif /* KSSL_DEBUG */ + +- rec->orig_len = rec->length; +- + ret = 1; + if (EVP_MD_CTX_md(s->read_hash) != NULL) + mac_size = EVP_MD_CTX_size(s->read_hash); +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.6.patch b/openssl-CVE-2013-0169.6.patch new file mode 100644 index 0000000..c110dd1 --- /dev/null +++ b/openssl-CVE-2013-0169.6.patch @@ -0,0 +1,262 @@ +From b23da2919b332fd83fa6de87caacb0651f64a3f5 Mon Sep 17 00:00:00 2001 +From: Ben Laurie +Date: Mon, 28 Jan 2013 17:34:33 +0000 +Subject: [PATCH] Update DTLS code to match CBC decoding in TLS. + +This change updates the DTLS code to match the constant-time CBC +behaviour in the TLS. +(cherry picked from commit 9f27de170d1b7bef3d46d41382dc4dafde8b3900) +--- + ssl/d1_enc.c | 13 +++++++-- + ssl/d1_pkt.c | 86 ++++++++++++++++++++++++++++++++++------------------------ + ssl/s3_enc.c | 4 --- + ssl/s3_pkt.c | 17 +++++------- + ssl/t1_enc.c | 4 --- + 5 files changed, 67 insertions(+), 57 deletions(-) + +diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c +index da42348..712c464 100644 +--- a/ssl/d1_enc.c ++++ b/ssl/d1_enc.c +@@ -126,6 +126,14 @@ + #include + #endif + ++/* dtls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. ++ * ++ * Returns: ++ * 0: (in non-constant time) if the record is publically invalid (i.e. too ++ * short etc). ++ * 1: if the record's padding is valid / the encryption was successful. ++ * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, ++ * an internal error occured. */ + int dtls1_enc(SSL *s, int send) + { + SSL3_RECORD *rec; +@@ -165,8 +173,7 @@ int dtls1_enc(SSL *s, int send) + if (EVP_MD_CTX_md(s->read_hash)) + { + mac_size=EVP_MD_CTX_size(s->read_hash); +- if (mac_size < 0) +- return -1; ++ OPENSSL_assert(mac_size >= 0); + } + ds=s->enc_read_ctx; + rec= &(s->s3->rrec); +@@ -231,7 +238,7 @@ int dtls1_enc(SSL *s, int send) + if (!send) + { + if (l == 0 || l%bs != 0) +- return -1; ++ return 0; + } + + EVP_Cipher(ds,rec->data,rec->input,l); +diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c +index 5ee7c0d..cbbf1d4 100644 +--- a/ssl/d1_pkt.c ++++ b/ssl/d1_pkt.c +@@ -368,15 +368,11 @@ static int + dtls1_process_record(SSL *s) + { + int i,al; +- int clear=0; + int enc_err; + SSL_SESSION *sess; + SSL3_RECORD *rr; + unsigned int mac_size; + unsigned char md[EVP_MAX_MD_SIZE]; +- int decryption_failed_or_bad_record_mac = 0; +- unsigned char *mac = NULL; +- + + rr= &(s->s3->rrec); + sess = s->session; +@@ -409,12 +405,16 @@ dtls1_process_record(SSL *s) + rr->orig_len=rr->length; + + enc_err = s->method->ssl3_enc->enc(s,0); +- if (enc_err <= 0) ++ /* enc_err is: ++ * 0: (in non-constant time) if the record is publically invalid. ++ * 1: if the padding is valid ++ * -1: if the padding is invalid */ ++ if (enc_err == 0) + { +- /* To minimize information leaked via timing, we will always +- * perform all computations before discarding the message. +- */ +- decryption_failed_or_bad_record_mac = 1; ++ /* For DTLS we simply ignore bad packets. */ ++ rr->length = 0; ++ s->packet_length = 0; ++ goto err; + } + + #ifdef TLS_DEBUG +@@ -424,45 +424,59 @@ printf("\n"); + #endif + + /* r->length is now the compressed data plus mac */ +- if ( (sess == NULL) || +- (s->enc_read_ctx == NULL) || +- (s->read_hash == NULL)) +- clear=1; +- +- if (!clear) ++ if ((sess != NULL) && ++ (s->enc_read_ctx != NULL) && ++ (EVP_MD_CTX_md(s->read_hash) != NULL)) + { +- /* !clear => s->read_hash != NULL => mac_size != -1 */ +- int t; +- t=EVP_MD_CTX_size(s->read_hash); +- OPENSSL_assert(t >= 0); +- mac_size=t; +- +- if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size) ++ /* s->read_hash != NULL => mac_size != -1 */ ++ unsigned char *mac = NULL; ++ unsigned char mac_tmp[EVP_MAX_MD_SIZE]; ++ mac_size=EVP_MD_CTX_size(s->read_hash); ++ OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); ++ ++ /* orig_len is the length of the record before any padding was ++ * removed. This is public information, as is the MAC in use, ++ * therefore we can safely process the record in a different ++ * amount of time if it's too short to possibly contain a MAC. ++ */ ++ if (rr->orig_len < mac_size || ++ /* CBC records must have a padding length byte too. */ ++ (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && ++ rr->orig_len < mac_size+1)) + { +-#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */ +- al=SSL_AD_RECORD_OVERFLOW; +- SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); ++ al=SSL_AD_DECODE_ERROR; ++ SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); + goto f_err; +-#else +- decryption_failed_or_bad_record_mac = 1; +-#endif + } +- /* check the MAC for rr->input (it's in mac_size bytes at the tail) */ +- if (rr->length >= mac_size) ++ ++ if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) + { ++ /* We update the length so that the TLS header bytes ++ * can be constructed correctly but we need to extract ++ * the MAC in constant time from within the record, ++ * without leaking the contents of the padding bytes. ++ * */ ++ mac = mac_tmp; ++ ssl3_cbc_copy_mac(mac_tmp, rr, mac_size); + rr->length -= mac_size; +- mac = &rr->data[rr->length]; + } + else +- rr->length = 0; +- i=s->method->ssl3_enc->mac(s,md,0); +- if (i < 0 || mac == NULL || CRYPTO_memcmp(md,mac,mac_size) != 0) + { +- decryption_failed_or_bad_record_mac = 1; ++ /* In this case there's no padding, so |rec->orig_len| ++ * equals |rec->length| and we checked that there's ++ * enough bytes for |mac_size| above. */ ++ rr->length -= mac_size; ++ mac = &rr->data[rr->length]; + } ++ ++ i=s->method->ssl3_enc->mac(s,md,0 /* not send */); ++ if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) ++ enc_err = -1; ++ if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size) ++ enc_err = -1; + } + +- if (decryption_failed_or_bad_record_mac) ++ if (enc_err < 0) + { + /* decryption failed, silently discard message */ + rr->length = 0; +diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c +index a5829dc..76d87b5 100644 +--- a/ssl/s3_enc.c ++++ b/ssl/s3_enc.c +@@ -530,11 +530,7 @@ int ssl3_enc(SSL *s, int send) + if (!send) + { + if (l == 0 || l%bs != 0) +- { +- SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); +- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); + return 0; +- } + /* otherwise, rec->length >= bs */ + } + +diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c +index 5bd0cd4..4730c6b 100644 +--- a/ssl/s3_pkt.c ++++ b/ssl/s3_pkt.c +@@ -290,7 +290,6 @@ static int ssl3_get_record(SSL *s) + unsigned char md[EVP_MAX_MD_SIZE]; + short version; + unsigned mac_size; +- int clear=0; + size_t extra; + + rr= &(s->s3->rrec); +@@ -407,8 +406,9 @@ fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); + * -1: if the padding is invalid */ + if (enc_err == 0) + { +- /* SSLerr() and ssl3_send_alert() have been called */ +- goto err; ++ al=SSL_AD_DECRYPTION_FAILED; ++ SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); ++ goto f_err; + } + + #ifdef TLS_DEBUG +@@ -418,14 +418,11 @@ printf("\n"); + #endif + + /* r->length is now the compressed data plus mac */ +- if ( (sess == NULL) || +- (s->enc_read_ctx == NULL) || +- (EVP_MD_CTX_md(s->read_hash) == NULL)) +- clear=1; +- +- if (!clear) ++ if ((sess != NULL) && ++ (s->enc_read_ctx != NULL) && ++ (EVP_MD_CTX_md(s->read_hash) != NULL)) + { +- /* !clear => s->read_hash != NULL => mac_size != -1 */ ++ /* s->read_hash != NULL => mac_size != -1 */ + unsigned char *mac = NULL; + unsigned char mac_tmp[EVP_MAX_MD_SIZE]; + mac_size=EVP_MD_CTX_size(s->read_hash); +diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c +index aaa4a5e..c38dae6 100644 +--- a/ssl/t1_enc.c ++++ b/ssl/t1_enc.c +@@ -737,11 +737,7 @@ int tls1_enc(SSL *s, int send) + if (!send) + { + if (l == 0 || l%bs != 0) +- { +- SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); +- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); + return 0; +- } + } + + EVP_Cipher(ds,rec->data,rec->input,l); +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.7.patch b/openssl-CVE-2013-0169.7.patch new file mode 100644 index 0000000..2ef467d --- /dev/null +++ b/openssl-CVE-2013-0169.7.patch @@ -0,0 +1,59 @@ +From 3cdaca2436643908863c6a62918b0d9703477655 Mon Sep 17 00:00:00 2001 +From: Andy Polyakov +Date: Fri, 1 Feb 2013 09:55:43 +0100 +Subject: [PATCH] ssl/s3_cbc.c: uint64_t portability fix. + +Break dependency on uint64_t. It's possible to declare bits as +unsigned int, because TLS packets are limited in size and 32-bit +value can't overflow. +(cherry picked from commit cab13fc8473856a43556d41d8dac5605f4ba1f91) +--- + ssl/s3_cbc.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c +index 6c5d43e..a2995c0 100644 +--- a/ssl/s3_cbc.c ++++ b/ssl/s3_cbc.c +@@ -53,8 +53,6 @@ + * + */ + +-#include +- + #include "ssl_locl.h" + + #include +@@ -419,7 +417,7 @@ void ssl3_cbc_digest_record( + unsigned sslv3_pad_length = 40, header_length, variance_blocks, + len, max_mac_bytes, num_blocks, + num_starting_blocks, k, mac_end_offset, c, index_a, index_b; +- uint64_t bits; ++ unsigned int bits; /* at most 18 bits */ + unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES]; + /* hmac_pad is the masked HMAC key. */ + unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE]; +@@ -579,14 +577,11 @@ void ssl3_cbc_digest_record( + md_transform(md_state, hmac_pad); + } + +- j = 0; +- if (md_length_size == 16) +- { +- memset(length_bytes, 0, 8); +- j = 8; +- } +- for (i = 0; i < 8; i++) +- length_bytes[i+j] = bits >> (8*(7-i)); ++ memset(length_bytes,0,md_length_size-4); ++ length_bytes[md_length_size-4] = (unsigned char)(bits>>24); ++ length_bytes[md_length_size-3] = (unsigned char)(bits>>16); ++ length_bytes[md_length_size-2] = (unsigned char)(bits>>8); ++ length_bytes[md_length_size-1] = (unsigned char)bits; + + if (k > 0) + { +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.8.patch b/openssl-CVE-2013-0169.8.patch new file mode 100644 index 0000000..0147b83 --- /dev/null +++ b/openssl-CVE-2013-0169.8.patch @@ -0,0 +1,124 @@ +From 11c48a0fd20d2ec091fde218449f3ba0ff1cf672 Mon Sep 17 00:00:00 2001 +From: Andy Polyakov +Date: Fri, 1 Feb 2013 09:59:56 +0100 +Subject: [PATCH] ssl/s3_cbc.c: md_state alignment portability fix. + +RISCs are picky and alignment granted by compiler for md_state can be +insufficient for SHA512. +(cherry picked from commit 36260233e7e3396feed884d3f501283e0453c04f) +--- + ssl/s3_cbc.c | 31 ++++++++++++++++--------------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c +index a2995c0..de3b433 100644 +--- a/ssl/s3_cbc.c ++++ b/ssl/s3_cbc.c +@@ -410,7 +410,8 @@ void ssl3_cbc_digest_record( + unsigned mac_secret_length, + char is_sslv3) + { +- unsigned char md_state[sizeof(SHA512_CTX)]; ++ union { double align; ++ unsigned char c[sizeof(SHA512_CTX)]; } md_state; + void (*md_final_raw)(void *ctx, unsigned char *md_out); + void (*md_transform)(void *ctx, const unsigned char *block); + unsigned md_size, md_block_size = 64; +@@ -436,32 +437,32 @@ void ssl3_cbc_digest_record( + switch (ctx->digest->type) + { + case NID_md5: +- MD5_Init((MD5_CTX*)md_state); ++ MD5_Init((MD5_CTX*)md_state.c); + md_final_raw = tls1_md5_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform; + md_size = 16; + sslv3_pad_length = 48; + break; + case NID_sha1: +- SHA1_Init((SHA_CTX*)md_state); ++ SHA1_Init((SHA_CTX*)md_state.c); + md_final_raw = tls1_sha1_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA1_Transform; + md_size = 20; + break; + case NID_sha224: +- SHA224_Init((SHA256_CTX*)md_state); ++ SHA224_Init((SHA256_CTX*)md_state.c); + md_final_raw = tls1_sha256_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform; + md_size = 224/8; + break; + case NID_sha256: +- SHA256_Init((SHA256_CTX*)md_state); ++ SHA256_Init((SHA256_CTX*)md_state.c); + md_final_raw = tls1_sha256_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform; + md_size = 32; + break; + case NID_sha384: +- SHA384_Init((SHA512_CTX*)md_state); ++ SHA384_Init((SHA512_CTX*)md_state.c); + md_final_raw = tls1_sha512_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform; + md_size = 384/8; +@@ -469,7 +470,7 @@ void ssl3_cbc_digest_record( + md_length_size = 16; + break; + case NID_sha512: +- SHA512_Init((SHA512_CTX*)md_state); ++ SHA512_Init((SHA512_CTX*)md_state.c); + md_final_raw = tls1_sha512_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform; + md_size = 64; +@@ -574,7 +575,7 @@ void ssl3_cbc_digest_record( + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x36; + +- md_transform(md_state, hmac_pad); ++ md_transform(md_state.c, hmac_pad); + } + + memset(length_bytes,0,md_length_size-4); +@@ -592,21 +593,21 @@ void ssl3_cbc_digest_record( + * block that the header consumes: either 7 bytes + * (SHA1) or 11 bytes (MD5). */ + unsigned overhang = header_length-md_block_size; +- md_transform(md_state, header); ++ md_transform(md_state.c, header); + memcpy(first_block, header + md_block_size, overhang); + memcpy(first_block + overhang, data, md_block_size-overhang); +- md_transform(md_state, first_block); ++ md_transform(md_state.c, first_block); + for (i = 1; i < k/md_block_size - 1; i++) +- md_transform(md_state, data + md_block_size*i - overhang); ++ md_transform(md_state.c, data + md_block_size*i - overhang); + } + else + { + /* k is a multiple of md_block_size. */ + memcpy(first_block, header, 13); + memcpy(first_block+13, data, md_block_size-13); +- md_transform(md_state, first_block); ++ md_transform(md_state.c, first_block); + for (i = 1; i < k/md_block_size; i++) +- md_transform(md_state, data + md_block_size*i - 13); ++ md_transform(md_state.c, data + md_block_size*i - 13); + } + } + +@@ -656,8 +657,8 @@ void ssl3_cbc_digest_record( + block[j] = b; + } + +- md_transform(md_state, block); +- md_final_raw(md_state, block); ++ md_transform(md_state.c, block); ++ md_final_raw(md_state.c, block); + /* If this is index_b, copy the hash value to |mac_out|. */ + for (j = 0; j < md_size; j++) + mac_out[j] |= block[j]&is_block_b; +-- +1.7.9.5 + + diff --git a/openssl-CVE-2013-0169.9.patch b/openssl-CVE-2013-0169.9.patch new file mode 100644 index 0000000..cc328df --- /dev/null +++ b/openssl-CVE-2013-0169.9.patch @@ -0,0 +1,100 @@ +From 33f44acbbe83ab718ae15c0d2c6a57e802705a36 Mon Sep 17 00:00:00 2001 +From: Andy Polyakov +Date: Fri, 1 Feb 2013 10:10:32 +0100 +Subject: [PATCH] s3/s3_cbc.c: allow for compilations with NO_SHA256|512. + (cherry picked from commit + d5371324d978e4096bf99b9d0fe71b2cb65d9dc8) + +--- + ssl/s3_cbc.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c +index de3b433..dc3fd3e 100644 +--- a/ssl/s3_cbc.c ++++ b/ssl/s3_cbc.c +@@ -338,7 +338,9 @@ static void tls1_sha1_final_raw(void* ctx, unsigned char *md_out) + l2n(sha1->h3, md_out); + l2n(sha1->h4, md_out); + } ++#define LARGEST_DIGEST_CTX SHA_CTX + ++#ifndef OPENSSL_NO_SHA256 + static void tls1_sha256_final_raw(void* ctx, unsigned char *md_out) + { + SHA256_CTX *sha256 = ctx; +@@ -349,7 +351,11 @@ static void tls1_sha256_final_raw(void* ctx, unsigned char *md_out) + l2n(sha256->h[i], md_out); + } + } ++#undef LARGEST_DIGEST_CTX ++#define LARGEST_DIGEST_CTX SHA256_CTX ++#endif + ++#ifndef OPENSSL_NO_SHA512 + static void tls1_sha512_final_raw(void* ctx, unsigned char *md_out) + { + SHA512_CTX *sha512 = ctx; +@@ -360,6 +366,9 @@ static void tls1_sha512_final_raw(void* ctx, unsigned char *md_out) + l2n8(sha512->h[i], md_out); + } + } ++#undef LARGEST_DIGEST_CTX ++#define LARGEST_DIGEST_CTX SHA512_CTX ++#endif + + /* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function + * which ssl3_cbc_digest_record supports. */ +@@ -369,10 +378,14 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) + { + case NID_md5: + case NID_sha1: ++#ifndef OPENSSL_NO_SHA256 + case NID_sha224: + case NID_sha256: ++#endif ++#ifndef OPENSSL_NO_SHA512 + case NID_sha384: + case NID_sha512: ++#endif + return 1; + default: + return 0; +@@ -411,7 +424,7 @@ void ssl3_cbc_digest_record( + char is_sslv3) + { + union { double align; +- unsigned char c[sizeof(SHA512_CTX)]; } md_state; ++ unsigned char c[sizeof(LARGEST_DIGEST_CTX)]; } md_state; + void (*md_final_raw)(void *ctx, unsigned char *md_out); + void (*md_transform)(void *ctx, const unsigned char *block); + unsigned md_size, md_block_size = 64; +@@ -449,6 +462,7 @@ void ssl3_cbc_digest_record( + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA1_Transform; + md_size = 20; + break; ++#ifndef OPENSSL_NO_SHA256 + case NID_sha224: + SHA224_Init((SHA256_CTX*)md_state.c); + md_final_raw = tls1_sha256_final_raw; +@@ -461,6 +475,8 @@ void ssl3_cbc_digest_record( + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform; + md_size = 32; + break; ++#endif ++#ifndef OPENSSL_NO_SHA512 + case NID_sha384: + SHA384_Init((SHA512_CTX*)md_state.c); + md_final_raw = tls1_sha512_final_raw; +@@ -477,6 +493,7 @@ void ssl3_cbc_digest_record( + md_block_size = 128; + md_length_size = 16; + break; ++#endif + default: + /* ssl3_cbc_record_digest_supported should have been + * called first to check that the hash function is +-- +1.7.9.5 + + diff --git a/openssl.spec b/openssl.spec index edc8056..b2207b1 100644 --- a/openssl.spec +++ b/openssl.spec @@ -18,7 +18,7 @@ Summary: Secure Sockets Layer communications libs & utils Name: openssl Version: %{maj}i -Release: %mkrel 2 +Release: %mkrel 3 License: BSD-like Group: System/Libraries URL: http://www.openssl.org/ @@ -49,6 +49,19 @@ Patch300: openssl-1.0.0-mips.patch Patch301: openssl-1.0.0-arm.patch Patch302: openssl-1.0.0-enginesdir.patch Patch400: openssl-1.0.0d-CVE-2012-2333.diff +Patch401: openssl-CVE-2013-0166.patch +Patch402: openssl-CVE-2013-0169.1.patch +Patch403: openssl-CVE-2013-0169.2.patch +Patch404: openssl-CVE-2013-0169.3.patch +Patch405: openssl-CVE-2013-0169.4.patch +Patch406: openssl-CVE-2013-0169.5.patch +Patch407: openssl-CVE-2013-0169.6.patch +Patch408: openssl-CVE-2013-0169.7.patch +Patch409: openssl-CVE-2013-0169.8.patch +Patch410: openssl-CVE-2013-0169.9.patch +Patch411: openssl-CVE-2013-0169.10.patch +Patch412: openssl-CVE-2013-0169.11.patch +Patch413: openssl-CVE-2013-0169.12.patch Requires: %{libname} = %{version}-%{release} Requires: perl-base Requires: rootcerts @@ -142,7 +155,19 @@ cryptographic algorithms and protocols, including DES, RC4, RSA and SSL. %patch302 -p1 -b .engines %patch400 -p0 - +%patch401 -p1 +%patch402 -p1 +%patch403 -p1 +%patch404 -p1 +%patch405 -p1 +%patch406 -p1 +%patch407 -p1 +%patch408 -p1 +%patch409 -p1 +%patch410 -p1 +%patch411 -p1 +%patch412 -p1 +%patch413 -p1 perl -pi -e "s,^(OPENSSL_LIBNAME=).+$,\1%{_lib}," Makefile.org engines/Makefile # fix perl path @@ -360,6 +385,9 @@ rm -fr %{buildroot} %changelog +* Thu Apr 11 2013 Danil Leontiev +- P401-413: security fix for CVE-2013-0166, CVE-2013-0169 + * Wed May 30 2012 Danil Leontiev 1.0.0d-2.5 - P27: security fix for CVE-2012-2333