crypto: Move the outbound session creation logic into the account.
parent
6cced25ae1
commit
de1988265d
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use cjson::Error as CjsonError;
|
use cjson::Error as CjsonError;
|
||||||
|
use matrix_sdk_common::identifiers::{DeviceId, UserId};
|
||||||
use olm_rs::errors::{OlmGroupSessionError, OlmSessionError};
|
use olm_rs::errors::{OlmGroupSessionError, OlmSessionError};
|
||||||
use serde_json::Error as SerdeError;
|
use serde_json::Error as SerdeError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -121,6 +122,29 @@ pub enum SignatureError {
|
||||||
VerificationError,
|
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 {
|
impl From<CjsonError> for SignatureError {
|
||||||
fn from(error: CjsonError) -> Self {
|
fn from(error: CjsonError) -> Self {
|
||||||
Self::CanonicalJsonError(error)
|
Self::CanonicalJsonError(error)
|
||||||
|
|
|
@ -306,76 +306,35 @@ impl OlmMachine {
|
||||||
|
|
||||||
for (user_id, user_devices) in &response.one_time_keys {
|
for (user_id, user_devices) in &response.one_time_keys {
|
||||||
for (device_id, key_map) in user_devices {
|
for (device_id, key_map) in user_devices {
|
||||||
let device = if let Some(d) = self
|
let device: Device = match self.store.get_device(&user_id, device_id).await {
|
||||||
.store
|
Ok(d) => {
|
||||||
.get_device(&user_id, device_id)
|
if let Some(d) = d {
|
||||||
.await
|
d
|
||||||
.expect("Can't get devices")
|
} else {
|
||||||
{
|
|
||||||
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(_) => {
|
|
||||||
warn!(
|
warn!(
|
||||||
"Tried to create an Olm session for {} {}, but
|
"Tried to create an Olm session for {} {}, but \
|
||||||
the requested key isn't a signed curve key",
|
the device is unknown",
|
||||||
user_id, device_id
|
user_id, device_id
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
Err(e) => {
|
||||||
warn!(
|
warn!(
|
||||||
"Tried to create an Olm session for {} {}, but the
|
"Tried to create an Olm session for {} {}, but \
|
||||||
signed one-time key is missing",
|
can't fetch the device from the store {:?}",
|
||||||
user_id, device_id
|
user_id, device_id, e
|
||||||
);
|
);
|
||||||
continue;
|
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Creating outbound Session for {} {}", user_id, device_id);
|
info!("Creating outbound Session for {} {}", user_id, device_id);
|
||||||
|
|
||||||
let session = match self
|
let session = match self.account.create_outbound_session(device, &key_map).await {
|
||||||
.account
|
|
||||||
.create_outbound_session(curve_key, &one_time_key)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(
|
warn!("{:?}", e);
|
||||||
"Error creating new Olm session for {} {}: {}",
|
|
||||||
user_id, device_id, e
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,7 +33,8 @@ use olm_rs::outbound_group_session::OlmOutboundGroupSession;
|
||||||
use olm_rs::session::OlmSession;
|
use olm_rs::session::OlmSession;
|
||||||
use olm_rs::PicklingMode;
|
use olm_rs::PicklingMode;
|
||||||
|
|
||||||
use crate::error::{EventError, MegolmResult};
|
use crate::device::Device;
|
||||||
|
use crate::error::{EventError, MegolmResult, SessionCreationError};
|
||||||
pub use olm_rs::{
|
pub use olm_rs::{
|
||||||
session::{OlmMessage, PreKeyMessage},
|
session::{OlmMessage, PreKeyMessage},
|
||||||
utility::OlmUtility,
|
utility::OlmUtility,
|
||||||
|
@ -386,7 +387,7 @@ impl Account {
|
||||||
///
|
///
|
||||||
/// * `their_one_time_key` - A signed one-time key that the other account
|
/// * `their_one_time_key` - A signed one-time key that the other account
|
||||||
/// created and shared with us.
|
/// created and shared with us.
|
||||||
pub(crate) async fn create_outbound_session(
|
pub(crate) async fn create_outbound_session_helper(
|
||||||
&self,
|
&self,
|
||||||
their_identity_key: &str,
|
their_identity_key: &str,
|
||||||
their_one_time_key: &SignedKey,
|
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.
|
/// Create a new session with another account given a pre-key Olm message.
|
||||||
///
|
///
|
||||||
/// Returns the newly created session or a `OlmSessionError` if creating a
|
/// 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 sender_key = bob.identity_keys().curve25519().to_owned();
|
||||||
let session = alice
|
let session = alice
|
||||||
.create_outbound_session(&sender_key, &one_time_key)
|
.create_outbound_session_helper(&sender_key, &one_time_key)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -1092,7 +1154,7 @@ pub(crate) mod test {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut bob_session = bob
|
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
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -876,7 +876,7 @@ mod test {
|
||||||
};
|
};
|
||||||
let sender_key = bob.identity_keys().curve25519().to_owned();
|
let sender_key = bob.identity_keys().curve25519().to_owned();
|
||||||
let session = alice
|
let session = alice
|
||||||
.create_outbound_session(&sender_key, &one_time_key)
|
.create_outbound_session_helper(&sender_key, &one_time_key)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue