Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wolfssl: Add SSLKEYLOGFILE support #5327

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions lib/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ LIB_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c \

LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h

LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/mbedtls.c \
vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c vtls/openssl.c \
vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c vtls/vtls.c \
vtls/wolfssl.c
LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c \
vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c \
vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \
vtls/vtls.c vtls/wolfssl.c

LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/mbedtls.h \
vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h vtls/openssl.h \
vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h
LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h \
vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h \
vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h

LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c

Expand Down
54 changes: 12 additions & 42 deletions lib/vquic/ngtcp2.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "strerror.h"
#include "dynbuf.h"
#include "vquic.h"
#include "vtls/keylog.h"

/* The last 3 #include files should be in this order */
#include "curl_printf.h"
Expand Down Expand Up @@ -186,51 +187,26 @@ static void quic_settings(struct quicsocket *qs,
}
}

static FILE *keylog_file; /* not thread-safe */
#ifdef USE_OPENSSL
static void keylog_callback(const SSL *ssl, const char *line)
{
(void)ssl;
fputs(line, keylog_file);
fputc('\n', keylog_file);
fflush(keylog_file);
Curl_tls_keylog_write_line(line);
}
#elif defined(USE_GNUTLS)
static int keylog_callback(gnutls_session_t session, const char *label,
const gnutls_datum_t *secret)
{
gnutls_datum_t crandom;
gnutls_datum_t srandom;
gnutls_datum_t crandom_hex = { NULL, 0 };
gnutls_datum_t secret_hex = { NULL, 0 };
int rc = 0;

gnutls_session_get_random(session, &crandom, &srandom);
if(crandom.size != 32) {
return -1;
}

rc = gnutls_hex_encode2(&crandom, &crandom_hex);
if(rc < 0) {
fprintf(stderr, "gnutls_hex_encode2 failed: %s\n",
gnutls_strerror(rc));
goto out;
}

rc = gnutls_hex_encode2(secret, &secret_hex);
if(rc < 0) {
fprintf(stderr, "gnutls_hex_encode2 failed: %s\n",
gnutls_strerror(rc));
goto out;
}

fprintf(keylog_file, "%s %s %s\n", label, crandom_hex.data, secret_hex.data);
fflush(keylog_file);

out:
gnutls_free(crandom_hex.data);
gnutls_free(secret_hex.data);
return rc;
Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
return 0;
}
#endif

