embedded-secure-fs/src/key.rs

82 lines
2.1 KiB
Rust

use chacha20poly1305::{aead::heapless::Vec, AeadInPlace, KeyInit};
use zeroize::{Zeroize, ZeroizeOnDrop};
const KEY_SIZE: usize = 32;
const PBKDF_SALT_SIZE: usize = 32;
const CHACHA_SALT_SIZE: usize = 12;
pub struct KeyDescription {
encrypted_key: [u8; KEY_SIZE],
pbkdf_salt: [u8; PBKDF_SALT_SIZE],
nonce: [u8; CHACHA_SALT_SIZE],
pbkdf_rounds: u32,
}
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct Key {
key: [u8; KEY_SIZE],
}
impl KeyDescription {
/// Measure the number of rounds to match the target time (in milliseconds)
/// `now` should return a timestamp in milliseconds
pub fn measure_rounds<F: Fn() -> u64>(target_time: u64, now: F) -> u32 {
let mut key = [0; KEY_SIZE];
let mut memory = [0; KEY_SIZE];
let salt = core::hint::black_box([0; PBKDF_SALT_SIZE]);
let passphrase = core::hint::black_box([0]);
let start_1 = (now)();
bcrypt_pbkdf::bcrypt_pbkdf_with_memory(passphrase, &salt, 1, &mut key, &mut memory)
.unwrap();
let end_1 = (now)();
let duration_1 = end_1 - start_1;
key = [0; KEY_SIZE];
memory = [0; KEY_SIZE];
let start_2 = (now)();
bcrypt_pbkdf::bcrypt_pbkdf_with_memory(passphrase, &salt, 17, &mut key, &mut memory)
.unwrap();
let end_2 = (now)();
let duration_2 = end_2 - start_2;
assert!(duration_2 > duration_1);
(target_time * 16 / (duration_2 - duration_1)) as u32
}
pub fn get_key(&self, passphrase: &mut [u8]) -> Result<Key, Error> {
let mut derived_key = [0; KEY_SIZE];
let mut memory = [0; KEY_SIZE];
bcrypt_pbkdf::bcrypt_pbkdf_with_memory(
&*passphrase,
&self.pbkdf_salt,
self.pbkdf_rounds,
&mut derived_key,
&mut memory,
)
.map_err(Error::Pbkdf)?;
passphrase.zeroize();
let mut key = Vec::<u8, KEY_SIZE>::from_slice(&self.encrypted_key)
.map_err(|_| Error::WrongKeySize)?;
let cipher = chacha20poly1305::ChaCha20Poly1305::new(&derived_key.into());
cipher
.decrypt_in_place(&self.nonce.into(), &[], &mut key)
.map_err(Error::Chacha)?;
Ok(Key {
key: key.into_array().map_err(|_| Error::WrongKeySize)?,
})
}
}
pub enum Error {
Chacha(chacha20poly1305::Error),
Pbkdf(bcrypt_pbkdf::Error),
WrongKeySize,
}