From Hauke Mehrtens

1. dtls: set ssl_set_server() in DTLS dissector so wireshark knows if this is client or server
2. SSL: add decrypt support for CCM and CCM_8 Ciphers per rfc 6655
3. dtls: add psk decrypt support

svn path=/trunk/; revision=53836
This commit is contained in:
Michael Mann 2013-12-08 00:58:06 +00:00
parent 7d10a416a3
commit 0f05597ab1
4 changed files with 227 additions and 181 deletions

View File

@ -2,6 +2,7 @@
* Routines for dtls dissection
* Copyright (c) 2006, Authesserre Samuel <sauthess@gmail.com>
* Copyright (c) 2007, Mikael Magnusson <mikma@users.sourceforge.net>
* Copyright (c) 2013, Hauke Mehrtens <hauke@hauke-m.de>
*
* $Id$
*
@ -227,6 +228,7 @@ static gint dtls_decrypted_data_avail = 0;
static uat_t *dtlsdecrypt_uat = NULL;
static const gchar *dtls_keys_list = NULL;
static const gchar *dtls_psk = NULL;
#ifdef HAVE_LIBGNUTLS
static const gchar *dtls_debug_file_name = NULL;
#endif
@ -374,6 +376,7 @@ static void dissect_dtls_heartbeat(tvbuff_t *tvb, packet_info *pinfo,
static void dissect_dtls_hnd_cli_hello(tvbuff_t *tvb,
packet_info *pinfo,
proto_tree *tree,
guint32 offset, guint32 length,
SslDecryptSession* ssl);
@ -1443,7 +1446,7 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
break;
case SSL_HND_CLIENT_HELLO:
dissect_dtls_hnd_cli_hello(sub_tvb, ssl_hand_tree, 0, length, ssl);
dissect_dtls_hnd_cli_hello(sub_tvb, pinfo, ssl_hand_tree, 0, length, ssl);
break;
case SSL_HND_SERVER_HELLO:
@ -1514,62 +1517,21 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
default:
break;
}
{
/* here we can have all the data to build session key */
StringInfo encrypted_pre_master;
gint ret;
guint encrlen = length, skip;
skip = 0;
if (!ssl)
/* here we can have all the data to build session key */
if (!ssl)
break;
/* check for required session data */
ssl_debug_printf("dissect_dtls_handshake found SSL_HND_CLIENT_KEY_EXCHG, state %X\n",
ssl->state);
if ((ssl->state & (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION)) !=
(SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION)) {
ssl_debug_printf("dissect_dtls_handshake not enough data to generate key (required state %X)\n",
(SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION));
if (ssl_generate_pre_master_secret(ssl, length, tvb, offset, dtls_psk, NULL) < 0) {
ssl_debug_printf("dissect_dtls_handshake can't generate pre master secret\n");
break;
}
/* Skip leading two bytes length field. Older openssl's DTLS implementation seems not to have this field.
* See implementation note in RFC 4346 section 7.4.7.1
*/
if (ssl->cipher_suite.kex==KEX_RSA && ssl->version_netorder != DTLSV1DOT0_VERSION_NOT) {
encrlen = tvb_get_ntohs(tvb, offset);
skip = 2;
if (encrlen > length - 2) {
ssl_debug_printf("dissect_dtls_handshake wrong encrypted length (%d max %d)\n", encrlen, length);
break;
}
}
encrypted_pre_master.data = (guchar *)wmem_alloc(wmem_file_scope(), encrlen);
encrypted_pre_master.data_len = encrlen;
tvb_memcpy(tvb, encrypted_pre_master.data, offset+skip, encrlen);
if (!ssl->private_key) {
ssl_debug_printf("dissect_dtls_handshake can't find private key\n");
break;
}
/* go with ssl key processing; encrypted_pre_master
* will be used for master secret store*/
ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key);
if (ret < 0) {
ssl_debug_printf("dissect_dtls_handshake can't decrypt pre master secret\n");
break;
}
if (ssl_generate_keyring_material(ssl)<0) {
}
if (ssl_generate_keyring_material(ssl) < 0) {
ssl_debug_printf("dissect_dtls_handshake can't generate keyring material\n");
break;
}
ssl->state |= SSL_HAVE_SESSION_KEY;
ssl_save_session(ssl, dtls_session_hash);
ssl_debug_printf("dissect_dtls_handshake session keys successfully generated\n");
}
ssl_save_session(ssl, dtls_session_hash);
ssl_debug_printf("dissect_dtls_handshake session keys successfully generated\n");
break;
case SSL_HND_FINISHED:
@ -1798,7 +1760,7 @@ dissect_dtls_hnd_hello_ext(tvbuff_t *tvb,
}
static void
dissect_dtls_hnd_cli_hello(tvbuff_t *tvb,
dissect_dtls_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset, guint32 length,
SslDecryptSession*ssl)
{
@ -1822,6 +1784,11 @@ dissect_dtls_hnd_cli_hello(tvbuff_t *tvb,
guint16 start_offset = offset;
guint8 cookie_length;
if (ssl) {
ssl_set_server(ssl, &pinfo->dst, pinfo->ptype, pinfo->destport);
ssl_find_private_key(ssl, dtls_key_hash, dtls_associations, pinfo);
}
if (tree || ssl)
{
/* show the client version */
@ -3527,6 +3494,9 @@ proto_register_dtls(void)
"Used by versions of Wireshark prior to 1.6",
&dtls_keys_list);
prefs_register_string_preference(dtls_module, "psk", "Pre-Shared-Key",
"Pre-Shared-Key as HEX string, should be 0 to 16 bytes",
&dtls_psk);
}
#endif

View File

@ -2,6 +2,8 @@
* ssl manipulation functions
* By Paolo Abeni <paolo.abeni@email.com>
*
* Copyright (c) 2013, Hauke Mehrtens <hauke@hauke-m.de>
*
* $Id$
*
* Wireshark - Network traffic analyzer
@ -1513,7 +1515,7 @@ static gint
ssl_cipher_init(gcry_cipher_hd_t *cipher, gint algo, guchar* sk,
guchar* iv, gint mode)
{
gint gcry_modes[]={GCRY_CIPHER_MODE_STREAM,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_MODE_CTR};
gint gcry_modes[]={GCRY_CIPHER_MODE_STREAM,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_MODE_CTR,GCRY_CIPHER_MODE_CTR,GCRY_CIPHER_MODE_CTR};
gint err;
if (algo == -1) {
/* NULL mode */
@ -1753,6 +1755,7 @@ static const SslDigestAlgo digests[]={
{"SHA1", 20},
{"SHA256", 32},
{"SHA384", 48},
{"Not Applicable", 0},
};
/* get index digest index */
@ -1921,6 +1924,18 @@ static SslCipherSuite cipher_suites[]={
{49200,KEX_DH,SIG_RSA,ENC_AES256,4,256,256,DIG_SHA384, SSL_CIPHER_MODE_GCM}, /* TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 */
{49201,KEX_DH,SIG_RSA,ENC_AES,4,128,128,DIG_SHA256, SSL_CIPHER_MODE_GCM}, /* TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 */
{49202,KEX_DH,SIG_RSA,ENC_AES256,4,256,256,DIG_SHA384, SSL_CIPHER_MODE_GCM}, /* TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 */
{0xC09C,KEX_RSA,SIG_RSA,ENC_AES,4,128,128,DIG_NA, SSL_CIPHER_MODE_CCM}, /* TLS_RSA_WITH_AES_128_CCM */
{0xC09D,KEX_RSA,SIG_RSA,ENC_AES256,4,256,256,DIG_NA, SSL_CIPHER_MODE_CCM}, /* TLS_RSA_WITH_AES_256_CCM */
{0xC09E,KEX_DH,SIG_RSA,ENC_AES,4,128,128,DIG_NA, SSL_CIPHER_MODE_CCM}, /* TLS_DHE_RSA_WITH_AES_128_CCM */
{0xC09F,KEX_DH,SIG_RSA,ENC_AES256,4,256,256,DIG_NA, SSL_CIPHER_MODE_CCM}, /* TLS_DHE_RSA_WITH_AES_256_CCM */
{0xC0A0,KEX_RSA,SIG_RSA,ENC_AES,4,128,128,DIG_NA, SSL_CIPHER_MODE_CCM_8}, /* TLS_RSA_WITH_AES_128_CCM_8 */
{0xC0A1,KEX_RSA,SIG_RSA,ENC_AES256,4,256,256,DIG_NA, SSL_CIPHER_MODE_CCM_8}, /* TLS_RSA_WITH_AES_256_CCM_8 */
{0xC0A2,KEX_DH,SIG_RSA,ENC_AES,4,128,128,DIG_NA, SSL_CIPHER_MODE_CCM_8}, /* TLS_DHE_RSA_WITH_AES_128_CCM_8 */
{0xC0A3,KEX_DH,SIG_RSA,ENC_AES256,4,256,256,DIG_NA, SSL_CIPHER_MODE_CCM_8}, /* TLS_DHE_RSA_WITH_AES_256_CCM_8 */
{0xC0A4,KEX_PSK,SIG_NONE,ENC_AES,4,128,128,DIG_NA, SSL_CIPHER_MODE_CCM}, /* TLS_PSK_WITH_AES_128_CCM */
{0xC0A5,KEX_PSK,SIG_NONE,ENC_AES256,4,256,256,DIG_NA, SSL_CIPHER_MODE_CCM}, /* TLS_PSK_WITH_AES_256_CCM */
{0xC0A8,KEX_PSK,SIG_NONE,ENC_AES,4,128,128,DIG_NA, SSL_CIPHER_MODE_CCM_8}, /* TLS_PSK_WITH_AES_128_CCM_8 */
{0xC0A9,KEX_PSK,SIG_NONE,ENC_AES256,4,256,256,DIG_NA, SSL_CIPHER_MODE_CCM_8}, /* TLS_PSK_WITH_AES_256_CCM_8 */
{-1, 0,0,0,0,0,0,0, 0}
};
@ -2286,6 +2301,135 @@ ssl_create_decoder(SslCipherSuite *cipher_suite, gint compression,
return dec;
}
int
ssl_generate_pre_master_secret(SslDecryptSession *ssl_session,
guint32 length, tvbuff_t *tvb, guint32 offset,
const gchar *ssl_psk, const gchar *keylog_filename)
{
/* check for required session data */
ssl_debug_printf("ssl_generate_pre_master_secret: found SSL_HND_CLIENT_KEY_EXCHG, state %X\n",
ssl_session->state);
if ((ssl_session->state & (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION)) !=
(SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION)) {
ssl_debug_printf("ssl_generate_pre_master_secret: not enough data to generate key (required state %X)\n",
(SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION));
return -1;
}
if (ssl_session->cipher_suite.kex == KEX_PSK)
{
/* calculate pre master secret*/
StringInfo pre_master_secret;
guint psk_len, pre_master_len;
int size;
unsigned char *out;
int i,j = 0;
char input[2];
if (!ssl_psk || (ssl_psk[0] == 0)) {
ssl_debug_printf("ssl_generate_pre_master_secret: can't find pre-shared-key\n");
return -1;
}
size = (int)strlen(ssl_psk);
/* The length of PSK ranges from 0..2^16-1 octets (times two for hex string) */
if (size < 0 || size % 2 != 0 || size >= (2 << 16))
{
ssl_debug_printf("ssl_generate_pre_master_secret: length of ssl.psk must be multiple of two");
return -1;
}
/* convert hex string into char*/
out = (unsigned char*) wmem_alloc(wmem_packet_scope(), size / 2);
for (i = 0; i < size; i+=2)
{
input[0] = ssl_psk[0 + i];
input[1] = ssl_psk[1 + i];
out[j++] = (unsigned int) strtoul((const char*)&input, NULL, 16);
}
ssl_session->psk = (guchar*) out;
psk_len = size / 2;
pre_master_len = psk_len * 2 + 4;
pre_master_secret.data = (guchar *)wmem_alloc(wmem_file_scope(), pre_master_len);
pre_master_secret.data_len = pre_master_len;
/* 2 bytes psk_len*/
pre_master_secret.data[0] = psk_len >> 8;
pre_master_secret.data[1] = psk_len & 0xFF;
/* psk_len bytes times 0*/
memset(&pre_master_secret.data[2], 0, psk_len);
/* 2 bytes psk_len*/
pre_master_secret.data[psk_len + 2] = psk_len >> 8;
pre_master_secret.data[psk_len + 3] = psk_len & 0xFF;
/* psk*/
memcpy(&pre_master_secret.data[psk_len + 4], ssl_session->psk, psk_len);
ssl_session->pre_master_secret.data = pre_master_secret.data;
ssl_session->pre_master_secret.data_len = pre_master_len;
/*ssl_debug_printf("pre master secret",&ssl->pre_master_secret);*/
/* Remove the master secret if it was there.
This forces keying material regeneration in
case we're renegotiating */
ssl_session->state &= ~(SSL_MASTER_SECRET|SSL_HAVE_SESSION_KEY);
ssl_session->state |= SSL_PRE_MASTER_SECRET;
return 0;
}
else
{
StringInfo encrypted_pre_master;
gint ret;
guint encrlen, skip;
encrlen = length;
skip = 0;
/* get encrypted data, on tls1 we have to skip two bytes
* (it's the encrypted len and should be equal to record len - 2)
* in case of rsa1024 that would be 128 + 2 = 130; for psk not necessary
*/
if (ssl_session->cipher_suite.kex == KEX_RSA &&
(ssl_session->version == SSL_VER_TLS || ssl_session->version == SSL_VER_TLSv1DOT1 ||
ssl_session->version == SSL_VER_TLSv1DOT2 || ssl_session->version == SSL_VER_DTLS ||
ssl_session->version == SSL_VER_DTLS1DOT2))
{
encrlen = tvb_get_ntohs(tvb, offset);
skip = 2;
if (encrlen > length - 2)
{
ssl_debug_printf("ssl_generate_pre_master_secret: wrong encrypted length (%d max %d)\n",
encrlen, length);
return -1;
}
}
encrypted_pre_master.data = (guchar *)wmem_alloc(wmem_file_scope(), encrlen);
encrypted_pre_master.data_len = encrlen;
tvb_memcpy(tvb, encrypted_pre_master.data, offset+skip, encrlen);
if (ssl_session->private_key) {
/* go with ssl key processessing; encrypted_pre_master
* will be used for master secret store*/
ret = ssl_decrypt_pre_master_secret(ssl_session, &encrypted_pre_master, ssl_session->private_key);
if (ret < 0) {
ssl_debug_printf("ssl_generate_pre_master_secret: can't decrypt pre master secret\n");
return -1;
}
return 0;
} else if (keylog_filename != NULL) {
/* try to find the key in the key log */
if (ssl_keylog_lookup(ssl_session, keylog_filename, &encrypted_pre_master) < 0) {
return -1;
}
return 0;
}
}
return -1;
}
int
ssl_generate_keyring_material(SslDecryptSession*ssl_session)
{
@ -2343,7 +2487,9 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session)
ptr=key_block.data;
/* AEAD ciphers do not have a separate MAC */
if (ssl_session->cipher_suite.mode == SSL_CIPHER_MODE_GCM) {
if (ssl_session->cipher_suite.mode == SSL_CIPHER_MODE_GCM ||
ssl_session->cipher_suite.mode == SSL_CIPHER_MODE_CCM ||
ssl_session->cipher_suite.mode == SSL_CIPHER_MODE_CCM_8) {
c_mk = s_mk = NULL;
} else {
c_mk=ptr; ptr+=ssl_cipher_suite_dig(&ssl_session->cipher_suite)->len;
@ -2844,7 +2990,9 @@ ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct,
}
/* Nonce for GenericAEADCipher */
if (decoder->cipher_suite->mode == SSL_CIPHER_MODE_GCM) {
if (decoder->cipher_suite->mode == SSL_CIPHER_MODE_GCM ||
decoder->cipher_suite->mode == SSL_CIPHER_MODE_CCM ||
decoder->cipher_suite->mode == SSL_CIPHER_MODE_CCM_8) {
/* 4 bytes write_iv, 8 bytes explicit_nonce, 4 bytes counter */
guchar gcm_nonce[16] = { 0 };
@ -2853,11 +3001,25 @@ ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct,
inl, SSL_EX_NONCE_LEN_GCM);
return -1;
}
memcpy(gcm_nonce, decoder->write_iv.data, decoder->write_iv.data_len); /* salt */
memcpy(gcm_nonce + decoder->write_iv.data_len, in, SSL_EX_NONCE_LEN_GCM);
/* NIST SP 800-38D, sect. 7.2 says that the 32-bit counter part starts
* at 1, and gets incremented before passing to the block cipher. */
gcm_nonce[4 + SSL_EX_NONCE_LEN_GCM + 3] = 2;
if (decoder->cipher_suite->mode == SSL_CIPHER_MODE_GCM) {
memcpy(gcm_nonce, decoder->write_iv.data, decoder->write_iv.data_len); /* salt */
memcpy(gcm_nonce + decoder->write_iv.data_len, in, SSL_EX_NONCE_LEN_GCM);
/* NIST SP 800-38D, sect. 7.2 says that the 32-bit counter part starts
* at 1, and gets incremented before passing to the block cipher. */
gcm_nonce[4 + SSL_EX_NONCE_LEN_GCM + 3] = 2;
} else { /* SSL_CIPHER_MODE_CCM and SSL_CIPHER_MODE_CCM_8 */
/* The nonce for CCM and GCM are the same, but the nonce is used as input
* in the CCM algorithm described in RFC 3610. The nonce generated here is
* the one from RFC 3610 sect 2.3. Encryption. */
/* Flags: (L-1) ; L = 16 - 1 - nonceSize */
gcm_nonce[0] = 3 - 1;
memcpy(gcm_nonce + 1, decoder->write_iv.data, decoder->write_iv.data_len); /* salt */
memcpy(gcm_nonce + 1 + decoder->write_iv.data_len, in, SSL_EX_NONCE_LEN_GCM);
gcm_nonce[4 + SSL_EX_NONCE_LEN_GCM + 3] = 1;
}
pad = gcry_cipher_setctr (decoder->evp, gcm_nonce, sizeof (gcm_nonce));
if (pad != 0) {
ssl_debug_printf("ssl_decrypt_record failed: failed to set CTR: %s %s\n",
@ -2878,8 +3040,10 @@ ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct,
ssl_print_data("Plaintext", out_str->data, inl);
worklen=inl;
/* RFC 5116 sect 5.1/5.3: AES128/256 GCM/CCM uses 16 bytes for auth tag */
if (decoder->cipher_suite->mode == SSL_CIPHER_MODE_GCM) {
/* RFC 5116 sect 5.1/5.3: AES128/256 GCM/CCM uses 16 bytes for auth tag
* RFC 6655 sect 6.1: AEAD_AES_128_CCM uses 16 bytes for auth tag */
if (decoder->cipher_suite->mode == SSL_CIPHER_MODE_GCM ||
decoder->cipher_suite->mode == SSL_CIPHER_MODE_CCM) {
if (worklen < 16) {
ssl_debug_printf("ssl_decrypt_record failed: missing tag, work %d\n", worklen);
return -1;
@ -2887,6 +3051,15 @@ ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct,
/* XXX - validate auth tag */
worklen -= 16;
}
/* RFC 6655 sect 6.1: AEAD_AES_128_CCM_8 uses 8 bytes for auth tag */
if (decoder->cipher_suite->mode == SSL_CIPHER_MODE_CCM_8) {
if (worklen < 8) {
ssl_debug_printf("ssl_decrypt_record failed: missing tag, work %d\n", worklen);
return -1;
}
/* XXX - validate auth tag */
worklen -= 8;
}
/* strip padding for GenericBlockCipher */
if (decoder->cipher_suite->mode == SSL_CIPHER_MODE_CBC) {

View File

@ -233,6 +233,8 @@ typedef struct _StringInfo {
#define SSL_CIPHER_MODE_STREAM 0 /* GenericStreamCipher */
#define SSL_CIPHER_MODE_CBC 1 /* GenericBlockCipher */
#define SSL_CIPHER_MODE_GCM 2 /* GenericAEADCipher */
#define SSL_CIPHER_MODE_CCM 3 /* AEAD_AES_{128,256}_CCM with 16 byte auth tag */
#define SSL_CIPHER_MODE_CCM_8 4 /* AEAD_AES_{128,256}_CCM with 8 byte auth tag */
/* Explicit nonce length */
#define SSL_EX_NONCE_LEN_GCM 8 /* RFC 5288 - section 3 */
@ -300,6 +302,7 @@ typedef struct _SslDecoder {
#define DIG_SHA 0x41
#define DIG_SHA256 0x42
#define DIG_SHA384 0x43
#define DIG_NA 0x44 /* Not Applicable */
typedef struct {
const gchar *name;
@ -447,6 +450,11 @@ ssl_find_private_key(SslDecryptSession *ssl_session, GHashTable *key_hash, GTree
extern gint
ssl_find_cipher(int num,SslCipherSuite* cs);
int
ssl_generate_pre_master_secret(SslDecryptSession *ssl_session,
guint32 length, tvbuff_t *tvb, guint32 offset,
const gchar *ssl_psk, const gchar *keylog_filename);
/** Expand the pre_master_secret to generate all the session information
* (master secret, session keys, ivs)
@param ssl_session the store for all the session data

View File

@ -2161,128 +2161,23 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
default:
break;
}
{
/* PAOLO: here we can have all the data to build session key*/
/* PAOLO: here we can have all the data to build session key*/
gint cipher_num;
if (!ssl)
break;
if (!ssl)
break;
cipher_num = ssl->cipher;
if (cipher_num == 0x8a || cipher_num == 0x8b || cipher_num == 0x8c || cipher_num == 0x8d)
{
/* calculate pre master secret*/
StringInfo pre_master_secret;
guint psk_len, pre_master_len;
int size;
unsigned char *out;
int i,j = 0;
char input[2];
if (!ssl_psk || (ssl_psk[0] == 0)) {
ssl_debug_printf("dissect_ssl3_handshake can't find pre-shared-key\n");
break;
}
size = (int)strlen(ssl_psk);
/* The length of PSK ranges from 0..2^16-1 octets (times two for hex string) */
if (size < 0 || size % 2 != 0 || size >= (2 << 16))
{
ssl_debug_printf("dissect_ssl3_handshake: length of ssl.psk must be multiple of two");
break;
}
/* convert hex string into char*/
out = (unsigned char*) wmem_alloc(wmem_packet_scope(), size / 2);
for (i = 0; i < size; i+=2)
{
input[0] = ssl_psk[0 + i];
input[1] = ssl_psk[1 + i];
out[j++] = (unsigned int) strtoul((const char*)&input, NULL, 16);
}
ssl->psk = (guchar*) out;
psk_len = size / 2;
pre_master_len = psk_len * 2 + 4;
pre_master_secret.data = (guchar *)wmem_alloc(wmem_file_scope(), pre_master_len);
pre_master_secret.data_len = pre_master_len;
/* 2 bytes psk_len*/
pre_master_secret.data[0] = psk_len >> 8;
pre_master_secret.data[1] = psk_len & 0xFF;
/* psk_len bytes times 0*/
memset(&pre_master_secret.data[2], 0, psk_len);
/* 2 bytes psk_len*/
pre_master_secret.data[psk_len + 2] = psk_len >> 8;
pre_master_secret.data[psk_len + 3] = psk_len & 0xFF;
/* psk*/
memcpy(&pre_master_secret.data[psk_len + 4], ssl->psk, psk_len);
ssl->pre_master_secret.data = pre_master_secret.data;
ssl->pre_master_secret.data_len = pre_master_len;
/*ssl_debug_printf("pre master secret",&ssl->pre_master_secret);*/
/* Remove the master secret if it was there.
This forces keying material regeneration in
case we're renegotiating */
ssl->state &= ~(SSL_MASTER_SECRET|SSL_HAVE_SESSION_KEY);
ssl->state |= SSL_PRE_MASTER_SECRET;
}
else
{
StringInfo encrypted_pre_master;
gint ret;
guint encrlen, skip;
encrlen = length;
skip = 0;
/* get encrypted data, on tls1 we have to skip two bytes
* (it's the encrypted len and should be equal to record len - 2)
* in case of rsa1024 that would be 128 + 2 = 130; for psk not necessary
*/
if (ssl->cipher_suite.kex==KEX_RSA && (ssl->version == SSL_VER_TLS||ssl->version == SSL_VER_TLSv1DOT1||ssl->version == SSL_VER_TLSv1DOT2))
{
encrlen = tvb_get_ntohs(tvb, offset);
skip = 2;
if (encrlen > length - 2)
{
ssl_debug_printf("dissect_ssl3_handshake wrong encrypted length (%d max %d)\n",
encrlen, length);
break;
}
}
encrypted_pre_master.data = (guchar *)wmem_alloc(wmem_file_scope(), encrlen);
encrypted_pre_master.data_len = encrlen;
tvb_memcpy(tvb, encrypted_pre_master.data, offset+skip, encrlen);
if (ssl->private_key) {
/* go with ssl key processessing; encrypted_pre_master
* will be used for master secret store*/
ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key);
if (ret < 0) {
ssl_debug_printf("dissect_ssl3_handshake can't decrypt pre master secret\n");
break;
}
} else {
/* try to find the key in the key log */
if (ssl_keylog_lookup(ssl, ssl_keylog_filename, &encrypted_pre_master)<0)
break;
}
}
if (ssl_generate_keyring_material(ssl)<0) {
ssl_debug_printf("dissect_ssl3_handshake can't generate keyring material\n");
break;
}
ssl_save_session(ssl, ssl_session_hash);
ssl_debug_printf("dissect_ssl3_handshake session keys successfully generated\n");
if (ssl_generate_pre_master_secret(ssl, length, tvb, offset, ssl_psk, ssl_keylog_filename) < 0) {
ssl_debug_printf("dissect_ssl3_handshake can't generate pre master secret\n");
break;
}
if (ssl_generate_keyring_material(ssl) < 0) {
ssl_debug_printf("dissect_ssl3_handshake can't generate keyring material\n");
break;
}
ssl_save_session(ssl, ssl_session_hash);
ssl_debug_printf("dissect_ssl3_handshake session keys successfully generated\n");
break;
case SSL_HND_FINISHED: