From db1aab959c18d0116abd10872ff986c9efeca883 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Thu, 26 Mar 2026 15:03:46 -0400 Subject: [PATCH] Rust wrapper: zeroize structs on drop --- wrapper/rust/wolfssl-wolfcrypt/Cargo.lock | 21 +++++ wrapper/rust/wolfssl-wolfcrypt/Cargo.toml | 1 + wrapper/rust/wolfssl-wolfcrypt/src/aes.rs | 75 ++++++++++++++++ wrapper/rust/wolfssl-wolfcrypt/src/blake2.rs | 57 ++++++++++++ .../src/chacha20_poly1305.rs | 16 ++-- wrapper/rust/wolfssl-wolfcrypt/src/cmac.rs | 8 ++ .../rust/wolfssl-wolfcrypt/src/curve25519.rs | 8 ++ wrapper/rust/wolfssl-wolfcrypt/src/dh.rs | 8 ++ .../rust/wolfssl-wolfcrypt/src/dilithium.rs | 8 ++ wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs | 16 ++++ wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs | 8 ++ wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs | 8 ++ wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs | 8 ++ wrapper/rust/wolfssl-wolfcrypt/src/lib.rs | 17 ++++ wrapper/rust/wolfssl-wolfcrypt/src/lms.rs | 8 ++ wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs | 8 ++ wrapper/rust/wolfssl-wolfcrypt/src/random.rs | 8 ++ wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs | 8 ++ wrapper/rust/wolfssl-wolfcrypt/src/sha.rs | 89 +++++++++++++++++++ 19 files changed, 374 insertions(+), 6 deletions(-) diff --git a/wrapper/rust/wolfssl-wolfcrypt/Cargo.lock b/wrapper/rust/wolfssl-wolfcrypt/Cargo.lock index 3a6dbadd24..9fe8a69681 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/Cargo.lock +++ b/wrapper/rust/wolfssl-wolfcrypt/Cargo.lock @@ -393,4 +393,25 @@ dependencies = [ "cipher", "rand_core 0.10.0", "regex", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] diff --git a/wrapper/rust/wolfssl-wolfcrypt/Cargo.toml b/wrapper/rust/wolfssl-wolfcrypt/Cargo.toml index 7dca3510e0..08ee5ac62b 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/Cargo.toml +++ b/wrapper/rust/wolfssl-wolfcrypt/Cargo.toml @@ -20,6 +20,7 @@ cipher = ["dep:cipher"] rand_core = { version = "0.10", optional = true, default-features = false } aead = { version = "0.5", optional = true, default-features = false } cipher = { version = "0.5", optional = true, default-features = false } +zeroize = { version = "1.3", default-features = false, features = ["derive"] } [dev-dependencies] aead = { version = "0.5", features = ["alloc", "dev"] } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs b/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs index d5275c01c1..d92f8911f9 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs @@ -27,6 +27,7 @@ Encryption Standard (AES) functionality. use crate::sys; use core::mem::{size_of_val, MaybeUninit}; +use zeroize::{Zeroize, ZeroizeOnDrop}; #[cfg(feature = "aead")] use aead::{AeadCore, AeadInPlace, KeyInit, KeySizeUser}; @@ -233,10 +234,17 @@ impl CBC { } } #[cfg(aes_cbc)] +impl Zeroize for CBC { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_aes); } + } +} +#[cfg(aes_cbc)] impl Drop for CBC { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesFree(&mut self.ws_aes); } + self.zeroize(); } } @@ -428,10 +436,17 @@ impl CCM { } } #[cfg(aes_ccm)] +impl Zeroize for CCM { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_aes); } + } +} +#[cfg(aes_ccm)] impl Drop for CCM { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesFree(&mut self.ws_aes); } + self.zeroize(); } } @@ -506,6 +521,7 @@ fn ccm_decrypt_in_place( /// AES-128-CCM authenticated encryption (12-byte nonce, 16-byte tag). #[cfg(all(aes_ccm, feature = "aead"))] +#[derive(Zeroize, ZeroizeOnDrop)] pub struct Aes128Ccm { key: [u8; 16], } @@ -557,6 +573,7 @@ impl AeadInPlace for Aes128Ccm { /// AES-256-CCM authenticated encryption (12-byte nonce, 16-byte tag). #[cfg(all(aes_ccm, feature = "aead"))] +#[derive(Zeroize, ZeroizeOnDrop)] pub struct Aes256Ccm { key: [u8; 32], } @@ -906,10 +923,17 @@ impl CFB { } } #[cfg(aes_cfb)] +impl Zeroize for CFB { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_aes); } + } +} +#[cfg(aes_cfb)] impl Drop for CFB { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesFree(&mut self.ws_aes); } + self.zeroize(); } } @@ -1076,10 +1100,17 @@ impl CTR { } } #[cfg(aes_ctr)] +impl Zeroize for CTR { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_aes); } + } +} +#[cfg(aes_ctr)] impl Drop for CTR { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesFree(&mut self.ws_aes); } + self.zeroize(); } } @@ -1384,10 +1415,17 @@ impl ECB { } } #[cfg(aes_ecb)] +impl Zeroize for ECB { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_aes); } + } +} +#[cfg(aes_ecb)] impl Drop for ECB { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesFree(&mut self.ws_aes); } + self.zeroize(); } } @@ -1579,10 +1617,17 @@ impl GCM { } } #[cfg(aes_gcm)] +impl Zeroize for GCM { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_aes); } + } +} +#[cfg(aes_gcm)] impl Drop for GCM { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesFree(&mut self.ws_aes); } + self.zeroize(); } } @@ -1658,6 +1703,7 @@ fn gcm_decrypt_in_place( /// AES-128-GCM authenticated encryption (12-byte nonce, 16-byte tag). #[cfg(all(aes_gcm, feature = "aead"))] +#[derive(Zeroize, ZeroizeOnDrop)] pub struct Aes128Gcm { key: [u8; 16], } @@ -1709,6 +1755,7 @@ impl AeadInPlace for Aes128Gcm { /// AES-256-GCM authenticated encryption (12-byte nonce, 16-byte tag). #[cfg(all(aes_gcm, feature = "aead"))] +#[derive(Zeroize, ZeroizeOnDrop)] pub struct Aes256Gcm { key: [u8; 32], } @@ -2034,10 +2081,17 @@ impl GCMStream { } } #[cfg(aes_gcm_stream)] +impl Zeroize for GCMStream { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_aes); } + } +} +#[cfg(aes_gcm_stream)] impl Drop for GCMStream { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesFree(&mut self.ws_aes); } + self.zeroize(); } } @@ -2215,10 +2269,17 @@ impl OFB { } } #[cfg(aes_ofb)] +impl Zeroize for OFB { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_aes); } + } +} +#[cfg(aes_ofb)] impl Drop for OFB { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesFree(&mut self.ws_aes); } + self.zeroize(); } } @@ -2586,10 +2647,17 @@ impl XTS { } } #[cfg(aes_xts)] +impl Zeroize for XTS { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_xtsaes); } + } +} +#[cfg(aes_xts)] impl Drop for XTS { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesXtsFree(&mut self.ws_xtsaes); } + self.zeroize(); } } @@ -2890,10 +2958,17 @@ impl XTSStream { } } #[cfg(aes_xts_stream)] +impl Zeroize for XTSStream { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_xtsaes); } + } +} +#[cfg(aes_xts_stream)] impl Drop for XTSStream { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_AesXtsFree(&mut self.ws_xtsaes); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/blake2.rs b/wrapper/rust/wolfssl-wolfcrypt/src/blake2.rs index 06021de68c..8b4ef5a3ae 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/blake2.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/blake2.rs @@ -27,6 +27,7 @@ functionality. use crate::sys; use core::mem::MaybeUninit; +use zeroize::Zeroize; /// Context for BLAKE2b computation. #[cfg(blake2b)] @@ -174,6 +175,20 @@ impl BLAKE2b { } +#[cfg(blake2b)] +impl Zeroize for BLAKE2b { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_blake2b); } + } +} + +#[cfg(blake2b)] +impl Drop for BLAKE2b { + fn drop(&mut self) { + self.zeroize(); + } +} + /// Context for HMAC-BLAKE2b computation. #[cfg(blake2b_hmac)] pub struct BLAKE2bHmac { @@ -311,6 +326,20 @@ impl BLAKE2bHmac { } +#[cfg(blake2b_hmac)] +impl Zeroize for BLAKE2bHmac { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_blake2b); } + } +} + +#[cfg(blake2b_hmac)] +impl Drop for BLAKE2bHmac { + fn drop(&mut self) { + self.zeroize(); + } +} + /// Context for BLAKE2s computation. #[cfg(blake2s)] pub struct BLAKE2s { @@ -457,6 +486,20 @@ impl BLAKE2s { } +#[cfg(blake2s)] +impl Zeroize for BLAKE2s { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_blake2s); } + } +} + +#[cfg(blake2s)] +impl Drop for BLAKE2s { + fn drop(&mut self) { + self.zeroize(); + } +} + /// Context for HMAC-BLAKE2s computation. #[cfg(blake2s_hmac)] pub struct BLAKE2sHmac { @@ -592,3 +635,17 @@ impl BLAKE2sHmac { Ok(()) } } + +#[cfg(blake2s_hmac)] +impl Zeroize for BLAKE2sHmac { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_blake2s); } + } +} + +#[cfg(blake2s_hmac)] +impl Drop for BLAKE2sHmac { + fn drop(&mut self) { + self.zeroize(); + } +} diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs b/wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs index 303b215378..795363c095 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs @@ -27,6 +27,7 @@ ChaCha20-Poly1305 functionality. use crate::sys; use core::mem::MaybeUninit; +use zeroize::{Zeroize, ZeroizeOnDrop}; pub struct ChaCha20Poly1305 { wc_ccp: sys::ChaChaPoly_Aead, @@ -243,14 +244,15 @@ impl ChaCha20Poly1305 { } } +impl Zeroize for ChaCha20Poly1305 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_ccp); } + } +} + impl Drop for ChaCha20Poly1305 { fn drop(&mut self) { - unsafe { - let ptr = &mut self.wc_ccp as *mut sys::ChaChaPoly_Aead as *mut u8; - for i in 0..core::mem::size_of::() { - core::ptr::write_volatile(ptr.add(i), 0); - } - } + self.zeroize(); } } @@ -261,6 +263,7 @@ impl Drop for ChaCha20Poly1305 { /// ChaCha20-Poly1305 AEAD instance holding a key for use with the /// `aead::KeyInit` and `aead::AeadInPlace` traits. #[cfg(feature = "aead")] +#[derive(Zeroize, ZeroizeOnDrop)] pub struct ChaCha20Poly1305Aead { key: [u8; 32], } @@ -449,6 +452,7 @@ impl XChaCha20Poly1305 { /// XChaCha20-Poly1305 AEAD instance holding a key for use with the /// `aead::KeyInit` and `aead::AeadInPlace` traits. #[cfg(all(xchacha20_poly1305, feature = "aead"))] +#[derive(Zeroize, ZeroizeOnDrop)] pub struct XChaCha20Poly1305Aead { key: [u8; 32], } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/cmac.rs b/wrapper/rust/wolfssl-wolfcrypt/src/cmac.rs index fa3ebebfd0..63755ab677 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/cmac.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/cmac.rs @@ -27,6 +27,7 @@ Message Authentication Code (CMAC) functionality. use crate::sys; use core::mem::MaybeUninit; +use zeroize::Zeroize; /// The `CMAC` struct manages the lifecycle of a wolfSSL `Cmac` object. /// @@ -408,9 +409,16 @@ impl CMAC { Ok(rc == 0) } } +impl Zeroize for CMAC { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_cmac); } + } +} + impl Drop for CMAC { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_CmacFree(&mut self.ws_cmac); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs b/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs index 9a80fb573e..d51f114b16 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs @@ -29,6 +29,7 @@ functionality. use crate::random::RNG; use crate::sys; use core::mem::MaybeUninit; +use zeroize::Zeroize; pub struct Curve25519Key { wc_key: sys::curve25519_key, @@ -654,6 +655,12 @@ impl Curve25519Key { } } +impl Zeroize for Curve25519Key { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_key); } + } +} + impl Drop for Curve25519Key { /// Safely free the underlying wolfSSL Curve25519Key context. /// @@ -664,5 +671,6 @@ impl Drop for Curve25519Key { /// preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_curve25519_free(&mut self.wc_key); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/dh.rs b/wrapper/rust/wolfssl-wolfcrypt/src/dh.rs index ffb31fd223..047b84896d 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/dh.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/dh.rs @@ -32,6 +32,7 @@ use crate::sys; #[cfg(random)] use crate::random::RNG; use core::mem::{MaybeUninit}; +use zeroize::Zeroize; pub struct DH { wc_dhkey: sys::DhKey, @@ -1579,6 +1580,12 @@ impl DH { } } +impl Zeroize for DH { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_dhkey); } + } +} + impl Drop for DH { /// Safely free the underlying wolfSSL DhKey context. /// @@ -1589,5 +1596,6 @@ impl Drop for DH { /// resources and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_FreeDhKey(&mut self.wc_dhkey); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/dilithium.rs b/wrapper/rust/wolfssl-wolfcrypt/src/dilithium.rs index 54fbd177c5..e57640aab7 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/dilithium.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/dilithium.rs @@ -62,6 +62,7 @@ use crate::sys; #[cfg(all(random, any(dilithium_make_key, dilithium_sign)))] use crate::random::RNG; use core::mem::MaybeUninit; +use zeroize::Zeroize; /// Rust wrapper for a wolfSSL `dilithium_key` object. /// @@ -1299,6 +1300,12 @@ impl Dilithium { } } +impl Zeroize for Dilithium { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_key); } + } +} + impl Drop for Dilithium { /// Safely free the underlying wolfSSL Dilithium key context. /// @@ -1306,5 +1313,6 @@ impl Drop for Dilithium { /// is called when the `Dilithium` struct goes out of scope. fn drop(&mut self) { unsafe { sys::wc_dilithium_free(&mut self.ws_key); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs b/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs index 4dd639a1c0..4221e70f25 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs @@ -32,6 +32,7 @@ use crate::sys; #[cfg(random)] use crate::random::RNG; use core::mem::{MaybeUninit}; +use zeroize::Zeroize; /// Rust wrapper for wolfSSL `ecc_point` object. pub struct ECCPoint { @@ -267,6 +268,13 @@ impl ECCPoint { } } +impl Zeroize for ECCPoint { + fn zeroize(&mut self) { + self.wc_ecc_point = core::ptr::null_mut(); + self.heap = core::ptr::null_mut(); + } +} + impl Drop for ECCPoint { /// Safely free the underlying wolfSSL ecc_point context. /// @@ -277,6 +285,7 @@ impl Drop for ECCPoint { /// resources and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_ecc_del_point_h(self.wc_ecc_point, self.heap); } + self.zeroize(); } } @@ -1957,6 +1966,12 @@ impl ECC { } } +impl Zeroize for ECC { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_ecc_key); } + } +} + impl Drop for ECC { /// Safely free the underlying wolfSSL ECC context. /// @@ -1967,5 +1982,6 @@ impl Drop for ECC { /// preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_ecc_free(&mut self.wc_ecc_key); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs b/wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs index e6af212e4d..26a2caa937 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs @@ -28,6 +28,7 @@ This module provides a Rust wrapper for the wolfCrypt library's EdDSA Curve use crate::sys; use crate::random::RNG; use core::mem::MaybeUninit; +use zeroize::Zeroize; /// The `Ed25519` struct manages the lifecycle of a wolfSSL `ed25519_key` /// object. @@ -1430,9 +1431,16 @@ impl Ed25519 { } } +impl Zeroize for Ed25519 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_key); } + } +} + impl Drop for Ed25519 { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_ed25519_free(&mut self.ws_key); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs b/wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs index 851f963f08..b4a23db7cc 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs @@ -28,6 +28,7 @@ This module provides a Rust wrapper for the wolfCrypt library's EdDSA Curve use crate::sys; use crate::random::RNG; use core::mem::MaybeUninit; +use zeroize::Zeroize; /// The `Ed448` struct manages the lifecycle of a wolfSSL `ed448_key` /// object. @@ -1355,9 +1356,16 @@ impl Ed448 { } } +impl Zeroize for Ed448 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_key); } + } +} + impl Drop for Ed448 { /// Safely free the wolfSSL resources. fn drop(&mut self) { unsafe { sys::wc_ed448_free(&mut self.ws_key); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs b/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs index 62e75d047e..893fe3e02c 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs @@ -27,6 +27,7 @@ functionality. use crate::sys; use core::mem::MaybeUninit; +use zeroize::Zeroize; /// Rust wrapper for wolfSSL `Hmac` object. pub struct HMAC { @@ -324,6 +325,12 @@ impl HMAC { } } +impl Zeroize for HMAC { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_hmac); } + } +} + impl Drop for HMAC { /// Safely free the underlying wolfSSL Hmac context. /// @@ -334,5 +341,6 @@ impl Drop for HMAC { /// resources and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_HmacFree(&mut self.wc_hmac); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs b/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs index fff3be2e14..b4552ef4de 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs @@ -23,6 +23,23 @@ /* bindgen-generated bindings to the C library */ pub mod sys; +/// Zeroize the raw bytes of a value. For use in `Zeroize` impls on C FFI +/// structs where `#[derive(Zeroize)]` cannot be used. +/// +/// # Safety +/// +/// `val` must be a valid, initialized value whose entire `size_of_val` byte +/// representation is safe to overwrite with zeroes. +pub(crate) unsafe fn zeroize_raw(val: &mut T) { + use zeroize::Zeroize; + unsafe { + core::slice::from_raw_parts_mut( + val as *mut T as *mut u8, + core::mem::size_of_val(val), + ).zeroize(); + } +} + pub mod aes; pub mod blake2; pub mod chacha20_poly1305; diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/lms.rs b/wrapper/rust/wolfssl-wolfcrypt/src/lms.rs index 61665079c6..4aa09a34db 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/lms.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/lms.rs @@ -89,6 +89,7 @@ use crate::sys; use core::mem::MaybeUninit; #[cfg(all(lms_make_key, random))] use crate::random::RNG; +use zeroize::Zeroize; /// Rust wrapper for a wolfSSL `LmsKey` object (LMS/HSS, RFC 8554). /// @@ -776,6 +777,12 @@ impl Lms { } } +impl Zeroize for Lms { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.ws_key); } + } +} + impl Drop for Lms { /// Safely free the underlying wolfSSL LMS/HSS key context. /// @@ -785,5 +792,6 @@ impl Drop for Lms { unsafe { sys::wc_LmsKey_Free(&mut self.ws_key); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs b/wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs index f07f55f7a1..a7d903be33 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs @@ -64,6 +64,7 @@ assert_eq!(ss_alice, ss_bob); use crate::sys; #[cfg(random)] use crate::random::RNG; +use zeroize::Zeroize; /// Rust wrapper for a wolfSSL `MlKemKey` object. /// @@ -784,6 +785,12 @@ impl MlKem { } } +impl Zeroize for MlKem { + fn zeroize(&mut self) { + self.ws_key = core::ptr::null_mut(); + } +} + impl Drop for MlKem { /// Safely free the underlying wolfSSL ML-KEM key context. /// @@ -793,5 +800,6 @@ impl Drop for MlKem { unsafe { sys::wc_MlKemKey_Delete(self.ws_key, core::ptr::null_mut()); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/random.rs b/wrapper/rust/wolfssl-wolfcrypt/src/random.rs index 798ecc1825..94ef3d70c4 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/random.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/random.rs @@ -46,6 +46,7 @@ rng.generate_block(&mut buffer).expect("Failed to generate a block"); use crate::sys; use core::mem::{size_of_val, MaybeUninit}; +use zeroize::Zeroize; /// A cryptographically secure random number generator based on the wolfSSL /// library. @@ -410,6 +411,12 @@ impl rand_core::TryRng for RNG { #[cfg(feature = "rand_core")] impl rand_core::TryCryptoRng for RNG {} +impl Zeroize for RNG { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_rng); } + } +} + impl Drop for RNG { /// Safely free the underlying wolfSSL RNG context. /// @@ -420,5 +427,6 @@ impl Drop for RNG { /// preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_FreeRng(&mut self.wc_rng); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs b/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs index 24796e46fa..19344b3bea 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs @@ -63,6 +63,7 @@ use crate::sys; #[cfg(random)] use crate::random::RNG; use core::mem::{MaybeUninit}; +use zeroize::Zeroize; /// The `RSA` struct manages the lifecycle of a wolfSSL `RsaKey` object. /// @@ -1283,6 +1284,12 @@ impl RSA { } } +impl Zeroize for RSA { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_rsakey); } + } +} + impl Drop for RSA { /// Safely free the underlying wolfSSL RSA context. /// @@ -1293,5 +1300,6 @@ impl Drop for RSA { /// preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_FreeRsaKey(&mut self.wc_rsakey); } + self.zeroize(); } } diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/sha.rs b/wrapper/rust/wolfssl-wolfcrypt/src/sha.rs index 9cbfcaf24c..a2731904fa 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/sha.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/sha.rs @@ -25,6 +25,7 @@ Algorithm (SHA) functionality. use crate::sys; use core::mem::MaybeUninit; +use zeroize::Zeroize; /// Context for SHA-1 computation. #[cfg(sha)] @@ -215,6 +216,13 @@ impl SHA { } } +#[cfg(sha)] +impl Zeroize for SHA { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_sha); } + } +} + #[cfg(sha)] impl Drop for SHA { /// Safely free the underlying wolfSSL SHA context. @@ -226,6 +234,7 @@ impl Drop for SHA { /// preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_ShaFree(&mut self.wc_sha); } + self.zeroize(); } } @@ -418,6 +427,13 @@ impl SHA224 { } } +#[cfg(sha224)] +impl Zeroize for SHA224 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_sha224); } + } +} + #[cfg(sha224)] impl Drop for SHA224 { /// Safely free the underlying wolfSSL SHA224 context. @@ -429,6 +445,7 @@ impl Drop for SHA224 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha224Free(&mut self.wc_sha224); } + self.zeroize(); } } @@ -621,6 +638,13 @@ impl SHA256 { } } +#[cfg(sha256)] +impl Zeroize for SHA256 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_sha256); } + } +} + #[cfg(sha256)] impl Drop for SHA256 { /// Safely free the underlying wolfSSL SHA256 context. @@ -632,6 +656,7 @@ impl Drop for SHA256 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha256Free(&mut self.wc_sha256); } + self.zeroize(); } } @@ -824,6 +849,13 @@ impl SHA384 { } } +#[cfg(sha384)] +impl Zeroize for SHA384 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_sha384); } + } +} + #[cfg(sha384)] impl Drop for SHA384 { /// Safely free the underlying wolfSSL SHA384 context. @@ -835,6 +867,7 @@ impl Drop for SHA384 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha384Free(&mut self.wc_sha384); } + self.zeroize(); } } @@ -1027,6 +1060,13 @@ impl SHA512 { } } +#[cfg(sha512)] +impl Zeroize for SHA512 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_sha512); } + } +} + #[cfg(sha512)] impl Drop for SHA512 { /// Safely free the underlying wolfSSL SHA512 context. @@ -1038,6 +1078,7 @@ impl Drop for SHA512 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha512Free(&mut self.wc_sha512); } + self.zeroize(); } } @@ -1230,6 +1271,13 @@ impl SHA3_224 { } } +#[cfg(sha3)] +impl Zeroize for SHA3_224 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_sha3); } + } +} + #[cfg(sha3)] impl Drop for SHA3_224 { /// Safely free the underlying wolfSSL SHA3_224 context. @@ -1241,6 +1289,7 @@ impl Drop for SHA3_224 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha3_224_Free(&mut self.wc_sha3); } + self.zeroize(); } } @@ -1433,6 +1482,13 @@ impl SHA3_256 { } } +#[cfg(sha3)] +impl Zeroize for SHA3_256 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_sha3); } + } +} + #[cfg(sha3)] impl Drop for SHA3_256 { /// Safely free the underlying wolfSSL SHA3_256 context. @@ -1444,6 +1500,7 @@ impl Drop for SHA3_256 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha3_256_Free(&mut self.wc_sha3); } + self.zeroize(); } } @@ -1636,6 +1693,13 @@ impl SHA3_384 { } } +#[cfg(sha3)] +impl Zeroize for SHA3_384 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_sha3); } + } +} + #[cfg(sha3)] impl Drop for SHA3_384 { /// Safely free the underlying wolfSSL SHA3_384 context. @@ -1647,6 +1711,7 @@ impl Drop for SHA3_384 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha3_384_Free(&mut self.wc_sha3); } + self.zeroize(); } } @@ -1839,6 +1904,13 @@ impl SHA3_512 { } } +#[cfg(sha3)] +impl Zeroize for SHA3_512 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_sha3); } + } +} + #[cfg(sha3)] impl Drop for SHA3_512 { /// Safely free the underlying wolfSSL SHA3_512 context. @@ -1850,6 +1922,7 @@ impl Drop for SHA3_512 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Sha3_512_Free(&mut self.wc_sha3); } + self.zeroize(); } } @@ -2109,6 +2182,13 @@ impl SHAKE128 { } } +#[cfg(shake128)] +impl Zeroize for SHAKE128 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_shake); } + } +} + #[cfg(shake128)] impl Drop for SHAKE128 { /// Safely free the underlying wolfSSL SHAKE128 context. @@ -2120,6 +2200,7 @@ impl Drop for SHAKE128 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Shake128_Free(&mut self.wc_shake); } + self.zeroize(); } } @@ -2379,6 +2460,13 @@ impl SHAKE256 { } } +#[cfg(shake256)] +impl Zeroize for SHAKE256 { + fn zeroize(&mut self) { + unsafe { crate::zeroize_raw(&mut self.wc_shake); } + } +} + #[cfg(shake256)] impl Drop for SHAKE256 { /// Safely free the underlying wolfSSL SHAKE256 context. @@ -2390,5 +2478,6 @@ impl Drop for SHAKE256 { /// and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_Shake256_Free(&mut self.wc_shake); } + self.zeroize(); } }