diff options
author | Peter Wu <peter@lekensteyn.nl> | 2018-03-19 21:41:42 +0100 |
---|---|---|
committer | Peter Wu <peter@lekensteyn.nl> | 2018-03-21 18:12:43 +0000 |
commit | eea63ae2a7f41332ae3b7da39513d184662494a2 (patch) | |
tree | 4eb96f418c63c6f8c60c7e85199b1c26d8e3bbce | |
parent | 184b943fbd4c113998419ed377f81aad0e2f43b9 (diff) |
TLS: allow cipher information to be retrieved
In preparation for QUIC packet decryption, add a method to retrieve the
cipher used in a TLS session. (QUIC embeds the TLS handshake.)
Change-Id: If58e16bd0a01808dafa455ddc6c67ad23f33d7da
Reviewed-on: https://code.wireshark.org/review/26558
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
-rw-r--r-- | epan/dissectors/packet-ssl-utils.c | 6 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl-utils.h | 5 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl.c | 69 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl.h | 6 |
4 files changed, 86 insertions, 0 deletions
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c index b75c55b2b5..fe7f255e41 100644 --- a/epan/dissectors/packet-ssl-utils.c +++ b/epan/dissectors/packet-ssl-utils.c @@ -2405,6 +2405,12 @@ ssl_find_cipher(int num) return NULL; } +int +ssl_get_cipher_algo(const SslCipherSuite *cipher_suite) +{ + return gcry_cipher_map_name(ciphers[cipher_suite->enc - 0x30]); +} + guint ssl_get_cipher_blocksize(const SslCipherSuite *cipher_suite) { diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h index 6df90e1563..d861370d7a 100644 --- a/epan/dissectors/packet-ssl-utils.h +++ b/epan/dissectors/packet-ssl-utils.h @@ -591,6 +591,11 @@ ssl_cipher_setiv(SSL_CIPHER_CTX *cipher, guchar* iv, gint iv_len); extern const SslCipherSuite * ssl_find_cipher(int num); + +/** Returns the Libgcrypt cipher identifier or 0 if unavailable. */ +int +ssl_get_cipher_algo(const SslCipherSuite *cipher_suite); + /** Obtains the block size for a CBC block cipher. * @param cipher_suite a cipher suite as returned by ssl_find_cipher(). * @return the block size of a cipher or 0 if unavailable. diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c index fcedd8517c..5b2785472e 100644 --- a/epan/dissectors/packet-ssl.c +++ b/epan/dissectors/packet-ssl.c @@ -95,6 +95,10 @@ /* Whether to provide support for authentication in addition to decryption. */ #define HAVE_LIBGCRYPT_AEAD #endif +#if GCRYPT_VERSION_NUMBER >= 0x010700 /* 1.7.0 */ +/* Whether AEAD_CHACHA20_POLY1305 can be supported. */ +#define HAVE_LIBGCRYPT_CHACHA20_POLY1305 +#endif void proto_register_ssl(void); @@ -3846,6 +3850,71 @@ ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb, const guint32 offset, return ret; } +gboolean +tls_get_cipher_info(packet_info *pinfo, int *cipher_algo, int *cipher_mode, int *hash_algo) +{ + conversation_t *conv = find_conversation_pinfo(pinfo, 0); + if (!conv) { + return FALSE; + } + + void *conv_data = conversation_get_proto_data(conv, proto_ssl); + if (conv_data == NULL) { + return FALSE; + } + + SslDecryptSession *ssl_session = (SslDecryptSession *)conv_data; + const SslCipherSuite *suite = ssl_find_cipher(ssl_session->session.cipher); + if (!suite) { + return FALSE; + } + + /* adapted from ssl_cipher_init in packet-ssl-utils.c */ + static const gint gcry_modes[] = { + GCRY_CIPHER_MODE_STREAM, + GCRY_CIPHER_MODE_CBC, +#ifdef HAVE_LIBGCRYPT_AEAD + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_MODE_CCM, + GCRY_CIPHER_MODE_CCM, +#else + -1, /* Do not bother with fallback support. */ + -1, + -1, +#endif +#ifdef HAVE_LIBGCRYPT_CHACHA20_POLY1305 + GCRY_CIPHER_MODE_POLY1305, +#else + -1, /* AEAD_CHACHA20_POLY1305 is unsupported. */ +#endif + }; + static const int gcry_mds[] = { + GCRY_MD_MD5, + GCRY_MD_SHA1, + GCRY_MD_SHA256, + GCRY_MD_SHA384, + -1, + }; + int mode = gcry_modes[suite->mode]; + int cipher_algo_id = ssl_get_cipher_algo(suite); + int hash_algo_id = gcry_mds[suite->dig-DIG_MD5]; + if (mode == -1 || cipher_algo_id == 0 || hash_algo_id == -1) { + /* Identifiers are unusable, fail. */ + return FALSE; + } + if (cipher_algo) { + *cipher_algo = cipher_algo_id; + } + if (cipher_mode) { + *cipher_mode = mode; + } + if (hash_algo) { + *hash_algo = hash_algo_id; + } + + return TRUE; +} + /* TLS Exporters {{{ */ #if GCRYPT_VERSION_NUMBER >= 0x010600 /* 1.6.0 */ /** diff --git a/epan/dissectors/packet-ssl.h b/epan/dissectors/packet-ssl.h index 71e365f1d1..02334cff55 100644 --- a/epan/dissectors/packet-ssl.h +++ b/epan/dissectors/packet-ssl.h @@ -27,6 +27,12 @@ WS_DLL_PUBLIC void ssl_set_master_secret(guint32 frame_num, address *addr_srv, a guint32 version, gint cipher, const guchar *_master_secret, const guchar *_client_random, const guchar *_server_random, guint32 client_seq, guint32 server_seq); +/** + * Retrieves Libgcrypt identifiers for the current TLS cipher. Only valid after + * the Server Hello has been processed and if the current conversation has TLS. + */ +extern gboolean +tls_get_cipher_info(packet_info *pinfo, int *cipher_algo, int *cipher_mode, int *hash_algo); /** * Computes the TLS 1.3 "TLS-Exporter(label, context_value, key_length)" value. |