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
This commit is contained in:
Yedaya Katsman 2024-10-21 23:28:28 +03:00 committed by Daniel Stenberg
parent 9ad2d8c557
commit 1d31f2592f
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 52 additions and 3 deletions

View file

@ -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 <curl/curl.h>

View file

@ -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 */