From 38366ff8bd0c0d6e5e48acdfe2b8ca8cebe390d8 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Tue, 16 Aug 2016 13:34:44 +0200 Subject: src/sslkeylog.c: OpenSSL 1.1.0 compatibility OpenSSL 1.1.0 makes some structures opaque, but luckily it provides new functions to extract the client random and master secret which is all we need from the structures. Tested with OpenSSL 1.1.0-pre6 using openssl s_client and OpenSSL 1.0.2.h using curl. --- src/sslkeylog.c | 66 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/src/sslkeylog.c b/src/sslkeylog.c index 8761d52..6a42510 100644 --- a/src/sslkeylog.c +++ b/src/sslkeylog.c @@ -39,7 +39,8 @@ static inline void put_hex(char *buffer, int pos, char c) buffer[pos+1] = c2 < 10 ? '0' + c2 : 'A' + c2 - 10; } -static void dump_to_fd(SSL *ssl, int fd) +static void dump_to_fd(int fd, unsigned char *client_random, + unsigned char *master_key, int master_key_length) { int pos, i; char line[PREFIX_LEN + 2 * SSL3_RANDOM_SIZE + 1 + @@ -49,13 +50,13 @@ static void dump_to_fd(SSL *ssl, int fd) pos = PREFIX_LEN; /* Client Random for SSLv3/TLS */ for (i = 0; i < SSL3_RANDOM_SIZE; i++) { - put_hex(line, pos, ssl->s3->client_random[i]); + put_hex(line, pos, client_random[i]); pos += 2; } line[pos++] = ' '; /* Master Secret (size is at most SSL_MAX_MASTER_KEY_LENGTH) */ - for (i = 0; i < ssl->session->master_key_length; i++) { - put_hex(line, pos, ssl->session->master_key[i]); + for (i = 0; i < master_key_length; i++) { + put_hex(line, pos, master_key[i]); pos += 2; } line[pos++] = '\n'; @@ -86,13 +87,22 @@ typedef struct ssl_tap_state { } ssl_tap_state_t; /* Copies SSL state for later comparison in tap_ssl_key. */ -static void ssl_tap_state_init(ssl_tap_state_t *state, SSL *ssl) +static void ssl_tap_state_init(ssl_tap_state_t *state, const SSL *ssl) { + const SSL_SESSION *session = SSL_get_session(ssl); + memset(state, 0, sizeof(ssl_tap_state_t)); - if (ssl->session && ssl->session->master_key_length > 0) { - state->master_key_length = ssl->session->master_key_length; - memcpy(state->master_key, ssl->session->master_key, - ssl->session->master_key_length); + if (session) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + state->master_key_length = SSL_SESSION_get_master_key(session, + state->master_key, SSL_MAX_MASTER_KEY_LENGTH); +#else + if (session->master_key_length > 0) { + state->master_key_length = session->master_key_length; + memcpy(state->master_key, session->master_key, + session->master_key_length); + } +#endif } } @@ -100,22 +110,42 @@ static void ssl_tap_state_init(ssl_tap_state_t *state, SSL *ssl) ssl_tap_state_t state; \ ssl_tap_state_init(&state, ssl) -static void tap_ssl_key(SSL *ssl, ssl_tap_state_t *state) +static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state) { - /* SSLv2 is not supported (Wireshark does not support it either). Write the - * logfile when the master key is available for SSLv3/TLSv1. */ - if (ssl->s3 != NULL && - ssl->session != NULL && ssl->session->master_key_length > 0) { + const SSL_SESSION *session = SSL_get_session(ssl); + unsigned char client_random[SSL3_RANDOM_SIZE]; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + int master_key_length = 0; + + if (session) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + /* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that + * we have a valid SSL context if we have a non-NULL session. */ + SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE); + master_key_length = SSL_SESSION_get_master_key(session, master_key, + SSL_MAX_MASTER_KEY_LENGTH); +#else + if (ssl->s3 && session->master_key_length > 0) { + memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE); + + master_key_length = session->master_key_length; + memcpy(master_key, session->master_key, master_key_length); + } +#endif + } + + /* Write the logfile when the master key is available for SSLv3/TLSv1. */ + if (master_key_length > 0) { /* Skip writing keys if it did not change. */ - if (state->master_key_length == ssl->session->master_key_length && - memcmp(state->master_key, ssl->session->master_key, - state->master_key_length) == 0) { + if (state->master_key_length == master_key_length && + memcmp(state->master_key, master_key, master_key_length) == 0) { return; } init_keylog_file(); if (keylog_file_fd >= 0) { - dump_to_fd(ssl, keylog_file_fd); + dump_to_fd(keylog_file_fd, client_random, master_key, + master_key_length); } } } -- cgit v1.2.1