crypto: Move the outbound session creation logic into the account.
parent
6cced25ae1
commit
de1988265d
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
use cjson::Error as CjsonError;
|
||||
use matrix_sdk_common::identifiers::{DeviceId, UserId};
|
||||
use olm_rs::errors::{OlmGroupSessionError, OlmSessionError};
|
||||
use serde_json::Error as SerdeError;
|
||||
use thiserror::Error;
|
||||
|
@ -121,6 +122,29 @@ pub enum SignatureError {
|
|||
VerificationError,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub(crate) enum SessionCreationError {
|
||||
#[error(
|
||||
"Failed to create a new Olm session for {0} {1}, the requested \
|
||||
one-time key isn't a signed curve key"
|
||||
)]
|
||||
OneTimeKeyNotSigned(UserId, DeviceId),
|
||||
#[error(
|
||||
"Tried to create a new Olm session for {0} {1}, but the signed \
|
||||
one-time key is missing"
|
||||
)]
|
||||
OneTimeKeyMissing(UserId, DeviceId),
|
||||
#[error("Failed to verify the one-time key signatures for {0} {1}: {2:?}")]
|
||||
InvalidSignature(UserId, DeviceId, SignatureError),
|
||||
#[error(
|
||||
"Tried to create an Olm session for {0} {1}, but the device is missing \
|
||||
a curve25519 key"
|
||||
)]
|
||||
DeviceMissingCurveKey(UserId, DeviceId),
|
||||
#[error("Error creating new Olm session for {0} {1}: {2:?}")]
|
||||
OlmError(UserId, DeviceId, OlmSessionError),
|
||||
}
|
||||
|
||||
impl From<CjsonError> for SignatureError {
|
||||
fn from(error: CjsonError) -> Self {
|
||||
Self::CanonicalJsonError(error)
|
||||
|
|
|
@ -306,76 +306,35 @@ impl OlmMachine {
|
|||
|
||||
for (user_id, user_devices) in &response.one_time_keys {
|
||||
for (device_id, key_map) in user_devices {
|
||||
let device = if let Some(d) = self
|
||||
.store
|
||||
.get_device(&user_id, device_id)
|
||||
.await
|
||||
.expect("Can't get devices")
|
||||
{
|
||||
d
|
||||
} else {
|
||||
warn!(
|
||||
"Tried to create an Olm session for {} {}, but the device is unknown",
|
||||
user_id, device_id
|
||||
);
|
||||
continue;
|
||||
};
|
||||
|
||||
// TODO move this logic into the account, pass the device to the
|
||||
// account when creating an outbound session.
|
||||
let one_time_key = if let Some(k) = key_map.values().next() {
|
||||
match k {
|
||||
OneTimeKey::SignedKey(k) => k,
|
||||
OneTimeKey::Key(_) => {
|
||||
let device: Device = match self.store.get_device(&user_id, device_id).await {
|
||||
Ok(d) => {
|
||||
if let Some(d) = d {
|
||||
d
|
||||
} else {
|
||||
warn!(
|
||||
"Tried to create an Olm session for {} {}, but
|
||||
the requested key isn't a signed curve key",
|
||||
"Tried to create an Olm session for {} {}, but \
|
||||
the device is unknown",
|
||||
user_id, device_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!(
|
||||
"Tried to create an Olm session for {} {}, but the
|
||||
signed one-time key is missing",
|
||||
user_id, device_id
|
||||
);
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Err(e) = device.verify_one_time_key(&one_time_key) {
|
||||
warn!(
|
||||
"Failed to verify the one-time key signatures for {} {}: {:?}",
|
||||
user_id, device_id, e
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let curve_key = if let Some(k) = device.get_key(KeyAlgorithm::Curve25519) {
|
||||
k
|
||||
} else {
|
||||
warn!(
|
||||
"Tried to create an Olm session for {} {}, but the
|
||||
device is missing the curve key",
|
||||
user_id, device_id
|
||||
);
|
||||
continue;
|
||||
Err(e) => {
|
||||
warn!(
|
||||
"Tried to create an Olm session for {} {}, but \
|
||||
can't fetch the device from the store {:?}",
|
||||
user_id, device_id, e
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
info!("Creating outbound Session for {} {}", user_id, device_id);
|
||||
|
||||
let session = match self
|
||||
.account
|
||||
.create_outbound_session(curve_key, &one_time_key)
|
||||
.await
|
||||
{
|
||||
let session = match self.account.create_outbound_session(device, &key_map).await {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
warn!(
|
||||
"Error creating new Olm session for {} {}: {}",
|
||||
user_id, device_id, e
|
||||
);
|
||||
warn!("{:?}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -33,7 +33,8 @@ use olm_rs::outbound_group_session::OlmOutboundGroupSession;
|
|||
use olm_rs::session::OlmSession;
|
||||
use olm_rs::PicklingMode;
|
||||
|
||||
use crate::error::{EventError, MegolmResult};
|
||||
use crate::device::Device;
|
||||
use crate::error::{EventError, MegolmResult, SessionCreationError};
|
||||
pub use olm_rs::{
|
||||
session::{OlmMessage, PreKeyMessage},
|
||||
utility::OlmUtility,
|
||||
|
@ -386,7 +387,7 @@ impl Account {
|
|||
///
|
||||
/// * `their_one_time_key` - A signed one-time key that the other account
|
||||
/// created and shared with us.
|
||||
pub(crate) async fn create_outbound_session(
|
||||
pub(crate) async fn create_outbound_session_helper(
|
||||
&self,
|
||||
their_identity_key: &str,
|
||||
their_one_time_key: &SignedKey,
|
||||
|
@ -409,6 +410,67 @@ impl Account {
|
|||
})
|
||||
}
|
||||
|
||||
/// Create a new session with another account given a one-time key and a
|
||||
/// device.
|
||||
///
|
||||
/// Returns the newly created session or a `OlmSessionError` if creating a
|
||||
/// session failed.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `device` - The other account's device.
|
||||
///
|
||||
/// * `key_map` - A map from the algorithm and device id to the one-time
|
||||
/// key that the other account created and shared with us.
|
||||
pub(crate) async fn create_outbound_session(
|
||||
&self,
|
||||
device: Device,
|
||||
key_map: &BTreeMap<AlgorithmAndDeviceId, OneTimeKey>,
|
||||
) -> Result<Session, SessionCreationError> {
|
||||
let one_time_key =
|
||||
key_map
|
||||
.values()
|
||||
.next()
|
||||
.ok_or(SessionCreationError::OneTimeKeyMissing(
|
||||
device.user_id().to_owned(),
|
||||
device.device_id().to_owned(),
|
||||
))?;
|
||||
|
||||
let one_time_key = match one_time_key {
|
||||
OneTimeKey::SignedKey(k) => k,
|
||||
OneTimeKey::Key(_) => {
|
||||
return Err(SessionCreationError::OneTimeKeyNotSigned(
|
||||
device.user_id().to_owned(),
|
||||
device.device_id().to_owned(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
device.verify_one_time_key(&one_time_key).map_err(|e| {
|
||||
SessionCreationError::InvalidSignature(
|
||||
device.user_id().to_owned(),
|
||||
device.device_id().to_owned(),
|
||||
e,
|
||||
)
|
||||
})?;
|
||||
|
||||
let curve_key = device.get_key(KeyAlgorithm::Curve25519).ok_or(
|
||||
SessionCreationError::DeviceMissingCurveKey(
|
||||
device.user_id().to_owned(),
|
||||
device.device_id().to_owned(),
|
||||
),
|
||||
)?;
|
||||
|
||||
self.create_outbound_session_helper(curve_key, &one_time_key)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
SessionCreationError::OlmError(
|
||||
device.user_id().to_owned(),
|
||||
device.device_id().to_owned(),
|
||||
e,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a new session with another account given a pre-key Olm message.
|
||||
///
|
||||
/// Returns the newly created session or a `OlmSessionError` if creating a
|
||||
|
@ -1014,7 +1076,7 @@ pub(crate) mod test {
|
|||
};
|
||||
let sender_key = bob.identity_keys().curve25519().to_owned();
|
||||
let session = alice
|
||||
.create_outbound_session(&sender_key, &one_time_key)
|
||||
.create_outbound_session_helper(&sender_key, &one_time_key)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -1092,7 +1154,7 @@ pub(crate) mod test {
|
|||
};
|
||||
|
||||
let mut bob_session = bob
|
||||
.create_outbound_session(alice_keys.curve25519(), &one_time_key)
|
||||
.create_outbound_session_helper(alice_keys.curve25519(), &one_time_key)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -876,7 +876,7 @@ mod test {
|
|||
};
|
||||
let sender_key = bob.identity_keys().curve25519().to_owned();
|
||||
let session = alice
|
||||
.create_outbound_session(&sender_key, &one_time_key)
|
||||
.create_outbound_session_helper(&sender_key, &one_time_key)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
Loading…
Reference in New Issue