added support for encrypt-then-mac

This commit is contained in:
mathewmarcus 2018-06-24 21:08:05 -05:00
parent 0d0a0b79b7
commit 57fc64ac77
3 changed files with 89 additions and 33 deletions

View file

@ -2467,10 +2467,15 @@ static int decode_extension_encrypt_then_mac(ssl,dir,seg,data)
segment *seg; segment *seg;
Data *data; Data *data;
{ {
int l,r; int l,r,*etm;
etm=&ssl->extensions->encrypt_then_mac;
SSL_DECODE_UINT16(ssl,"extension length",0,data,&l); SSL_DECODE_UINT16(ssl,"extension length",0,data,&l);
data->len-=l; data->len-=l;
data->data+=l; data->data+=l;
*etm=dir==DIR_I2R?1:*etm==1;
return(0); return(0);
} }
static int decode_extension_extended_master_secret(ssl,dir,seg,data) static int decode_extension_extended_master_secret(ssl,dir,seg,data)
@ -2508,7 +2513,7 @@ decoder extension_decoder[] = {
{ {
0, 0,
"server_name", "server_name",
decode_extension_server_name decode_extension,
}, },
{ {
1, 1,

View file

@ -68,6 +68,7 @@ typedef struct d_queue_ {
} r_queue; } r_queue;
typedef struct ssl_extensions_ { typedef struct ssl_extensions_ {
int encrypt_then_mac;
int extended_master_secret; int extended_master_secret;
} ssl_extensions; } ssl_extensions;

View file

@ -94,7 +94,7 @@ char *ciphers[]={
static int tls_check_mac PROTO_LIST((ssl_rec_decoder *d,int ct, static int tls_check_mac PROTO_LIST((ssl_rec_decoder *d,int ct,
int ver,UCHAR *data,UINT4 datalen,UCHAR *mac)); int ver,UCHAR *data,UINT4 datalen,UCHAR *iv,UINT4 ivlen,UCHAR *mac));
static int fmt_seq PROTO_LIST((UINT4 num,UCHAR *buf)); static int fmt_seq PROTO_LIST((UINT4 num,UCHAR *buf));
int ssl_create_rec_decoder(dp,cs,mk,sk,iv) int ssl_create_rec_decoder(dp,cs,mk,sk,iv)
@ -161,7 +161,8 @@ int ssl_destroy_rec_decoder(dp)
*dp=0; *dp=0;
return(0); return(0);
} }
int ssl_decode_rec_data(ssl,d,ct,version,in,inl,out,outl) int ssl_decode_rec_data(ssl,d,ct,version,in,inl,out,outl)
ssl_obj *ssl; ssl_obj *ssl;
ssl_rec_decoder *d; ssl_rec_decoder *d;
@ -174,50 +175,91 @@ int ssl_decode_rec_data(ssl,d,ct,version,in,inl,out,outl)
{ {
#ifdef OPENSSL #ifdef OPENSSL
int pad; int pad;
int r; int r,encpadl;
UCHAR *mac; UCHAR *mac,*iv;
CRDUMP("Ciphertext",in,inl); CRDUMP("Ciphertext",in,inl);
/* First decrypt*/
EVP_Cipher(d->evp,out,in,inl);
CRDUMP("Plaintext",out,inl); if(ssl->extensions->encrypt_then_mac){
*outl=inl; *outl=inl;
/* Now strip off the padding*/
if(d->cs->block>1){
pad=out[inl-1];
*outl-=(pad+1);
}
/* And the MAC */ /* First strip off the MAC */
*outl-=d->cs->dig_len; *outl-=d->cs->dig_len;
mac=out+(*outl); mac=in+(*outl);
CRDUMP("Record data",out,*outl);
/* Now check the MAC */ encpadl=*outl;
if(ssl->version==0x300){ /* Now decrypt */
if(r=ssl3_check_mac(d,ct,version,out,*outl,mac)) EVP_Cipher(d->evp,out,in,*outl);
ERETURN(r); CRDUMP("Plaintext",out,*outl);
}
else{ /* And then strip off the padding*/
if(d->cs->block>1){
pad=out[*outl-1];
*outl-=(pad+1);
}
/* TLS 1.1 and beyond: remove explicit IV, only used with /* TLS 1.1 and beyond: remove explicit IV, only used with
* non-stream ciphers. */ * non-stream ciphers. */
if (ssl->version>=0x0302 && ssl->cs->block > 1) { if (ssl->version>=0x0302 && ssl->cs->block > 1) {
UINT4 blk = ssl->cs->block; UINT4 blk = ssl->cs->block;
if (blk <= *outl) { if (blk <= *outl) {
*outl-=blk; *outl-=blk;
memmove(out, out+blk, *outl); memmove(out, out+blk, *outl);
} }
else { else {
DBG((0,"Block size greater than Plaintext!")); DBG((0,"Block size greater than Plaintext!"));
ERETURN(SSL_BAD_MAC); ERETURN(SSL_BAD_MAC);
} }
if(r=tls_check_mac(d,ct,version,in+blk,encpadl,in,blk,mac))
ERETURN(r);
} }
if(r=tls_check_mac(d,ct,version,out,*outl,mac)) else
ERETURN(r); if(r=tls_check_mac(d,ct,version,in,encpadl,NULL,0,mac))
ERETURN(r);
} }
else {
/* First decrypt*/
EVP_Cipher(d->evp,out,in,inl);
CRDUMP("Plaintext",out,inl);
*outl=inl;
/* Now strip off the padding*/
if(d->cs->block>1){
pad=out[inl-1];
*outl-=(pad+1);
}
/* And the MAC */
*outl-=d->cs->dig_len;
mac=out+(*outl);
CRDUMP("Record data",out,*outl);
/* Now check the MAC */
if(ssl->version==0x300){
if(r=ssl3_check_mac(d,ct,version,out,*outl,mac))
ERETURN(r);
}
else{
/* TLS 1.1 and beyond: remove explicit IV, only used with
* non-stream ciphers. */
if (ssl->version>=0x0302 && ssl->cs->block > 1) {
UINT4 blk = ssl->cs->block;
if (blk <= *outl) {
*outl-=blk;
memmove(out, out+blk, *outl);
}
else {
DBG((0,"Block size greater than Plaintext!"));
ERETURN(SSL_BAD_MAC);
}
}
if(r=tls_check_mac(d,ct,version,out,*outl,NULL,0,mac))
ERETURN(r);
}
}
#endif #endif
return(0); return(0);
} }
@ -241,13 +283,15 @@ static int fmt_seq(num,buf)
return(0); return(0);
} }
static int tls_check_mac(d,ct,ver,data,datalen,mac) static int tls_check_mac(d,ct,ver,data,datalen,iv,ivlen,mac)
ssl_rec_decoder *d; ssl_rec_decoder *d;
int ct; int ct;
int ver; int ver;
UCHAR *data; UCHAR *data;
UINT4 datalen; UINT4 datalen;
UCHAR *iv;
UINT4 ivlen;
UCHAR *mac; UCHAR *mac;
{ {
HMAC_CTX hm; HMAC_CTX hm;
@ -272,7 +316,13 @@ static int tls_check_mac(d,ct,ver,data,datalen,mac)
buf[1]=LSB(datalen); buf[1]=LSB(datalen);
HMAC_Update(&hm,buf,2); HMAC_Update(&hm,buf,2);
HMAC_Update(&hm,data,datalen); /* for encrypt-then-mac with an explicit IV */
if(ivlen && iv){
HMAC_Update(&hm,iv,ivlen);
HMAC_Update(&hm,data,datalen-ivlen);
}
else
HMAC_Update(&hm,data,datalen);
HMAC_Final(&hm,buf,&l); HMAC_Final(&hm,buf,&l);
if(memcmp(mac,buf,l)) if(memcmp(mac,buf,l))