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 c5f9268378..e67022fc6f 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 2b275faf6a..79581e4410 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 07a5e97ce5..c13b495a08 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 b14597076d..de5354aefd 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 85ff7022de..2e0c173ecd 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 9c2c41287a..d3bd768c0e 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 0967b2dfe4..7f1a042b3d 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 7cf1d19dde..6a4f62af7c 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 5a0bd66e4b..3fcb77b4dc 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"); }
-- 
2.25.1