Merge pull request #18 from mathewmarcus/dh_aes_gcm_support

Dh aes gcm support
This commit is contained in:
Alexandre Dulaunoy 2018-07-05 20:55:34 +02:00 committed by GitHub
commit eb8fdd4f98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 219 additions and 65 deletions

View file

@ -104,7 +104,7 @@ int err_exit(str,num)
int usage()
{
fprintf(stderr,"Usage: ssldump [-r dumpfile] [-i interface] \n");
fprintf(stderr,"Usage: ssldump [-r dumpfile] [-i interface] [-l sslkeylogfile] \n");
fprintf(stderr," [-k keyfile] [-p password] [-vtaTnsAxVNde]\n");
fprintf(stderr," [filter]\n");
exit(0);
@ -293,7 +293,7 @@ int main(argc,argv)
signal(SIGINT,sig_handler);
while((c=getopt(argc,argv,"vr:F:f:S:yTt:ai:k:p:nsAxXhHVNdqem:P"))!=EOF){
while((c=getopt(argc,argv,"vr:F:f:S:yTt:ai:k:l:p:nsAxXhHVNdqem:P"))!=EOF){
switch(c){
case 'v':
print_version();
@ -326,6 +326,9 @@ int main(argc,argv)
case 'k':
SSL_keyfile=strdup(optarg);
break;
case 'l':
SSL_keylogfile=strdup(optarg);
break;
case 'p':
SSL_password=strdup(optarg);
break;
@ -465,6 +468,8 @@ int main(argc,argv)
free(interface_name);
if(SSL_keyfile)
free(SSL_keyfile);
if(SSL_keylogfile)
free(SSL_keylogfile);
if(SSL_password)
free(SSL_password);

View file

@ -108,5 +108,18 @@ int debug(int class,char *format,...);
#define UNIMPLEMENTED do { fprintf(stderr,"Function %s unimplemented\n",__FUNCTION__); abort(); } while(0)
#ifdef STDC_HEADERS
#include <string.h>
#endif
#ifndef STRNICMP
#ifdef _WIN32
#define STRNICMP(a,b,n) strnicmp(a,b,n)
#else
#define STRNICMP(a,b,n) strncasecmp(a,b,n)
#endif
#endif
#endif

View file

@ -130,18 +130,18 @@ static SSL_CipherSuite CipherSuites[]={
{153,KEX_DH,SIG_DSS,ENC_SEED,16,128,128,DIG_SHA,20,0},
{154,KEX_DH,SIG_RSA,ENC_SEED,16,128,128,DIG_SHA,20,0},
{155,KEX_DH,SIG_NONE,ENC_SEED,16,128,128,DIG_SHA,20,0},
{156,KEX_RSA,SIG_RSA,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{157,KEX_RSA,SIG_RSA,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{158,KEX_DH,SIG_RSA,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{159,KEX_DH,SIG_RSA,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{160,KEX_DH,SIG_RSA,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{161,KEX_DH,SIG_RSA,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{162,KEX_DH,SIG_DSS,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{163,KEX_DH,SIG_DSS,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{164,KEX_DH,SIG_DSS,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{165,KEX_DH,SIG_DSS,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{166,KEX_DH,SIG_NONE,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{167,KEX_DH,SIG_NONE,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{156,KEX_RSA,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{157,KEX_RSA,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
{158,KEX_DH,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{159,KEX_DH,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
{160,KEX_DH,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{161,KEX_DH,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
{162,KEX_DH,SIG_DSS,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{163,KEX_DH,SIG_DSS,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
{164,KEX_DH,SIG_DSS,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{165,KEX_DH,SIG_DSS,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
{166,KEX_DH,SIG_NONE,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{167,KEX_DH,SIG_NONE,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
// Missing: 168-185
{186,KEX_RSA,SIG_RSA,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0},
{187,KEX_DH,SIG_DSS,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0},
@ -188,14 +188,14 @@ static SSL_CipherSuite CipherSuites[]={
{49192,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA384,48,0},
{49193,KEX_DH,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA256,32,0},
{49194,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA384,48,0},
{49195,KEX_DH,SIG_DSS,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{49196,KEX_DH,SIG_DSS,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{49197,KEX_DH,SIG_DSS,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{49198,KEX_DH,SIG_DSS,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{49199,KEX_DH,SIG_RSA,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{49200,KEX_DH,SIG_RSA,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{49201,KEX_DH,SIG_RSA,ENC_AES128,4,128,128,DIG_SHA256,32,0},
{49202,KEX_DH,SIG_RSA,ENC_AES256,4,256,256,DIG_SHA384,48,0},
{49195,KEX_DH,SIG_DSS,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{49196,KEX_DH,SIG_DSS,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
{49197,KEX_DH,SIG_DSS,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{49198,KEX_DH,SIG_DSS,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
{49199,KEX_DH,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{49200,KEX_DH,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
{49201,KEX_DH,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0},
{49202,KEX_DH,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0},
// Missing: 49203-49211
{49266,KEX_DH,SIG_DSS,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0},
{49267,KEX_DH,SIG_DSS,ENC_CAMELLIA256,16,256,256,DIG_SHA256,48,0},

View file

@ -466,8 +466,10 @@ static int decode_HandshakeType_ClientKeyExchange(ssl,dir,seg,data)
break;
case KEX_DH:
SSL_DECODE_OPAQUE_ARRAY(ssl,"DiffieHellmanClientPublicValue",
-(1<<15-1),P_HL,data,0);
SSL_DECODE_OPAQUE_ARRAY(ssl,"DiffieHellmanClientPublicValue",
-((1<<7)-1),P_HL,data,0);
ssl_process_client_key_exchange(ssl,
ssl->decoder,NULL,0);
}
}
return(0);

View file

@ -77,6 +77,7 @@ static int print_ssl_record PROTO_LIST((ssl_obj *obj,int direction,
segment *q,UCHAR *data,int len));
char *SSL_keyfile=0;
char *SSL_password=0;
char *SSL_keylogfile=0;
#define NEGATE 0x800000
@ -218,7 +219,7 @@ static int create_ssl_ctx(handle,ctxp)
ssl_decode_ctx *ctx=0;
int r,_status;
if(r=ssl_decode_ctx_create(&ctx,SSL_keyfile,SSL_password))
if(r=ssl_decode_ctx_create(&ctx,SSL_keyfile,SSL_password,SSL_keylogfile))
ABORT(r);
*ctxp=(proto_ctx *)ctx;

View file

@ -82,6 +82,7 @@ extern proto_mod ssl_mod;
extern UINT4 SSL_print_flags;
extern char *SSL_keyfile;
extern char *SSL_password;
extern char *SSL_keylogfile;
#endif

View file

@ -61,6 +61,8 @@ static char *RCSSTRING="$Id: ssl_rec.c,v 1.3 2000/11/03 06:38:06 ekr Exp $";
struct ssl_rec_decoder_ {
SSL_CipherSuite *cs;
Data *mac_key;
Data *implicit_iv; /* for AEAD ciphers */
Data *write_key; /* for AEAD ciphers */
#ifdef OPENSSL
EVP_CIPHER_CTX *evp;
#endif
@ -89,7 +91,9 @@ char *ciphers[]={
"CAMELLIA128",
"CAMELLIA256",
"SEED",
NULL
NULL,
"aes-128-gcm",
"aes-256-gcm"
};
@ -123,8 +127,28 @@ int ssl_create_rec_decoder(dp,cs,mk,sk,iv)
ABORT(R_NO_MEMORY);
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);
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 initialize 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 *)malloc(sizeof(EVP_CIPHER_CTX))))
ABORT(R_NO_MEMORY);
EVP_CIPHER_CTX_init(dec->evp);
@ -150,6 +174,8 @@ int ssl_destroy_rec_decoder(dp)
d=*dp;
r_data_destroy(&d->mac_key);
r_data_destroy(&d->implicit_iv);
r_data_destroy(&d->write_key);
#ifdef OPENSSL
if(d->evp){
EVP_CIPHER_CTX_cleanup(d->evp);
@ -163,6 +189,9 @@ int ssl_destroy_rec_decoder(dp)
}
#define MSB(a) ((a>>8)&0xff)
#define LSB(a) (a&0xff)
int ssl_decode_rec_data(ssl,d,ct,version,in,inl,out,outl)
ssl_obj *ssl;
ssl_rec_decoder *d;
@ -175,12 +204,48 @@ int ssl_decode_rec_data(ssl,d,ct,version,in,inl,out,outl)
{
#ifdef OPENSSL
int pad;
int r,encpadl;
UCHAR *mac,*iv;
int r,encpadl,x;
UCHAR *mac,*iv,aead_tag[13],aead_nonce[12];
CRDUMP("Ciphertext",in,inl);
if(IS_AEAD_CIPHER(d->cs)){
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;
if(ssl->extensions->encrypt_then_mac==2){
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);
EVP_DecryptUpdate(d->evp,NULL,outl,aead_tag,13);
EVP_DecryptUpdate(d->evp,out,outl,in,inl);
if (!(x=EVP_DecryptFinal(d->evp,NULL,&x)))
ERETURN(SSL_BAD_MAC);
}
/*
Encrypt-then-MAC is not used with AEAD ciphers, as per:
https://tools.ietf.org/html/rfc7366#section-3
*/
else if(ssl->extensions->encrypt_then_mac==2){
*outl=inl;
/* First strip off the MAC */
@ -265,8 +330,6 @@ int ssl_decode_rec_data(ssl,d,ct,version,in,inl,out,outl)
}
#define MSB(a) ((a>>8)&0xff)
#define LSB(a) (a&0xff)
#ifdef OPENSSL
/* This should go to 2^128, but we're never really going to see

View file

@ -55,5 +55,6 @@ int ssl_create_rec_decoder PROTO_LIST((ssl_rec_decoder **dp,
int ssl_decode_rec_data PROTO_LIST((ssl_obj *ssl,ssl_rec_decoder *d,
int ct,int version,UCHAR *in,int inl,UCHAR *out,int *outl));
#define IS_AEAD_CIPHER(cs) (cs->enc==0x3b||cs->enc==0x3c)
#endif

View file

@ -77,6 +77,8 @@ typedef struct SSL_CipherSuite_ {
#define ENC_CAMELLIA256 0x38
#define ENC_SEED 0x39
#define ENC_NULL 0x3a
#define ENC_AES128_GCM 0x3b
#define ENC_AES256_GCM 0x3c
#define DIG_MD5 0x40
#define DIG_SHA 0x41

View file

@ -76,6 +76,7 @@ struct ssl_decode_ctx_ {
SSL_CTX *ssl_ctx;
SSL *ssl;
r_assoc *session_cache;
FILE *ssl_key_log_file;
#else
char dummy; /* Some compilers (Win32) don't like empty
structs */
@ -115,6 +116,7 @@ static int ssl_generate_keying_material PROTO_LIST((ssl_obj *ssl,
ssl_decoder *d));
static int ssl_generate_session_hash PROTO_LIST((ssl_obj *ssl,
ssl_decoder *d));
static int ssl_read_key_log_file PROTO_LIST((ssl_decoder *d));
#endif
static int ssl_create_session_lookup_key PROTO_LIST((ssl_obj *ssl,
@ -132,10 +134,11 @@ static int password_cb(char *buf,int num,int rwflag,void *userdata)
return(strlen(ssl_password));
}
int ssl_decode_ctx_create(dp,keyfile,pass)
int ssl_decode_ctx_create(dp,keyfile,pass,keylogfile)
ssl_decode_ctx **dp;
char *keyfile;
char *pass;
char *keylogfile;
{
#ifdef OPENSSL
ssl_decode_ctx *d=0;
@ -169,6 +172,11 @@ int ssl_decode_ctx_create(dp,keyfile,pass)
if(r_assoc_create(&d->session_cache))
ABORT(R_NO_MEMORY);
if(keylogfile && !(d->ssl_key_log_file=fopen(keylogfile, "r"))){
fprintf(stderr,"Failed to open ssl key log file");
ABORT(R_INTERNAL);
}
X509V3_add_standard_extensions();
*dp=d;
@ -539,39 +547,42 @@ int ssl_process_client_key_exchange(ssl,d,msg,len)
#ifdef OPENSSL
int r,_status;
int i;
EVP_PKEY *pk;
if(ssl->cs->kex!=KEX_RSA)
return(-1);
if(d->ephemeral_rsa)
return(-1);
pk=SSL_get_privatekey(d->ctx->ssl);
if(!pk)
return(-1);
if(pk->type!=EVP_PKEY_RSA)
return(-1);
if(r=r_data_alloc(&d->PMS,BN_num_bytes(pk->pkey.rsa->n)))
ABORT(r);
i=RSA_private_decrypt(len,msg,d->PMS->data,
pk->pkey.rsa,RSA_PKCS1_PADDING);
if(i!=48)
ABORT(SSL_BAD_PMS);
d->PMS->len=48;
CRDUMPD("PMS",d->PMS);
/* Remove the master secret if it was there
to force keying material regeneration in
case we're renegotiating */
r_data_destroy(&d->MS);
if(!d->ctx->ssl_key_log_file ||
ssl_read_key_log_file(d) ||
!d->MS){
if(ssl->cs->kex!=KEX_RSA)
return(-1);
if(d->ephemeral_rsa)
return(-1);
pk=SSL_get_privatekey(d->ctx->ssl);
if(!pk)
return(-1);
if(pk->type!=EVP_PKEY_RSA)
return(-1);
if(r=r_data_alloc(&d->PMS,BN_num_bytes(pk->pkey.rsa->n)))
ABORT(r);
i=RSA_private_decrypt(len,msg,d->PMS->data,
pk->pkey.rsa,RSA_PKCS1_PADDING);
if(i!=48)
ABORT(SSL_BAD_PMS);
d->PMS->len=48;
CRDUMPD("PMS",d->PMS);
}
switch(ssl->version){
case SSLV3_VERSION:
@ -731,7 +742,8 @@ static int tls12_prf(ssl,secret,usage,rnd1,rnd2,out)
memcpy(ptr,rnd2->data,rnd2->len); ptr+=rnd2->len;
/* Earlier versions of openssl didn't have SHA256 of course... */
dgi = MAX(DIG_SHA256, ssl->cs->dig)-0x40;
dgi = MAX(DIG_SHA256, ssl->cs->dig);
dgi-=0x40;
if ((md=EVP_get_digestbyname(digests[dgi])) == NULL) {
DBG((0,"Cannot get EVP for digest %s, openssl library current?",
digests[dgi]));
@ -876,7 +888,8 @@ static int ssl_generate_keying_material(ssl,d)
/* Compute the key block. First figure out how much data
we need*/
needed=ssl->cs->dig_len*2;
/* Ideally find a cleaner way to check for AEAD cipher */
needed=!IS_AEAD_CIPHER(ssl->cs)?ssl->cs->dig_len*2:0;
needed+=ssl->cs->bits / 4;
if(ssl->cs->block>1) needed+=ssl->cs->block*2;
@ -888,8 +901,11 @@ static int ssl_generate_keying_material(ssl,d)
ABORT(r);
ptr=key_block->data;
c_mk=ptr; ptr+=ssl->cs->dig_len;
s_mk=ptr; ptr+=ssl->cs->dig_len;
/* Ideally find a cleaner way to check for AEAD cipher */
if(!IS_AEAD_CIPHER(ssl->cs)){
c_mk=ptr; ptr+=ssl->cs->dig_len;
s_mk=ptr; ptr+=ssl->cs->dig_len;
}
c_wk=ptr; ptr+=ssl->cs->eff_bits/8;
s_wk=ptr; ptr+=ssl->cs->eff_bits/8;
@ -1051,4 +1067,46 @@ static int ssl_generate_session_hash(ssl,d)
abort:
return(_status);
}
static int ssl_read_key_log_file(d)
ssl_decoder *d;
{
int r,_status,dgi,n;
unsigned int t;
size_t l=0;
char *line,*label_data;
while ((n=getline(&line,&l,d->ctx->ssl_key_log_file))!=-1) {
if(n==(d->client_random->len*2)+112 &&
!strncmp(line,"CLIENT_RANDOM",13)) {
if(!(label_data=malloc((d->client_random->len*2)+1)))
ABORT(r);
for(int i=0;i<d->client_random->len;i++)
if(snprintf(label_data+(i*2),3,"%02x",d->client_random->data[i])!=2)
ABORT(r);
if(STRNICMP(line+14,label_data,64))
continue;
if(r=r_data_alloc(&d->MS,48))
ABORT(r);
for(int i=0; i < d->MS->len; i++) {
if(sscanf(line+14+65+(i*2),"%2x",&t)!=1)
ABORT(r);
*(d->MS->data+i)=(char)t;
}
}
/*
Eventually add support for other labels defined here:
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
*/
}
_status=0;
abort:
fseek(d->ctx->ssl_key_log_file, SEEK_SET, 0);
return(_status);
}
#endif

View file

@ -51,7 +51,7 @@
#define CRDUMPD(a,b) P_(P_CR) {exdump(ssl,a,b);printf("\n");}
int ssl_decode_ctx_create PROTO_LIST((ssl_decode_ctx **ctx,
char *keyfile,char *password));
char *keyfile,char *password,char *keylogfile));
int ssl_decoder_destroy PROTO_LIST((ssl_decoder **dp));
int ssl_decoder_create PROTO_LIST((ssl_decoder **dp,ssl_decode_ctx *ctx));
int ssl_set_client_random PROTO_LIST((ssl_decoder *dp,

View file

@ -74,6 +74,10 @@ ssldump \- dump SSL traffic on a network
.I keyfile
]
[
.B \-l
.I sslkeylogfile
]
[
.B \-p
.I password
]
@ -210,6 +214,10 @@ Use \fIkeyfile\fP as the location of the SSL keyfile (OpenSSL format)
Previous versions of ssldump automatically looked in ./server.pem.
Now you must specify your keyfile every time.
.TP
.BI \-l " sslkeylogfile"
Use \fIsslkeylogfile\fP as the location of the SSLKEYLOGFILE
(https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format)
.TP
.BI \-p " password"
Use \fIpassword\fP as the SSL keyfile password.
.TP