"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "ssl/ssl_rec.c" between
ssldump-0.9b3.tar.gz and ssldump-1.3.tar.gz

About: ssldump is an SSLv3/TLS network protocol analyzer.

ssl_rec.c  (ssldump-0.9b3):ssl_rec.c  (ssldump-1.3)
skipping to change at line 44 skipping to change at line 44
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMA GE. OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMA GE.
$Id: ssl_rec.c,v 1.3 2000/11/03 06:38:06 ekr Exp $ $Id: ssl_rec.c,v 1.3 2000/11/03 06:38:06 ekr Exp $
ekr@rtfm.com Wed Aug 18 15:46:57 1999 ekr@rtfm.com Wed Aug 18 15:46:57 1999
*/ */
static char *RCSSTRING="$Id: ssl_rec.c,v 1.3 2000/11/03 06:38:06 ekr Exp $";
#include "network.h" #include "network.h"
#include "ssl_h.h" #include "ssl_h.h"
#include "sslprint.h" #include "sslprint.h"
#include "ssl.enums.h" #include "ssl.enums.h"
#ifdef OPENSSL #ifdef OPENSSL
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/hmac.h> #include <openssl/hmac.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#endif #endif
#include "ssldecode.h" #include "ssldecode.h"
#include "ssl_rec.h" #include "ssl_rec.h"
struct ssl_rec_decoder_ { struct ssl_rec_decoder_ {
SSL_CipherSuite *cs; SSL_CipherSuite *cs;
Data *mac_key; Data *mac_key;
Data *implicit_iv; /* for AEAD ciphers */
Data *write_key; /* for AEAD ciphers */
#ifdef OPENSSL #ifdef OPENSSL
EVP_CIPHER_CTX *evp; EVP_CIPHER_CTX *evp;
#endif #endif
UINT4 seq; UINT4 seq;
}; };
static char *digests[]={ char *digests[]={
"MD5", "MD5",
"SHA1" "SHA1",
"SHA224",
"SHA256",
"SHA384",
"SHA512",
NULL
}; };
static char *ciphers[]={ char *ciphers[]={
"DES", "DES",
"DES3", "3DES",
"RC4", "RC4",
"RC2", "RC2",
"IDEA" "IDEA",
"AES128",
"AES256",
"CAMELLIA128",
"CAMELLIA256",
"SEED",
NULL,
"aes-128-gcm",
"aes-256-gcm"
}; };
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)
ssl_rec_decoder **dp; ssl_rec_decoder **dp;
SSL_CipherSuite *cs; SSL_CipherSuite *cs;
UCHAR *mk; UCHAR *mk;
UCHAR *sk; UCHAR *sk;
UCHAR *iv; UCHAR *iv;
{ {
int r,_status; int r,_status;
ssl_rec_decoder *dec=0; ssl_rec_decoder *dec=0;
#ifdef OPENSSL #ifdef OPENSSL
const EVP_CIPHER *ciph=0; const EVP_CIPHER *ciph=0;
/* Find the SSLeay cipher */ /* Find the SSLeay cipher */
if(cs->enc!=ENC_NULL){ if(cs->enc!=ENC_NULL){
ciph=(EVP_CIPHER *)EVP_get_cipherbyname(ciphers[cs->enc-0x30]); ciph=(EVP_CIPHER *)EVP_get_cipherbyname(ciphers[cs->enc-0x30]);
if(!ciph)
ABORT(R_INTERNAL);
}
else {
ciph=EVP_enc_null();
} }
if(!(dec=(ssl_rec_decoder *)calloc(sizeof(ssl_rec_decoder),1))) if(!(dec=(ssl_rec_decoder *)calloc(1,sizeof(ssl_rec_decoder))))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
dec->cs=cs; dec->cs=cs;
if(r=r_data_create(&dec->mac_key,mk,cs->dig_len))
if((r=r_data_alloc(&dec->mac_key,cs->dig_len)))
ABORT(r);
if((r=r_data_alloc(&dec->implicit_iv,cs->block)))
ABORT(r); ABORT(r);
if(!(dec->evp=(EVP_CIPHER_CTX *)malloc(sizeof(EVP_CIPHER_CTX)))) memcpy(dec->implicit_iv->data,iv,cs->block);
if((r=r_data_create(&dec->write_key,sk,cs->eff_bits/8)))
ABORT(r);
/*
This is necessary for AEAD ciphers, because we must wait to fully initial
ize the cipher
in order to include the implicit IV
*/
if(IS_AEAD_CIPHER(cs)){
sk=NULL;
iv=NULL;
}
else
memcpy(dec->mac_key->data,mk,cs->dig_len);
if(!(dec->evp=EVP_CIPHER_CTX_new()))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
EVP_CIPHER_CTX_init(dec->evp); EVP_CIPHER_CTX_init(dec->evp);
EVP_CipherInit(dec->evp,ciph,sk,iv,0); EVP_CipherInit(dec->evp,ciph,sk,iv,0);
#endif #endif
*dp=dec; *dp=dec;
_status=0; _status=0;
abort: abort:
if(_status){ if(_status){
ssl_destroy_rec_decoder(&dec); ssl_destroy_rec_decoder(&dec);
skipping to change at line 132 skipping to change at line 170
int ssl_destroy_rec_decoder(dp) int ssl_destroy_rec_decoder(dp)
ssl_rec_decoder **dp; ssl_rec_decoder **dp;
{ {
ssl_rec_decoder *d; ssl_rec_decoder *d;
if(!dp || !*dp) if(!dp || !*dp)
return(0); return(0);
d=*dp; d=*dp;
r_data_destroy(&d->mac_key); r_data_destroy(&d->mac_key);
r_data_destroy(&d->implicit_iv);
r_data_destroy(&d->write_key);
#ifdef OPENSSL #ifdef OPENSSL
if(d->evp){ if(d->evp){
EVP_CIPHER_CTX_cleanup(d->evp); EVP_CIPHER_CTX_free(d->evp);
free(d->evp);
} }
free(*dp); free(*dp);
#endif #endif
*dp=0; *dp=0;
return(0); return(0);
} }
#define MSB(a) ((a>>8)&0xff)
#define LSB(a) (a&0xff)
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;
int ct; int ct;
int version; int version;
UCHAR *in; UCHAR *in;
int inl; int inl;
UCHAR *out; UCHAR *out;
int *outl; int *outl;
{ {
#ifdef OPENSSL #ifdef OPENSSL
int pad; int pad;
int r; int r,encpadl,x;
UCHAR *mac; UCHAR *mac,aead_tag[13],aead_nonce[12];
CRDUMP("Ciphertext",in,inl); CRDUMP("Ciphertext",in,inl);
/* First decrypt*/ if(IS_AEAD_CIPHER(d->cs)){
EVP_Cipher(d->evp,out,in,inl); memcpy(aead_nonce,d->implicit_iv->data,d->implicit_iv->len);
memcpy(aead_nonce+d->implicit_iv->len,in,12-d->implicit_iv->len);
in+=12-d->implicit_iv->len;
inl-=12-d->implicit_iv->len;
EVP_DecryptInit(d->evp,
NULL,
d->write_key->data,
aead_nonce);
/*
Then tag is always 16 bytes, as per:
https://tools.ietf.org/html/rfc5116#section-5.2
*/
EVP_CIPHER_CTX_ctrl(d->evp,EVP_CTRL_GCM_SET_TAG,16,in+(inl-16));
inl-=16;
fmt_seq(d->seq,aead_tag);
d->seq++;
aead_tag[8]=ct;
aead_tag[9]=MSB(version);
aead_tag[10]=LSB(version);
aead_tag[11]=MSB(inl);
aead_tag[12]=LSB(inl);
CRDUMP("Plaintext",out,inl); EVP_DecryptUpdate(d->evp,NULL,outl,aead_tag,13);
*outl=inl; EVP_DecryptUpdate(d->evp,out,outl,in,inl);
/* Now strip off the padding*/ if (!(x=EVP_DecryptFinal(d->evp,NULL,&x)))
if(d->cs->block!=1){ ERETURN(SSL_BAD_MAC);
pad=out[inl-1];
*outl-=(pad+1);
} }
/* And the MAC */ /*
*outl-=d->cs->dig_len; Encrypt-then-MAC is not used with AEAD ciphers, as per:
mac=out+(*outl); https://tools.ietf.org/html/rfc7366#section-3
CRDUMP("Record data",out,*outl); */
else if(ssl->extensions->encrypt_then_mac==2){
/* Now check the MAC */ *outl=inl;
if(ssl->version==0x300){
if(r=ssl3_check_mac(d,ct,version,out,*outl,mac)) /* First strip off the MAC */
ERETURN(r); *outl-=d->cs->dig_len;
mac=in+(*outl);
encpadl=*outl;
/* Now decrypt */
EVP_Cipher(d->evp,out,in,*outl);
CRDUMP("Plaintext",out,*outl);
/* 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
* 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,in+blk,encpadl,in,blk,mac)))
ERETURN(r);
}
else
if((r=tls_check_mac(d,ct,version,in,encpadl,NULL,0,mac)))
ERETURN(r);
} }
else{ else {
if(r=tls_check_mac(d,ct,version,out,*outl,mac)) /* First decrypt*/
ERETURN(r); 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);
} }
#define MSB(a) ((a>>8)&0xff)
#define LSB(a) (a&0xff)
#ifdef OPENSSL #ifdef OPENSSL
/* This should go to 2^128, but we're never really going to see /* This should go to 2^128, but we're never really going to see
more than 2^64, so we cheat*/ more than 2^64, so we cheat*/
static int fmt_seq(num,buf) static int fmt_seq(num,buf)
UINT4 num; UINT4 num;
UCHAR *buf; UCHAR *buf;
{ {
UINT4 netnum; UINT4 netnum;
memset(buf,0,8); memset(buf,0,8);
netnum=htonl(num); netnum=htonl(num);
memcpy(buf+4,&netnum,4); memcpy(buf+4,&netnum,4);
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 = HMAC_CTX_new();
if(!hm)
ERETURN(R_NO_MEMORY);
const EVP_MD *md; const EVP_MD *md;
UINT4 l; UINT4 l;
UCHAR buf[20]; UCHAR buf[128];
md=EVP_get_digestbyname(digests[d->cs->dig-0x40]); md=EVP_get_digestbyname(digests[d->cs->dig-0x40]);
HMAC_Init(&hm,d->mac_key->data,d->mac_key->len,md); HMAC_Init_ex(hm,d->mac_key->data,d->mac_key->len,md,NULL);
fmt_seq(d->seq,buf); fmt_seq(d->seq,buf);
d->seq++; d->seq++;
HMAC_Update(&hm,buf,8); HMAC_Update(hm,buf,8);
buf[0]=ct; buf[0]=ct;
HMAC_Update(&hm,buf,1); HMAC_Update(hm,buf,1);
buf[0]=MSB(ver); buf[0]=MSB(ver);
buf[1]=LSB(ver); buf[1]=LSB(ver);
HMAC_Update(&hm,buf,2); HMAC_Update(hm,buf,2);
buf[0]=MSB(datalen); buf[0]=MSB(datalen);
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))
ERETURN(SSL_BAD_MAC); ERETURN(SSL_BAD_MAC);
HMAC_cleanup(&hm); HMAC_CTX_free(hm);
return(0); return(0);
} }
int ssl3_check_mac(d,ct,ver,data,datalen,mac) int ssl3_check_mac(d,ct,ver,data,datalen,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 *mac; UCHAR *mac;
{ {
EVP_MD_CTX mc; EVP_MD_CTX *mc = EVP_MD_CTX_new();
const EVP_MD *md; const EVP_MD *md;
UINT4 l; UINT4 l;
UCHAR buf[64],dgst[20]; UCHAR buf[64],dgst[20];
int pad_ct; int pad_ct;
pad_ct=(d->cs->dig==DIG_SHA)?40:48; pad_ct=(d->cs->dig==DIG_SHA)?40:48;
md=EVP_get_digestbyname(digests[d->cs->dig-0x40]); md=EVP_get_digestbyname(digests[d->cs->dig-0x40]);
EVP_DigestInit(&mc,md); EVP_DigestInit(mc,md);
EVP_DigestUpdate(&mc,d->mac_key->data,d->mac_key->len); EVP_DigestUpdate(mc,d->mac_key->data,d->mac_key->len);
memset(buf,0x36,pad_ct); memset(buf,0x36,pad_ct);
EVP_DigestUpdate(&mc,buf,pad_ct); EVP_DigestUpdate(mc,buf,pad_ct);
fmt_seq(d->seq,buf); fmt_seq(d->seq,buf);
d->seq++; d->seq++;
EVP_DigestUpdate(&mc,buf,8); EVP_DigestUpdate(mc,buf,8);
buf[0]=ct; buf[0]=ct;
EVP_DigestUpdate(&mc,buf,1); EVP_DigestUpdate(mc,buf,1);
buf[0]=MSB(datalen); buf[0]=MSB(datalen);
buf[1]=LSB(datalen); buf[1]=LSB(datalen);
EVP_DigestUpdate(&mc,buf,2); EVP_DigestUpdate(mc,buf,2);
EVP_DigestUpdate(&mc,data,datalen); EVP_DigestUpdate(mc,data,datalen);
EVP_DigestFinal(&mc,dgst,&l); EVP_DigestFinal(mc,dgst,&l);
EVP_DigestInit(&mc,md); EVP_DigestInit(mc,md);
EVP_DigestUpdate(&mc,d->mac_key->data,d->mac_key->len); EVP_DigestUpdate(mc,d->mac_key->data,d->mac_key->len);
memset(buf,0x5c,pad_ct); memset(buf,0x5c,pad_ct);
EVP_DigestUpdate(&mc,buf,pad_ct); EVP_DigestUpdate(mc,buf,pad_ct);
EVP_DigestUpdate(&mc,dgst,l); EVP_DigestUpdate(mc,dgst,l);
EVP_DigestFinal(&mc,dgst,&l); EVP_DigestFinal(mc,dgst,&l);
if(memcmp(mac,dgst,l)) if(memcmp(mac,dgst,l))
ERETURN(SSL_BAD_MAC); ERETURN(SSL_BAD_MAC);
EVP_MD_CTX_free(mc);
return(0); return(0);
} }
#endif #endif
 End of changes. 50 change blocks. 
63 lines changed or deleted 206 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)