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 e130841bcc)

Conflicts:
	crypto/evp/c_allc.c
	ssl/ssl_algs.c
	ssl/ssl_locl.h
	ssl/t1_enc.c
(cherry picked from commit 3622239826698a0e534dcf0473204c724bb9b4b4)

Conflicts:
	ssl/d1_enc.c
	ssl/s3_enc.c
	ssl/s3_pkt.c
	ssl/ssl3.h
	ssl/ssl_algs.c
	ssl/t1_enc.c
This commit is contained in:
Ben Laurie
2013-01-28 17:31:49 +00:00
committed by Dr. Stephen Henson
parent 7ad132b133
commit 35a65e814b
8 changed files with 221 additions and 190 deletions

View File

@@ -131,11 +131,17 @@ int dtls1_enc(SSL *s, int send)
SSL3_RECORD *rec;
EVP_CIPHER_CTX *ds;
unsigned long l;
int bs,i,ii,j,k;
int bs,i,j,k,mac_size=0;
const EVP_CIPHER *enc;
if (send)
{
if (EVP_MD_CTX_md(s->write_hash))
{
mac_size=EVP_MD_CTX_size(s->write_hash);
if (mac_size < 0)
return -1;
}
ds=s->enc_write_ctx;
rec= &(s->s3->wrec);
if (s->enc_write_ctx == NULL)
@@ -156,6 +162,12 @@ int dtls1_enc(SSL *s, int send)
}
else
{
if (EVP_MD_CTX_md(s->read_hash))
{
mac_size=EVP_MD_CTX_size(s->read_hash);
if (mac_size < 0)
return -1;
}
ds=s->enc_read_ctx;
rec= &(s->s3->rrec);
if (s->enc_read_ctx == NULL)
@@ -234,44 +246,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);
}