use crate::crypto::key::{AbstractKey, Key, Nonce};
use crate::crypto::secret::Secret;
use crate::crypto::wrap::WrappedKey;
use crate::error::*;
use data_encoding;
use once_cell::sync::Lazy;
use rmp_serde;
use serde::{Deserialize, Serialize};
use std::fs;
use std::io::{self, Read, Write};
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use tracing::{debug, error};
static AUTH_TOKEN_CONTENTS: Lazy<Secret> = Lazy::new(|| {
let data: &[u8] = b"3c017f717b39247c351154a41d2850e4187284da4b928f13c723d54440ba2dfe";
let mut secret = Secret::with_len(data.len()).unwrap();
unsafe { secret.as_mut_slice() }.copy_from_slice(data);
secret
});
fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false;
}
let mut diff: u8 = 0;
for (x, y) in a.iter().zip(b.iter()) {
diff |= x ^ y;
}
diff == 0
}
fn is_master_key<K: AbstractKey>(key: &K, nonce: Option<&Nonce>, token: &[u8]) -> bool {
let decrypted = match key.decrypt(nonce, token) {
Err(_) => return false,
Ok(d) => d,
};
unsafe { constant_time_eq(decrypted.as_slice(), AUTH_TOKEN_CONTENTS.as_slice()) }
}
#[derive(Deserialize, Serialize)]
pub struct KeyStore {
#[serde(skip_serializing, skip_deserializing)]
master_key: Option<Key>,
token_nonce: Option<Nonce>,
token: Vec<u8>,
wrapped_keys: Vec<WrappedKey>,
}
impl KeyStore {
pub fn new() -> Result<Self> {
let master_key = Key::new_random()?;
let (nonce, ciphertext) = master_key.encrypt(&AUTH_TOKEN_CONTENTS, None)?;
Ok(KeyStore {
master_key: Some(master_key),
token_nonce: nonce,
token: ciphertext,
wrapped_keys: Vec::new(),
})
}
pub fn load_slice(data: &[u8]) -> Result<Self> {
Ok(rmp_serde::from_slice(data)?)
}
pub fn load_read<R: Read>(rd: R) -> Result<Self> {
Ok(rmp_serde::from_read(rd)?)
}
pub fn get_id(&self) -> String {
data_encoding::HEXLOWER.encode(&self.token)
}
pub fn is_open(&self) -> bool {
self.master_key.is_some()
}
pub fn is_persistable(&self) -> bool {
!self.wrapped_keys.is_empty()
}
pub fn open<K: AbstractKey>(&mut self, key: &K) -> Result<()> {
if self.master_key.is_some() {
return Ok(());
}
let mut master_key: Option<Key> = None;
for wrapped_key in self.wrapped_keys.iter() {
match wrapped_key.unwrap(key) {
Ok(k) => {
if is_master_key(&k, self.token_nonce.as_ref(), self.token.as_slice()) {
master_key = Some(k);
break;
} else {
debug!(
"unwrapped key {:?}, but unwrapped key doesn't match our expected master key",
wrapped_key.get_digest()
);
}
}
Err(e) => debug!(
"failed to unwrap key {:?}: {:?}",
wrapped_key.get_digest(),
e
),
}
}
if master_key.is_none() {
return Err(Error::InvalidArgument(
"KeyStore unlocking failed: the given key is not present in this KeyStore"
.to_string(),
));
}
self.master_key = master_key;
Ok(())
}
pub fn to_vec(&self) -> Result<Vec<u8>> {
Ok(rmp_serde::to_vec(self)?)
}
pub fn get_master_key(&self) -> Result<&Key> {
if let Some(k) = self.master_key.as_ref() {
return Ok(k);
}
Err(Error::Precondition(
"KeyStore must be opened before you can access the master key".to_string(),
))
}
pub fn add_key<K: AbstractKey>(&mut self, key: &K) -> Result<bool> {
let wrapped_key = match self.master_key.as_ref() {
None => {
return Err(Error::Precondition(
"KeyStore must be `new` or opened to add keys".to_string(),
));
}
Some(mk) => WrappedKey::wrap( mk, key)?,
};
if self
.wrapped_keys
.iter()
.any(|k| k.get_wrapping_digest() == wrapped_key.get_wrapping_digest())
{
return Ok(false);
}
self.wrapped_keys.push(wrapped_key);
Ok(true)
}
pub fn remove_key<K: AbstractKey>(&mut self, key: &K) -> Result<bool> {
if self.wrapped_keys.len() == 1 {
if let Some(wrapped_key) = self.wrapped_keys.first() {
if *wrapped_key.get_wrapping_digest() == key.get_digest() {
return Err(Error::Precondition(
"refusing to remove all valid keys from this KeyStore".to_string(),
));
}
}
}
let original_length = self.wrapped_keys.len();
self.wrapped_keys
.retain(|k| *k.get_wrapping_digest() != key.get_digest());
Ok(original_length != self.wrapped_keys.len())
}
pub fn iter_wrapped_keys(&self) -> impl Iterator<Item = &WrappedKey> {
self.wrapped_keys.iter()
}
}
fn persist_key_store<P: AsRef<Path>>(path: P, keystore: &KeyStore) -> Result<()> {
if !keystore.is_persistable() {
return Err(Error::Precondition(
"KeyStore with no wrapping keys cannot be persisted".to_string(),
));
}
let mut f = fs::File::create(path.as_ref())?;
let data = keystore.to_vec()?;
f.write_all(data.as_slice())?;
Ok(())
}
pub struct DiskKeyStore {
path: PathBuf,
inner: KeyStore,
}
impl DiskKeyStore {
pub fn new<P: AsRef<Path>>(path: P, force_overwrite: bool) -> Result<Self> {
let path_ref = path.as_ref();
let existing_len = match fs::metadata(path_ref) {
Ok(m) => m.len(),
Err(e) if e.kind() == io::ErrorKind::NotFound => 0,
Err(e) => return Err(e.into()),
};
let inner = if !force_overwrite && existing_len > 0 {
match fs::File::open(path_ref) {
Ok(mut f) => KeyStore::load_read(&mut f)?,
Err(e) if e.kind() == io::ErrorKind::NotFound => KeyStore::new()?,
Err(e) => return Err(e.into()),
}
} else {
KeyStore::new()?
};
Ok(DiskKeyStore {
path: path_ref.to_path_buf(),
inner,
})
}
}
impl Deref for DiskKeyStore {
type Target = KeyStore;
fn deref(&self) -> &KeyStore {
&self.inner
}
}
impl DerefMut for DiskKeyStore {
fn deref_mut(&mut self) -> &mut KeyStore {
&mut self.inner
}
}
impl Drop for DiskKeyStore {
fn drop(&mut self) {
if let Err(e) = persist_key_store(&self.path, &self.inner) {
error!("{} (KeyStore {})", e, self.inner.get_id());
}
}
}