Expand Down Expand Up @@ -327,7 +303,6 @@ static SSL_QUIC_METHOD quic_method = {quic_set_encryption_secrets,
static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
{
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
const char *keylog_filename;

SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
Expand All @@ -348,12 +323,10 @@ static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)

SSL_CTX_set_quic_method(ssl_ctx, &quic_method);

keylog_filename = getenv("SSLKEYLOGFILE");
if(keylog_filename) {
keylog_file = fopen(keylog_filename, "wb");
if(keylog_file) {
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
}
/* Open the file if a TLS or QUIC backend has not done this before. */
Curl_tls_keylog_open();
if(Curl_tls_keylog_enabled()) {
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
}

return ssl_ctx;
Expand Down Expand Up @@ -496,7 +469,6 @@ static int quic_init_ssl(struct quicsocket *qs)
gnutls_datum_t alpn = {NULL, 0};
/* this will need some attention when HTTPS proxy over QUIC get fixed */
const char * const hostname = qs->conn->host.name;
const char *keylog_filename;
int rc;

if(qs->ssl)
Expand Down Expand Up @@ -529,12 +501,10 @@ static int quic_init_ssl(struct quicsocket *qs)
return 1;
}

keylog_filename = getenv("SSLKEYLOGFILE");
if(keylog_filename) {
keylog_file = fopen(keylog_filename, "wb");
if(keylog_file) {
gnutls_session_set_keylog_function(qs->ssl, keylog_callback);
}
/* Open the file if a TLS or QUIC backend has not done this before. */
Curl_tls_keylog_open();
if(Curl_tls_keylog_enabled()) {
gnutls_session_set_keylog_function(qs->ssl, keylog_callback);
}

if(qs->cred)
Expand Down
156 changes: 156 additions & 0 deletions lib/vtls/keylog.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "curl_setup.h"

#include "keylog.h"

/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"

#define KEYLOG_LABEL_MAXLEN (sizeof("CLIENT_HANDSHAKE_TRAFFIC_SECRET") - 1)

#define CLIENT_RANDOM_SIZE 32

/*
* The master secret in TLS 1.2 and before is always 48 bytes. In TLS 1.3, the
* secret size depends on the cipher suite's hash function which is 32 bytes
* for SHA-256 and 48 bytes for SHA-384.
*/
#define SECRET_MAXLEN 48


/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
static FILE *keylog_file_fp;

void
Curl_tls_keylog_open(void)
{
char *keylog_file_name;

if(!keylog_file_fp) {
keylog_file_name = curl_getenv("SSLKEYLOGFILE");
if(keylog_file_name) {
keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
if(keylog_file_fp) {
#ifdef WIN32
if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
#else
if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
#endif
{
fclose(keylog_file_fp);
keylog_file_fp = NULL;
}
}
Curl_safefree(keylog_file_name);
}
}
}

void
Curl_tls_keylog_close(void)
{
if(keylog_file_fp) {
fclose(keylog_file_fp);
keylog_file_fp = NULL;
}
}

bool
Curl_tls_keylog_enabled(void)
{
return keylog_file_fp != NULL;
}

bool
Curl_tls_keylog_write_line(const char *line)
{
/* The current maximum valid keylog line length LF and NUL is 195. */
size_t linelen;
char buf[256];

if(!keylog_file_fp || !line) {
return false;
}

linelen = strlen(line);
if(linelen == 0 || linelen > sizeof(buf) - 2) {
/* Empty line or too big to fit in a LF and NUL. */
return false;
}

memcpy(buf, line, linelen);
if(line[linelen - 1] != '\n') {
buf[linelen++] = '\n';
}
buf[linelen] = '\0';

/* Using fputs here instead of fprintf since libcurl's fprintf replacement
may not be thread-safe. */
fputs(buf, keylog_file_fp);
return true;
}

bool
Curl_tls_keylog_write(const char *label,
const unsigned char client_random[CLIENT_RANDOM_SIZE],
const unsigned char *secret, size_t secretlen)
{
const char *hex = "0123456789ABCDEF";
size_t pos, i;
char line[KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 +
2 * SECRET_MAXLEN + 1 + 1];

if(!keylog_file_fp) {
return false;
}

pos = strlen(label);
if(pos > KEYLOG_LABEL_MAXLEN || !secretlen || secretlen > SECRET_MAXLEN) {
/* Should never happen - sanity check anyway. */
return false;
}

memcpy(line, label, pos);
line[pos++] = ' ';

/* Client Random */
for(i = 0; i < CLIENT_RANDOM_SIZE; i++) {
line[pos++] = hex[client_random[i] >> 4];
line[pos++] = hex[client_random[i] & 0xF];
}
line[pos++] = ' ';

/* Secret */
for(i = 0; i < secretlen; i++) {
line[pos++] = hex[secret[i] >> 4];
line[pos++] = hex[secret[i] & 0xF];
}
line[pos++] = '\n';
line[pos] = '\0';

/* Using fputs here instead of fprintf since libcurl's fprintf replacement
may not be thread-safe. */
fputs(line, keylog_file_fp);
return true;
}
56 changes: 56 additions & 0 deletions lib/vtls/keylog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef HEADER_CURL_KEYLOG_H
#define HEADER_CURL_KEYLOG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "curl_setup.h"

/*
* Opens the TLS key log file if requested by the user. The SSLKEYLOGFILE
* environment variable specifies the output file.
*/
void Curl_tls_keylog_open(void);

/*
* Closes the TLS key log file if not already.
*/
void Curl_tls_keylog_close(void);

/*
* Returns true if the user successfully enabled the TLS key log file.
*/
bool Curl_tls_keylog_enabled(void);

/*
* Appends a key log file entry.
* Returns true iff the key log file is open and a valid entry was provided.
*/
bool Curl_tls_keylog_write(const char *label,
const unsigned char client_random[32],
const unsigned char *secret, size_t secretlen);

/*
* Appends a line to the key log file, ensure it is terminated by a LF.
* Returns true iff the key log file is open and a valid line was provided.
*/
bool Curl_tls_keylog_write_line(const char *line);

#endif /* HEADER_CURL_KEYLOG_H */
Loading