mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-10-01 19:05:07 +02:00
80 lines
2.1 KiB
Rust
80 lines
2.1 KiB
Rust
use std::convert::TryInto;
|
|
use std::mem::size_of;
|
|
use std::ptr::write_volatile;
|
|
|
|
/// Container for secrets that clears them on drop.
|
|
///
|
|
/// We can't be totally sure that things like libraries are doing this and it's
|
|
/// hard to get every use of a secret anywhere, but using this in our code at
|
|
/// least reduces the number of secrets that are left lying around in memory.
|
|
///
|
|
/// This is generally a low-risk thing since it's process memory that's protected,
|
|
/// but it's still not a bad idea due to things like swap or obscure side channel
|
|
/// attacks that allow memory to be read.
|
|
#[derive(Clone, PartialEq, Eq)]
|
|
pub struct Secret<const L: usize>(pub(crate) [u8; L]);
|
|
|
|
impl<const L: usize> Secret<L> {
|
|
#[inline(always)]
|
|
pub fn new() -> Self {
|
|
Self([0_u8; L])
|
|
}
|
|
|
|
/// Copy bytes into secret, will panic if size does not match.
|
|
#[inline(always)]
|
|
pub fn from_bytes(b: &[u8]) -> Self {
|
|
Self(b.try_into().unwrap())
|
|
}
|
|
}
|
|
|
|
impl<const L: usize> Drop for Secret<L> {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
let p = self.0.as_mut_ptr();
|
|
if (L % size_of::<usize>()) == 0 {
|
|
for i in 0..(L / size_of::<usize>()) {
|
|
write_volatile(p.cast::<usize>().offset(i as isize), 0_usize);
|
|
}
|
|
} else {
|
|
for i in 0..L {
|
|
write_volatile(p.offset(i as isize), 0_u8);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<const L: usize> Default for Secret<L> {
|
|
#[inline(always)]
|
|
fn default() -> Self {
|
|
Self([0_u8; L])
|
|
}
|
|
}
|
|
|
|
impl<const L: usize> AsRef<[u8]> for Secret<L> {
|
|
#[inline(always)]
|
|
fn as_ref(&self) -> &[u8] {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl<const L: usize> AsRef<[u8; L]> for Secret<L> {
|
|
#[inline(always)]
|
|
fn as_ref(&self) -> &[u8; L] {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl<const L: usize> AsMut<[u8]> for Secret<L> {
|
|
#[inline(always)]
|
|
fn as_mut(&mut self) -> &mut [u8] {
|
|
&mut self.0
|
|
}
|
|
}
|
|
|
|
impl<const L: usize> AsMut<[u8; L]> for Secret<L> {
|
|
#[inline(always)]
|
|
fn as_mut(&mut self) -> &mut [u8; L] {
|
|
&mut self.0
|
|
}
|
|
}
|