crypto: Rework our errors making them more specific.
parent
5de32c025f
commit
fc0d4a7d35
|
@ -111,7 +111,7 @@ impl Client {
|
||||||
pub fn new(session: Option<Session>) -> Result<Self> {
|
pub fn new(session: Option<Session>) -> Result<Self> {
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
let olm = match &session {
|
let olm = match &session {
|
||||||
Some(s) => Some(OlmMachine::new(&s.user_id, &s.device_id)?),
|
Some(s) => Some(OlmMachine::new(&s.user_id, &s.device_id)),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ impl Client {
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
{
|
{
|
||||||
let mut olm = self.olm.lock().await;
|
let mut olm = self.olm.lock().await;
|
||||||
*olm = Some(OlmMachine::new(&response.user_id, &response.device_id)?);
|
*olm = Some(OlmMachine::new(&response.user_id, &response.device_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -26,7 +26,7 @@ use thiserror::Error;
|
||||||
use url::ParseError;
|
use url::ParseError;
|
||||||
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use matrix_sdk_crypto::OlmError;
|
use matrix_sdk_crypto::{MegolmError, OlmError};
|
||||||
|
|
||||||
/// Result type of the rust-sdk.
|
/// Result type of the rust-sdk.
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
@ -59,6 +59,9 @@ pub enum Error {
|
||||||
/// An error occurred during a E2EE operation.
|
/// An error occurred during a E2EE operation.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
OlmError(#[from] OlmError),
|
OlmError(#[from] OlmError),
|
||||||
|
/// An error occurred during a E2EE group operation.
|
||||||
|
#[error(transparent)]
|
||||||
|
MegolmError(#[from] MegolmError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<RumaResponseError<RumaClientError>> for Error {
|
impl From<RumaResponseError<RumaClientError>> for Error {
|
||||||
|
|
|
@ -101,8 +101,8 @@ impl Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the key of the given key algorithm belonging to this device.
|
/// Get the key of the given key algorithm belonging to this device.
|
||||||
pub fn get_key(&self, algorithm: &KeyAlgorithm) -> Option<&String> {
|
pub fn get_key(&self, algorithm: KeyAlgorithm) -> Option<&String> {
|
||||||
self.keys.get(algorithm)
|
self.keys.get(&algorithm)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a map containing all the device keys.
|
/// Get a map containing all the device keys.
|
||||||
|
@ -274,11 +274,11 @@ pub(crate) mod test {
|
||||||
device.display_name().as_ref().unwrap()
|
device.display_name().as_ref().unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
device.get_key(&KeyAlgorithm::Curve25519).unwrap(),
|
device.get_key(KeyAlgorithm::Curve25519).unwrap(),
|
||||||
"wjLpTLRqbqBzLs63aYaEv2Boi6cFEbbM/sSRQ2oAKk4"
|
"wjLpTLRqbqBzLs63aYaEv2Boi6cFEbbM/sSRQ2oAKk4"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
device.get_key(&KeyAlgorithm::Ed25519).unwrap(),
|
device.get_key(KeyAlgorithm::Ed25519).unwrap(),
|
||||||
"nE6W2fCblxDcOFmeEtCHNl8/l8bXcu7GKyAswA4r3mM"
|
"nE6W2fCblxDcOFmeEtCHNl8/l8bXcu7GKyAswA4r3mM"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,37 +19,59 @@ use thiserror::Error;
|
||||||
|
|
||||||
use super::store::CryptoStoreError;
|
use super::store::CryptoStoreError;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, OlmError>;
|
pub type OlmResult<T> = std::result::Result<T, OlmError>;
|
||||||
|
pub type MegolmResult<T> = std::result::Result<T, MegolmError>;
|
||||||
|
pub type VerificationResult<T> = std::result::Result<T, SignatureError>;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum OlmError {
|
pub enum OlmError {
|
||||||
#[error("signature verification failed")]
|
#[error(transparent)]
|
||||||
Signature(#[from] SignatureError),
|
EventError(#[from] EventError),
|
||||||
#[error("failed to read or write to the crypto store {0}")]
|
#[error(transparent)]
|
||||||
Store(#[from] CryptoStoreError),
|
JsonError(#[from] SerdeError),
|
||||||
#[error("decryption failed likely because a Olm session was wedged")]
|
|
||||||
SessionWedged,
|
|
||||||
#[error("the Olm message has a unsupported type")]
|
|
||||||
UnsupportedOlmType,
|
|
||||||
#[error("the Encrypted message has been encrypted with a unsupported algorithm.")]
|
|
||||||
UnsupportedAlgorithm,
|
|
||||||
#[error("the Encrypted message doesn't contain a ciphertext for our device")]
|
|
||||||
MissingCiphertext,
|
|
||||||
#[error("decryption failed because the session to decrypt the message is missing")]
|
|
||||||
MissingSession,
|
|
||||||
#[error("the Encrypted message is missing the signing key of the sender")]
|
|
||||||
MissingSigningKey,
|
|
||||||
#[error("can't finish Olm Session operation {0}")]
|
#[error("can't finish Olm Session operation {0}")]
|
||||||
OlmSession(#[from] OlmSessionError),
|
OlmSession(#[from] OlmSessionError),
|
||||||
#[error("can't finish Olm Session operation {0}")]
|
#[error("can't finish Olm Session operation {0}")]
|
||||||
OlmGroupSession(#[from] OlmGroupSessionError),
|
OlmGroupSession(#[from] OlmGroupSessionError),
|
||||||
#[error("error deserializing a string to json")]
|
#[error("failed to read or write to the crypto store {0}")]
|
||||||
JsonError(#[from] SerdeError),
|
Store(#[from] CryptoStoreError),
|
||||||
#[error("the provided JSON value isn't an object")]
|
#[error("decryption failed likely because a Olm session was wedged")]
|
||||||
NotAnObject,
|
SessionWedged,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type VerificationResult<T> = std::result::Result<T, SignatureError>;
|
#[derive(Error, Debug)]
|
||||||
|
pub enum MegolmError {
|
||||||
|
#[error("decryption failed because the session to decrypt the message is missing")]
|
||||||
|
MissingSession,
|
||||||
|
#[error(transparent)]
|
||||||
|
JsonError(#[from] SerdeError),
|
||||||
|
#[error(transparent)]
|
||||||
|
EventError(#[from] EventError),
|
||||||
|
#[error("can't finish Olm group session operation {0}")]
|
||||||
|
OlmGroupSession(#[from] OlmGroupSessionError),
|
||||||
|
#[error(transparent)]
|
||||||
|
Store(#[from] CryptoStoreError),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum EventError {
|
||||||
|
#[error("the Olm message has a unsupported type")]
|
||||||
|
UnsupportedOlmType,
|
||||||
|
#[error("the Encrypted message has been encrypted with a unsupported algorithm.")]
|
||||||
|
UnsupportedAlgorithm,
|
||||||
|
#[error("the provided JSON value isn't an object")]
|
||||||
|
NotAnObject,
|
||||||
|
#[error("the Encrypted message doesn't contain a ciphertext for our device")]
|
||||||
|
MissingCiphertext,
|
||||||
|
#[error("the Encrypted message is missing the signing key of the sender")]
|
||||||
|
MissingSigningKey,
|
||||||
|
#[error("the Encrypted message is missing the field {0}")]
|
||||||
|
MissingField(String),
|
||||||
|
#[error("the sender of the plaintext doesn't match the sender of the encrypted message.")]
|
||||||
|
MissmatchedSender,
|
||||||
|
#[error("the keys of the message don't match the keys in our database.")]
|
||||||
|
MissmatchedKeys,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum SignatureError {
|
pub enum SignatureError {
|
||||||
|
|
|
@ -23,6 +23,6 @@ mod olm;
|
||||||
mod store;
|
mod store;
|
||||||
|
|
||||||
pub use device::{Device, TrustState};
|
pub use device::{Device, TrustState};
|
||||||
pub use error::OlmError;
|
pub use error::{MegolmError, OlmError};
|
||||||
pub use machine::{OlmMachine, OneTimeKeys};
|
pub use machine::{OlmMachine, OneTimeKeys};
|
||||||
pub use store::{CryptoStore, CryptoStoreError};
|
pub use store::{CryptoStore, CryptoStoreError};
|
||||||
|
|
|
@ -21,7 +21,9 @@ use std::result::Result as StdResult;
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::error::{OlmError, Result, SignatureError, VerificationResult};
|
use super::error::{
|
||||||
|
EventError, MegolmError, MegolmResult, OlmError, OlmResult, SignatureError, VerificationResult,
|
||||||
|
};
|
||||||
use super::olm::{
|
use super::olm::{
|
||||||
Account, GroupSessionKey, IdentityKeys, InboundGroupSession, OlmMessage, OlmUtility,
|
Account, GroupSessionKey, IdentityKeys, InboundGroupSession, OlmMessage, OlmUtility,
|
||||||
OutboundGroupSession, Session,
|
OutboundGroupSession, Session,
|
||||||
|
@ -29,7 +31,7 @@ use super::olm::{
|
||||||
use super::store::memorystore::MemoryStore;
|
use super::store::memorystore::MemoryStore;
|
||||||
#[cfg(feature = "sqlite-cryptostore")]
|
#[cfg(feature = "sqlite-cryptostore")]
|
||||||
use super::store::sqlite::SqliteStore;
|
use super::store::sqlite::SqliteStore;
|
||||||
use super::{device::Device, CryptoStore};
|
use super::{device::Device, store::Result as StoreError, CryptoStore};
|
||||||
|
|
||||||
use matrix_sdk_types::api;
|
use matrix_sdk_types::api;
|
||||||
use matrix_sdk_types::events::{
|
use matrix_sdk_types::events::{
|
||||||
|
@ -102,8 +104,8 @@ impl OlmMachine {
|
||||||
const MAX_TO_DEVICE_MESSAGES: usize = 20;
|
const MAX_TO_DEVICE_MESSAGES: usize = 20;
|
||||||
|
|
||||||
/// Create a new account.
|
/// Create a new account.
|
||||||
pub fn new(user_id: &UserId, device_id: &str) -> Result<Self> {
|
pub fn new(user_id: &UserId, device_id: &str) -> Self {
|
||||||
Ok(OlmMachine {
|
OlmMachine {
|
||||||
user_id: user_id.clone(),
|
user_id: user_id.clone(),
|
||||||
device_id: device_id.to_owned(),
|
device_id: device_id.to_owned(),
|
||||||
account: Account::new(),
|
account: Account::new(),
|
||||||
|
@ -111,7 +113,7 @@ impl OlmMachine {
|
||||||
store: Box::new(MemoryStore::new()),
|
store: Box::new(MemoryStore::new()),
|
||||||
users_for_key_query: HashSet::new(),
|
users_for_key_query: HashSet::new(),
|
||||||
outbound_group_sessions: HashMap::new(),
|
outbound_group_sessions: HashMap::new(),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "sqlite-cryptostore")]
|
#[cfg(feature = "sqlite-cryptostore")]
|
||||||
|
@ -121,7 +123,7 @@ impl OlmMachine {
|
||||||
device_id: &str,
|
device_id: &str,
|
||||||
path: P,
|
path: P,
|
||||||
passphrase: String,
|
passphrase: String,
|
||||||
) -> Result<Self> {
|
) -> StoreError<Self> {
|
||||||
let mut store =
|
let mut store =
|
||||||
SqliteStore::open_with_passphrase(&user_id, device_id, path, passphrase).await?;
|
SqliteStore::open_with_passphrase(&user_id, device_id, path, passphrase).await?;
|
||||||
|
|
||||||
|
@ -197,7 +199,7 @@ impl OlmMachine {
|
||||||
pub async fn receive_keys_upload_response(
|
pub async fn receive_keys_upload_response(
|
||||||
&mut self,
|
&mut self,
|
||||||
response: &keys::upload_keys::Response,
|
response: &keys::upload_keys::Response,
|
||||||
) -> Result<()> {
|
) -> OlmResult<()> {
|
||||||
if !self.account.shared() {
|
if !self.account.shared() {
|
||||||
debug!("Marking account as shared");
|
debug!("Marking account as shared");
|
||||||
}
|
}
|
||||||
|
@ -226,14 +228,14 @@ impl OlmMachine {
|
||||||
pub async fn get_missing_sessions(
|
pub async fn get_missing_sessions(
|
||||||
&mut self,
|
&mut self,
|
||||||
users: impl Iterator<Item = &UserId>,
|
users: impl Iterator<Item = &UserId>,
|
||||||
) -> Result<BTreeMap<UserId, BTreeMap<DeviceId, KeyAlgorithm>>> {
|
) -> OlmResult<BTreeMap<UserId, BTreeMap<DeviceId, KeyAlgorithm>>> {
|
||||||
let mut missing = BTreeMap::new();
|
let mut missing = BTreeMap::new();
|
||||||
|
|
||||||
for user_id in users {
|
for user_id in users {
|
||||||
let user_devices = self.store.get_user_devices(user_id).await?;
|
let user_devices = self.store.get_user_devices(user_id).await?;
|
||||||
|
|
||||||
for device in user_devices.devices() {
|
for device in user_devices.devices() {
|
||||||
let sender_key = if let Some(k) = device.get_key(&KeyAlgorithm::Curve25519) {
|
let sender_key = if let Some(k) = device.get_key(KeyAlgorithm::Curve25519) {
|
||||||
k
|
k
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -267,7 +269,7 @@ impl OlmMachine {
|
||||||
pub async fn receive_keys_claim_response(
|
pub async fn receive_keys_claim_response(
|
||||||
&mut self,
|
&mut self,
|
||||||
response: &keys::claim_keys::Response,
|
response: &keys::claim_keys::Response,
|
||||||
) -> Result<()> {
|
) -> OlmResult<()> {
|
||||||
// TODO log the failures here
|
// TODO log the failures here
|
||||||
|
|
||||||
for (user_id, user_devices) in &response.one_time_keys {
|
for (user_id, user_devices) in &response.one_time_keys {
|
||||||
|
@ -308,7 +310,7 @@ impl OlmMachine {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let signing_key = if let Some(k) = device.get_key(&KeyAlgorithm::Ed25519) {
|
let signing_key = if let Some(k) = device.get_key(KeyAlgorithm::Ed25519) {
|
||||||
k
|
k
|
||||||
} else {
|
} else {
|
||||||
warn!(
|
warn!(
|
||||||
|
@ -330,7 +332,7 @@ impl OlmMachine {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let curve_key = if let Some(k) = device.get_key(&KeyAlgorithm::Curve25519) {
|
let curve_key = if let Some(k) = device.get_key(KeyAlgorithm::Curve25519) {
|
||||||
k
|
k
|
||||||
} else {
|
} else {
|
||||||
warn!(
|
warn!(
|
||||||
|
@ -384,7 +386,7 @@ impl OlmMachine {
|
||||||
pub async fn receive_keys_query_response(
|
pub async fn receive_keys_query_response(
|
||||||
&mut self,
|
&mut self,
|
||||||
response: &keys::get_keys::Response,
|
response: &keys::get_keys::Response,
|
||||||
) -> Result<Vec<Device>> {
|
) -> OlmResult<Vec<Device>> {
|
||||||
let mut changed_devices = Vec::new();
|
let mut changed_devices = Vec::new();
|
||||||
|
|
||||||
for (user_id, device_map) in &response.device_keys {
|
for (user_id, device_map) in &response.device_keys {
|
||||||
|
@ -430,7 +432,7 @@ impl OlmMachine {
|
||||||
let device = self.store.get_device(&user_id, device_id).await?;
|
let device = self.store.get_device(&user_id, device_id).await?;
|
||||||
|
|
||||||
let device = if let Some(mut d) = device {
|
let device = if let Some(mut d) = device {
|
||||||
let stored_signing_key = d.get_key(&KeyAlgorithm::Ed25519);
|
let stored_signing_key = d.get_key(KeyAlgorithm::Ed25519);
|
||||||
|
|
||||||
if let Some(stored_signing_key) = stored_signing_key {
|
if let Some(stored_signing_key) = stored_signing_key {
|
||||||
if stored_signing_key != signing_key {
|
if stored_signing_key != signing_key {
|
||||||
|
@ -688,7 +690,7 @@ impl OlmMachine {
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
sender_key: &str,
|
sender_key: &str,
|
||||||
message: &OlmMessage,
|
message: &OlmMessage,
|
||||||
) -> Result<Option<String>> {
|
) -> OlmResult<Option<String>> {
|
||||||
let s = self.store.get_sessions(sender_key).await?;
|
let s = self.store.get_sessions(sender_key).await?;
|
||||||
|
|
||||||
// We don't have any existing sessions, return early.
|
// We don't have any existing sessions, return early.
|
||||||
|
@ -750,7 +752,7 @@ impl OlmMachine {
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
sender_key: &str,
|
sender_key: &str,
|
||||||
message: OlmMessage,
|
message: OlmMessage,
|
||||||
) -> Result<(EventJson<ToDeviceEvent>, String)> {
|
) -> OlmResult<(EventJson<ToDeviceEvent>, String)> {
|
||||||
// First try to decrypt using an existing session.
|
// First try to decrypt using an existing session.
|
||||||
let plaintext = if let Some(p) = self
|
let plaintext = if let Some(p) = self
|
||||||
.try_decrypt_olm_event(sender, sender_key, &message)
|
.try_decrypt_olm_event(sender, sender_key, &message)
|
||||||
|
@ -817,49 +819,49 @@ impl OlmMachine {
|
||||||
&self,
|
&self,
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
plaintext: &str,
|
plaintext: &str,
|
||||||
) -> Result<(EventJson<ToDeviceEvent>, String)> {
|
) -> OlmResult<(EventJson<ToDeviceEvent>, String)> {
|
||||||
// TODO make the errors a bit more specific.
|
// TODO make the errors a bit more specific.
|
||||||
let decrypted_json: Value = serde_json::from_str(&plaintext)?;
|
let decrypted_json: Value = serde_json::from_str(&plaintext)?;
|
||||||
|
|
||||||
let encrytped_sender = decrypted_json
|
let encrytped_sender = decrypted_json
|
||||||
.get("sender")
|
.get("sender")
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or(OlmError::MissingCiphertext)?;
|
.ok_or(EventError::MissingField("sender".to_string()))?;
|
||||||
let encrytped_sender: UserId = serde_json::from_value(encrytped_sender)?;
|
let encrytped_sender: UserId = serde_json::from_value(encrytped_sender)?;
|
||||||
let recipient = decrypted_json
|
let recipient = decrypted_json
|
||||||
.get("recipient")
|
.get("recipient")
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or(OlmError::MissingCiphertext)?;
|
.ok_or(EventError::MissingField("recipient".to_string()))?;
|
||||||
let recipient: UserId = serde_json::from_value(recipient)?;
|
let recipient: UserId = serde_json::from_value(recipient)?;
|
||||||
|
|
||||||
let recipient_keys: BTreeMap<KeyAlgorithm, String> = serde_json::from_value(
|
let recipient_keys: BTreeMap<KeyAlgorithm, String> = serde_json::from_value(
|
||||||
decrypted_json
|
decrypted_json
|
||||||
.get("recipient_keys")
|
.get("recipient_keys")
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or(OlmError::MissingCiphertext)?,
|
.ok_or(EventError::MissingField("recipient_keys".to_string()))?,
|
||||||
)?;
|
)?;
|
||||||
let keys: BTreeMap<KeyAlgorithm, String> = serde_json::from_value(
|
let keys: BTreeMap<KeyAlgorithm, String> = serde_json::from_value(
|
||||||
decrypted_json
|
decrypted_json
|
||||||
.get("keys")
|
.get("keys")
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or(OlmError::MissingCiphertext)?,
|
.ok_or(EventError::MissingField("keys".to_string()))?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if recipient != self.user_id || sender != &encrytped_sender {
|
if recipient != self.user_id || sender != &encrytped_sender {
|
||||||
return Err(OlmError::MissingCiphertext);
|
return Err(EventError::MissmatchedSender)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.account.identity_keys().ed25519()
|
if self.account.identity_keys().ed25519()
|
||||||
!= recipient_keys
|
!= recipient_keys
|
||||||
.get(&KeyAlgorithm::Ed25519)
|
.get(&KeyAlgorithm::Ed25519)
|
||||||
.ok_or(OlmError::MissingCiphertext)?
|
.ok_or(EventError::MissingSigningKey)?
|
||||||
{
|
{
|
||||||
return Err(OlmError::MissingCiphertext);
|
return Err(EventError::MissmatchedKeys)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let signing_key = keys
|
let signing_key = keys
|
||||||
.get(&KeyAlgorithm::Ed25519)
|
.get(&KeyAlgorithm::Ed25519)
|
||||||
.ok_or(OlmError::MissingSigningKey)?;
|
.ok_or(EventError::MissingSigningKey)?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
serde_json::from_value::<EventJson<ToDeviceEvent>>(decrypted_json)?,
|
serde_json::from_value::<EventJson<ToDeviceEvent>>(decrypted_json)?,
|
||||||
|
@ -878,14 +880,14 @@ impl OlmMachine {
|
||||||
async fn decrypt_to_device_event(
|
async fn decrypt_to_device_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: &ToDeviceEncrypted,
|
event: &ToDeviceEncrypted,
|
||||||
) -> Result<EventJson<ToDeviceEvent>> {
|
) -> OlmResult<EventJson<ToDeviceEvent>> {
|
||||||
info!("Decrypting to-device event");
|
info!("Decrypting to-device event");
|
||||||
|
|
||||||
let content = if let EncryptedEventContent::OlmV1Curve25519AesSha2(c) = &event.content {
|
let content = if let EncryptedEventContent::OlmV1Curve25519AesSha2(c) = &event.content {
|
||||||
c
|
c
|
||||||
} else {
|
} else {
|
||||||
warn!("Error, unsupported encryption algorithm");
|
warn!("Error, unsupported encryption algorithm");
|
||||||
return Err(OlmError::UnsupportedAlgorithm);
|
return Err(EventError::UnsupportedAlgorithm)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
let identity_keys = self.account.identity_keys();
|
let identity_keys = self.account.identity_keys();
|
||||||
|
@ -897,12 +899,12 @@ impl OlmMachine {
|
||||||
let message_type: u8 = ciphertext
|
let message_type: u8 = ciphertext
|
||||||
.message_type
|
.message_type
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| OlmError::UnsupportedOlmType)?;
|
.map_err(|_| EventError::UnsupportedOlmType)?;
|
||||||
|
|
||||||
// Create a OlmMessage from the ciphertext and the type.
|
// Create a OlmMessage from the ciphertext and the type.
|
||||||
let message =
|
let message =
|
||||||
OlmMessage::from_type_and_ciphertext(message_type.into(), ciphertext.body.clone())
|
OlmMessage::from_type_and_ciphertext(message_type.into(), ciphertext.body.clone())
|
||||||
.map_err(|_| OlmError::UnsupportedOlmType)?;
|
.map_err(|_| EventError::UnsupportedOlmType)?;
|
||||||
|
|
||||||
// Decrypt the OlmMessage and get a Ruma event out of it.
|
// Decrypt the OlmMessage and get a Ruma event out of it.
|
||||||
let (mut decrypted_event, signing_key) = self
|
let (mut decrypted_event, signing_key) = self
|
||||||
|
@ -923,7 +925,7 @@ impl OlmMachine {
|
||||||
Ok(decrypted_event)
|
Ok(decrypted_event)
|
||||||
} else {
|
} else {
|
||||||
warn!("Olm event doesn't contain a ciphertext for our key");
|
warn!("Olm event doesn't contain a ciphertext for our key");
|
||||||
Err(OlmError::MissingCiphertext)
|
Err(EventError::MissingCiphertext)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -932,7 +934,7 @@ impl OlmMachine {
|
||||||
sender_key: &str,
|
sender_key: &str,
|
||||||
signing_key: &str,
|
signing_key: &str,
|
||||||
event: &mut ToDeviceRoomKey,
|
event: &mut ToDeviceRoomKey,
|
||||||
) -> Result<()> {
|
) -> OlmResult<()> {
|
||||||
match event.content.algorithm {
|
match event.content.algorithm {
|
||||||
Algorithm::MegolmV1AesSha2 => {
|
Algorithm::MegolmV1AesSha2 => {
|
||||||
let session_key = GroupSessionKey(mem::take(&mut event.content.session_key));
|
let session_key = GroupSessionKey(mem::take(&mut event.content.session_key));
|
||||||
|
@ -956,7 +958,7 @@ impl OlmMachine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_outbound_group_session(&mut self, room_id: &RoomId) -> Result<()> {
|
async fn create_outbound_group_session(&mut self, room_id: &RoomId) -> OlmResult<()> {
|
||||||
let session = OutboundGroupSession::new(room_id);
|
let session = OutboundGroupSession::new(room_id);
|
||||||
let identity_keys = self.account.identity_keys();
|
let identity_keys = self.account.identity_keys();
|
||||||
|
|
||||||
|
@ -982,7 +984,7 @@ impl OlmMachine {
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
content: MessageEventContent,
|
content: MessageEventContent,
|
||||||
) -> Result<EncryptedEventContent> {
|
) -> MegolmResult<EncryptedEventContent> {
|
||||||
let session = self.outbound_group_sessions.get(room_id);
|
let session = self.outbound_group_sessions.get(room_id);
|
||||||
|
|
||||||
let session = if let Some(s) = session {
|
let session = if let Some(s) = session {
|
||||||
|
@ -1027,15 +1029,15 @@ impl OlmMachine {
|
||||||
recipient_device: &Device,
|
recipient_device: &Device,
|
||||||
event_type: EventType,
|
event_type: EventType,
|
||||||
content: Value,
|
content: Value,
|
||||||
) -> Result<EncryptedEventContent> {
|
) -> OlmResult<EncryptedEventContent> {
|
||||||
let identity_keys = self.account.identity_keys();
|
let identity_keys = self.account.identity_keys();
|
||||||
|
|
||||||
let recipient_signing_key = recipient_device
|
let recipient_signing_key = recipient_device
|
||||||
.get_key(&KeyAlgorithm::Ed25519)
|
.get_key(KeyAlgorithm::Ed25519)
|
||||||
.ok_or(OlmError::MissingSigningKey)?;
|
.ok_or(EventError::MissingSigningKey)?;
|
||||||
let recipient_sender_key = recipient_device
|
let recipient_sender_key = recipient_device
|
||||||
.get_key(&KeyAlgorithm::Curve25519)
|
.get_key(KeyAlgorithm::Curve25519)
|
||||||
.ok_or(OlmError::MissingSigningKey)?;
|
.ok_or(EventError::MissingSigningKey)?;
|
||||||
|
|
||||||
let payload = json!({
|
let payload = json!({
|
||||||
"sender": self.user_id,
|
"sender": self.user_id,
|
||||||
|
@ -1107,7 +1109,7 @@ impl OlmMachine {
|
||||||
&mut self,
|
&mut self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
users: I,
|
users: I,
|
||||||
) -> Result<Vec<ToDeviceRequest>>
|
) -> OlmResult<Vec<ToDeviceRequest>>
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = &'a UserId>,
|
I: IntoIterator<Item = &'a UserId>,
|
||||||
{
|
{
|
||||||
|
@ -1133,7 +1135,7 @@ impl OlmMachine {
|
||||||
|
|
||||||
for user_id in users {
|
for user_id in users {
|
||||||
for device in self.store.get_user_devices(user_id).await?.devices() {
|
for device in self.store.get_user_devices(user_id).await?.devices() {
|
||||||
let sender_key = if let Some(k) = device.get_key(&KeyAlgorithm::Curve25519) {
|
let sender_key = if let Some(k) = device.get_key(KeyAlgorithm::Curve25519) {
|
||||||
k
|
k
|
||||||
} else {
|
} else {
|
||||||
warn!(
|
warn!(
|
||||||
|
@ -1204,7 +1206,7 @@ impl OlmMachine {
|
||||||
_sender_key: &str,
|
_sender_key: &str,
|
||||||
_signing_key: &str,
|
_signing_key: &str,
|
||||||
_event: &ToDeviceForwardedRoomKey,
|
_event: &ToDeviceForwardedRoomKey,
|
||||||
) -> Result<()> {
|
) -> OlmResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
@ -1214,7 +1216,7 @@ impl OlmMachine {
|
||||||
sender_key: &str,
|
sender_key: &str,
|
||||||
signing_key: &str,
|
signing_key: &str,
|
||||||
event: &mut EventJson<ToDeviceEvent>,
|
event: &mut EventJson<ToDeviceEvent>,
|
||||||
) -> Result<()> {
|
) -> OlmResult<()> {
|
||||||
let event = if let Ok(e) = event.deserialize() {
|
let event = if let Ok(e) = event.deserialize() {
|
||||||
e
|
e
|
||||||
} else {
|
} else {
|
||||||
|
@ -1305,10 +1307,10 @@ impl OlmMachine {
|
||||||
pub async fn decrypt_room_event(
|
pub async fn decrypt_room_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: &EncryptedEvent,
|
event: &EncryptedEvent,
|
||||||
) -> Result<EventJson<RoomEvent>> {
|
) -> MegolmResult<EventJson<RoomEvent>> {
|
||||||
let content = match &event.content {
|
let content = match &event.content {
|
||||||
EncryptedEventContent::MegolmV1AesSha2(c) => c,
|
EncryptedEventContent::MegolmV1AesSha2(c) => c,
|
||||||
_ => return Err(OlmError::UnsupportedAlgorithm),
|
_ => return Err(EventError::UnsupportedAlgorithm)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
let room_id = event.room_id.as_ref().unwrap();
|
let room_id = event.room_id.as_ref().unwrap();
|
||||||
|
@ -1318,7 +1320,7 @@ impl OlmMachine {
|
||||||
.get_inbound_group_session(&room_id, &content.sender_key, &content.session_id)
|
.get_inbound_group_session(&room_id, &content.sender_key, &content.session_id)
|
||||||
.await?;
|
.await?;
|
||||||
// TODO check if the olm session is wedged and re-request the key.
|
// TODO check if the olm session is wedged and re-request the key.
|
||||||
let session = session.ok_or(OlmError::MissingSession)?;
|
let session = session.ok_or(MegolmError::MissingSession)?;
|
||||||
|
|
||||||
let (plaintext, _) = session.decrypt(content.ciphertext.clone()).await?;
|
let (plaintext, _) = session.decrypt(content.ciphertext.clone()).await?;
|
||||||
// TODO check the message index.
|
// TODO check the message index.
|
||||||
|
@ -1327,7 +1329,7 @@ impl OlmMachine {
|
||||||
let mut decrypted_value = serde_json::from_str::<Value>(&plaintext)?;
|
let mut decrypted_value = serde_json::from_str::<Value>(&plaintext)?;
|
||||||
let decrypted_object = decrypted_value
|
let decrypted_object = decrypted_value
|
||||||
.as_object_mut()
|
.as_object_mut()
|
||||||
.ok_or(OlmError::NotAnObject)?;
|
.ok_or(EventError::NotAnObject)?;
|
||||||
|
|
||||||
// TODO better number conversion here.
|
// TODO better number conversion here.
|
||||||
let server_ts = event
|
let server_ts = event
|
||||||
|
@ -1479,7 +1481,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_prepared_machine() -> (OlmMachine, OneTimeKeys) {
|
async fn get_prepared_machine() -> (OlmMachine, OneTimeKeys) {
|
||||||
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
||||||
machine.uploaded_signed_key_count = Some(AtomicU64::new(0));
|
machine.uploaded_signed_key_count = Some(AtomicU64::new(0));
|
||||||
let (_, otk) = machine
|
let (_, otk) = machine
|
||||||
.keys_for_upload()
|
.keys_for_upload()
|
||||||
|
@ -1511,7 +1513,7 @@ mod test {
|
||||||
|
|
||||||
let alice_id = alice_id();
|
let alice_id = alice_id();
|
||||||
let alice_device = alice_device_id();
|
let alice_device = alice_device_id();
|
||||||
let alice = OlmMachine::new(&alice_id, &alice_device).unwrap();
|
let alice = OlmMachine::new(&alice_id, &alice_device);
|
||||||
|
|
||||||
let alice_deivce = Device::from(&alice);
|
let alice_deivce = Device::from(&alice);
|
||||||
let bob_device = Device::from(&bob);
|
let bob_device = Device::from(&bob);
|
||||||
|
@ -1579,13 +1581,13 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn create_olm_machine() {
|
async fn create_olm_machine() {
|
||||||
let machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
let machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
||||||
assert!(machine.should_upload_keys().await);
|
assert!(machine.should_upload_keys().await);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn receive_keys_upload_response() {
|
async fn receive_keys_upload_response() {
|
||||||
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
||||||
let mut response = keys_upload_response();
|
let mut response = keys_upload_response();
|
||||||
|
|
||||||
response
|
response
|
||||||
|
@ -1623,7 +1625,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn generate_one_time_keys() {
|
async fn generate_one_time_keys() {
|
||||||
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
||||||
|
|
||||||
let mut response = keys_upload_response();
|
let mut response = keys_upload_response();
|
||||||
|
|
||||||
|
@ -1650,7 +1652,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_device_key_signing() {
|
async fn test_device_key_signing() {
|
||||||
let machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
let machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
||||||
|
|
||||||
let mut device_keys = machine.device_keys().await;
|
let mut device_keys = machine.device_keys().await;
|
||||||
let identity_keys = machine.account.identity_keys();
|
let identity_keys = machine.account.identity_keys();
|
||||||
|
@ -1667,7 +1669,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_invalid_signature() {
|
async fn test_invalid_signature() {
|
||||||
let machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
let machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
||||||
|
|
||||||
let mut device_keys = machine.device_keys().await;
|
let mut device_keys = machine.device_keys().await;
|
||||||
|
|
||||||
|
@ -1682,7 +1684,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_one_time_key_signing() {
|
async fn test_one_time_key_signing() {
|
||||||
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
||||||
machine.uploaded_signed_key_count = Some(AtomicU64::new(49));
|
machine.uploaded_signed_key_count = Some(AtomicU64::new(49));
|
||||||
|
|
||||||
let mut one_time_keys = machine.signed_one_time_keys().await.unwrap();
|
let mut one_time_keys = machine.signed_one_time_keys().await.unwrap();
|
||||||
|
@ -1702,7 +1704,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_keys_for_upload() {
|
async fn test_keys_for_upload() {
|
||||||
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
||||||
machine.uploaded_signed_key_count = Some(AtomicU64::default());
|
machine.uploaded_signed_key_count = Some(AtomicU64::default());
|
||||||
|
|
||||||
let identity_keys = machine.account.identity_keys();
|
let identity_keys = machine.account.identity_keys();
|
||||||
|
|
Loading…
Reference in New Issue