Security fix

This commit is contained in:
Danila Leontiev 2013-04-11 17:24:48 +04:00
parent 69b60e8591
commit 6b98c1cdb9
14 changed files with 2646 additions and 2 deletions

View file

@ -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

View file

@ -0,0 +1,161 @@
From 9c00a950604aca819cee977f1dcb4b45f2af3aa6 Mon Sep 17 00:00:00 2001
From: Ben Laurie <ben@links.org>
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

View file

@ -0,0 +1,122 @@
From f306b87d766e6ecf30824635c7c395b67cff9dbc Mon Sep 17 00:00:00 2001
From: Adam Langley <agl@chromium.org>
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

View file

@ -0,0 +1,89 @@
From 47061af1062e36b87242810f7f5279ee7240b9e4 Mon Sep 17 00:00:00 2001
From: Andy Polyakov <appro@openssl.org>
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_lt(unsigned a, unsigned b)
+ {
+ a -= b;
+ return DUPLICATE_MSB_TO_ALL(a);
+ }
+
/* constant_time_ge 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

View file

@ -0,0 +1,70 @@
From 579f3a631ebeef5eb0135977640a835968d3ad6c Mon Sep 17 00:00:00 2001
From: Andy Polyakov <appro@openssl.org>
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

View file

@ -0,0 +1,682 @@
From e5420be6cd09af2550b128575a675490cfba0483 Mon Sep 17 00:00:00 2001
From: Ben Laurie <ben@links.org>
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; i<ds->cipher->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; i<l; i++)
- printf(" %02x", rec->data[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<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); }
--
1.7.9.5

View file

@ -0,0 +1,717 @@
From f852b60797dc68aa86c99c4f7b905488d1538d99 Mon Sep 17 00:00:00 2001
From: Ben Laurie <ben@links.org>
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 <stdint.h>
+
+#include "ssl_locl.h"
+
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+
+/* 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

View file

@ -0,0 +1,66 @@
From 080f39539295d2c7c932e79dd670526b90a215a8 Mon Sep 17 00:00:00 2001
From: Ben Laurie <ben@links.org>
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

View file

@ -0,0 +1,123 @@
From 610dfc3ef4c4019394534023115226f4ed0e7204 Mon Sep 17 00:00:00 2001
From: Ben Laurie <ben@links.org>
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

View file

@ -0,0 +1,262 @@
From b23da2919b332fd83fa6de87caacb0651f64a3f5 Mon Sep 17 00:00:00 2001
From: Ben Laurie <ben@links.org>
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 <openssl/des.h>
#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

View file

@ -0,0 +1,59 @@
From 3cdaca2436643908863c6a62918b0d9703477655 Mon Sep 17 00:00:00 2001
From: Andy Polyakov <appro@openssl.org>
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 <stdint.h>
-
#include "ssl_locl.h"
#include <openssl/md5.h>
@@ -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

View file

@ -0,0 +1,124 @@
From 11c48a0fd20d2ec091fde218449f3ba0ff1cf672 Mon Sep 17 00:00:00 2001
From: Andy Polyakov <appro@openssl.org>
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

View file

@ -0,0 +1,100 @@
From 33f44acbbe83ab718ae15c0d2c6a57e802705a36 Mon Sep 17 00:00:00 2001
From: Andy Polyakov <appro@openssl.org>
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

View file

@ -18,7 +18,7 @@
Summary: Secure Sockets Layer communications libs & utils Summary: Secure Sockets Layer communications libs & utils
Name: openssl Name: openssl
Version: %{maj}i Version: %{maj}i
Release: %mkrel 2 Release: %mkrel 3
License: BSD-like License: BSD-like
Group: System/Libraries Group: System/Libraries
URL: http://www.openssl.org/ URL: http://www.openssl.org/
@ -49,6 +49,19 @@ Patch300: openssl-1.0.0-mips.patch
Patch301: openssl-1.0.0-arm.patch Patch301: openssl-1.0.0-arm.patch
Patch302: openssl-1.0.0-enginesdir.patch Patch302: openssl-1.0.0-enginesdir.patch
Patch400: openssl-1.0.0d-CVE-2012-2333.diff 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: %{libname} = %{version}-%{release}
Requires: perl-base Requires: perl-base
Requires: rootcerts Requires: rootcerts
@ -142,7 +155,19 @@ cryptographic algorithms and protocols, including DES, RC4, RSA and SSL.
%patch302 -p1 -b .engines %patch302 -p1 -b .engines
%patch400 -p0 %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 perl -pi -e "s,^(OPENSSL_LIBNAME=).+$,\1%{_lib}," Makefile.org engines/Makefile
# fix perl path # fix perl path
@ -360,6 +385,9 @@ rm -fr %{buildroot}
%changelog %changelog
* Thu Apr 11 2013 Danil Leontiev <danila.leontiev@rosalab.ru>
- P401-413: security fix for CVE-2013-0166, CVE-2013-0169
* Wed May 30 2012 Danil Leontiev <danila.leontiev@rosalab.ru> 1.0.0d-2.5 * Wed May 30 2012 Danil Leontiev <danila.leontiev@rosalab.ru> 1.0.0d-2.5
- P27: security fix for CVE-2012-2333 - P27: security fix for CVE-2012-2333