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:PROT_NONE
when theSecretVec
has no outstanding borrowsPROT_READ
when it has outstanding immutable borrowsPROT_WRITE
when it has an outstanding mutable borrow
- 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
isdrop
ped mlock(2)
is called on the underlying memorymunlock(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
Clone
ing 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-mprotect
ed
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_mut
s 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
sourceimpl<T: Bytes> SecretVec<T>
impl<T: Bytes> SecretVec<T>
sourcepub fn new<F>(len: usize, f: F) -> Self where
F: FnOnce(&mut [T]),
pub fn new<F>(len: usize, f: F) -> Self where
F: FnOnce(&mut [T]),
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]);
sourcepub fn borrow(&self) -> Ref<'_, T>
pub fn borrow(&self) -> Ref<'_, T>
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);
sourcepub fn borrow_mut(&mut self) -> RefMut<'_, T>
pub fn borrow_mut(&mut self) -> RefMut<'_, T>
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]);
sourceimpl<T: Bytes + Randomizable> SecretVec<T>
impl<T: Bytes + Randomizable> SecretVec<T>
Trait Implementations
impl<T: Eq + Bytes> Eq for SecretVec<T>
impl<T: Bytes> StructuralEq for SecretVec<T>
Auto Trait Implementations
impl<T> !RefUnwindSafe for SecretVec<T>
impl<T> Send for SecretVec<T> where
T: Send,
impl<T> !Sync for SecretVec<T>
impl<T> Unpin for SecretVec<T>
impl<T> UnwindSafe for SecretVec<T> where
T: RefUnwindSafe,
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<T> ToOwned for T where
T: Clone,
impl<T> ToOwned for T where
T: Clone,
type Owned = T
type Owned = T
The resulting type after obtaining ownership.
sourcefn clone_into(&self, target: &mut T)
fn clone_into(&self, target: &mut T)
toowned_clone_into
)Uses borrowed data to replace owned data, usually by cloning. Read more