From 58426ad1fbc0e82d3f53e12ff79a729378a0b574 Mon Sep 17 00:00:00 2001 From: David Palm Date: Tue, 29 Apr 2025 12:01:24 +0200 Subject: [PATCH 1/2] Test zeroization when going out of scope --- secrecy/Cargo.toml | 23 ++++++++++-------- secrecy/src/lib.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/secrecy/Cargo.toml b/secrecy/Cargo.toml index f1b60c2e..112bbdc6 100644 --- a/secrecy/Cargo.toml +++ b/secrecy/Cargo.toml @@ -1,20 +1,20 @@ [package] -name = "secrecy" +name = "secrecy" description = """ Wrapper types and traits for secret management which help ensure they aren't accidentally copied, logged, or otherwise exposed (as much as possible), and also ensure secrets are securely wiped from memory when dropped. """ -version = "0.10.3" -authors = ["Tony Arcieri "] -license = "Apache-2.0 OR MIT" -homepage = "https://github.com/iqlusioninc/crates/" -repository = "https://github.com/iqlusioninc/crates/tree/main/secrecy" -readme = "README.md" -categories = ["cryptography", "memory-management", "no-std", "os"] -keywords = ["clear", "memory", "secret", "secure", "wipe"] -edition = "2021" +version = "0.10.3" +authors = ["Tony Arcieri "] +license = "Apache-2.0 OR MIT" +homepage = "https://github.com/iqlusioninc/crates/" +repository = "https://github.com/iqlusioninc/crates/tree/main/secrecy" +readme = "README.md" +categories = ["cryptography", "memory-management", "no-std", "os"] +keywords = ["clear", "memory", "secret", "secure", "wipe"] +edition = "2021" rust-version = "1.60" [dependencies] @@ -23,6 +23,9 @@ zeroize = { version = "1.6", default-features = false, features = ["alloc"] } # optional dependencies serde = { version = "1", optional = true, default-features = false, features = ["alloc"] } +[features] +test-allocator = [] + [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] diff --git a/secrecy/src/lib.rs b/secrecy/src/lib.rs index 2f1866fd..1080819c 100644 --- a/secrecy/src/lib.rs +++ b/secrecy/src/lib.rs @@ -29,9 +29,9 @@ //! types of `SecretBox` to be serializable with `serde`, you will need to impl //! the [`SerializableSecret`] marker trait on `T`. -#![no_std] +#![cfg_attr(not(feature = "test-allocator"), no_std)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![forbid(unsafe_code)] +#![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms, unused_qualifications)] extern crate alloc; @@ -345,4 +345,59 @@ mod tests { let secret = SecretString::from_str("test").unwrap(); assert_eq!(secret.expose_secret(), "test"); } + + #[cfg(feature = "test-allocator")] + mod secret_with_custom_allocator { + + use super::super::*; + use core::ptr; + + use std::alloc::{GlobalAlloc, Layout, System}; + // Allocator that leaks all memory it allocates, thus leaving the memory open for inspection. + struct UnfreeAllocator; + #[allow(unsafe_code)] + unsafe impl GlobalAlloc for UnfreeAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + System.alloc(layout) + } + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + let _ = (ptr, layout); + } + } + + #[global_allocator] + static UNFREE_ALLOCATOR: UnfreeAllocator = UnfreeAllocator; + + #[test] + #[allow(unsafe_code, unused_assignments)] + fn clears_memory_when_scope_ends() { + let mut ptr: *const u128 = ptr::null(); + unsafe { + { + let secret = SecretBox::init_with(|| 0xdeadbeef_u128); + let secretboxptr = &secret as *const SecretBox; + // Points to the inner_secret of the `SecretBox` + let boxptr = secretboxptr as *const *const u128; + // Pointer to actual heap data + ptr = *boxptr; + + assert!(!ptr.is_null(), "ptr is null before drop, not ok"); + let bytes: &[u8] = + core::slice::from_raw_parts(ptr as *const u8, size_of::()); + assert!( + !bytes.iter().all(|&b| b == 0), + "Expected non-zero data, instead found 0s: {:X?}", + bytes + ); + } + // Check that the memory is cleared after the scope ends + let bytes: &[u8] = core::slice::from_raw_parts(ptr as *const u8, size_of::()); + assert!( + bytes.iter().all(|&b| b == 0), + "Expected zeroized memory, instead found: {:X?}", + bytes + ); + } + } + } } From ac4ce0d9eed785c29b3db687639b8d8c45f16d0b Mon Sep 17 00:00:00 2001 From: David Palm Date: Tue, 29 Apr 2025 12:06:30 +0200 Subject: [PATCH 2/2] Import size_of --- secrecy/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/secrecy/src/lib.rs b/secrecy/src/lib.rs index 1080819c..54644280 100644 --- a/secrecy/src/lib.rs +++ b/secrecy/src/lib.rs @@ -350,6 +350,7 @@ mod tests { mod secret_with_custom_allocator { use super::super::*; + use core::mem::size_of; use core::ptr; use std::alloc::{GlobalAlloc, Layout, System};