crypto: Properly handle errors in the pickle key decryption.
parent
d175c47a05
commit
ac0df5dea9
|
@ -308,6 +308,10 @@ pub enum CryptoStoreError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
SessionUnpickling(#[from] SessionUnpicklingError),
|
SessionUnpickling(#[from] SessionUnpicklingError),
|
||||||
|
|
||||||
|
/// Failed to decrypt an pickled object.
|
||||||
|
#[error("An object failed to be decrypted while unpickling")]
|
||||||
|
UnpicklingError,
|
||||||
|
|
||||||
/// A Matirx identifier failed to be validated.
|
/// A Matirx identifier failed to be validated.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
IdentifierValidation(#[from] IdentifierValidationError),
|
IdentifierValidation(#[from] IdentifierValidationError),
|
||||||
|
|
|
@ -16,7 +16,7 @@ use std::convert::TryFrom;
|
||||||
|
|
||||||
use aes_gcm::{
|
use aes_gcm::{
|
||||||
aead::{generic_array::GenericArray, Aead, NewAead},
|
aead::{generic_array::GenericArray, Aead, NewAead},
|
||||||
Aes256Gcm,
|
Aes256Gcm, Error as DecryptionError,
|
||||||
};
|
};
|
||||||
use getrandom::getrandom;
|
use getrandom::getrandom;
|
||||||
use hmac::Hmac;
|
use hmac::Hmac;
|
||||||
|
@ -58,6 +58,18 @@ pub struct PickleKey {
|
||||||
aes256_key: Vec<u8>,
|
aes256_key: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for PickleKey {
|
||||||
|
fn default() -> Self {
|
||||||
|
let mut key = vec![0u8; KEY_SIZE];
|
||||||
|
getrandom(&mut key).expect("Can't generate new pickle key");
|
||||||
|
|
||||||
|
Self {
|
||||||
|
version: VERSION,
|
||||||
|
aes256_key: key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<Vec<u8>> for PickleKey {
|
impl TryFrom<Vec<u8>> for PickleKey {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
||||||
|
@ -75,13 +87,7 @@ impl TryFrom<Vec<u8>> for PickleKey {
|
||||||
impl PickleKey {
|
impl PickleKey {
|
||||||
/// Generate a new random pickle key.
|
/// Generate a new random pickle key.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut key = vec![0u8; KEY_SIZE];
|
Default::default()
|
||||||
getrandom(&mut key).expect("Can't generate new pickle key");
|
|
||||||
|
|
||||||
Self {
|
|
||||||
version: VERSION,
|
|
||||||
aes256_key: key,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_key(passphrase: &str, salt: &[u8]) -> Zeroizing<Vec<u8>> {
|
fn expand_key(passphrase: &str, salt: &[u8]) -> Zeroizing<Vec<u8>> {
|
||||||
|
@ -137,20 +143,21 @@ impl PickleKey {
|
||||||
/// pickle key.
|
/// pickle key.
|
||||||
///
|
///
|
||||||
/// * `encrypted` - The exported and encrypted version of the pickle key.
|
/// * `encrypted` - The exported and encrypted version of the pickle key.
|
||||||
pub fn from_encrypted(passphrase: &str, encrypted: EncryptedPickleKey) -> Self {
|
pub fn from_encrypted(
|
||||||
|
passphrase: &str,
|
||||||
|
encrypted: EncryptedPickleKey,
|
||||||
|
) -> Result<Self, DecryptionError> {
|
||||||
let key = PickleKey::expand_key(passphrase, &encrypted.kdf_salt);
|
let key = PickleKey::expand_key(passphrase, &encrypted.kdf_salt);
|
||||||
let key = GenericArray::from_slice(key.as_ref());
|
let key = GenericArray::from_slice(key.as_ref());
|
||||||
let cipher = Aes256Gcm::new(&key);
|
let cipher = Aes256Gcm::new(&key);
|
||||||
let nonce = GenericArray::from_slice(&encrypted.nonce);
|
let nonce = GenericArray::from_slice(&encrypted.nonce);
|
||||||
|
|
||||||
let decrypted_key = cipher
|
let decrypted_key = cipher.decrypt(nonce, encrypted.ciphertext.as_ref())?;
|
||||||
.decrypt(nonce, encrypted.ciphertext.as_ref())
|
|
||||||
.expect("Can't decrypt pickle");
|
|
||||||
|
|
||||||
Self {
|
Ok(Self {
|
||||||
version: encrypted.version,
|
version: encrypted.version,
|
||||||
aes256_key: decrypted_key,
|
aes256_key: decrypted_key,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +176,7 @@ mod test {
|
||||||
let pickle_key = PickleKey::new();
|
let pickle_key = PickleKey::new();
|
||||||
|
|
||||||
let encrypted = pickle_key.encrypt(passphrase);
|
let encrypted = pickle_key.encrypt(passphrase);
|
||||||
let decrypted = PickleKey::from_encrypted(passphrase, encrypted);
|
let decrypted = PickleKey::from_encrypted(passphrase, encrypted).unwrap();
|
||||||
|
|
||||||
assert_eq!(pickle_key, decrypted);
|
assert_eq!(pickle_key, decrypted);
|
||||||
}
|
}
|
||||||
|
|
|
@ -516,8 +516,9 @@ impl SqliteStore {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(if let Some(row) = row {
|
Ok(if let Some(row) = row {
|
||||||
let encrypted: EncryptedPickleKey = serde_json::from_str(&row.0).unwrap();
|
let encrypted: EncryptedPickleKey = serde_json::from_str(&row.0)?;
|
||||||
PickleKey::from_encrypted(passphrase, encrypted)
|
PickleKey::from_encrypted(passphrase, encrypted)
|
||||||
|
.map_err(|_| CryptoStoreError::UnpicklingError)?
|
||||||
} else {
|
} else {
|
||||||
let key = PickleKey::new();
|
let key = PickleKey::new();
|
||||||
let encrypted = key.encrypt(passphrase);
|
let encrypted = key.encrypt(passphrase);
|
||||||
|
|
Loading…
Reference in New Issue