use super::*; #[non_exhaustive] #[derive(Debug)] pub(super) enum EncryptedEntryErrorKind { KeyNeeded, Decrypt(aes::Error), Deserialize(serde_cbor::Error), Encrypt(aes::Error), Serialize(serde_cbor::Error), } /// Error type returned when performing encryption/decryption operations on `Data` through `MaybeEncrypted`. #[non_exhaustive] #[derive(Debug)] pub struct EncryptedEntryError(Box); impl EncryptedEntryError { /// Consume into a nicely readable `eyre::Report` pub fn report(self) -> eyre::Report { let (whe, sug) = match self.0.as_ref() { EncryptedEntryErrorKind::Serialize(_) => ("Object serialisation", "Bad data?"), EncryptedEntryErrorKind::Deserialize(_) => ("Object deserialisation", "Corrupted data?"), EncryptedEntryErrorKind::Decrypt(_) => ("Data decryption", "Bad key?"), EncryptedEntryErrorKind::Encrypt(_) => ("Data encryption" ,"Bad key?"), EncryptedEntryErrorKind::KeyNeeded => return eyre::Report::from(self) .with_suggestion(|| "Try providing a key"), }; Err::(self) .with_section(|| whe.header("In operation")) .with_warning(|| sug) .unwrap_err() } } impl error::Error for EncryptedEntryError { fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(match self.0.as_ref() { EncryptedEntryErrorKind::Decrypt(d) => d, EncryptedEntryErrorKind::Deserialize(d) => d, EncryptedEntryErrorKind::Encrypt(d) => d, EncryptedEntryErrorKind::Serialize(d) => d, _ => return None, }) } } impl fmt::Display for EncryptedEntryError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.0.as_ref() { EncryptedEntryErrorKind::KeyNeeded => write!(f, "this entry needed a decryption key but none was provided"), EncryptedEntryErrorKind::Decrypt(_) => write!(f, "decryption failed"), EncryptedEntryErrorKind::Deserialize(_) => write!(f, "deserialisation failed"), EncryptedEntryErrorKind::Encrypt(_) => write!(f, "encryption failed"), EncryptedEntryErrorKind::Serialize(_) => write!(f, "serialisation failed"), } } } impl From for EncryptedEntryError { #[inline] fn from(from: EncryptedEntryErrorKind) -> Self { Self(Box::new(from)) } } /// Encrypt a `Data` entry into this buffer pub(super) async fn encrypt_data_entry(output: &mut T, data: &Data, key: &AesKey) -> Result where T: ?Sized + AsyncWrite + Unpin { let bytes = serde_cbor::to_vec(data).map_err(EncryptedEntryErrorKind::Serialize)?; Ok(aes::encrypt_stream(key, &mut &bytes[..], output).await.map_err(EncryptedEntryErrorKind::Encrypt)?) } /// Decrypt an encrypted `Data` entry pub(super) async fn decrypt_data_entry(input: &mut T, key: &AesKey, init_buf: Option>) -> Result where T: AsyncRead + Unpin { let mut output = init_buf.unwrap_or_default(); aes::decrypt_stream(key, input, &mut output).await.map_err(EncryptedEntryErrorKind::Decrypt)?; Ok(serde_cbor::from_slice(&output[..]).map_err(EncryptedEntryErrorKind::Deserialize)?) } impl MaybeEncrypted { /// Create a new non-encrypted entry #[inline(always)] pub const fn new_raw(data: Data) -> Self { Self::Unencrypted(data) } /// Create a new encrypted entry #[inline] pub fn new_encrypted(data: Data, encrypt: &AesKey) -> Result { let mut buffer = Vec::new(); encrypt_data_entry(&mut buffer, &data, encrypt).now_or_never().unwrap()?; Ok(Self::Encrypted(buffer)) } /// Is this data entry encrypted #[inline] pub fn is_encrypted(&self) -> bool { if let MaybeEncrypted::Encrypted(_) = &self { true } else { false } } /// Consume into a decrypted data instance #[inline] pub fn into_unencrypted(self, key: Option<&AesKey>) -> Result { Ok(Self::Unencrypted(self.into_data(key)?)) } /// Make this entry unencrypted pub fn make_unencrypted(&mut self, key: Option<&AesKey>) -> Result<(), EncryptedEntryError> { match self { MaybeEncrypted::Encrypted(bytes) => { *self = MaybeEncrypted::Unencrypted(decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?); }, _ => (), } Ok(()) } /// Make this entry encrypted pub fn make_encrypted(&mut self, key: Option<&AesKey>) -> Result<(), EncryptedEntryError> { match self { MaybeEncrypted::Unencrypted(data) => { let mut buffer = Vec::new(); encrypt_data_entry(&mut buffer, data, key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?).now_or_never().unwrap()?; *self = Self::Encrypted(buffer); }, _ => (), } Ok(()) } /// Consume into an encrypted data instance pub fn into_encrypted(self, key: Option<&AesKey>) -> Result { match self { MaybeEncrypted::Unencrypted(data) => Self::new_encrypted(data, key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?), _ => Ok(self), } } /// Attempt to get the `Data`, decrypting it if needed. pub fn get_data<'a>(&'a self, key: Option<&AesKey>) -> Result, EncryptedEntryError> { Ok(match self { Self::Unencrypted(data) => Cow::Borrowed(&data), Self::Encrypted(bytes) => { // decrypt Cow::Owned(decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?) }, }) } /// Consume into the data object, decrypting it if needed. pub fn into_data(self, key: Option<&AesKey>) -> Result { Ok(match self { Self::Encrypted(bytes) => { decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()? }, Self::Unencrypted(data) => data, }) } }