crypto: Add error handling to the signing module.
parent
ac0df5dea9
commit
c9db63509f
|
@ -21,6 +21,7 @@ use aes_gcm::{
|
||||||
use base64::{decode_config, encode_config, DecodeError, URL_SAFE_NO_PAD};
|
use base64::{decode_config, encode_config, DecodeError, URL_SAFE_NO_PAD};
|
||||||
use getrandom::getrandom;
|
use getrandom::getrandom;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Error as JsonError;
|
||||||
use std::{
|
use std::{
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
sync::{
|
sync::{
|
||||||
|
@ -28,6 +29,7 @@ use std::{
|
||||||
Arc,
|
Arc,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use thiserror::Error;
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
use olm_rs::{errors::OlmUtilityError, pk::OlmPkSigning, utility::OlmUtility};
|
use olm_rs::{errors::OlmUtilityError, pk::OlmPkSigning, utility::OlmUtility};
|
||||||
|
@ -53,6 +55,22 @@ fn decode<T: AsRef<[u8]>>(input: T) -> Result<Vec<u8>, DecodeError> {
|
||||||
decode_config(input, URL_SAFE_NO_PAD)
|
decode_config(input, URL_SAFE_NO_PAD)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error type reporting failures in the Signign operations.
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum SigningError {
|
||||||
|
/// Error decoding the base64 encoded pickle data.
|
||||||
|
#[error(transparent)]
|
||||||
|
Decode(#[from] DecodeError),
|
||||||
|
|
||||||
|
/// Error decrypting the pickled signing seed
|
||||||
|
#[error("Error decrypting the pickled signign seed")]
|
||||||
|
Decryption(String),
|
||||||
|
|
||||||
|
/// Error deserializing the pickle data.
|
||||||
|
#[error(transparent)]
|
||||||
|
Json(#[from] JsonError),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Signing {
|
pub struct Signing {
|
||||||
inner: Arc<Mutex<OlmPkSigning>>,
|
inner: Arc<Mutex<OlmPkSigning>>,
|
||||||
|
@ -105,13 +123,13 @@ impl MasterSigning {
|
||||||
PickledMasterSigning { pickle, public_key }
|
PickledMasterSigning { pickle, public_key }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_pickle(pickle: PickledMasterSigning, pickle_key: &[u8]) -> Self {
|
fn from_pickle(pickle: PickledMasterSigning, pickle_key: &[u8]) -> Result<Self, SigningError> {
|
||||||
let inner = Signing::from_pickle(pickle.pickle, pickle_key);
|
let inner = Signing::from_pickle(pickle.pickle, pickle_key)?;
|
||||||
|
|
||||||
Self {
|
Ok(Self {
|
||||||
inner,
|
inner,
|
||||||
public_key: pickle.public_key.into(),
|
public_key: pickle.public_key.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sign_subkey<'a>(&self, subkey: &mut CrossSigningKey) {
|
async fn sign_subkey<'a>(&self, subkey: &mut CrossSigningKey) {
|
||||||
|
@ -145,13 +163,13 @@ impl UserSigning {
|
||||||
PickledUserSigning { pickle, public_key }
|
PickledUserSigning { pickle, public_key }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_pickle(pickle: PickledUserSigning, pickle_key: &[u8]) -> Self {
|
fn from_pickle(pickle: PickledUserSigning, pickle_key: &[u8]) -> Result<Self, SigningError> {
|
||||||
let inner = Signing::from_pickle(pickle.pickle, pickle_key);
|
let inner = Signing::from_pickle(pickle.pickle, pickle_key)?;
|
||||||
|
|
||||||
Self {
|
Ok(Self {
|
||||||
inner,
|
inner,
|
||||||
public_key: pickle.public_key.into(),
|
public_key: pickle.public_key.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,13 +180,13 @@ impl SelfSigning {
|
||||||
PickledSelfSigning { pickle, public_key }
|
PickledSelfSigning { pickle, public_key }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_pickle(pickle: PickledSelfSigning, pickle_key: &[u8]) -> Self {
|
fn from_pickle(pickle: PickledSelfSigning, pickle_key: &[u8]) -> Result<Self, SigningError> {
|
||||||
let inner = Signing::from_pickle(pickle.pickle, pickle_key);
|
let inner = Signing::from_pickle(pickle.pickle, pickle_key)?;
|
||||||
|
|
||||||
Self {
|
Ok(Self {
|
||||||
inner,
|
inner,
|
||||||
public_key: pickle.public_key.into(),
|
public_key: pickle.public_key.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,21 +277,21 @@ impl Signing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_pickle(pickle: PickledSigning, pickle_key: &[u8]) -> Self {
|
fn from_pickle(pickle: PickledSigning, pickle_key: &[u8]) -> Result<Self, SigningError> {
|
||||||
let pickled: InnerPickle = serde_json::from_str(pickle.as_str()).unwrap();
|
let pickled: InnerPickle = serde_json::from_str(pickle.as_str())?;
|
||||||
|
|
||||||
let key = GenericArray::from_slice(pickle_key);
|
let key = GenericArray::from_slice(pickle_key);
|
||||||
let cipher = Aes256Gcm::new(key);
|
let cipher = Aes256Gcm::new(key);
|
||||||
|
|
||||||
let nonce = decode(pickled.nonce).unwrap();
|
let nonce = decode(pickled.nonce)?;
|
||||||
let nonce = GenericArray::from_slice(&nonce);
|
let nonce = GenericArray::from_slice(&nonce);
|
||||||
let ciphertext = &decode(pickled.ciphertext).unwrap();
|
let ciphertext = &decode(pickled.ciphertext)?;
|
||||||
|
|
||||||
let seed = cipher
|
let seed = cipher
|
||||||
.decrypt(&nonce, ciphertext.as_slice())
|
.decrypt(&nonce, ciphertext.as_slice())
|
||||||
.expect("Can't decrypt pickle");
|
.map_err(|e| SigningError::Decryption(e.to_string()))?;
|
||||||
|
|
||||||
Self::from_seed(seed)
|
Ok(Self::from_seed(seed))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn pickle(&self, pickle_key: &[u8]) -> PickledSigning {
|
async fn pickle(&self, pickle_key: &[u8]) -> PickledSigning {
|
||||||
|
@ -412,32 +430,35 @@ impl PrivateCrossSigningIdentity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn from_pickle(pickle: PickledCrossSigningIdentity, pickle_key: &[u8]) -> Self {
|
pub async fn from_pickle(
|
||||||
|
pickle: PickledCrossSigningIdentity,
|
||||||
|
pickle_key: &[u8],
|
||||||
|
) -> Result<Self, SigningError> {
|
||||||
let master = if let Some(m) = pickle.master_key {
|
let master = if let Some(m) = pickle.master_key {
|
||||||
Some(MasterSigning::from_pickle(m, pickle_key))
|
Some(MasterSigning::from_pickle(m, pickle_key)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let self_signing = if let Some(s) = pickle.self_signing_key {
|
let self_signing = if let Some(s) = pickle.self_signing_key {
|
||||||
Some(SelfSigning::from_pickle(s, pickle_key))
|
Some(SelfSigning::from_pickle(s, pickle_key)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let user_signing = if let Some(u) = pickle.user_signing_key {
|
let user_signing = if let Some(u) = pickle.user_signing_key {
|
||||||
Some(UserSigning::from_pickle(u, pickle_key))
|
Some(UserSigning::from_pickle(u, pickle_key)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Ok(Self {
|
||||||
user_id: Arc::new(pickle.user_id),
|
user_id: Arc::new(pickle.user_id),
|
||||||
shared: Arc::new(AtomicBool::from(pickle.shared)),
|
shared: Arc::new(AtomicBool::from(pickle.shared)),
|
||||||
master_key: Arc::new(Mutex::new(master)),
|
master_key: Arc::new(Mutex::new(master)),
|
||||||
self_signing_key: Arc::new(Mutex::new(self_signing)),
|
self_signing_key: Arc::new(Mutex::new(self_signing)),
|
||||||
user_signing_key: Arc::new(Mutex::new(user_signing)),
|
user_signing_key: Arc::new(Mutex::new(user_signing)),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn as_upload_request(&self) -> UploadSigningKeysRequest {
|
pub(crate) async fn as_upload_request(&self) -> UploadSigningKeysRequest {
|
||||||
|
@ -509,7 +530,7 @@ mod test {
|
||||||
let signing = Signing::new();
|
let signing = Signing::new();
|
||||||
let pickled = signing.pickle(pickle_key()).await;
|
let pickled = signing.pickle(pickle_key()).await;
|
||||||
|
|
||||||
let unpickled = Signing::from_pickle(pickled, pickle_key());
|
let unpickled = Signing::from_pickle(pickled, pickle_key()).unwrap();
|
||||||
|
|
||||||
assert_eq!(signing.public_key(), unpickled.public_key());
|
assert_eq!(signing.public_key(), unpickled.public_key());
|
||||||
}
|
}
|
||||||
|
@ -554,7 +575,9 @@ mod test {
|
||||||
|
|
||||||
let pickled = identity.pickle(pickle_key()).await;
|
let pickled = identity.pickle(pickle_key()).await;
|
||||||
|
|
||||||
let unpickled = PrivateCrossSigningIdentity::from_pickle(pickled, pickle_key()).await;
|
let unpickled = PrivateCrossSigningIdentity::from_pickle(pickled, pickle_key())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(identity.user_id, unpickled.user_id);
|
assert_eq!(identity.user_id, unpickled.user_id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Reference in New Issue