From 35a65e814beb899fa1c69a7673a8956c6059dce7 Mon Sep 17 00:00:00 2001 From: Ben Laurie 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 (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 --- crypto/evp/c_allc.c | 1 + ssl/Makefile | 4 +- ssl/d1_enc.c | 53 ++++++------------ ssl/s3_enc.c | 108 +++++++++++++++++++++++-------------- ssl/s3_pkt.c | 80 +++++++++++++-------------- ssl/ssl3.h | 4 ++ ssl/ssl_locl.h | 34 ++++++++++++ ssl/t1_enc.c | 129 +++++++++++++++++++------------------------- 8 files changed, 222 insertions(+), 191 deletions(-) diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c index e45cee8ab0..354090f21f 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 5ac350745a..64f021dd5d 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 baa75f9186..0ff1b41ae1 100644 --- a/ssl/d1_enc.c +++ b/ssl/d1_enc.c @@ -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); } diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 759231d9d4..845557bb75 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -438,7 +438,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) @@ -499,22 +499,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); } @@ -591,7 +581,7 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send) EVP_MD_CTX md_ctx; const EVP_MD *hash; unsigned char *p,rec_char; - unsigned int md_size; + size_t md_size; int npad; if (send) @@ -612,28 +602,68 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send) md_size=EVP_MD_size(hash); npad=(48/md_size)*md_size; - /* Chop the digest off the end :-) */ - EVP_MD_CTX_init(&md_ctx); - - EVP_DigestInit_ex( &md_ctx,hash, NULL); - 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_DigestInit_ex( &md_ctx,hash, NULL); - 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 0e041c0ce0..dabcfd2464 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c @@ -246,11 +246,9 @@ static int ssl3_get_record(SSL *s) unsigned char *p; unsigned char md[EVP_MAX_MD_SIZE]; short version; - unsigned 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; @@ -356,17 +354,10 @@ again: 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 @@ -383,44 +374,55 @@ printf("\n"); if (!clear) { - mac_size=EVP_MD_size(s->read_hash); - - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) + /* !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 <= 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_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 >= 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 b9a85effa0..7709effe3e 100644 --- a/ssl/ssl3.h +++ b/ssl/ssl3.h @@ -304,6 +304,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 */ PQ_64BIT seq_num; /* 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_locl.h b/ssl/ssl_locl.h index 9059b7d6e7..fefc0bcc8f 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -189,6 +189,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, \ @@ -1002,6 +1011,31 @@ 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 #endif diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 3516fe15be..bb0cae15a4 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -533,7 +533,7 @@ int tls1_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,pad=0,ret,mac_size=0; const EVP_CIPHER *enc; if (send) @@ -559,11 +559,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 { @@ -591,14 +591,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", - (void *)ds,rec->data,rec->input,l); - printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%ld %ld], %d iv_len\n", - ds->buf_len, ds->cipher->key_len, - (unsigned long)DES_KEY_SZ, - (unsigned long)DES_SCHEDULE_SZ, - ds->cipher->iv_len); + 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); printf("\t\tIV: "); for (i=0; icipher->iv_len; i++) printf("%02X", ds->iv[i]); printf("\n"); @@ -629,49 +628,17 @@ 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); 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, EVP_MD_CTX *in_ctx, unsigned char *out) @@ -721,8 +688,10 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) const EVP_MD *hash; unsigned int md_size; int i; - HMAC_CTX hmac; - unsigned char buf[5]; + EVP_MD_CTX hmac, *mac_ctx; + 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; if (send) { @@ -741,20 +710,6 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) md_size=EVP_MD_size(hash); - buf[0]=rec->type; - if (ssl->version == DTLS1_VERSION && ssl->client_version == DTLS1_BAD_VER) - { - buf[1]=TLS1_VERSION_MAJOR; - buf[2]=TLS1_VERSION_MINOR; - } - else { - 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 */ HMAC_CTX_init(&hmac); HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL); @@ -766,16 +721,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); - HMAC_Update(&hmac,dtlsseq,8); + memcpy(header, dtlsseq, 8); } else - HMAC_Update(&hmac,seq,8); + memcpy(header, seq, 8); - HMAC_Update(&hmac,buf,5); - HMAC_Update(&hmac,rec->input,rec->length); - HMAC_Final(&hmac,md,&md_size); - HMAC_CTX_cleanup(&hmac); + 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; + 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); #ifdef TLS_DEBUG printf("sec="); {unsigned int z; for (z=0; z