pub struct SecretVec<T: Bytes> { /* private fields */ }
Expand description

A type for protecting variable-length secrets allocated on the heap.

Heap-allocated secrets have distinct security needs from stack-allocated ones. They provide the following guarantees:

  • any attempt to access the memory without having been borrowed appropriately will result in immediate program termination; the memory is protected with mprotect(2) as follows:
  • the allocated region has guard pages preceding and following it—both set to PROT_NONE—ensuring that overflows and (large enough) underflows cause immediate program termination
  • a canary is placed just before the memory location (and after the guard page) in order to detect smaller underflows; if this memory has been written to (and the canary modified), the program will immediately abort when the SecretVec is dropped
  • mlock(2) is called on the underlying memory
  • munlock(2) is called on the underlying memory when no longer in use
  • the underlying memory is zeroed when no longer in use
  • they are best-effort compared in constant time
  • they are best-effort prevented from being printed by Debug.
  • they are best-effort protected from Cloneing the interior data

To fulfill these guarantees, SecretVec uses an API similar to (but not exactly like) that of RefCell. You must call borrow to (immutably) borrow the protected data inside and you must call borrow_mut to access it mutably. Unlike RefCell which hides interior mutability with immutable borrows, these two calls follow standard borrowing rules: borrow_mut takes a &mut self, so the borrow checker statically ensures the exclusivity of mutable borrows.

These borrow and borrow_mut calls return a wrapper around the interior that ensures the memory is re-mprotected when all active borrows leave scope. These wrappers Deref to the underlying value so you can to work with them as if they were the underlying type, with a few excepitons: they have specific implementations for Clone, Debug, PartialEq, and Eq that try to ensure that the underlying memory isn’t copied out of protected area, that the contents are never printed, and that two secrets are only ever compared in constant time.

Care must be taken not to over-aggressively dereference these wrappers, as once you’re working with the real underlying type, we can’t prevent direct calls to their implementations of these traits. Care must also be taken not to call any other methods on these types that introduce copying.

Example: generate a cryptographically-random 128-bit SecretVec

Initialize a SecretVec with cryptographically random data:

let secret = SecretVec::<u8>::random(16);

assert_eq!(secret.size(), 16);

Example: move mutable data into a SecretVec

Existing data can be moved into a SecretVec. When doing so, we make a best-effort attempt to zero out the data in the original location. Any prior copies will be unaffected, so please exercise as much caution as possible when handling data before it can be protected.

let mut value = [1u8, 2, 3, 4];

// the contents of `value` will be copied into the SecretVec before
// being zeroed out
let secret = SecretVec::from(&mut value[..]);

// the contents of `value` have been zeroed
assert_eq!(value, [0, 0, 0, 0]);

Example: compilation failure from incompatible borrows

Unlike RefCell, which hides interior mutability behind immutable borrows, a SecretVec can’t have an outstanding borrow and borrow_mut at the same time.

let mut secret   = SecretVec::<u32>::zero(8);
let     secret_r = secret.borrow();

// error[E0502]: cannot borrow `secret` as mutable because it is
// also borrowed as immutable
secret.borrow_mut();

Example: compilation failure from multiple mutable borrows

Unlike RefCell, which hides interior mutability behind immutable borrows, a SecretVec can’t have multiple outstanding borrow_muts at the same time.

let mut secret   = SecretVec::<u32>::zero(8);
let     secret_w = secret.borrow_mut();

// error[E0499]: cannot borrow `secret` as mutable more than once
// at a time
secret.borrow_mut();

Implementations

Instantiates and returns a new SecretVec.

Accepts a callback function that is responsible for initializing its contents. The value yielded to the initialization callback will be filled with garbage bytes.

Example:

let secret = SecretVec::<u8>::new(2, |s| {
    s[0] = 0x10;
    s[1] = 0x20;
});

assert_eq!(*secret.borrow(), [0x10, 0x20]);

Instantiates and returns a new SecretVec. Has equivalent semantics to new, but allows the callback to return success or failure through a Result.

Errors

Returns Err only if the user-provided callback does.

Returns the number of elements in the SecretVec.

Returns true if length of the SecretVec is zero.

Returns the size in bytes of the SecretVec.

Immutably borrows the contents of the SecretVec. Returns a wrapper that ensures the underlying memory is mprotect(2)ed once all borrows exit scope.

Example:

let secret    = SecretVec::<u8>::from(&mut [1, 2][..]);
let secret_r1 = secret.borrow();
let secret_r2 = secret.borrow();

assert_eq!(secret_r1[0], 1);
assert_eq!(secret_r2[1], 2);
assert_eq!(secret_r1, secret_r2);

Mutably borrows the contents of the SecretVec. Returns a wrapper that ensures the underlying memory is mprotect(2)ed once this borrow exits scope.

Example:

let mut secret   = SecretVec::<u8>::zero(2);
let mut secret_w = secret.borrow_mut();

secret_w[0] = 0xaa;

assert_eq!(*secret_w, [0xaa, 0x00]);

Creates a new SecretVec with len elements, filled with cryptographically-random bytes.

Creates a new SecretVec with len elements, filled with zeroes.

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Creates a new SecretVec from existing, unprotected data, and immediately zeroes out the memory of the data being moved in.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

Uses borrowed data to replace owned data, usually by cloning. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.