diff options
-rw-r--r-- | epan/dissectors/packet-ssl-utils.c | 134 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl-utils.h | 11 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl.c | 5 |
3 files changed, 80 insertions, 70 deletions
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c index 3c63c167bf..8b91397e02 100644 --- a/epan/dissectors/packet-ssl-utils.c +++ b/epan/dissectors/packet-ssl-utils.c @@ -1982,7 +1982,7 @@ static const SslDigestAlgo digests[]={ /* get index digest index */ static const SslDigestAlgo * -ssl_cipher_suite_dig(SslCipherSuite *cs) { +ssl_cipher_suite_dig(const SslCipherSuite *cs) { return &digests[cs->dig - DIG_MD5]; } @@ -2000,7 +2000,7 @@ static const gchar *ciphers[]={ "*UNKNOWN*" }; -static SslCipherSuite cipher_suites[]={ +static const SslCipherSuite cipher_suites[]={ {0x0001,KEX_RSA, ENC_NULL, 1, 0, 0,DIG_MD5, MODE_STREAM}, /* TLS_RSA_WITH_NULL_MD5 */ {0x0002,KEX_RSA, ENC_NULL, 1, 0, 0,DIG_SHA, MODE_STREAM}, /* TLS_RSA_WITH_NULL_SHA */ {0x0003,KEX_RSA, ENC_RC4, 1,128, 40,DIG_MD5, MODE_STREAM}, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */ @@ -2253,27 +2253,25 @@ static SslCipherSuite cipher_suites[]={ #define MAX_BLOCK_SIZE 16 #define MAX_KEY_SIZE 32 -int -ssl_find_cipher(int num,SslCipherSuite* cs) +const SslCipherSuite * +ssl_find_cipher(int num) { - SslCipherSuite *c; - + const SslCipherSuite *c; for(c=cipher_suites;c->number!=-1;c++){ if(c->number==num){ - *cs=*c; - return 0; + return c; } } - return -1; + return NULL; } #else /* ! HAVE_LIBGCRYPT */ -int -ssl_find_cipher(int num,SslCipherSuite* cs) +const SslCipherSuite * +ssl_find_cipher(int num) { ssl_debug_printf("ssl_find_cipher: dummy without gnutls. num %d cs %p\n", num,cs); - return 0; + return NULL; } #endif /* ! HAVE_LIBGCRYPT */ @@ -2510,7 +2508,8 @@ ssl3_prf(StringInfo* secret, const gchar* usage, return TRUE; } -/* out_len is the wanted output length for the pseudorandom function */ +/* out_len is the wanted output length for the pseudorandom function. + * Ensure that ssl->cipher_suite is set. */ static gboolean prf(SslDecryptSession *ssl, StringInfo *secret, const gchar *usage, StringInfo *rnd1, StringInfo *rnd2, StringInfo *out, guint out_len) @@ -2526,7 +2525,7 @@ prf(SslDecryptSession *ssl, StringInfo *secret, const gchar *usage, return tls_prf(secret, usage, rnd1, rnd2, out, out_len); default: /* TLSv1.2 */ - switch (ssl->cipher_suite.dig) { + switch (ssl->cipher_suite->dig) { case DIG_SHA384: return tls12_prf(GCRY_MD_SHA384, secret, usage, rnd1, rnd2, out, out_len); @@ -2590,7 +2589,9 @@ ssl_generate_keyring_material(SslDecryptSession*ssl) { ssl_debug_printf("ssl_generate_keyring_material: impossible without gnutls. ssl %p\n", ssl); - return 0; + /* We cannot determine whether the cipher suite is valid. Fail such that + * ssl_set_master_secret bails out. */ + return -1; } void ssl_change_cipher(SslDecryptSession *ssl_session, gboolean server) @@ -2740,7 +2741,7 @@ ssl_change_cipher(SslDecryptSession *ssl_session, gboolean server) /* Init cipher state given some security parameters. {{{ */ static SslDecoder* -ssl_create_decoder(SslCipherSuite *cipher_suite, gint compression, +ssl_create_decoder(const SslCipherSuite *cipher_suite, gint compression, guint8 *mk, guint8 *sk, guint8 *iv) { SslDecoder *dec; @@ -2781,6 +2782,7 @@ ssl_create_decoder(SslCipherSuite *cipher_suite, gint compression, dec->decomp = ssl_create_decompressor(compression); dec->flow = ssl_create_flow(); + /* TODO this does nothing as dec->evp is always NULL. */ if (dec->evp) ssl_cipher_cleanup(&dec->evp); @@ -2829,7 +2831,7 @@ ssl_generate_pre_master_secret(SslDecryptSession *ssl_session, return TRUE; } - if (ssl_session->cipher_suite.kex == KEX_PSK) + if (ssl_session->cipher_suite->kex == KEX_PSK) { /* calculate pre master secret*/ StringInfo pre_master_secret; @@ -2892,7 +2894,7 @@ ssl_generate_pre_master_secret(SslDecryptSession *ssl_session, * (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 && + if (ssl_session->cipher_suite->kex == KEX_RSA && (ssl_session->session.version == TLSV1_VERSION || ssl_session->session.version == TLSV1DOT1_VERSION || ssl_session->session.version == TLSV1DOT2_VERSION || @@ -2951,6 +2953,7 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) gint needed; guint8 *ptr, *c_iv = _iv_c,*s_iv = _iv_s; guint8 *c_wk = NULL, *s_wk = NULL, *c_mk = NULL, *s_mk = NULL; + const SslCipherSuite *cipher_suite = ssl_session->cipher_suite; /* check for enough info to proced */ guint need_all = SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION; @@ -2963,7 +2966,7 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) * the Client Hello is missing (MAC keys are now skipped though). */ need_all = SSL_CIPHER|SSL_VERSION; if ((ssl_session->state & need_all) == need_all && - ssl_session->cipher_suite.enc == ENC_NULL) { + cipher_suite->enc == ENC_NULL) { ssl_debug_printf("%s NULL cipher found, will create a decoder but " "skip MAC validation as keys are missing.\n", G_STRFUNC); goto create_decoders; @@ -2993,7 +2996,7 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) ret = tls_handshake_hash(ssl_session, &handshake_hashed_data); break; default: - switch (ssl_session->cipher_suite.dig) { + switch (cipher_suite->dig) { case DIG_SHA384: ret = tls12_handshake_hash(ssl_session, GCRY_MD_SHA384, &handshake_hashed_data); break; @@ -3042,10 +3045,10 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) } /* Compute the key block. First figure out how much data we need*/ - needed=ssl_cipher_suite_dig(&ssl_session->cipher_suite)->len*2; - needed+=ssl_session->cipher_suite.bits / 4; - if(ssl_session->cipher_suite.block>1) - needed+=ssl_session->cipher_suite.block*2; + needed=ssl_cipher_suite_dig(cipher_suite)->len*2; + needed+=cipher_suite->bits / 4; + if(cipher_suite->block>1) + needed+=cipher_suite->block*2; key_block.data = (guchar *)g_malloc(needed); ssl_debug_printf("%s sess key generation\n", G_STRFUNC); @@ -3059,32 +3062,32 @@ 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 == MODE_GCM || - ssl_session->cipher_suite.mode == MODE_CCM || - ssl_session->cipher_suite.mode == MODE_CCM_8) { + if (cipher_suite->mode == MODE_GCM || + cipher_suite->mode == MODE_CCM || + cipher_suite->mode == MODE_CCM_8) { c_mk = s_mk = NULL; } else { - c_mk=ptr; ptr+=ssl_cipher_suite_dig(&ssl_session->cipher_suite)->len; - s_mk=ptr; ptr+=ssl_cipher_suite_dig(&ssl_session->cipher_suite)->len; + c_mk=ptr; ptr+=ssl_cipher_suite_dig(cipher_suite)->len; + s_mk=ptr; ptr+=ssl_cipher_suite_dig(cipher_suite)->len; } - c_wk=ptr; ptr+=ssl_session->cipher_suite.eff_bits/8; - s_wk=ptr; ptr+=ssl_session->cipher_suite.eff_bits/8; + c_wk=ptr; ptr+=cipher_suite->eff_bits/8; + s_wk=ptr; ptr+=cipher_suite->eff_bits/8; - if(ssl_session->cipher_suite.block>1){ - c_iv=ptr; ptr+=ssl_session->cipher_suite.block; - s_iv=ptr; /*ptr+=ssl_session->cipher_suite.block;*/ + if(cipher_suite->block>1){ + c_iv=ptr; ptr+=cipher_suite->block; + s_iv=ptr; /*ptr+=cipher_suite->block;*/ } /* export ciphers work with a smaller key length */ - if (ssl_session->cipher_suite.eff_bits < ssl_session->cipher_suite.bits) { - if(ssl_session->cipher_suite.block>1){ + if (cipher_suite->eff_bits < cipher_suite->bits) { + if(cipher_suite->block>1){ /* We only have room for MAX_BLOCK_SIZE bytes IVs, but that's all we should need. This is a sanity check */ - if(ssl_session->cipher_suite.block>MAX_BLOCK_SIZE) { + if(cipher_suite->block>MAX_BLOCK_SIZE) { ssl_debug_printf("%s cipher suite block must be at most %d nut is %d\n", - G_STRFUNC, MAX_BLOCK_SIZE, ssl_session->cipher_suite.block); + G_STRFUNC, MAX_BLOCK_SIZE, cipher_suite->block); goto fail; } @@ -3097,11 +3100,11 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) ssl_debug_printf("%s ssl3_generate_export_iv\n", G_STRFUNC); ssl3_generate_export_iv(&ssl_session->client_random, &ssl_session->server_random, &iv_c, - ssl_session->cipher_suite.block); + cipher_suite->block); ssl_debug_printf("%s ssl3_generate_export_iv(2)\n", G_STRFUNC); ssl3_generate_export_iv(&ssl_session->server_random, &ssl_session->client_random, &iv_s, - ssl_session->cipher_suite.block); + cipher_suite->block); } else{ guint8 _iv_block[MAX_BLOCK_SIZE * 2]; @@ -3118,14 +3121,14 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) if (!prf(ssl_session, &key_null, "IV block", &ssl_session->client_random, &ssl_session->server_random, &iv_block, - ssl_session->cipher_suite.block * 2)) { + cipher_suite->block * 2)) { ssl_debug_printf("%s can't generate tls31 iv block\n", G_STRFUNC); goto fail; } - memcpy(_iv_c,iv_block.data,ssl_session->cipher_suite.block); - memcpy(_iv_s,iv_block.data+ssl_session->cipher_suite.block, - ssl_session->cipher_suite.block); + memcpy(_iv_c,iv_block.data,cipher_suite->block); + memcpy(_iv_s,iv_block.data+cipher_suite->block, + cipher_suite->block); } c_iv=_iv_c; @@ -3138,7 +3141,7 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) ssl_debug_printf("%s MD5(client_random)\n", G_STRFUNC); ssl_md5_init(&md5); - ssl_md5_update(&md5,c_wk,ssl_session->cipher_suite.eff_bits/8); + ssl_md5_update(&md5,c_wk,cipher_suite->eff_bits/8); ssl_md5_update(&md5,ssl_session->client_random.data, ssl_session->client_random.data_len); ssl_md5_update(&md5,ssl_session->server_random.data, @@ -3149,7 +3152,7 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) ssl_md5_init(&md5); ssl_debug_printf("%s MD5(server_random)\n", G_STRFUNC); - ssl_md5_update(&md5,s_wk,ssl_session->cipher_suite.eff_bits/8); + ssl_md5_update(&md5,s_wk,cipher_suite->eff_bits/8); ssl_md5_update(&md5,ssl_session->server_random.data, ssl_session->server_random.data_len); ssl_md5_update(&md5,ssl_session->client_random.data, @@ -3164,7 +3167,7 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) key_s.data = _key_s; k.data = c_wk; - k.data_len = ssl_session->cipher_suite.eff_bits/8; + k.data_len = cipher_suite->eff_bits/8; ssl_debug_printf("%s PRF(key_c)\n", G_STRFUNC); if (!prf(ssl_session, &k, "client write key", &ssl_session->client_random, @@ -3175,7 +3178,7 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) c_wk=_key_c; k.data = s_wk; - k.data_len = ssl_session->cipher_suite.eff_bits/8; + k.data_len = cipher_suite->eff_bits/8; ssl_debug_printf("%s PRF(key_s)\n", G_STRFUNC); if (!prf(ssl_session, &k, "server write key", &ssl_session->client_random, @@ -3189,15 +3192,15 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) /* show key material info */ if (c_mk != NULL) { - ssl_print_data("Client MAC key",c_mk,ssl_cipher_suite_dig(&ssl_session->cipher_suite)->len); - ssl_print_data("Server MAC key",s_mk,ssl_cipher_suite_dig(&ssl_session->cipher_suite)->len); + ssl_print_data("Client MAC key",c_mk,ssl_cipher_suite_dig(cipher_suite)->len); + ssl_print_data("Server MAC key",s_mk,ssl_cipher_suite_dig(cipher_suite)->len); } - ssl_print_data("Client Write key",c_wk,ssl_session->cipher_suite.bits/8); - ssl_print_data("Server Write key",s_wk,ssl_session->cipher_suite.bits/8); + ssl_print_data("Client Write key",c_wk,cipher_suite->bits/8); + ssl_print_data("Server Write key",s_wk,cipher_suite->bits/8); - if(ssl_session->cipher_suite.block>1) { - ssl_print_data("Client Write IV",c_iv,ssl_session->cipher_suite.block); - ssl_print_data("Server Write IV",s_iv,ssl_session->cipher_suite.block); + if(cipher_suite->block>1) { + ssl_print_data("Client Write IV",c_iv,cipher_suite->block); + ssl_print_data("Server Write IV",s_iv,cipher_suite->block); } else { ssl_print_data("Client Write IV",c_iv,8); @@ -3207,13 +3210,13 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session) create_decoders: /* create both client and server ciphers*/ ssl_debug_printf("%s ssl_create_decoder(client)\n", G_STRFUNC); - ssl_session->client_new = ssl_create_decoder(&ssl_session->cipher_suite, ssl_session->session.compression, c_mk, c_wk, c_iv); + ssl_session->client_new = ssl_create_decoder(cipher_suite, ssl_session->session.compression, c_mk, c_wk, c_iv); if (!ssl_session->client_new) { ssl_debug_printf("%s can't init client decoder\n", G_STRFUNC); goto fail; } ssl_debug_printf("%s ssl_create_decoder(server)\n", G_STRFUNC); - ssl_session->server_new = ssl_create_decoder(&ssl_session->cipher_suite, ssl_session->session.compression, s_mk, s_wk, s_iv); + ssl_session->server_new = ssl_create_decoder(cipher_suite, ssl_session->session.compression, s_mk, s_wk, s_iv); if (!ssl_session->server_new) { ssl_debug_printf("%s can't init client decoder\n", G_STRFUNC); goto fail; @@ -3242,7 +3245,7 @@ ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session, if (!encrypted_pre_master) return FALSE; - if (KEX_IS_DH(ssl_session->cipher_suite.kex)) { + if (KEX_IS_DH(ssl_session->cipher_suite->kex)) { ssl_debug_printf("%s: session uses Diffie-Hellman key exchange " "(cipher suite 0x%04X %s) and cannot be decrypted " "using a RSA private key file.\n", @@ -3250,9 +3253,9 @@ ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session, val_to_str_ext_const(ssl_session->session.cipher, &ssl_31_ciphersuite_ext, "unknown")); return FALSE; - } else if(ssl_session->cipher_suite.kex != KEX_RSA) { + } else if(ssl_session->cipher_suite->kex != KEX_RSA) { ssl_debug_printf("%s key exchange %d different from KEX_RSA (%d)\n", - G_STRFUNC, ssl_session->cipher_suite.kex, KEX_RSA); + G_STRFUNC, ssl_session->cipher_suite->kex, KEX_RSA); return FALSE; } @@ -3461,6 +3464,8 @@ dtls_check_mac(SslDecoder*decoder, gint ct,int ver, guint8* data, /* Decryption integrity check }}} */ /* Record decryption glue based on security parameters {{{ */ +/* Assume that we are called only for a non-NULL decoder which also means that + * we have a non-NULL decoder->cipher_suite. */ int ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct, const guchar* in, guint inl, StringInfo* comp_str, StringInfo* out_str, guint* outl) @@ -4581,6 +4586,10 @@ ssl_finalize_decryption(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map) ssl_debug_printf(" session key already available, nothing to do.\n"); return; } + if (!(ssl->state & SSL_CIPHER)) { + ssl_debug_printf(" Cipher suite (Server Hello) is missing!\n"); + return; + } /* for decryption, there needs to be a master secret (which can be derived * from pre-master secret). If missing, try to pick a master key from cache @@ -4593,7 +4602,7 @@ ssl_finalize_decryption(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map) mk_map->tickets, &ssl->session_ticket)) && !ssl_restore_master_key(ssl, "Client Random", FALSE, mk_map->crandom, &ssl->client_random)) { - if (ssl->cipher_suite.enc != ENC_NULL) { + if (ssl->cipher_suite->enc != ENC_NULL) { /* how unfortunate, the master secret could not be found */ ssl_debug_printf(" Cannot find master secret\n"); return; @@ -5878,7 +5887,8 @@ ssl_dissect_hnd_srv_hello(ssl_common_dissect_t *hf, tvbuff_t *tvb, /* store selected cipher suite for decryption */ ssl->session.cipher = tvb_get_ntohs(tvb, offset); - if (ssl_find_cipher(ssl->session.cipher, &ssl->cipher_suite) < 0) { + if (!(ssl->cipher_suite = ssl_find_cipher(ssl->session.cipher))) { + ssl->state &= ~SSL_CIPHER; ssl_debug_printf("%s can't find cipher suite 0x%04X\n", G_STRFUNC, ssl->session.cipher); } else { diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h index dd109a2d96..6891ec3db5 100644 --- a/epan/dissectors/packet-ssl-utils.h +++ b/epan/dissectors/packet-ssl-utils.h @@ -270,7 +270,7 @@ typedef struct _SslFlow { typedef struct _SslDecompress SslDecompress; typedef struct _SslDecoder { - SslCipherSuite* cipher_suite; + const SslCipherSuite *cipher_suite; gint compression; guchar _mac_key_or_write_iv[48]; StringInfo mac_key; /* for block and stream ciphers */ @@ -389,7 +389,7 @@ typedef struct _SslDecryptSession { StringInfo client_data_for_iv; gint state; - SslCipherSuite cipher_suite; + const SslCipherSuite *cipher_suite; SslDecoder *server; SslDecoder *client; SslDecoder *server_new; @@ -484,10 +484,9 @@ ssl_cipher_setiv(SSL_CIPHER_CTX *cipher, guchar* iv, gint iv_len); /** Search for the specified cipher suite id @param num the id of the cipher suite to be searched - @param cs pointer to the cipher suite struct to be filled - @return 0 if the cipher suite is found, -1 elsewhere */ -extern gint -ssl_find_cipher(int num,SslCipherSuite* cs); + @return pointer to the cipher suite struct (or NULL if not found). */ +extern const SslCipherSuite * +ssl_find_cipher(int num); gboolean ssl_generate_pre_master_secret(SslDecryptSession *ssl_session, diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c index 4621e16537..04332c4995 100644 --- a/epan/dissectors/packet-ssl.c +++ b/epan/dissectors/packet-ssl.c @@ -3302,7 +3302,8 @@ void ssl_set_master_secret(guint32 frame_num, address *addr_srv, address *addr_c /* cipher */ if (cipher > 0) { ssl->session.cipher = cipher; - if (ssl_find_cipher(ssl->session.cipher,&ssl->cipher_suite) < 0) { + if (!(ssl->cipher_suite = ssl_find_cipher(ssl->session.cipher))) { + ssl->state &= ~SSL_CIPHER; ssl_debug_printf("ssl_set_master_secret can't find cipher suite 0x%X\n", ssl->session.cipher); } else { ssl->state |= SSL_CIPHER; @@ -3352,7 +3353,7 @@ void ssl_set_master_secret(guint32 frame_num, address *addr_srv, address *addr_c } /* update IV from last data */ - iv_len = (ssl->cipher_suite.block>1) ? ssl->cipher_suite.block : 8; + iv_len = (ssl->cipher_suite->block>1) ? ssl->cipher_suite->block : 8; if (ssl->client && ((ssl->client->seq > 0) || (ssl->client_data_for_iv.data_len > iv_len))) { ssl_cipher_setiv(&ssl->client->evp, ssl->client_data_for_iv.data + ssl->client_data_for_iv.data_len - iv_len, iv_len); ssl_print_data("ssl_set_master_secret client IV updated",ssl->client_data_for_iv.data + ssl->client_data_for_iv.data_len - iv_len, iv_len); |