diff --git a/.github/workflows/qc.yaml b/.github/workflows/qc.yaml index eda617a..903282e 100644 --- a/.github/workflows/qc.yaml +++ b/.github/workflows/qc.yaml @@ -154,5 +154,5 @@ jobs: cargo fuzz run fuzz_handle_msg -- -max_total_time=5 ulimit -s 8192000 && RUST_MIN_STACK=33554432000 && cargo fuzz run fuzz_kyber_encaps -- -max_total_time=5 cargo fuzz run fuzz_mceliece_encaps -- -max_total_time=5 - cargo fuzz run fuzz_box_sodium_alloc -- -max_total_time=5 - cargo fuzz run fuzz_vec_sodium_alloc -- -max_total_time=5 + cargo fuzz run fuzz_box_secret_alloc -- -max_total_time=5 + cargo fuzz run fuzz_vec_secret_alloc -- -max_total_time=5 diff --git a/Cargo.lock b/Cargo.lock index b4f59a0..918c4cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,9 +46,18 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "c4f263788a35611fba42eb41ff811c5d0360c58b97402570312a350736e2542e" + +[[package]] +name = "allocator-api2-tests" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6d832cc75b9841b21c847420f1334645387f088324f34eac923a98efa3d89" +dependencies = [ + "allocator-api2", +] [[package]] name = "anes" @@ -804,6 +813,17 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memsec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa0916b001582d253822171bd23f4a0229d32b9507fae236f5da8cad515ba7c" +dependencies = [ + "getrandom", + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1190,9 +1210,13 @@ dependencies = [ name = "rosenpass-secret-memory" version = "0.1.0" dependencies = [ + "allocator-api2", + "allocator-api2-tests", "anyhow", "lazy_static", "libsodium-sys-stable", + "log", + "memsec", "rand", "rosenpass-sodium", "rosenpass-to", @@ -1704,6 +1728,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -1722,6 +1755,21 @@ dependencies = [ "windows-targets 0.52.0", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -1752,6 +1800,12 @@ dependencies = [ "windows_x86_64_msvc 0.52.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -1764,6 +1818,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -1776,6 +1836,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -1788,6 +1854,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -1800,6 +1872,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -1812,6 +1890,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -1824,6 +1908,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" diff --git a/Cargo.toml b/Cargo.toml index 3ab316f..96337f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,9 @@ paste = "1.0.14" env_logger = "0.10.1" toml = "0.7.8" static_assertions = "1.1.0" -allocator-api2 = "0.2.16" +allocator-api2 = "0.2.14" +allocator-api2-tests = "0.2.14" +memsec = "0.6.3" rand = "0.8.5" log = { version = "0.4.20" } clap = { version = "4.4.10", features = ["derive"] } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 89000db..0e26f23 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -49,13 +49,13 @@ test = false doc = false [[bin]] -name = "fuzz_box_sodium_alloc" -path = "fuzz_targets/box_sodium_alloc.rs" +name = "fuzz_box_secret_alloc" +path = "fuzz_targets/box_secret_alloc.rs" test = false doc = false [[bin]] -name = "fuzz_vec_sodium_alloc" -path = "fuzz_targets/vec_sodium_alloc.rs" +name = "fuzz_vec_secret_alloc" +path = "fuzz_targets/vec_secret_alloc.rs" test = false doc = false diff --git a/fuzz/fuzz_targets/box_secret_alloc.rs b/fuzz/fuzz_targets/box_secret_alloc.rs new file mode 100644 index 0000000..872ef8f --- /dev/null +++ b/fuzz/fuzz_targets/box_secret_alloc.rs @@ -0,0 +1,8 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use rosenpass_secret_memory::alloc::secret_box; + +fuzz_target!(|data: &[u8]| { + let _ = secret_box(data); +}); diff --git a/fuzz/fuzz_targets/box_sodium_alloc.rs b/fuzz/fuzz_targets/box_sodium_alloc.rs deleted file mode 100644 index e1b1799..0000000 --- a/fuzz/fuzz_targets/box_sodium_alloc.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![no_main] - -use libfuzzer_sys::fuzz_target; -use rosenpass_sodium::{ - alloc::{Alloc as SodiumAlloc, Box as SodiumBox}, - init, -}; - -fuzz_target!(|data: &[u8]| { - let _ = init(); - let _ = SodiumBox::new_in(data, SodiumAlloc::new()); -}); diff --git a/fuzz/fuzz_targets/vec_secret_alloc.rs b/fuzz/fuzz_targets/vec_secret_alloc.rs new file mode 100644 index 0000000..66b4ae2 --- /dev/null +++ b/fuzz/fuzz_targets/vec_secret_alloc.rs @@ -0,0 +1,9 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use rosenpass_secret_memory::alloc::secret_vec; + +fuzz_target!(|data: &[u8]| { + let mut vec = secret_vec(); + vec.extend_from_slice(data); +}); diff --git a/fuzz/fuzz_targets/vec_sodium_alloc.rs b/fuzz/fuzz_targets/vec_sodium_alloc.rs deleted file mode 100644 index a37368d..0000000 --- a/fuzz/fuzz_targets/vec_sodium_alloc.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![no_main] - -use libfuzzer_sys::fuzz_target; -use rosenpass_sodium::{ - alloc::{Alloc as SodiumAlloc, Vec as SodiumVec}, - init, -}; - -fuzz_target!(|data: &[u8]| { - let _ = init(); - let mut vec = SodiumVec::new_in(SodiumAlloc::new()); - vec.extend_from_slice(data); -}); diff --git a/secret-memory/Cargo.toml b/secret-memory/Cargo.toml index 45b5169..ebb4d19 100644 --- a/secret-memory/Cargo.toml +++ b/secret-memory/Cargo.toml @@ -18,3 +18,9 @@ libsodium-sys-stable = { workspace = true } lazy_static = { workspace = true } zeroize = { workspace = true } rand = { workspace = true } +memsec = { workspace = true } +allocator-api2 = { workspace = true } +log = { workspace = true } + +[dev-dependencies] +allocator-api2-tests = { workspace = true } diff --git a/secret-memory/src/alloc/memsec.rs b/secret-memory/src/alloc/memsec.rs new file mode 100644 index 0000000..cfbf99a --- /dev/null +++ b/secret-memory/src/alloc/memsec.rs @@ -0,0 +1,108 @@ +use std::fmt; +use std::ptr::NonNull; + +use allocator_api2::alloc::{AllocError, Allocator, Layout}; + +#[derive(Copy, Clone, Default)] +struct MemsecAllocatorContents; + +/// Memory allocation using sodium_malloc/sodium_free +#[derive(Copy, Clone, Default)] +pub struct MemsecAllocator { + _dummy_private_data: MemsecAllocatorContents, +} + +/// A box backed by the memsec allocator +pub type MemsecBox = allocator_api2::boxed::Box; + +/// A vector backed by the memsec allocator +pub type MemsecVec = allocator_api2::vec::Vec; + +pub fn memsec_box(x: T) -> MemsecBox { + MemsecBox::::new_in(x, MemsecAllocator::new()) +} + +pub fn memsec_vec() -> MemsecVec { + MemsecVec::::new_in(MemsecAllocator::new()) +} + +impl MemsecAllocator { + pub fn new() -> Self { + Self { + _dummy_private_data: MemsecAllocatorContents, + } + } +} + +unsafe impl Allocator for MemsecAllocator { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + // Call memsec allocator + let mem: Option> = unsafe { memsec::malloc_sized(layout.size()) }; + + // Unwrap the option + let Some(mem) = mem else { + log::error!("Allocation {layout:?} was requested but memsec returned a null pointer"); + return Err(AllocError); + }; + + // Ensure the right alignment is used + let off = (mem.as_ptr() as *const u8).align_offset(layout.align()); + if off != 0 { + log::error!("Allocation {layout:?} was requested but memsec returned allocation \ + with offset {off} from the requested alignment. Memsec always allocates values \ + at the end of a memory page for security reasons, custom alignments are not supported. \ + You could try allocating an oversized value."); + unsafe { memsec::free(mem) }; + return Err(AllocError); + }; + + Ok(mem) + } + + unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { + unsafe { + memsec::free(ptr); + } + } +} + +impl fmt::Debug for MemsecAllocator { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str("") + } +} + +#[cfg(test)] +mod test { + use allocator_api2_tests::make_test; + + use super::*; + + make_test! { test_sizes(MemsecAllocator::new()) } + make_test! { test_vec(MemsecAllocator::new()) } + make_test! { test_many_boxes(MemsecAllocator::new()) } + + #[test] + fn memsec_allocation() { + let alloc = MemsecAllocator::new(); + memsec_allocation_impl::<0>(&alloc); + memsec_allocation_impl::<7>(&alloc); + memsec_allocation_impl::<8>(&alloc); + memsec_allocation_impl::<64>(&alloc); + memsec_allocation_impl::<999>(&alloc); + } + + fn memsec_allocation_impl(alloc: &MemsecAllocator) { + let layout = Layout::new::<[u8; N]>(); + let mem = alloc.allocate(layout).unwrap(); + + // https://libsodium.gitbook.io/doc/memory_management#guarded-heap-allocations + // promises us that allocated memory is initialized with the magic byte 0xDB + // and memsec promises to provide a reimplementation of the libsodium mechanism; + // it uses the magic value 0xD0 though + assert_eq!(unsafe { mem.as_ref() }, &[0xD0u8; N]); + + let mem = NonNull::new(mem.as_ptr() as *mut u8).unwrap(); + unsafe { alloc.deallocate(mem, layout) }; + } +} diff --git a/secret-memory/src/alloc/mod.rs b/secret-memory/src/alloc/mod.rs new file mode 100644 index 0000000..e97fd8d --- /dev/null +++ b/secret-memory/src/alloc/mod.rs @@ -0,0 +1,6 @@ +pub mod memsec; + +pub use crate::alloc::memsec::{ + memsec_box as secret_box, memsec_vec as secret_vec, MemsecAllocator as SecretAllocator, + MemsecBox as SecretBox, MemsecVec as SecretVec, +}; diff --git a/secret-memory/src/lib.rs b/secret-memory/src/lib.rs index 75a6e72..b38ed75 100644 --- a/secret-memory/src/lib.rs +++ b/secret-memory/src/lib.rs @@ -2,6 +2,8 @@ pub mod debug; pub mod file; pub mod rand; +pub mod alloc; + mod public; pub use crate::public::Public; diff --git a/secret-memory/src/secret.rs b/secret-memory/src/secret.rs index 54cc5a4..74764fe 100644 --- a/secret-memory/src/secret.rs +++ b/secret-memory/src/secret.rs @@ -1,15 +1,18 @@ -use crate::file::StoreSecret; +use std::{collections::HashMap, convert::TryInto, fmt, path::Path, sync::Mutex}; + use anyhow::Context; use lazy_static::lazy_static; use rand::{Fill as Randomize, Rng}; -use rosenpass_sodium::alloc::{Alloc as SodiumAlloc, Box as SodiumBox, Vec as SodiumVec}; +use zeroize::{Zeroize, ZeroizeOnDrop}; + use rosenpass_util::{ b64::b64_reader, file::{fopen_r, LoadValue, LoadValueB64, ReadExactToEnd}, functional::mutating, }; -use std::{collections::HashMap, convert::TryInto, fmt, path::Path, sync::Mutex}; -use zeroize::{Zeroize, ZeroizeOnDrop}; + +use crate::alloc::{secret_box, SecretBox, SecretVec}; +use crate::file::StoreSecret; // This might become a problem in library usage; it's effectively a memory // leak which probably isn't a problem right now because most memory will @@ -28,7 +31,7 @@ lazy_static! { /// [libsodium documentation](https://libsodium.gitbook.io/doc/memory_management#guarded-heap-allocations) #[derive(Debug)] // TODO check on Debug derive, is that clever struct SecretMemoryPool { - pool: HashMap>>, + pool: HashMap>>, } impl SecretMemoryPool { @@ -41,13 +44,13 @@ impl SecretMemoryPool { } /// Return secret back to the pool for future re-use - pub fn release(&mut self, mut sec: SodiumBox<[u8; N]>) { + pub fn release(&mut self, mut sec: SecretBox<[u8; N]>) { sec.zeroize(); // This conversion sequence is weird but at least it guarantees // that the heap allocation is preserved according to the docs - let sec: SodiumVec = sec.into(); - let sec: SodiumBox<[u8]> = sec.into(); + let sec: SecretVec = sec.into(); + let sec: SecretBox<[u8]> = sec.into(); self.pool.entry(N).or_default().push(sec); } @@ -56,10 +59,10 @@ impl SecretMemoryPool { /// chunk is found in the inventory. /// /// The secret is guaranteed to be full of nullbytes - pub fn take(&mut self) -> SodiumBox<[u8; N]> { + pub fn take(&mut self) -> SecretBox<[u8; N]> { let entry = self.pool.entry(N).or_default(); match entry.pop() { - None => SodiumBox::new_in([0u8; N], SodiumAlloc::default()), + None => secret_box([0u8; N]), Some(sec) => sec.try_into().unwrap(), } } @@ -67,7 +70,7 @@ impl SecretMemoryPool { /// Storeage for a secret backed by [rosenpass_sodium::alloc::Alloc] pub struct Secret { - storage: Option>, + storage: Option>, } impl Secret { @@ -200,7 +203,7 @@ mod test { rosenpass_sodium::init().unwrap(); const N: usize = 0x100; let mut pool = SecretMemoryPool::new(); - let secret: SodiumBox<[u8; N]> = pool.take(); + let secret: SecretBox<[u8; N]> = pool.take(); assert_eq!(secret.as_ref(), &[0; N]); } @@ -210,7 +213,7 @@ mod test { rosenpass_sodium::init().unwrap(); const N: usize = 0x100; let mut pool = SecretMemoryPool::new(); - let secret: SodiumBox<[u8; N]> = pool.take(); + let secret: SecretBox<[u8; N]> = pool.take(); std::mem::drop(pool); assert_eq!(secret.as_ref(), &[0; N]); } @@ -221,14 +224,14 @@ mod test { rosenpass_sodium::init().unwrap(); const N: usize = 1; let mut pool = SecretMemoryPool::new(); - let mut secret: SodiumBox<[u8; N]> = pool.take(); + let mut secret: SecretBox<[u8; N]> = pool.take(); let old_secret_ptr = secret.as_ref().as_ptr(); secret.as_mut()[0] = 0x13; pool.release(secret); // now check that we get the same ptr - let new_secret: SodiumBox<[u8; N]> = pool.take(); + let new_secret: SecretBox<[u8; N]> = pool.take(); assert_eq!(old_secret_ptr, new_secret.as_ref().as_ptr()); // and that the secret was zeroized diff --git a/sodium/src/alloc/allocator.rs b/sodium/src/alloc/allocator.rs deleted file mode 100644 index ad1314c..0000000 --- a/sodium/src/alloc/allocator.rs +++ /dev/null @@ -1,95 +0,0 @@ -use allocator_api2::alloc::{AllocError, Allocator, Layout}; -use libsodium_sys as libsodium; -use std::fmt; -use std::os::raw::c_void; -use std::ptr::NonNull; - -#[derive(Clone, Default)] -struct AllocatorContents; - -/// Memory allocation using sodium_malloc/sodium_free -#[derive(Clone, Default)] -pub struct Alloc { - _dummy_private_data: AllocatorContents, -} - -impl Alloc { - pub fn new() -> Self { - Alloc { - _dummy_private_data: AllocatorContents, - } - } -} - -unsafe impl Allocator for Alloc { - fn allocate(&self, layout: Layout) -> Result, AllocError> { - // Call sodium allocator - let ptr = unsafe { libsodium::sodium_malloc(layout.size()) }; - - // Ensure the right allocation is used - let off = ptr.align_offset(layout.align()); - if off != 0 { - log::error!("Allocation {layout:?} was requested but libsodium returned allocation \ - with offset {off} from the requested alignment. Libsodium always allocates values \ - at the end of a memory page for security reasons, custom alignments are not supported. \ - You could try allocating an oversized value."); - return Err(AllocError); - } - - // Convert to a pointer size - let ptr = core::ptr::slice_from_raw_parts_mut(ptr as *mut u8, layout.size()); - - // Conversion to a *const u8, then to a &[u8] - match NonNull::new(ptr) { - None => { - log::error!( - "Allocation {layout:?} was requested but libsodium returned a null pointer" - ); - Err(AllocError) - } - Some(ret) => Ok(ret), - } - } - - unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { - unsafe { - libsodium::sodium_free(ptr.as_ptr() as *mut c_void); - } - } -} - -impl fmt::Debug for Alloc { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str("") - } -} - -#[cfg(test)] -mod test { - use super::*; - - /// checks that the can malloc with libsodium - #[test] - fn sodium_allocation() { - crate::init().unwrap(); - let alloc = Alloc::new(); - sodium_allocation_impl::<0>(&alloc); - sodium_allocation_impl::<7>(&alloc); - sodium_allocation_impl::<8>(&alloc); - sodium_allocation_impl::<64>(&alloc); - sodium_allocation_impl::<999>(&alloc); - } - - fn sodium_allocation_impl(alloc: &Alloc) { - crate::init().unwrap(); - let layout = Layout::new::<[u8; N]>(); - let mem = alloc.allocate(layout).unwrap(); - - // https://libsodium.gitbook.io/doc/memory_management#guarded-heap-allocations - // promises us that allocated memory is initialized with the magic byte 0xDB - assert_eq!(unsafe { mem.as_ref() }, &[0xDBu8; N]); - - let mem = NonNull::new(mem.as_ptr() as *mut u8).unwrap(); - unsafe { alloc.deallocate(mem, layout) }; - } -} diff --git a/sodium/src/alloc/mod.rs b/sodium/src/alloc/mod.rs deleted file mode 100644 index 0dceb01..0000000 --- a/sodium/src/alloc/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Access to sodium_malloc/sodium_free - -mod allocator; -pub use allocator::Alloc; - -/// A box backed by sodium_malloc -pub type Box = allocator_api2::boxed::Box; - -/// A vector backed by sodium_malloc -pub type Vec = allocator_api2::vec::Vec; diff --git a/sodium/src/lib.rs b/sodium/src/lib.rs index 752e1a7..606bbd0 100644 --- a/sodium/src/lib.rs +++ b/sodium/src/lib.rs @@ -16,6 +16,5 @@ pub fn init() -> anyhow::Result<()> { } pub mod aead; -pub mod alloc; pub mod hash; pub mod helpers;