Allow dumping SSL session keys on TRACE_SESSION_KEY
This dumps SSL session keys to a log file specified by the SSLKEYLOGFILE environment variable. This permits decrypting SSL trafic in wireshark with a tcpdump capture for example. cf. https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format https://security.stackexchange.com/questions/35639/decrypting-tls-in-wireshark-when-using-dhe-rsa-ciphersuites/42350#42350 https://wiki.wireshark.org/SSL#Using_the_.28Pre.29-Master-Secret https://jimshaver.net/2015/02/11/decrypting-tls-browser-traffic-with-wireshark-the-easy-way/ Looks like we miss the required function from SSL... SSL_SESSION_print_keylog is only in 1.1.0. Also added dumping of client_random as it's required by wireshark.
This commit is contained in:
parent
84c62f1d46
commit
e62e979e60
@ -11,6 +11,7 @@
|
||||
|
||||
#ifdef OPENSSL_ENABLED
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/ssl3.h> // for TRACE_SESSION_KEY only
|
||||
# include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
@ -32,9 +33,94 @@
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
|
||||
//#define TRACE_SESSION_KEY
|
||||
|
||||
|
||||
#ifdef OPENSSL_ENABLED
|
||||
|
||||
#ifdef TRACE_SESSION_KEY
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
/*
|
||||
* print session id and master key in NSS keylog format (RSA
|
||||
* Session-ID:<session id> Master-Key:<master key>)
|
||||
*/
|
||||
int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (x == NULL)
|
||||
goto err;
|
||||
if (x->session_id_length == 0 || x->master_key_length == 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* the RSA prefix is required by the format's definition although there's
|
||||
* nothing RSA-specific in the output, therefore, we don't have to check if
|
||||
* the cipher suite is based on RSA
|
||||
*/
|
||||
if (BIO_puts(bp, "RSA ") <= 0)
|
||||
goto err;
|
||||
|
||||
if (BIO_puts(bp, "Session-ID:") <= 0)
|
||||
goto err;
|
||||
for (i = 0; i < x->session_id_length; i++) {
|
||||
if (BIO_printf(bp, "%02X", x->session_id[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, " Master-Key:") <= 0)
|
||||
goto err;
|
||||
for (i = 0; i < (size_t)x->master_key_length; i++) {
|
||||
if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto err;
|
||||
|
||||
return (1);
|
||||
err:
|
||||
return (0);
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
/*
|
||||
* print client random id and master key in NSS keylog format
|
||||
* as session ID is not enough.
|
||||
*/
|
||||
int SSL_SESSION_print_client_random(BIO *bp, const SSL *ssl)
|
||||
{
|
||||
const SSL_SESSION *x = SSL_get_session(ssl);
|
||||
size_t i;
|
||||
|
||||
if (x == NULL)
|
||||
goto err;
|
||||
if (x->session_id_length == 0 || x->master_key_length == 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* the RSA prefix is required by the format's definition although there's
|
||||
* nothing RSA-specific in the output, therefore, we don't have to check if
|
||||
* the cipher suite is based on RSA
|
||||
*/
|
||||
if (BIO_puts(bp, "CLIENT_RANDOM ") <= 0)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < sizeof(ssl->s3->client_random); i++) {
|
||||
if (BIO_printf(bp, "%02X", ssl->s3->client_random[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, " ") <= 0)
|
||||
goto err;
|
||||
for (i = 0; i < (size_t)x->master_key_length; i++) {
|
||||
if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0)
|
||||
goto err;
|
||||
}
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto err;
|
||||
|
||||
return (1);
|
||||
err:
|
||||
return (0);
|
||||
}
|
||||
#endif /* TRACE_SESSION_KEY */
|
||||
|
||||
class BSecureSocket::Private {
|
||||
public:
|
||||
@ -59,6 +145,11 @@ private:
|
||||
static SSL_CTX* sContext;
|
||||
// FIXME When do we SSL_CTX_free it?
|
||||
static pthread_once_t sInitOnce;
|
||||
#ifdef TRACE_SESSION_KEY
|
||||
public:
|
||||
static BIO* sKeyLogBIO;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -66,6 +157,9 @@ private:
|
||||
/* static */ int BSecureSocket::Private::sDataIndex;
|
||||
/* static */ pthread_once_t BSecureSocket::Private::sInitOnce
|
||||
= PTHREAD_ONCE_INIT;
|
||||
#ifdef TRACE_SESSION_KEY
|
||||
/* static */ BIO* BSecureSocket::Private::sKeyLogBIO = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
BSecureSocket::Private::Private()
|
||||
@ -286,6 +380,17 @@ BSecureSocket::Private::_CreateContext()
|
||||
// Get an unique index number for storing application data in SSL
|
||||
// structs. We will store a pointer to the BSecureSocket class there.
|
||||
sDataIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
||||
|
||||
#ifdef TRACE_SESSION_KEY
|
||||
FILE *keylog = NULL;
|
||||
const char *logpath = getenv("SSLKEYLOGFILE");
|
||||
if (logpath)
|
||||
keylog = fopen(logpath, "w+");
|
||||
if (keylog) {
|
||||
fprintf(keylog, "# Key Log File generated by Haiku Network Kit\n");
|
||||
sKeyLogBIO = BIO_new_fp(keylog, BIO_NOCLOSE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -477,6 +582,7 @@ BSecureSocket::_SetupCommon(const char* host)
|
||||
SSL_set_tlsext_host_name(fPrivate->fSSL, host);
|
||||
}
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -495,6 +601,14 @@ BSecureSocket::_SetupConnect(const char* host)
|
||||
return fPrivate->ErrorCode(returnValue);
|
||||
}
|
||||
|
||||
#ifdef TRACE_SESSION_KEY
|
||||
fprintf(stderr, "SSL SESSION INFO:\n");
|
||||
//SSL_SESSION_print_fp(stderr, SSL_get_session(fPrivate->fSSL));
|
||||
SSL_SESSION_print_keylog(fPrivate->sKeyLogBIO, SSL_get_session(fPrivate->fSSL));
|
||||
SSL_SESSION_print_client_random(fPrivate->sKeyLogBIO, fPrivate->fSSL);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user