"Fossies" - the Fresh Open Source Software Archive  

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

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

ssldecode.c  (ssldump-0.9b3):ssldecode.c  (ssldump-1.3)
skipping to change at line 52 skipping to change at line 52
*/ */
#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>
#include <openssl/md5.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
#endif #endif
#include "ssldecode.h" #include "ssldecode.h"
#include "ssl_rec.h" #include "ssl_rec.h"
#include "r_assoc.h" #include "r_assoc.h"
static char *RCSSTRING="$Id: ssldecode.c,v 1.9 2002/08/17 01:33:17 ekr Exp $";
#define PRF(ssl,secret,usage,rnd1,rnd2,out) (ssl->version==SSLV3_VERSION)? \ #define PRF(ssl,secret,usage,rnd1,rnd2,out) (ssl->version==SSLV3_VERSION)? \
ssl3_prf(ssl,secret,usage,rnd1,rnd2,out): \ ssl3_prf(ssl,secret,usage,rnd1,rnd2,out): \
tls_prf(ssl,secret,usage,rnd1,rnd2,out) ((ssl->version == TLSV12_VERSION) ? \
tls12_prf(ssl,secret,usage,rnd1,rnd2,out): \
tls_prf(ssl,secret,usage,rnd1,rnd2,out))
static char *ssl_password; static char *ssl_password;
extern char *digests[];
extern UINT4 SSL_print_flags; extern UINT4 SSL_print_flags;
struct ssl_decode_ctx_ { struct ssl_decode_ctx_ {
#ifdef OPENSSL #ifdef OPENSSL
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
SSL *ssl; SSL *ssl;
r_assoc *session_cache; r_assoc *session_cache;
FILE *ssl_key_log_file;
#else #else
char dummy; /* Some compilers (Win32) don't like empty char dummy; /* Some compilers (Win32) don't like empty
structs */ structs */
#endif #endif
}; };
struct ssl_decoder_ { struct ssl_decoder_ {
ssl_decode_ctx *ctx; ssl_decode_ctx *ctx;
Data *session_id; Data *session_id;
SSL_CipherSuite *cs; SSL_CipherSuite *cs;
Data *client_random; Data *client_random;
Data *server_random; Data *server_random;
int ephemeral_rsa; int ephemeral_rsa;
Data *PMS; Data *PMS;
Data *MS; Data *MS;
Data *handshake_messages;
Data *session_hash;
ssl_rec_decoder *c_to_s; ssl_rec_decoder *c_to_s;
ssl_rec_decoder *s_to_c; ssl_rec_decoder *s_to_c;
ssl_rec_decoder *c_to_s_n; ssl_rec_decoder *c_to_s_n;
ssl_rec_decoder *s_to_c_n; ssl_rec_decoder *s_to_c_n;
}; };
#ifdef OPENSSL #ifdef OPENSSL
static int tls_P_hash PROTO_LIST((ssl_obj *ssl,Data *secret,Data *seed, static int tls_P_hash PROTO_LIST((ssl_obj *ssl,Data *secret,Data *seed,
const EVP_MD *md,Data *out)); const EVP_MD *md,Data *out));
static int tls12_prf PROTO_LIST((ssl_obj *ssl,Data *secret,char *usage,
Data *rnd1,Data *rnd2,Data *out));
static int tls_prf PROTO_LIST((ssl_obj *ssl,Data *secret,char *usage, static int tls_prf PROTO_LIST((ssl_obj *ssl,Data *secret,char *usage,
Data *rnd1,Data *rnd2,Data *out)); Data *rnd1,Data *rnd2,Data *out));
static int ssl3_prf PROTO_LIST((ssl_obj *ssl,Data *secret,char *usage, static int ssl3_prf PROTO_LIST((ssl_obj *ssl,Data *secret,char *usage,
Data *rnd1,Data *rnd2,Data *out)); Data *rnd1,Data *rnd2,Data *out));
static int ssl3_generate_export_iv PROTO_LIST((ssl_obj *ssl, static int ssl3_generate_export_iv PROTO_LIST((ssl_obj *ssl,
Data *rnd1,Data *rnd2,Data *out)); Data *rnd1,Data *rnd2,Data *out));
static int ssl_generate_keying_material PROTO_LIST((ssl_obj *ssl, static int ssl_generate_keying_material PROTO_LIST((ssl_obj *ssl,
ssl_decoder *d)); 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 #endif
static int ssl_create_session_lookup_key PROTO_LIST((ssl_obj *ssl, static int ssl_create_session_lookup_key PROTO_LIST((ssl_obj *ssl,
UCHAR *id,UINT4 idlen,UCHAR **keyp,UINT4 *keyl)); UCHAR *id,UINT4 idlen,UCHAR **keyp,UINT4 *keyl));
int ssl_save_session PROTO_LIST((ssl_obj *ssl,ssl_decoder *d)); int ssl_save_session PROTO_LIST((ssl_obj *ssl,ssl_decoder *d));
int ssl_restore_session PROTO_LIST((ssl_obj *ssl,ssl_decoder *d)); int ssl_restore_session PROTO_LIST((ssl_obj *ssl,ssl_decoder *d));
/*The password code is not thread safe*/ /*The password code is not thread safe*/
static int password_cb(char *buf,int num,int rwflag,void *userdata) static int password_cb(char *buf,int num,int rwflag,void *userdata)
{ {
if(num<strlen(ssl_password)+1) if(num<strlen(ssl_password)+1)
return(0); return(0);
strcpy(buf,ssl_password); strcpy(buf,ssl_password);
return(strlen(ssl_password)); 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; ssl_decode_ctx **dp;
char *keyfile; char *keyfile;
char *pass; char *pass;
char *keylogfile;
{ {
#ifdef OPENSSL #ifdef OPENSSL
ssl_decode_ctx *d=0; ssl_decode_ctx *d=0;
int r,_status; int _status;
SSLeay_add_all_algorithms(); SSL_library_init();
OpenSSL_add_all_algorithms();
if(!(d=(ssl_decode_ctx *)malloc(sizeof(ssl_decode_ctx)))) if(!(d=(ssl_decode_ctx *)malloc(sizeof(ssl_decode_ctx))))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
if(!(d->ssl_ctx=SSL_CTX_new(SSLv23_server_method()))) if(!(d->ssl_ctx=SSL_CTX_new(SSLv23_server_method())))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
if(keyfile){ if(keyfile){
if(pass){ if(pass){
ssl_password=pass; ssl_password=pass;
SSL_CTX_set_default_passwd_cb(d->ssl_ctx,password_cb); SSL_CTX_set_default_passwd_cb(d->ssl_ctx,password_cb);
} }
#if 0 #if 0
skipping to change at line 157 skipping to change at line 170
fprintf(stderr,"Problem loading private key\n"); fprintf(stderr,"Problem loading private key\n");
ABORT(R_INTERNAL); ABORT(R_INTERNAL);
} }
} }
if(!(d->ssl=SSL_new(d->ssl_ctx))) if(!(d->ssl=SSL_new(d->ssl_ctx)))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
if(r_assoc_create(&d->session_cache)) if(r_assoc_create(&d->session_cache))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
if (keylogfile) {
if(!(d->ssl_key_log_file=fopen(keylogfile, "r"))){
fprintf(stderr,"Failed to open ssl key log file");
ABORT(R_INTERNAL);
}
} else {
d->ssl_key_log_file = NULL;
}
X509V3_add_standard_extensions(); X509V3_add_standard_extensions();
*dp=d; *dp=d;
_status=0; _status=0;
abort: abort:
return(_status); return(_status);
#else #else
return(0); return(0);
#endif #endif
} }
int ssl_decode_ctx_destroy(dp)
ssl_decode_ctx **dp;
{
#ifdef OPENSSL
ssl_decode_ctx *d = *dp;
if(d->ssl_key_log_file) {
fclose(d->ssl_key_log_file);
}
r_assoc *x = d->session_cache;
r_assoc_destroy(&d->session_cache);
SSL_CTX_free(d->ssl_ctx);
SSL_free(d->ssl);
free(d);
#endif
return(0);
}
int ssl_decoder_create(dp,ctx) int ssl_decoder_create(dp,ctx)
ssl_decoder **dp; ssl_decoder **dp;
ssl_decode_ctx *ctx; ssl_decode_ctx *ctx;
{ {
int _status; int _status;
ssl_decoder *d=0; ssl_decoder *d=0;
#ifdef OPENSSL #ifdef OPENSSL
if(!(d=(ssl_decoder *)calloc(sizeof(ssl_decoder),1))) if(!(d=(ssl_decoder *)calloc(1,sizeof(ssl_decoder))))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
d->ctx=ctx; d->ctx=ctx;
*dp=d; *dp=d;
_status=0; _status=0;
abort: abort:
if(_status) if(_status)
ssl_decoder_destroy(&d); ssl_decoder_destroy(&d);
return(_status); return(_status);
#else #else
skipping to change at line 206 skipping to change at line 247
ssl_decoder *d; ssl_decoder *d;
if(!dp || !*dp) if(!dp || !*dp)
return(0); return(0);
d=*dp; d=*dp;
r_data_destroy(&d->client_random); r_data_destroy(&d->client_random);
r_data_destroy(&d->server_random); r_data_destroy(&d->server_random);
r_data_destroy(&d->session_id); r_data_destroy(&d->session_id);
r_data_destroy(&d->PMS); r_data_destroy(&d->PMS);
r_data_destroy(&d->MS); r_data_destroy(&d->MS);
r_data_destroy(&d->handshake_messages);
r_data_destroy(&d->session_hash);
ssl_destroy_rec_decoder(&d->c_to_s); ssl_destroy_rec_decoder(&d->c_to_s);
ssl_destroy_rec_decoder(&d->c_to_s_n); ssl_destroy_rec_decoder(&d->c_to_s_n);
ssl_destroy_rec_decoder(&d->s_to_c); ssl_destroy_rec_decoder(&d->s_to_c);
ssl_destroy_rec_decoder(&d->s_to_c_n); ssl_destroy_rec_decoder(&d->s_to_c_n);
free(d); free(d);
*dp=0; *dp=0;
#endif #endif
return(0); return(0);
} }
int ssl_set_client_random(d,msg,len) int ssl_set_client_random(d,msg,len)
ssl_decoder *d; ssl_decoder *d;
UCHAR *msg; UCHAR *msg;
int len; int len;
{ {
#ifdef OPENSSL #ifdef OPENSSL
int r; int r;
if(r=r_data_create(&d->client_random,msg,len)) r_data_destroy(&d->client_random);
if((r=r_data_create(&d->client_random,msg,len)))
ERETURN(r); ERETURN(r);
#endif #endif
return(0); return(0);
} }
int ssl_set_server_random(d,msg,len) int ssl_set_server_random(d,msg,len)
ssl_decoder *d; ssl_decoder *d;
UCHAR *msg; UCHAR *msg;
int len; int len;
{ {
#ifdef OPENSSL #ifdef OPENSSL
int r; int r;
if(r=r_data_create(&d->server_random,msg,len)) r_data_destroy(&d->server_random);
if((r=r_data_create(&d->server_random,msg,len)))
ERETURN(r); ERETURN(r);
#endif #endif
return(0); return(0);
} }
int ssl_set_client_session_id(d,msg,len) int ssl_set_client_session_id(d,msg,len)
ssl_decoder *d; ssl_decoder *d;
UCHAR *msg; UCHAR *msg;
int len; int len;
{ {
#ifdef OPENSSL #ifdef OPENSSL
int r; int r;
if(r=r_data_create(&d->session_id,msg,len)) if(len>0) {
ERETURN(r); r_data_destroy(&d->session_id);
if((r=r_data_create(&d->session_id,msg,len)))
ERETURN(r);
}
#endif #endif
return(0); return(0);
} }
int ssl_process_server_session_id(ssl,d,msg,len) int ssl_process_server_session_id(ssl,d,msg,len)
ssl_obj *ssl; ssl_obj *ssl;
ssl_decoder *d; ssl_decoder *d;
UCHAR *msg; UCHAR *msg;
int len; int len;
{ {
#ifdef OPENSSL #ifdef OPENSSL
int r,_status; int r,_status;
Data idd; Data idd;
int restored=0; int restored=0;
INIT_DATA(idd,msg,len); INIT_DATA(idd,msg,len);
/* First check to see if the client tried to restore */ /* First check to see if the client tried to restore */
if(d->session_id){ if(d->session_id){
/* Now check to see if we restored */ /* Now check to see if we restored */
if(r_data_compare(&idd,d->session_id)) if((r=r_data_compare(&idd,d->session_id)))
goto abort; ABORT(r);
/* Now try to look up the session. We may not be able /* Now try to look up the session. We may not be able
to find it if, for instance, the original session to find it if, for instance, the original session
was initiated with something other than static RSA */ was initiated with something other than static RSA */
if(r=ssl_restore_session(ssl,d)) if((r=ssl_restore_session(ssl,d)))
ABORT(r); ABORT(r);
restored=1; restored=1;
} }
_status=0; _status=0;
abort: abort:
if(!restored){ if(!restored){
/* Copy over the session ID */ /* Copy over the session ID */
r_data_zfree(d->session_id); r_data_destroy(&d->session_id);
r_data_create(&d->session_id,msg,len); r_data_create(&d->session_id,msg,len);
} }
return(_status); return(_status);
#else #else
return(0); return(0);
#endif #endif
} }
int ssl_process_client_session_id(ssl,d,msg,len)
ssl_obj *ssl;
ssl_decoder *d;
UCHAR *msg;
int len;
{
#ifdef OPENSSL
int _status;
/* First check if the client set session id */
//todo: check that session_id in decoder and msg are the same (and if not th
en take from msg?)
if(d->session_id)
{
/* Remove the master secret */
//todo: better save and destroy only when successfully read key log
r_data_destroy(&d->MS);
if(d->ctx->ssl_key_log_file && (ssl_read_key_log_file(d)==0) && d->MS)
{
//we found master secret for session in keylog
//try to save session
_status = ssl_save_session(ssl,d);
}
else
{
//just return error
_status = -1;
}
}
else
{
_status = -1;
}
return(_status);
#else
return(0);
#endif
}
int ssl_process_change_cipher_spec(ssl,d,direction) int ssl_process_change_cipher_spec(ssl,d,direction)
ssl_obj *ssl; ssl_obj *ssl;
ssl_decoder *d; ssl_decoder *d;
int direction; int direction;
{ {
#ifdef OPENSSL #ifdef OPENSSL
if(direction==DIR_I2R){ if(direction==DIR_I2R){
d->c_to_s=d->c_to_s_n; d->c_to_s=d->c_to_s_n;
d->c_to_s_n=0; d->c_to_s_n=0;
if(d->c_to_s) ssl->process_ciphertext |= direction; if(d->c_to_s) ssl->process_ciphertext |= direction;
skipping to change at line 355 skipping to change at line 442
ssl->record_encryption=REC_PLAINTEXT; ssl->record_encryption=REC_PLAINTEXT;
return(0); return(0);
} }
} }
ssl->record_encryption=REC_CIPHERTEXT; ssl->record_encryption=REC_CIPHERTEXT;
#ifdef OPENSSL #ifdef OPENSSL
if(!(out=(UCHAR *)malloc(d->len))) if(!(out=(UCHAR *)malloc(d->len)))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
if(r=ssl_decode_rec_data(ssl,rd,ct,version,d->data,d->len,out,&outl)){ if((r=ssl_decode_rec_data(ssl,rd,ct,version,d->data,d->len,out,&outl))){
ABORT(r); ABORT(r);
} }
memcpy(d->data,out,outl); memcpy(d->data,out,outl);
d->len=outl; d->len=outl;
ssl->record_encryption=REC_DECRYPTED_CIPHERTEXT; ssl->record_encryption=REC_DECRYPTED_CIPHERTEXT;
_status=0; _status=0;
abort: abort:
FREE(out); FREE(out);
return(_status); return(_status);
#else #else
return(0); return(0);
#endif #endif
} }
int ssl_update_handshake_messages(ssl,data)
ssl_obj *ssl;
Data *data;
{
#ifdef OPENSSL
Data *hms;
UCHAR *d;
int l,r;
hms = ssl->decoder->handshake_messages;
d = data->data-4;
l = data->len+4;
if(hms){
if(!(hms->data = realloc(hms->data,l+hms->len)))
ERETURN(R_NO_MEMORY);
memcpy(hms->data+hms->len,d,l);
hms->len+=l;
}
else{
if((r=r_data_create(&hms,d,l)))
ERETURN(r);
ssl->decoder->handshake_messages=hms;
}
#endif
return(0);
}
static int ssl_create_session_lookup_key(ssl,id,idlen,keyp,keyl) static int ssl_create_session_lookup_key(ssl,id,idlen,keyp,keyl)
ssl_obj *ssl; ssl_obj *ssl;
UCHAR *id; UCHAR *id;
UINT4 idlen; UINT4 idlen;
UCHAR **keyp; UCHAR **keyp;
UINT4 *keyl; UINT4 *keyl;
{ {
UCHAR *key=0; UCHAR *key=0;
UINT4 l; UINT4 l;
int r,_status; int _status;
l=idlen+strlen(ssl->server_name)+idlen+15; /* HOST + PORT + id */ l=idlen+strlen(ssl->server_name)+idlen+15; /* HOST + PORT + id */
if(!(key=(UCHAR *)malloc(l))) if(!(key=(UCHAR *)malloc(l)))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
*keyp=key; *keyp=key;
memcpy(key,id,idlen); memcpy(key,id,idlen);
*keyl=idlen; *keyl=idlen;
key+=idlen; key+=idlen;
sprintf(key,"%s:%d",ssl->server_name,ssl->server_port); snprintf((char *)key,l,"%s:%d",ssl->server_name,ssl->server_port);
*keyl+=strlen(key); *keyl+=strlen((char *)key);
_status=0; _status=0;
abort: abort:
return(_status); return(_status);
} }
/* Look up the session id in the session cache and generate /* Look up the session id in the session cache and generate
the appropriate keying material */ the appropriate keying material */
int ssl_restore_session(ssl,d) int ssl_restore_session(ssl,d)
ssl_obj *ssl; ssl_obj *ssl;
ssl_decoder *d; ssl_decoder *d;
{ {
UCHAR *lookup_key=0; UCHAR *lookup_key=0;
void *msv; void *msv;
Data *msd; Data *msd;
int lookup_key_len; int lookup_key_len;
int r,_status; int r,_status;
#ifdef OPENSSL #ifdef OPENSSL
if(r=ssl_create_session_lookup_key(ssl, if((r=ssl_create_session_lookup_key(ssl,
d->session_id->data,d->session_id->len,&lookup_key, d->session_id->data,d->session_id->len,&lookup_key,
&lookup_key_len)) (UINT4 *) &lookup_key_len)))
ABORT(r); ABORT(r);
if(r=r_assoc_fetch(d->ctx->session_cache,lookup_key,lookup_key_len, if((r=r_assoc_fetch(d->ctx->session_cache,(char *) lookup_key,lookup_key_len
&msv)) ,
&msv)))
ABORT(r); ABORT(r);
msd=(Data *)msv; msd=(Data *)msv;
if(r=r_data_create(&d->MS,msd->data,msd->len)) if((r=r_data_create(&d->MS,msd->data,msd->len)))
ABORT(r); ABORT(r);
CRDUMPD("Restored MS",d->MS); CRDUMPD("Restored MS",d->MS);
switch(ssl->version){ switch(ssl->version){
case SSLV3_VERSION: case SSLV3_VERSION:
if(r=ssl_generate_keying_material(ssl,d))
ABORT(r);
break;
case TLSV1_VERSION: case TLSV1_VERSION:
if(r=ssl_generate_keying_material(ssl,d)) case TLSV11_VERSION:
case TLSV12_VERSION:
if((r=ssl_generate_keying_material(ssl,d)))
ABORT(r); ABORT(r);
break; break;
default: default:
ABORT(SSL_CANT_DO_CIPHER); ABORT(SSL_CANT_DO_CIPHER);
} }
_status=0; _status=0;
abort: abort:
FREE(lookup_key); FREE(lookup_key);
return(_status); return(_status);
skipping to change at line 456 skipping to change at line 572
} }
/* Look up the session id in the session cache and generate /* Look up the session id in the session cache and generate
the appropriate keying material */ the appropriate keying material */
int ssl_save_session(ssl,d) int ssl_save_session(ssl,d)
ssl_obj *ssl; ssl_obj *ssl;
ssl_decoder *d; ssl_decoder *d;
{ {
#ifdef OPENSSL #ifdef OPENSSL
UCHAR *lookup_key=0; UCHAR *lookup_key=0;
void *msv;
Data *msd=0; Data *msd=0;
int lookup_key_len; int lookup_key_len;
int r,_status; int r,_status;
if(r=ssl_create_session_lookup_key(ssl,d->session_id->data, if((r=ssl_create_session_lookup_key(ssl,d->session_id->data,
d->session_id->len,&lookup_key, d->session_id->len,&lookup_key,
&lookup_key_len)) (UINT4 *) &lookup_key_len)))
ABORT(r); ABORT(r);
if(r=r_data_create(&msd,d->MS->data,d->MS->len)) if((r=r_data_create(&msd,d->MS->data,d->MS->len)))
ABORT(r); ABORT(r);
if(r=r_assoc_insert(d->ctx->session_cache,lookup_key,lookup_key_len, if((r=r_assoc_insert(d->ctx->session_cache,(char *)lookup_key,lookup_key_len ,
(void *)msd,0,(int (*)(void *))r_data_zfree, (void *)msd,0,(int (*)(void *))r_data_zfree,
R_ASSOC_NEW | R_ASSOC_REPLACE)) R_ASSOC_NEW | R_ASSOC_REPLACE)))
ABORT(r); ABORT(r);
_status=0; _status=0;
abort: abort:
if(_status){ if(_status){
r_data_zfree(msd); r_data_zfree(msd);
} }
FREE(lookup_key); FREE(lookup_key);
return(_status); return(_status);
#else #else
skipping to change at line 495 skipping to change at line 610
offer PFS. Yuck. */ offer PFS. Yuck. */
int ssl_process_client_key_exchange(ssl,d,msg,len) int ssl_process_client_key_exchange(ssl,d,msg,len)
ssl_obj *ssl; ssl_obj *ssl;
ssl_decoder *d; ssl_decoder *d;
UCHAR *msg; UCHAR *msg;
int len; int len;
{ {
#ifdef OPENSSL #ifdef OPENSSL
int r,_status; int r,_status;
int i; int i;
EVP_PKEY *pk; EVP_PKEY *pk;
const BIGNUM *n;
if(ssl->cs->kex!=KEX_RSA) /* Remove the master secret if it was there
return(-1); to force keying material regeneration in
case we're renegotiating */
r_data_destroy(&d->MS);
if(d->ephemeral_rsa) if(!d->ctx->ssl_key_log_file ||
return(-1); ssl_read_key_log_file(d) ||
!d->MS){
if(ssl->cs->kex!=KEX_RSA)
return(-1);
pk=SSL_get_privatekey(d->ctx->ssl); if(d->ephemeral_rsa)
if(!pk) return(-1);
return(-1);
if(pk->type!=EVP_PKEY_RSA) pk=SSL_get_privatekey(d->ctx->ssl);
return(-1); if(!pk)
return(-1);
if(r=r_data_alloc(&d->PMS,BN_num_bytes(pk->pkey.rsa->n))) if(EVP_PKEY_id(pk)!=EVP_PKEY_RSA)
ABORT(r); return(-1);
i=RSA_private_decrypt(len,msg,d->PMS->data, RSA_get0_key(EVP_PKEY_get0_RSA(pk), &n, NULL, NULL);
pk->pkey.rsa,RSA_PKCS1_PADDING); if((r=r_data_alloc(&d->PMS,BN_num_bytes(n))))
ABORT(r);
if(i!=48) i=RSA_private_decrypt(len,msg,d->PMS->data,
ABORT(SSL_BAD_PMS); EVP_PKEY_get0_RSA(pk),RSA_PKCS1_PADDING);
d->PMS->len=48; if(i!=48)
ABORT(SSL_BAD_PMS);
CRDUMPD("PMS",d->PMS); d->PMS->len=48;
/* Remove the master secret if it was there CRDUMPD("PMS",d->PMS);
to force keying material regeneration in }
case we're renegotiating */
r_data_destroy(&d->MS);
switch(ssl->version){ switch(ssl->version){
case SSLV3_VERSION: case SSLV3_VERSION:
if(r=ssl_generate_keying_material(ssl,d))
ABORT(r);
break;
case TLSV1_VERSION: case TLSV1_VERSION:
if(r=ssl_generate_keying_material(ssl,d)) case TLSV11_VERSION:
case TLSV12_VERSION:
if((r=ssl_generate_keying_material(ssl,d)))
ABORT(r); ABORT(r);
break; break;
default: default:
ABORT(SSL_CANT_DO_CIPHER); ABORT(SSL_CANT_DO_CIPHER);
} }
/* Now store the data in the session cache */ /* Now store the data in the session cache */
if(r=ssl_save_session(ssl,d)) if((r=ssl_save_session(ssl,d)))
ABORT(r); ABORT(r);
_status=0; _status=0;
abort: abort:
return(_status); return(_status);
#else #else
return 0; return 0;
#endif #endif
} }
skipping to change at line 567 skipping to change at line 686
ssl_obj *ssl; ssl_obj *ssl;
Data *secret; Data *secret;
Data *seed; Data *seed;
const EVP_MD *md; const EVP_MD *md;
Data *out; Data *out;
{ {
UCHAR *ptr=out->data; UCHAR *ptr=out->data;
int left=out->len; int left=out->len;
int tocpy; int tocpy;
UCHAR *A; UCHAR *A;
UCHAR _A[20],tmp[20]; UCHAR _A[128],tmp[128];
unsigned int A_l,tmp_l; unsigned int A_l,tmp_l;
HMAC_CTX hm; HMAC_CTX *hm = HMAC_CTX_new();
CRDUMPD("P_hash secret",secret); CRDUMPD("P_hash secret",secret);
CRDUMPD("P_hash seed",seed); CRDUMPD("P_hash seed",seed);
A=seed->data; A=seed->data;
A_l=seed->len; A_l=seed->len;
while(left){ while(left){
HMAC_Init(&hm,secret->data,secret->len,md); HMAC_Init_ex(hm,secret->data,secret->len,md,NULL);
HMAC_Update(&hm,A,A_l); HMAC_Update(hm,A,A_l);
HMAC_Final(&hm,_A,&A_l); HMAC_Final(hm,_A,&A_l);
A=_A; A=_A;
HMAC_Init(&hm,secret->data,secret->len,md); HMAC_Init_ex(hm,secret->data,secret->len,md,NULL);
HMAC_Update(&hm,A,A_l); HMAC_Update(hm,A,A_l);
HMAC_Update(&hm,seed->data,seed->len); HMAC_Update(hm,seed->data,seed->len);
HMAC_Final(&hm,tmp,&tmp_l); HMAC_Final(hm,tmp,&tmp_l);
tocpy=MIN(left,tmp_l); tocpy=MIN(left,tmp_l);
memcpy(ptr,tmp,tocpy); memcpy(ptr,tmp,tocpy);
ptr+=tocpy; ptr+=tocpy;
left-=tocpy; left-=tocpy;
} }
HMAC_cleanup(&hm); HMAC_CTX_free(hm);
CRDUMPD("P_hash out",out); CRDUMPD("P_hash out",out);
return (0); return (0);
} }
static int tls_prf(ssl,secret,usage,rnd1,rnd2,out) static int tls_prf(ssl,secret,usage,rnd1,rnd2,out)
ssl_obj *ssl; ssl_obj *ssl;
Data *secret; Data *secret;
char *usage; char *usage;
Data *rnd1; Data *rnd1;
Data *rnd2; Data *rnd2;
Data *out; Data *out;
{ {
int r,_status; int r,_status;
Data *md5_out=0,*sha_out=0; Data *md5_out=0,*sha_out=0;
Data *seed; Data *seed;
UCHAR *ptr; UCHAR *ptr;
Data *S1=0,*S2=0; Data *S1=0,*S2=0;
int i,S_l; int i,S_l;
if(r=r_data_alloc(&md5_out,MAX(out->len,16))) if((r=r_data_alloc(&md5_out,MAX(out->len,16))))
ABORT(r); ABORT(r);
if(r=r_data_alloc(&sha_out,MAX(out->len,20))) if((r=r_data_alloc(&sha_out,MAX(out->len,20))))
ABORT(r); ABORT(r);
if(r=r_data_alloc(&seed,strlen(usage)+rnd1->len+rnd2->len)) if((r=r_data_alloc(&seed,strlen(usage)+rnd1->len+rnd2->len)))
ABORT(r); ABORT(r);
ptr=seed->data; ptr=seed->data;
memcpy(ptr,usage,strlen(usage)); ptr+=strlen(usage); memcpy(ptr,usage,strlen(usage)); ptr+=strlen(usage);
memcpy(ptr,rnd1->data,rnd1->len); ptr+=rnd1->len; memcpy(ptr,rnd1->data,rnd1->len); ptr+=rnd1->len;
memcpy(ptr,rnd2->data,rnd2->len); ptr+=rnd2->len; memcpy(ptr,rnd2->data,rnd2->len); ptr+=rnd2->len;
S_l=secret->len/2 + secret->len%2; S_l=secret->len/2 + secret->len%2;
if(r=r_data_alloc(&S1,S_l)) if((r=r_data_alloc(&S1,S_l)))
ABORT(r); ABORT(r);
if(r=r_data_alloc(&S2,S_l)) if((r=r_data_alloc(&S2,S_l)))
ABORT(r); ABORT(r);
memcpy(S1->data,secret->data,S_l); memcpy(S1->data,secret->data,S_l);
memcpy(S2->data,secret->data + (secret->len - S_l),S_l); memcpy(S2->data,secret->data + (secret->len - S_l),S_l);
if(r=tls_P_hash if((r=tls_P_hash
(ssl,S1,seed,EVP_get_digestbyname("MD5"),md5_out)) (ssl,S1,seed,EVP_get_digestbyname("MD5"),md5_out)))
ABORT(r); ABORT(r);
if(r=tls_P_hash(ssl,S2,seed,EVP_get_digestbyname("SHA1"),sha_out)) if((r=tls_P_hash(ssl,S2,seed,EVP_get_digestbyname("SHA1"),sha_out)))
ABORT(r); ABORT(r);
for(i=0;i<out->len;i++) for(i=0;i<out->len;i++)
out->data[i]=md5_out->data[i] ^ sha_out->data[i]; out->data[i]=md5_out->data[i] ^ sha_out->data[i];
CRDUMPD("PRF out",out); CRDUMPD("PRF out",out);
_status=0; _status=0;
abort: abort:
r_data_destroy(&md5_out); r_data_destroy(&md5_out);
r_data_destroy(&sha_out); r_data_destroy(&sha_out);
r_data_destroy(&seed); r_data_destroy(&seed);
r_data_destroy(&S1); r_data_destroy(&S1);
r_data_destroy(&S2); r_data_destroy(&S2);
return(_status); return(_status);
} }
static int tls12_prf(ssl,secret,usage,rnd1,rnd2,out)
ssl_obj *ssl;
Data *secret;
char *usage;
Data *rnd1;
Data *rnd2;
Data *out;
{
const EVP_MD *md;
int r,_status;
Data *sha_out=0;
Data *seed;
UCHAR *ptr;
int i, dgi;
if((r=r_data_alloc(&sha_out,MAX(out->len,64)))) /* assume max SHA512 */
ABORT(r);
if((r=r_data_alloc(&seed,strlen(usage)+rnd1->len+rnd2->len)))
ABORT(r);
ptr=seed->data;
memcpy(ptr,usage,strlen(usage)); ptr+=strlen(usage);
memcpy(ptr,rnd1->data,rnd1->len); ptr+=rnd1->len;
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);
dgi-=0x40;
if ((md=EVP_get_digestbyname(digests[dgi])) == NULL) {
DBG((0,"Cannot get EVP for digest %s, openssl library current?",
digests[dgi]));
ERETURN(SSL_BAD_MAC);
}
if((r=tls_P_hash(ssl,secret,seed,md,sha_out)))
ABORT(r);
for(i=0;i<out->len;i++)
out->data[i]=sha_out->data[i];
CRDUMPD("PRF out",out);
_status=0;
abort:
r_data_destroy(&sha_out);
r_data_destroy(&seed);
return(_status);
}
static int ssl3_generate_export_iv(ssl,r1,r2,out) static int ssl3_generate_export_iv(ssl,r1,r2,out)
ssl_obj *ssl; ssl_obj *ssl;
Data *r1; Data *r1;
Data *r2; Data *r2;
Data *out; Data *out;
{ {
MD5_CTX md5; MD5_CTX md5;
UCHAR tmp[16]; UCHAR tmp[16];
MD5_Init(&md5); MD5_Init(&md5);
skipping to change at line 737 skipping to change at line 903
CRDUMPD("rnd2",rnd2); CRDUMPD("rnd2",rnd2);
} }
SHA1_Final(buf,&sha); SHA1_Final(buf,&sha);
CRDUMP("SHA out",buf,20); CRDUMP("SHA out",buf,20);
SHA1_Init(&sha); SHA1_Init(&sha);
MD5_Update(&md5,secret->data,secret->len); MD5_Update(&md5,secret->data,secret->len);
MD5_Update(&md5,buf,20); MD5_Update(&md5,buf,20);
MD5_Final(outbuf,&md5); MD5_Final((unsigned char *)outbuf,&md5);
tocpy=MIN(out->len-off,16); tocpy=MIN(out->len-off,16);
memcpy(out->data+off,outbuf,tocpy); memcpy(out->data+off,outbuf,tocpy);
CRDUMP("MD5 out",outbuf,16); CRDUMP("MD5 out",(UCHAR *)outbuf,16);
MD5_Init(&md5); MD5_Init(&md5);
} }
return(0); return(0);
} }
static int ssl_generate_keying_material(ssl,d) static int ssl_generate_keying_material(ssl,d)
ssl_obj *ssl; ssl_obj *ssl;
ssl_decoder *d; ssl_decoder *d;
{ {
Data *key_block=0; Data *key_block=0,temp;
UCHAR _iv_c[8],_iv_s[8]; UCHAR _iv_c[8],_iv_s[8];
UCHAR _key_c[16],_key_s[16]; UCHAR _key_c[16],_key_s[16];
int needed; int needed;
int r,_status; int r,_status;
UCHAR *ptr,*c_wk,*s_wk,*c_mk,*s_mk,*c_iv,*s_iv; UCHAR *ptr,*c_wk,*s_wk,*c_mk=NULL,*s_mk=NULL,*c_iv=NULL,*s_iv=NULL;
if(!d->MS){ if(!d->MS){
if(r=r_data_alloc(&d->MS,48)) if((r=r_data_alloc(&d->MS,48)))
ABORT(r); ABORT(r);
if(r=PRF(ssl,d->PMS,"master secret",d->client_random,d->server_random, if (ssl->extensions->extended_master_secret==2) {
d->MS)) if((r=ssl_generate_session_hash(ssl,d)))
ABORT(r); ABORT(r);
temp.len=0;
if((r=PRF(ssl,d->PMS,"extended master secret",d->session_hash,&temp,
d->MS)))
ABORT(r);
}
else
if((r=PRF(ssl,d->PMS,"master secret",d->client_random,d->server_random,
d->MS)))
ABORT(r);
CRDUMPD("MS",d->MS); CRDUMPD("MS",d->MS);
} }
/* Compute the key block. First figure out how much data /* Compute the key block. First figure out how much data
we need*/ 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; needed+=ssl->cs->bits / 4;
if(ssl->cs->block>1) needed+=ssl->cs->block*2; if(ssl->cs->block>1) needed+=ssl->cs->block*2;
if(r=r_data_alloc(&key_block,needed)) if((r=r_data_alloc(&key_block,needed)))
ABORT(r); ABORT(r);
if(r=PRF(ssl,d->MS,"key expansion",d->server_random,d->client_random, if((r=PRF(ssl,d->MS,"key expansion",d->server_random,d->client_random,
key_block)) key_block)))
ABORT(r); ABORT(r);
ptr=key_block->data; ptr=key_block->data;
c_mk=ptr; ptr+=ssl->cs->dig_len; /* Ideally find a cleaner way to check for AEAD cipher */
s_mk=ptr; ptr+=ssl->cs->dig_len; 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; c_wk=ptr; ptr+=ssl->cs->eff_bits/8;
s_wk=ptr; ptr+=ssl->cs->eff_bits/8; s_wk=ptr; ptr+=ssl->cs->eff_bits/8;
if(ssl->cs->block>1){ if(ssl->cs->block>1){
c_iv=ptr; ptr+=ssl->cs->block; c_iv=ptr; ptr+=ssl->cs->block;
s_iv=ptr; ptr+=ssl->cs->block; s_iv=ptr; ptr+=ssl->cs->block;
} }
if(ssl->cs->export){ if(ssl->cs->export){
Data iv_c,iv_s; Data iv_c,iv_s;
Data c_iv_d,s_iv_d;
Data key_c,key_s; Data key_c,key_s;
Data k; Data k;
if(ssl->cs->block>1){ if(ssl->cs->block>1){
ATTACH_DATA(iv_c,_iv_c); ATTACH_DATA(iv_c,_iv_c);
ATTACH_DATA(iv_s,_iv_s); ATTACH_DATA(iv_s,_iv_s);
if(ssl->version==SSLV3_VERSION){ if(ssl->version==SSLV3_VERSION){
if(r=ssl3_generate_export_iv(ssl,d->client_random, if((r=ssl3_generate_export_iv(ssl,d->client_random,
d->server_random,&iv_c)) d->server_random,&iv_c)))
ABORT(r); ABORT(r);
if(r=ssl3_generate_export_iv(ssl,d->server_random, if((r=ssl3_generate_export_iv(ssl,d->server_random,
d->client_random,&iv_s)) d->client_random,&iv_s)))
ABORT(r); ABORT(r);
} }
else{ else{
UCHAR _iv_block[16]; UCHAR _iv_block[16];
Data iv_block; Data iv_block;
Data key_null; Data key_null;
UCHAR _key_null; UCHAR _key_null;
INIT_DATA(key_null,&_key_null,0); INIT_DATA(key_null,&_key_null,0);
/* We only have room for 8 bit IVs, but that's /* We only have room for 8 bit IVs, but that's
all we should need. This is a sanity check */ all we should need. This is a sanity check */
if(ssl->cs->block>8) if(ssl->cs->block>8)
ABORT(R_INTERNAL); ABORT(R_INTERNAL);
ATTACH_DATA(iv_block,_iv_block); ATTACH_DATA(iv_block,_iv_block);
if(r=PRF(ssl,&key_null,"IV block",d->client_random, if((r=PRF(ssl,&key_null,"IV block",d->client_random,
d->server_random,&iv_block)) d->server_random,&iv_block)))
ABORT(r); ABORT(r);
memcpy(_iv_c,iv_block.data,8); memcpy(_iv_c,iv_block.data,8);
memcpy(_iv_s,iv_block.data+8,8); memcpy(_iv_s,iv_block.data+8,8);
} }
c_iv=_iv_c; c_iv=_iv_c;
s_iv=_iv_s; s_iv=_iv_s;
} }
skipping to change at line 860 skipping to change at line 1039
MD5_Update(&md5,s_wk,ssl->cs->eff_bits/8); MD5_Update(&md5,s_wk,ssl->cs->eff_bits/8);
MD5_Update(&md5,d->server_random->data,d->server_random->len); MD5_Update(&md5,d->server_random->data,d->server_random->len);
MD5_Update(&md5,d->client_random->data,d->client_random->len); MD5_Update(&md5,d->client_random->data,d->client_random->len);
MD5_Final(_key_s,&md5); MD5_Final(_key_s,&md5);
s_wk=_key_s; s_wk=_key_s;
} }
else{ else{
ATTACH_DATA(key_c,_key_c); ATTACH_DATA(key_c,_key_c);
ATTACH_DATA(key_s,_key_s); ATTACH_DATA(key_s,_key_s);
INIT_DATA(k,c_wk,ssl->cs->eff_bits/8); INIT_DATA(k,c_wk,ssl->cs->eff_bits/8);
if(r=PRF(ssl,&k,"client write key",d->client_random,d->server_random, if((r=PRF(ssl,&k,"client write key",d->client_random,d->server_random,
&key_c)) &key_c)))
ABORT(r); ABORT(r);
c_wk=_key_c; c_wk=_key_c;
INIT_DATA(k,s_wk,ssl->cs->eff_bits/8); INIT_DATA(k,s_wk,ssl->cs->eff_bits/8);
if(r=PRF(ssl,&k,"server write key",d->client_random,d->server_random, if((r=PRF(ssl,&k,"server write key",d->client_random,d->server_random,
&key_s)) &key_s)))
ABORT(r); ABORT(r);
s_wk=_key_s; s_wk=_key_s;
} }
} }
CRDUMP("Client MAC key",c_mk,ssl->cs->dig_len); CRDUMP("Client MAC key",c_mk,ssl->cs->dig_len);
CRDUMP("Server MAC key",s_mk,ssl->cs->dig_len); CRDUMP("Server MAC key",s_mk,ssl->cs->dig_len);
CRDUMP("Client Write key",c_wk,ssl->cs->bits/8); CRDUMP("Client Write key",c_wk,ssl->cs->bits/8);
CRDUMP("Server Write key",s_wk,ssl->cs->bits/8); CRDUMP("Server Write key",s_wk,ssl->cs->bits/8);
if(ssl->cs->block>1){ if(ssl->cs->block>1){
CRDUMP("Client Write IV",c_iv,ssl->cs->block); CRDUMP("Client Write IV",c_iv,ssl->cs->block);
CRDUMP("Server Write IV",s_iv,ssl->cs->block); CRDUMP("Server Write IV",s_iv,ssl->cs->block);
} }
if(r=ssl_create_rec_decoder(&d->c_to_s_n, if((r=ssl_create_rec_decoder(&d->c_to_s_n,
ssl->cs,c_mk,c_wk,c_iv)) ssl->cs,c_mk,c_wk,c_iv)))
ABORT(r); ABORT(r);
if(r=ssl_create_rec_decoder(&d->s_to_c_n, if((r=ssl_create_rec_decoder(&d->s_to_c_n,
ssl->cs,s_mk,s_wk,s_iv)) ssl->cs,s_mk,s_wk,s_iv)))
ABORT(r); ABORT(r);
_status=0; _status=0;
abort: abort:
if(key_block){ if(key_block){
r_data_zfree(key_block); r_data_zfree(key_block);
free(key_block); free(key_block);
} }
return(_status); return(_status);
} }
static int ssl_generate_session_hash(ssl,d)
ssl_obj *ssl;
ssl_decoder *d;
{
int r,_status,dgi;
unsigned int len;
const EVP_MD *md;
EVP_MD_CTX *dgictx = EVP_MD_CTX_create();
if((r=r_data_alloc(&d->session_hash,EVP_MAX_MD_SIZE)))
ABORT(r);
switch(ssl->version){
case TLSV12_VERSION:
dgi = MAX(DIG_SHA256,ssl->cs->dig)-0x40;
if ((md=EVP_get_digestbyname(digests[dgi])) == NULL) {
DBG((0,"Cannot get EVP for digest %s, openssl library current?",
digests[dgi]));
ERETURN(SSL_BAD_MAC);
}
EVP_DigestInit(dgictx,md);
EVP_DigestUpdate(dgictx,d->handshake_messages->data,d->handshake_messages
->len);
EVP_DigestFinal(dgictx,d->session_hash->data,(unsigned int *) &d->session
_hash->len);
break;
case SSLV3_VERSION:
case TLSV1_VERSION:
case TLSV11_VERSION:
EVP_DigestInit(dgictx,EVP_get_digestbyname("MD5"));
EVP_DigestUpdate(dgictx,d->handshake_messages->data,d->handshake_messages
->len);
EVP_DigestFinal_ex(dgictx,d->session_hash->data,(unsigned int *) &d->sess
ion_hash->len);
EVP_DigestInit(dgictx,EVP_get_digestbyname("SHA1"));
EVP_DigestUpdate(dgictx,d->handshake_messages->data,d->handshake_messages
->len);
EVP_DigestFinal(dgictx,d->session_hash->data+d->session_hash->len,&len);
d->session_hash->len+=len;
break;
default:
ABORT(SSL_CANT_DO_CIPHER);
}
_status=0;
abort:
return(_status);
}
static int ssl_read_key_log_file(d)
ssl_decoder *d;
{
int r,_status,n,i;
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(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(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_Fo
rmat
*/
}
_status=0;
abort:
if (d->ctx->ssl_key_log_file != NULL)
fseek(d->ctx->ssl_key_log_file, 0, SEEK_SET);
return(_status);
}
#endif #endif
 End of changes. 86 change blocks. 
108 lines changed or deleted 385 lines changed or added

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