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.
This commit is contained in:
parent
6cb19b7681
commit
9f27de170d
13
ssl/d1_enc.c
13
ssl/d1_enc.c
@ -126,6 +126,14 @@
|
|||||||
#include <openssl/des.h>
|
#include <openssl/des.h>
|
||||||
#endif
|
#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)
|
int dtls1_enc(SSL *s, int send)
|
||||||
{
|
{
|
||||||
SSL3_RECORD *rec;
|
SSL3_RECORD *rec;
|
||||||
@ -165,8 +173,7 @@ int dtls1_enc(SSL *s, int send)
|
|||||||
if (EVP_MD_CTX_md(s->read_hash))
|
if (EVP_MD_CTX_md(s->read_hash))
|
||||||
{
|
{
|
||||||
mac_size=EVP_MD_CTX_size(s->read_hash);
|
mac_size=EVP_MD_CTX_size(s->read_hash);
|
||||||
if (mac_size < 0)
|
OPENSSL_assert(mac_size >= 0);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
ds=s->enc_read_ctx;
|
ds=s->enc_read_ctx;
|
||||||
rec= &(s->s3->rrec);
|
rec= &(s->s3->rrec);
|
||||||
@ -231,7 +238,7 @@ int dtls1_enc(SSL *s, int send)
|
|||||||
if (!send)
|
if (!send)
|
||||||
{
|
{
|
||||||
if (l == 0 || l%bs != 0)
|
if (l == 0 || l%bs != 0)
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EVP_Cipher(ds,rec->data,rec->input,l);
|
EVP_Cipher(ds,rec->data,rec->input,l);
|
||||||
|
88
ssl/d1_pkt.c
88
ssl/d1_pkt.c
@ -376,15 +376,11 @@ static int
|
|||||||
dtls1_process_record(SSL *s)
|
dtls1_process_record(SSL *s)
|
||||||
{
|
{
|
||||||
int i,al;
|
int i,al;
|
||||||
int clear=0;
|
|
||||||
int enc_err;
|
int enc_err;
|
||||||
SSL_SESSION *sess;
|
SSL_SESSION *sess;
|
||||||
SSL3_RECORD *rr;
|
SSL3_RECORD *rr;
|
||||||
unsigned int mac_size;
|
unsigned int mac_size;
|
||||||
unsigned char md[EVP_MAX_MD_SIZE];
|
unsigned char md[EVP_MAX_MD_SIZE];
|
||||||
int decryption_failed_or_bad_record_mac = 0;
|
|
||||||
unsigned char *mac = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
rr= &(s->s3->rrec);
|
rr= &(s->s3->rrec);
|
||||||
sess = s->session;
|
sess = s->session;
|
||||||
@ -417,12 +413,16 @@ dtls1_process_record(SSL *s)
|
|||||||
rr->orig_len=rr->length;
|
rr->orig_len=rr->length;
|
||||||
|
|
||||||
enc_err = s->method->ssl3_enc->enc(s,0);
|
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
|
/* For DTLS we simply ignore bad packets. */
|
||||||
* perform all computations before discarding the message.
|
rr->length = 0;
|
||||||
*/
|
s->packet_length = 0;
|
||||||
decryption_failed_or_bad_record_mac = 1;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TLS_DEBUG
|
#ifdef TLS_DEBUG
|
||||||
@ -432,45 +432,59 @@ printf("\n");
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* r->length is now the compressed data plus mac */
|
/* r->length is now the compressed data plus mac */
|
||||||
if ( (sess == NULL) ||
|
if ((sess != NULL) &&
|
||||||
(s->enc_read_ctx == NULL) ||
|
(s->enc_read_ctx != NULL) &&
|
||||||
(s->read_hash == NULL))
|
(EVP_MD_CTX_md(s->read_hash) != NULL))
|
||||||
clear=1;
|
|
||||||
|
|
||||||
if (!clear)
|
|
||||||
{
|
{
|
||||||
/* !clear => s->read_hash != NULL => mac_size != -1 */
|
/* s->read_hash != NULL => mac_size != -1 */
|
||||||
int t;
|
unsigned char *mac = NULL;
|
||||||
t=EVP_MD_CTX_size(s->read_hash);
|
unsigned char mac_tmp[EVP_MAX_MD_SIZE];
|
||||||
OPENSSL_assert(t >= 0);
|
mac_size=EVP_MD_CTX_size(s->read_hash);
|
||||||
mac_size=t;
|
OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
|
||||||
|
|
||||||
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+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_DECODE_ERROR;
|
||||||
al=SSL_AD_RECORD_OVERFLOW;
|
SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
|
||||||
SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG);
|
|
||||||
goto f_err;
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 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;
|
rr->length -= mac_size;
|
||||||
mac = &rr->data[rr->length];
|
mac = &rr->data[rr->length];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
rr->length = 0;
|
i=s->method->ssl3_enc->mac(s,md,0 /* not send */);
|
||||||
i=s->method->ssl3_enc->mac(s,md,0);
|
if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
|
||||||
if (i < 0 || mac == NULL || CRYPTO_memcmp(md,mac,mac_size) != 0)
|
enc_err = -1;
|
||||||
{
|
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size)
|
||||||
decryption_failed_or_bad_record_mac = 1;
|
enc_err = -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decryption_failed_or_bad_record_mac)
|
if (enc_err < 0)
|
||||||
{
|
{
|
||||||
/* decryption failed, silently discard message */
|
/* decryption failed, silently discard message */
|
||||||
rr->length = 0;
|
rr->length = 0;
|
||||||
|
@ -531,11 +531,7 @@ int ssl3_enc(SSL *s, int send)
|
|||||||
if (!send)
|
if (!send)
|
||||||
{
|
{
|
||||||
if (l == 0 || l%bs != 0)
|
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;
|
return 0;
|
||||||
}
|
|
||||||
/* otherwise, rec->length >= bs */
|
/* otherwise, rec->length >= bs */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
ssl/s3_pkt.c
17
ssl/s3_pkt.c
@ -291,7 +291,6 @@ static int ssl3_get_record(SSL *s)
|
|||||||
unsigned char md[EVP_MAX_MD_SIZE];
|
unsigned char md[EVP_MAX_MD_SIZE];
|
||||||
short version;
|
short version;
|
||||||
unsigned mac_size;
|
unsigned mac_size;
|
||||||
int clear=0;
|
|
||||||
size_t extra;
|
size_t extra;
|
||||||
|
|
||||||
rr= &(s->s3->rrec);
|
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 */
|
* -1: if the padding is invalid */
|
||||||
if (enc_err == 0)
|
if (enc_err == 0)
|
||||||
{
|
{
|
||||||
/* SSLerr() and ssl3_send_alert() have been called */
|
al=SSL_AD_DECRYPTION_FAILED;
|
||||||
goto err;
|
SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
|
||||||
|
goto f_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TLS_DEBUG
|
#ifdef TLS_DEBUG
|
||||||
@ -419,14 +419,11 @@ printf("\n");
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* r->length is now the compressed data plus mac */
|
/* r->length is now the compressed data plus mac */
|
||||||
if ( (sess == NULL) ||
|
if ((sess != NULL) &&
|
||||||
(s->enc_read_ctx == NULL) ||
|
(s->enc_read_ctx != NULL) &&
|
||||||
(EVP_MD_CTX_md(s->read_hash) == NULL))
|
(EVP_MD_CTX_md(s->read_hash) != NULL))
|
||||||
clear=1;
|
|
||||||
|
|
||||||
if (!clear)
|
|
||||||
{
|
{
|
||||||
/* !clear => s->read_hash != NULL => mac_size != -1 */
|
/* s->read_hash != NULL => mac_size != -1 */
|
||||||
unsigned char *mac = NULL;
|
unsigned char *mac = NULL;
|
||||||
unsigned char mac_tmp[EVP_MAX_MD_SIZE];
|
unsigned char mac_tmp[EVP_MAX_MD_SIZE];
|
||||||
mac_size=EVP_MD_CTX_size(s->read_hash);
|
mac_size=EVP_MD_CTX_size(s->read_hash);
|
||||||
|
@ -825,12 +825,8 @@ int tls1_enc(SSL *s, int send)
|
|||||||
if (!send)
|
if (!send)
|
||||||
{
|
{
|
||||||
if (l == 0 || l%bs != 0)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
i = EVP_Cipher(ds,rec->data,rec->input,l);
|
i = EVP_Cipher(ds,rec->data,rec->input,l);
|
||||||
if ((EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_CUSTOM_CIPHER)
|
if ((EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_CUSTOM_CIPHER)
|
||||||
|
Loading…
Reference in New Issue
Block a user