1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#![cfg_attr(feature = "nightly_allocator_api", feature(allocator_api))]
#![cfg_attr(feature = "nightly_core_intrinsics", feature(core_intrinsics))]
#![cfg_attr(not(feature = "std"), no_std)]
#![forbid(future_incompatible, rust_2018_compatibility, unsafe_op_in_unsafe_fn)]
#![deny(rust_2018_idioms)]
#![warn(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
//! `secmem-alloc` is a crate designed allocate private/secret memory. It is
//! intended to be used for storing cryptographic secrets in memory. This crate
//! provides custom allocators using various techniques to improve secrecy of
//! the memory, most notably zeroization on deallocation.
//!
//! # Examples
//! For example, we read in a secret password from standard-in, which we want to
//! zeroize on drop (deallocation). Note that this code does leave the password
//! visible on the prompt; it is only to give an idea of how to use this crate.
//!
//! ```
//! #![feature(allocator_api)]
//! // requires `nightly_allocator_api` crate feature to be enabled and a nightly compiler
//! use secmem_alloc::allocator_api::Allocator;
//! use secmem_alloc::zeroizing_alloc::ZeroizeAlloc;
//! use std::alloc::Global;
//!
//! fn read_password<A: Allocator>(buf: &mut Vec<u8, A>) {
//!     // query password from the user and put it in `buf`
//! }
//!
//! fn main() {
//!     println!("Please enter your password: ");
//!     let mut stdin = std::io::stdin();
//!     let allocator = ZeroizeAlloc::new(Global);
//!     let mut password = Vec::new_in(allocator);
//!     read_password(&mut password);
//!
//!     // use `password` however you like
//!     // you can even grow and shrink the vector `password` and if it needs to be reallocated, the
//!     // old allocation is immediately zeroized
//!
//!     // password is automatically zeroized on drop (deallocation)
//! }
//! ```
//!
//! As a second example assume you have a cryptographic secret key of 256 bytes,
//! which should be zeroized on drop. In addition, we don't want the key to be
//! written to swap.
//!
//! ```
//! // requires no crate features and works on stable
//! // if you enable the `nightly_allocator_api` crate feature, the following line is necessary
//! #![feature(allocator_api)]
//!
//! use secmem_alloc::allocator_api::Allocator;
//! use secmem_alloc::boxed::Box;
//! use secmem_alloc::sec_alloc::SecStackSinglePageAlloc;
//!
//! fn get_secret_key<A: Allocator>(buf: &mut Box<[u8; 256], A>) {
//!     // fill `buf` with the bytes of the secret key
//! }
//!
//! fn main() {
//!     let allocator: SecStackSinglePageAlloc =
//!         SecStackSinglePageAlloc::new().expect("could not create allocator");
//!     let mut key = Box::new_in([0_u8; 256], &allocator);
//!     get_secret_key(&mut key);
//!
//!     // use `key` however you like
//!     // `key` will not be written to swap except possibly on hibernation
//!
//!     // `key` is automatically zeroized on drop (deallocation)
//! }
//! ```
//!
//!
//! # Cargo features
//! - `std` (default): Enable functionality that requires `std`. Currently only
//!   required for `Error` implements and required for tests. This feature is
//!   enabled by default.
//! - `cc` (default): Enable functionality which requires a C compiler. This is
//!   currently only used to implement a secure memory zeroizer
//!   `AsmRepStosZeroizer` written in assembly. This feature is enabled by
//!   default.
//! - `nightly_allocator_api` (requires nightly): Use the nightly allocator api
//!   from the standard library (actually the `core` crate), gated behind the
//!   nightly-only feature `allocator_api`. When disabled, a copy of the
//!   allocator api included in this crate, available through
//!   `secmem_alloc::allocator_api`, will be used. This features requires a
//!   nightly compiler.
//! - `nightly_core_intrinsics` (requires nightly): Use the intrinsics from the
//!   standard library (actually the `core` crate), gated behind the
//!   nightly-only feature `core_intrinsics`. This enables the extremely fast
//!   `VolatileMemsetZeroizer` zeroizer, and various other small optimisations.
//!   This features requires a nightly compiler.
//! - `nightly` (requires nightly): Enable all nightly-only features (i.e. the
//!   above two). Enabling this feature is highly recommended when a nightly
//!   compiler is available. This features requires a nightly compiler.
//! - `dev` (requires nightly): This feature enables all features required to
//!   run the test-suite, and should only be enabled for that purpose. This
//!   features currently requires a nightly compiler.

extern crate alloc;

mod internals;
mod util;

#[cfg(not(feature = "nightly_allocator_api"))]
pub mod allocator_api;
#[cfg(feature = "nightly_allocator_api")]
/// Nightly allocator api, imported from the standard library.
pub mod allocator_api {
    pub use core::alloc::{AllocError, Allocator};
}

pub mod boxed;
pub mod sec_alloc;
pub mod zeroize;
pub mod zeroizing_alloc;

#[cfg(test)]
mod tests {
    /// > Freedom is the freedom to say that two plus two makes four.
    ///
    /// Nineteen Eighty-Four, George Orwell
    #[test]
    fn freedom() {
        assert_ne!(2 + 2, 5);
        assert_eq!(2 + 2, 4);
    }
}