Crate hard[][src]

Expand description

Security-hardened buffers for storing sensitive data in memory.

This crate provides hardened buffer types backed by memory allocated using libsodium’s secure memory management utilities. The intention is to provide types for securely storing sensitive data (cryptographic keys, passwords, etc).

Memory allocated using hard is placed directly at the end of a page, followed by a guard page, so any buffer overflow will immediately result in the termination of the program. A canary is placed before the allocated memory to detect modifications on free, and another guard page is placed before this. The operating system is advised not to swap the memory to disk, or include it in crash reports/core dumps. Finally, when the memory is freed, it is securely cleared, in such a way that the compiler will not attempt to optimise away the operation.

Hard also provides an interface for marking memory as read-only/no-access when its modification/access is not required. This can be used to protect sensitive data from access while not in use. Enable the restricted-types feature to generate the code necessary for this: Extra types will be generated for each buffer type, which only support readonly/noaccess contents.

Examples

use hard::{buffer_type, Buffer, BufferMut};

// Create a new public buffer type, which will store 32 bytes (= 256 bits) of sensitive data:
buffer_type! {
    /// Stores a 256-bit key.
    pub Key(32);
}

// The new type implements a couple of basic traits for its construction and initialisation:
let mut my_key = Key::new().unwrap();
my_key.zero();

// It also implements `Deref`, and similar types associated with smart pointers, so we can
// treat it like an array [u8; 32]:
my_key.copy_from_slice(b"Some data to store in the buffer");
my_key[0] ^= 0xab;
my_key[1] ^= 0xcd;

// Mark the buffer as read-only, which will prevent modification to its contents:
// This requires the "restricted-types" feature to be enabled!
let my_key = my_key.into_readonly().unwrap();

// We can also mark the buffer as no-access, which prevents reading its contents as well as
// writing to it. Again, this requires the "restricted-types" feature!
let my_key = my_key.into_noaccess().unwrap();

// And finally, we can convert it back to the standard readable, mutable buffer like so:
let my_key = my_key.into_mut().unwrap();

// When the buffer is dropped, its contents are securely erased, preventing leakage of the
// contents via uninitialised memory.

We can also create anonymous buffers, which provide access to hardened memory without the need to worry about creating new types for whatever operation we perform:

use hard::{buffer, Buffer, BufferMut};

// Create a 512 byte buffer.
let mut some_data = buffer!(512).unwrap();

// Copy in some data
some_data.copy_from_slice(&[0xab; 512]);

// Debugging a buffer does not directly print its contents, although deref'ing it does do so.
println!("{:?}, {:?}", some_data, *some_data);

// Once again, dropping the buffer erases its contents.

For more information, see the buffer and buffer_type macros, and the traits the buffer types implement: Buffer and BufferMut.

Re-exports

pub use paste;

Modules

Low level memory-management utilities.

Macros

Create a fixed-size anonymous buffer.

Create a new fixed-size buffer type.

Enums

Represents an error encountered while using Hard.

Traits

Trait implemented by any buffer type generated with buffer_type.

Trait implemented by any buffer type with mutable contents.

Functions

Initialise Sodium.