secmem_alloc/lib.rs
1// https://github.com/rust-lang/rust/issues/32838
2#![cfg_attr(feature = "nightly_allocator_api", feature(allocator_api))]
3// for `volatile_memset`
4#![cfg_attr(feature = "nightly_core_intrinsics", feature(core_intrinsics))]
5#![cfg_attr(not(feature = "std"), no_std)]
6#![forbid(rust_2018_compatibility, unsafe_op_in_unsafe_fn)]
7#![deny(future_incompatible, rust_2018_idioms)]
8#![warn(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
9// on nightly, enable some unstable lints
10#![cfg_attr(
11 feature = "nightly",
12 deny(fuzzy_provenance_casts, lossy_provenance_casts)
13)]
14//! `secmem-alloc` is a crate designed allocate private/secret memory. It is
15//! intended to be used for storing cryptographic secrets in memory. This crate
16//! provides custom allocators using various techniques to improve secrecy of
17//! the memory, most notably zeroization on deallocation.
18//!
19//! # Examples
20//! For example, we read in a secret password from standard-in, which we want to
21//! zeroize on drop (deallocation). Note that this code does leave the password
22//! visible on the prompt; it is only to give an idea of how to use this crate.
23//!
24//! ```
25//! #![feature(allocator_api)]
26//! // requires `nightly_allocator_api` crate feature to be enabled and a nightly compiler
27//! use secmem_alloc::allocator_api::{Allocator, Global, Vec};
28//! use secmem_alloc::zeroizing_alloc::ZeroizeAlloc;
29//!
30//! fn read_password<A: Allocator>(buf: &mut Vec<u8, A>) {
31//! // query password from the user and put it in `buf`
32//! }
33//!
34//! fn main() {
35//! println!("Please enter your password: ");
36//! let mut stdin = std::io::stdin();
37//! let allocator = ZeroizeAlloc::new(Global);
38//! let mut password = Vec::new_in(allocator);
39//! read_password(&mut password);
40//!
41//! // use `password` however you like
42//! // you can even grow and shrink the vector `password` and if it needs to be reallocated, the
43//! // old allocation is immediately zeroized
44//!
45//! // password is automatically zeroized on drop (deallocation)
46//! }
47//! ```
48//!
49//! As a second example assume you have a cryptographic secret key of 256 bytes,
50//! which should be zeroized on drop. In addition, we don't want the key to be
51//! written to swap.
52//!
53//! ```
54//! // requires no crate features and works on stable
55//! // if you enable the `nightly_allocator_api` crate feature, the following line is necessary
56//! #![feature(allocator_api)]
57//!
58//! use secmem_alloc::allocator_api::{Allocator, Box};
59//! use secmem_alloc::sec_alloc::SecStackSinglePageAlloc;
60//!
61//! fn get_secret_key<A: Allocator>(buf: &mut Box<[u8; 256], A>) {
62//! // fill `buf` with the bytes of the secret key
63//! }
64//!
65//! fn main() {
66//! let allocator: SecStackSinglePageAlloc =
67//! SecStackSinglePageAlloc::new().expect("could not create allocator");
68//! let mut key = Box::new_in([0_u8; 256], &allocator);
69//! get_secret_key(&mut key);
70//!
71//! // use `key` however you like
72//! // `key` will not be written to swap except possibly on hibernation
73//!
74//! // `key` is automatically zeroized on drop (deallocation)
75//! }
76//! ```
77//!
78//!
79//! # Cargo features
80//! - `std` (default): Enable functionality that requires `std`. Currently only
81//! required for `Error` implements and required for tests. This feature is
82//! enabled by default.
83//! - `nightly_allocator_api` (requires nightly): Use the nightly allocator api
84//! from the standard library (actually the `core` crate), gated behind the
85//! nightly-only feature `allocator_api`. When disabled, a copy of the
86//! allocator api included in this crate, available through
87//! `secmem_alloc::allocator_api`, will be used. This feature requires a
88//! nightly compiler.
89//! - `nightly_core_intrinsics` (requires nightly): Use the intrinsics from the
90//! standard library (actually the `core` crate), gated behind the
91//! nightly-only feature `core_intrinsics`. This allows for a slightly faster
92//! [`zeroize_mem`] implementation, and various other small optimisations.
93//! This feature requires a nightly compiler.
94//! - `nightly` (requires nightly): Enable all nightly-only features (i.e. the
95//! above two). Enabling this feature is highly recommended when a nightly
96//! compiler is available. This feature requires a nightly compiler.
97//! - `dev` (requires nightly): This feature enables all features required to
98//! run the test-suite, and should only be enabled for that purpose. This
99//! feature currently requires a nightly compiler.
100//!
101//!
102//! # MSRV Policy
103//! Since this crate still depends on several nightly features for optimal
104//! functioning, the MSRV is expected to track the latest stable relatively
105//! closely. Therefore, we might bump the MSRV in patch version bumps. This
106//! shouldn't be an issue given the new MSRV aware dependency resolver in
107//! cargo. This policy might change as more unstable features get stabilised.
108
109extern crate alloc;
110
111/// Re-exports the most important items of the [`allocator-api2` crate].
112///
113/// [`allocator-api2` crate]: https://crates.io/crates/allocator-api2
114pub mod allocator_api {
115 pub use allocator_api2::alloc::{Allocator, Global};
116 pub use allocator_api2::boxed::Box;
117 pub use allocator_api2::vec::Vec;
118}
119
120mod internals;
121mod macros;
122mod util;
123mod zeroize;
124
125pub use zeroize::zeroize_mem;
126
127pub mod sec_alloc;
128pub mod zeroizing_alloc;
129
130#[cfg(test)]
131mod tests {
132 /// > Freedom is the freedom to say that two plus two makes four.
133 ///
134 /// Nineteen Eighty-Four, George Orwell
135 #[test]
136 fn freedom() {
137 assert_ne!(2 + 2, 5);
138 assert_eq!(2 + 2, 4);
139 }
140}