From: Yedaya Katsman Date: Mon, 21 Oct 2024 20:28:28 +0000 (+0300) Subject: rustls: Add support for SSLKEYLOGFILE X-Git-Tag: curl-8_13_0~53 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d31f2592f94a4674ec27ee191ef7e30753d79eb;p=thirdparty%2Fcurl.git rustls: Add support for SSLKEYLOGFILE With rustls-ffi 0.15+ we can set up a callback for writing TLS secrets hooked up to call Curl_tls_keylog_write. To make sure the associated file is cleaned up we update the Curl_ssl struct for the rustls-ffi vtls backend to have a cleanup callback. Closes #16828 --- diff --git a/docs/cmdline-opts/_ENVIRONMENT.md b/docs/cmdline-opts/_ENVIRONMENT.md index 97c75bcb72..d415f2aa19 100644 --- a/docs/cmdline-opts/_ENVIRONMENT.md +++ b/docs/cmdline-opts/_ENVIRONMENT.md @@ -102,7 +102,7 @@ If you set this environment variable to a filename, curl stores TLS secrets from its connections in that file when invoked to enable you to analyze the TLS traffic in real time using network analyzing tools such as Wireshark. This works with the following TLS backends: OpenSSL, LibreSSL (TLS 1.2 max), -BoringSSL, GnuTLS and wolfSSL. +BoringSSL, GnuTLS, wolfSSL and Rustls. ## `USERPROFILE` On Windows, this variable is used when trying to find the home directory. If diff --git a/lib/vtls/keylog.c b/lib/vtls/keylog.c index 32ccd38cc7..1e76845b33 100644 --- a/lib/vtls/keylog.c +++ b/lib/vtls/keylog.c @@ -27,7 +27,8 @@ defined(USE_GNUTLS) || \ defined(USE_WOLFSSL) || \ (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \ - defined(USE_QUICHE) + defined(USE_QUICHE) || \ + defined(USE_RUSTLS) #include "keylog.h" #include diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index 6117ada0d2..3d5d573c04 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -38,6 +38,7 @@ #include "vtls.h" #include "vtls_int.h" #include "rustls.h" +#include "keylog.h" #include "strerror.h" #include "cipher_suite.h" #include "x509asn1.h" @@ -518,6 +519,19 @@ add_ciphers: *selected_size = count; } +static void +cr_keylog_log_cb(struct rustls_str label, + const uint8_t *client_random, size_t client_random_len, + const uint8_t *secret, size_t secret_len) +{ + char clabel[KEYLOG_LABEL_MAXLEN]; + (void)client_random_len; + DEBUGASSERT(client_random_len == CLIENT_RANDOM_SIZE); + /* Turning a "rustls_str" into a null delimited "c" string */ + msnprintf(clabel, label.len + 1, "%.*s", (int)label.len, label.data); + Curl_tls_keylog_write(clabel, client_random, secret, secret_len); +} + static CURLcode init_config_builder(struct Curl_easy *data, const struct ssl_primary_config *conn_config, @@ -774,6 +788,29 @@ cleanup: return result; } +static CURLcode +init_config_builder_keylog(struct Curl_easy *data, + struct rustls_client_config_builder *builder) +{ + rustls_result rr; + + Curl_tls_keylog_open(); + if(!Curl_tls_keylog_enabled()) { + return CURLE_OK; + } + + rr = rustls_client_config_builder_set_key_log(builder, + cr_keylog_log_cb, + NULL); + if(rr != RUSTLS_RESULT_OK) { + rustls_failf(data, rr, "rustls_client_config_builder_set_key_log"); + Curl_tls_keylog_close(); + return map_error(rr); + } + + return CURLE_OK; +} + static CURLcode cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, struct rustls_ssl_backend_data *const backend) @@ -819,6 +856,12 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, } } + result = init_config_builder_keylog(data, config_builder); + if(result != CURLE_OK) { + rustls_client_config_builder_free(config_builder); + return result; + } + rr = rustls_client_config_builder_build( config_builder, &backend->config); @@ -1125,6 +1168,11 @@ cr_random(struct Curl_easy *data, unsigned char *entropy, size_t length) return map_error(rresult); } +static void cr_cleanup(void) +{ + Curl_tls_keylog_close(); +} + const struct Curl_ssl Curl_ssl_rustls = { { CURLSSLBACKEND_RUSTLS, "rustls" }, SSLSUPP_CAINFO_BLOB | /* supports */ @@ -1135,7 +1183,7 @@ const struct Curl_ssl Curl_ssl_rustls = { sizeof(struct rustls_ssl_backend_data), NULL, /* init */ - NULL, /* cleanup */ + cr_cleanup, /* cleanup */ cr_version, /* version */ cr_shutdown, /* shutdown */ cr_data_pending, /* data_pending */