diff --git a/wolfssl/src/ssl.rs b/wolfssl/src/ssl.rs index 7a8c63f..56b0140 100644 --- a/wolfssl/src/ssl.rs +++ b/wolfssl/src/ssl.rs @@ -184,7 +184,7 @@ pub struct Session { io: Box, #[cfg(feature = "debug")] - secret_cb: Option, + secret_cb: Option>, } /// Error creating a [`Session`] object. @@ -1131,13 +1131,20 @@ impl Session { /// Enable TLS1.3 key logging for applications #[cfg(feature = "debug")] pub(crate) fn enable_tls13_keylog(&mut self, secret_cb: Tls13SecretCallbacksArg) -> Result<()> { - self.secret_cb = Some(secret_cb.clone()); + self.secret_cb = Some(Box::new(secret_cb)); - // SAFETY: `secret_cb` is an Arc pointer and we save one strong reference inside `Session` - // This prevents the memory being freed when `secret_cb` goes out of scope. - // So it is safe to send this pointer as callback context and `secret_cb` will be valid - // as long the connection is valid - let secret_cb = Box::into_raw(Box::new(secret_cb)) as *mut c_void; + // SAFETY: `secret_cb` is a `Box` pointer so the address is + // stable. (The address is the address of the heap allocation + // containing the `Tls13Secretcallbacksarg` which is an `Arc`. + // + // We free `self.ssl` (the `wolfssl_sys::WOLFSSL`) on drop of + // `self`, any use of the callback must have stopped before + // the drop, since nothing can also be making calls into the session. + // + // Therefore `secret_cb` here is valid for as long as it needs to be. + let secret_cb: &mut Tls13SecretCallbacksArg = self.secret_cb.as_mut().unwrap(); + let secret_cb: *mut Tls13SecretCallbacksArg = secret_cb as *mut Tls13SecretCallbacksArg; + let secret_cb = secret_cb as *mut c_void; // SAFETY: No documentation available for [`wolfSSL_KeepArrays`] [`wolfSSL_set_tls13_secret_cb`]. // But based on api implementation, it expects a valid pointer to `WOLFSSL`. @@ -1168,9 +1175,13 @@ impl Session { debug_assert!(!secret.is_null()); debug_assert!(!ctx.is_null()); - // SAFETY: We have only one strong reference in `self.secret_cb` - // Leak the Box pointer, so that it will not be freed while this function return - let secret_cb = Box::leak(Box::from_raw(ctx as *mut Tls13SecretCallbacksArg)); + // SAFETY: We know this pointer is to the contents of the + // `Box` at `self.secret_cb` which is + // owned by the `Session`. See `enable_tls13_keylog` above for + // an argument to why calls to this callback cannot happen + // after the `Session` is dropped. + let secret_cb = ctx as *mut Tls13SecretCallbacksArg; + let secret_cb: &Tls13SecretCallbacksArg = &*secret_cb; let mut random: Vec = vec![0; RANDOM_SIZE]; let get_random = if 1 == wolfssl_sys::wolfSSL_is_server(ssl) {