-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
client/server: support for KeyLog trait, SSLKEYLOGFILE
For debugging purposes it's quite helpful to be able to log session secrets to a file specified by the `SSLKEYLOGFILE`, for example to use with Wireshark to decrypt session traffic. This commit adds two methods to rustls-ffi for both client and server configurations to facilitate this: 1. `rustls_server_config_builder_set_key_log_file()` and `rustls_client_config_builder_set_key_log_file()` enable using the Rustls `KeyLogFile` implementation of the `KeyLog` trait. This option simply honours the `SSLKEYLOGFILE` env var and spits out a NSS formatted key log file appropriate for use with Wireshark and other tools that support this format. 2. `rustls_server_config_builder_set_key_log()` and `rustls_client_config_builder_set_key_log()` enable providing C callbacks that will be invoked to decide which secrets are logged, and to do the logging. This allows for fine-grained control over how secrets are logged and may be more appropriate for applications that already handle this task for other TLS backends (e.g. curl). The client and server examples are updated to optionally use these new features. If the `SSLKEYLOG` env. var is set, both will use the `_set_key_log_file()` fns to set up the standard file based key logging. If the `STDERRKEYLOG` env var is set then both will use the `_set_key_log()` fns to set up custom callbacks that will print the hex-encoded secret data to stderr as a simple demonstration.
- Loading branch information
Showing
10 changed files
with
470 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
//! Provides FFI abstractions for the [`rustls::KeyLog`] trait. | ||
|
||
use std::ffi::c_int; | ||
use std::fmt; | ||
|
||
use crate::rslice::rustls_str; | ||
|
||
/// An optional callback for logging key material. | ||
/// | ||
/// See the documentation on `rustls_client_config_builder_set_key_log` and | ||
/// `rustls_server_config_builder_set_key_log` for more information about the | ||
/// lifetimes of the parameters. | ||
pub type rustls_keylog_log_callback = Option< | ||
unsafe extern "C" fn( | ||
label: rustls_str, | ||
client_random: *const u8, | ||
client_random_len: usize, | ||
secret: *const u8, | ||
secret_len: usize, | ||
), | ||
>; | ||
|
||
/// An optional callback for deciding if key material will be logged. | ||
/// | ||
/// See the documentation on `rustls_client_config_builder_set_key_log` and | ||
/// `rustls_server_config_builder_set_key_log` for more information about the | ||
/// lifetimes of the parameters. | ||
pub type rustls_keylog_will_log_callback = Option<unsafe extern "C" fn(label: rustls_str) -> c_int>; | ||
|
||
/// A type alias for a keylog log callback that has been extracted from an option. | ||
pub(crate) type KeylogLogCallback = unsafe extern "C" fn( | ||
label: rustls_str, | ||
client_random: *const u8, | ||
client_random_len: usize, | ||
secret: *const u8, | ||
secret_len: usize, | ||
); | ||
|
||
/// An implementation of `rustls::KeyLog` based on C callbacks. | ||
pub(crate) struct CallbackKeyLog { | ||
// We use the crate-internal rust type here - it is _not_ Option wrapped. | ||
pub(crate) log_cb: KeylogLogCallback, | ||
// We use the pub type alias here - it is Option wrapped and may be None. | ||
pub(crate) will_log_cb: rustls_keylog_will_log_callback, | ||
} | ||
|
||
impl rustls::KeyLog for CallbackKeyLog { | ||
fn log(&self, label: &str, client_random: &[u8], secret: &[u8]) { | ||
unsafe { | ||
(self.log_cb)( | ||
// Safety: Rustls will never give us a label containing NULL. | ||
rustls_str::try_from(label).unwrap(), | ||
client_random.as_ptr(), | ||
client_random.len(), | ||
secret.as_ptr(), | ||
secret.len(), | ||
); | ||
} | ||
} | ||
|
||
fn will_log(&self, label: &str) -> bool { | ||
match self.will_log_cb { | ||
Some(cb) => { | ||
// Safety: Rustls will never give us a label containing NULL. | ||
let label = rustls_str::try_from(label).unwrap(); | ||
// Log iff the cb returned non-zero. | ||
!matches!(unsafe { (cb)(label) }, 0) | ||
} | ||
// Default to logging everything. | ||
None => true, | ||
} | ||
} | ||
} | ||
|
||
impl fmt::Debug for CallbackKeyLog { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
f.debug_struct("CallbackKeyLog").finish() | ||
} | ||
} | ||
|
||
/// Safety: `CallbackKeyLog` is Send because we don't allocate or deallocate any of its | ||
/// fields. | ||
unsafe impl Send for CallbackKeyLog {} | ||
|
||
/// Safety: Verifier is Sync if the C code passes us a callback that | ||
/// obeys the concurrency safety requirements documented in | ||
/// `rustls_client_config_builder_set_key_log` and `rustls_server_config_builder_set_key_log`. | ||
unsafe impl Sync for CallbackKeyLog {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.