use crate::prelude::*; use zeroize::Zeroize; const LEN: usize = 4096; pub struct Vec { data: Box>, _lock: region::LockGuard, } impl Default for Vec { fn default() -> Self { let data = Box::new(arrayvec::ArrayVec::<_, LEN>::new()); // XXX it'd be nice to handle this better than .unwrap(), but it'd be // a lot of effort let lock = region::lock(data.as_ptr(), data.capacity()).unwrap(); Self { data, _lock: lock } } } impl Vec { pub fn new() -> Self { Self::default() } pub fn data(&self) -> &[u8] { self.data.as_slice() } pub fn data_mut(&mut self) -> &mut [u8] { self.data.as_mut_slice() } pub fn zero(&mut self) { self.truncate(0); self.data.extend(std::iter::repeat(0).take(LEN)); } pub fn extend(&mut self, it: impl Iterator) { self.data.extend(it); } pub fn truncate(&mut self, len: usize) { self.data.truncate(len); } } impl Drop for Vec { fn drop(&mut self) { self.zero(); self.data.as_mut().zeroize(); } } impl Clone for Vec { fn clone(&self) -> Self { let mut new_vec = Self::new(); new_vec.extend(self.data().iter().copied()); new_vec } } #[derive(Clone)] pub struct Password { password: Vec, } impl Password { pub fn new(password: Vec) -> Self { Self { password } } pub fn password(&self) -> &[u8] { self.password.data() } } #[derive(Clone)] pub struct Keys { keys: Vec, } impl Keys { pub fn new(keys: Vec) -> Self { Self { keys } } pub fn enc_key(&self) -> &[u8] { &self.keys.data()[0..32] } pub fn mac_key(&self) -> &[u8] { &self.keys.data()[32..64] } } #[derive(Clone)] pub struct PasswordHash { hash: Vec, } impl PasswordHash { pub fn new(hash: Vec) -> Self { Self { hash } } pub fn hash(&self) -> &[u8] { self.hash.data() } } #[derive(Clone)] pub struct PrivateKey { private_key: Vec, } impl PrivateKey { pub fn new(private_key: Vec) -> Self { Self { private_key } } pub fn private_key(&self) -> &[u8] { self.private_key.data() } } #[derive(Clone)] pub struct ApiKey { client_id: Password, client_secret: Password, } impl ApiKey { pub fn new(client_id: Password, client_secret: Password) -> Self { Self { client_id, client_secret, } } pub fn client_id(&self) -> &[u8] { self.client_id.password() } pub fn client_secret(&self) -> &[u8] { self.client_secret.password() } } #[derive(Clone)] pub enum LoginCredentials { Password { password: Password }, ApiKey { apikey: ApiKey }, } impl LoginCredentials { pub fn from_password(password: Password) -> Self { Self::Password { password } } pub fn from_apikey(apikey: ApiKey) -> Self { Self::ApiKey { apikey } } pub fn to_hashed( self, email: &str, iterations: u32, ) -> Result { match self { Self::Password { password } => { let identity = crate::identity::Identity::new( email, &password, iterations, )?; Ok(HashedLoginCredentials::Password { password_hash: identity.master_password_hash, }) } Self::ApiKey { apikey } => { Ok(HashedLoginCredentials::ApiKey { apikey }) } } } } #[derive(Clone)] pub enum HashedLoginCredentials { Password { password_hash: PasswordHash }, ApiKey { apikey: ApiKey }, }