提交 9f27de17 编写于 作者: B Ben Laurie

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.
上级 6cb19b76
......@@ -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);
......
......@@ -376,15 +376,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;
......@@ -417,12 +413,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
......@@ -432,45 +432,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;
......
......@@ -531,11 +531,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 */
}
......
......@@ -291,7 +291,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);
......@@ -408,8 +407,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
......@@ -419,14 +419,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);
......
......@@ -825,11 +825,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;
}
}
i = EVP_Cipher(ds,rec->data,rec->input,l);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册