pub const DEFAULT_VAULT_PAGES: usize = 4;
pub const DEFAULT_VAULT_PAGE_SIZE: usize = 4096_usize;
struct SealingKeyPages([[u8; DEFAULT_VAULT_PAGE_SIZE]; DEFAULT_VAULT_PAGES]);
mod keymaker {
use super::{SealingKeyPages, DEFAULT_VAULT_PAGES, DEFAULT_VAULT_PAGE_SIZE};
use crate::{
EncryptedMem, MemSecurityErr, MemSecurityResult, ZeroizeBytes, ZeroizeBytesArray,
TAG_LENGTH,
};
use chacha20poly1305::{
aead::{bytes::BytesMut, AeadInPlace, KeyInit},
Key, XChaCha12Poly1305, XNonce,
};
use nanorand::{ChaCha8, Rng};
lazy_static::lazy_static! {
static ref PREKEY: SealingKeyPages = {
let mut pages = [[0u8; DEFAULT_VAULT_PAGE_SIZE]; DEFAULT_VAULT_PAGES];
(0..DEFAULT_VAULT_PAGES).for_each(|vault_page_index| {
let mut chacha_rng = ChaCha8::new();
let mut random_bytes = [0; DEFAULT_VAULT_PAGE_SIZE];
(0..DEFAULT_VAULT_PAGE_SIZE).for_each(|index| {
random_bytes[index] = chacha_rng.generate::<u8>();
});
pages[vault_page_index] = random_bytes;
});
SealingKeyPages(pages)
};
}
impl<const N: usize> EncryptedMem<N> {
fn sealing_key(&self) -> ZeroizeBytes {
let mut blake3_hasher = blake3::Hasher::new();
PREKEY.0.iter().for_each(|page| {
blake3_hasher.update(page);
});
let mut key = ZeroizeBytes::new_with_capacity(32);
key.set(aead::bytes::BytesMut::from(
blake3_hasher.finalize().as_bytes().as_slice(),
));
key
}
pub fn encrypt(
&mut self,
plaintext: &ZeroizeBytesArray<N>,
) -> MemSecurityResult<&mut Self> {
let cipher = XChaCha12Poly1305::new(&Key::from_slice(self.sealing_key().expose()));
let mut buffer = BytesMut::with_capacity(N + TAG_LENGTH); buffer.extend_from_slice(plaintext.expose());
match cipher
.encrypt_in_place(
&XNonce::from_slice(self.xnonce().expose_borrowed()),
b"",
&mut buffer,
) {
Ok(_) => (),
Err(_) => return Err(MemSecurityErr::EncryptionErr)
}
let ciphertext = ZeroizeBytesArray::with_additional_capacity(TAG_LENGTH).set(buffer);
self.add_ciphertext(ciphertext);
Ok(self)
}
pub fn decrypt(&mut self) -> MemSecurityResult<ZeroizeBytesArray<N>> {
let cipher = XChaCha12Poly1305::new(&Key::from_slice(self.sealing_key().expose()));
let mut buffer = BytesMut::with_capacity(N + TAG_LENGTH); buffer.extend_from_slice(self.ciphertext().expose());
match cipher.decrypt_in_place(
&XNonce::from_slice(self.xnonce().expose_borrowed()),
b"",
&mut buffer,
) {
Ok(_) => Ok(ZeroizeBytesArray::new().set(buffer)),
Err(_) => {
buffer.fill(0); drop(buffer);
Err(MemSecurityErr::DecryptionError)
}
}
}
}
}