chore: Bump Ruma.

This commit is contained in:
Damir Jelić
2021-12-08 13:03:11 +01:00
parent f97aed0e41
commit 009ead2eea
21 changed files with 297 additions and 159 deletions

View File

@@ -27,5 +27,8 @@ byteorder = "1.4.3"
image = { version = "0.23.14", optional = true }
qrcode = { version = "0.12.0", default-features = false }
rqrr = { version = "0.4.0", optional = true }
ruma-identifiers = { git = "https://github.com/ruma/ruma", rev = "6c4892664" }
thiserror = "1.0.25"
[dependencies.ruma-identifiers]
git = "https://github.com/ruma/ruma/"
rev = "fdbc4d6d1dd273c8a6ac95b329943ed8c68df70d"

View File

@@ -37,8 +37,8 @@ url = "2"
warp = { version = "0.3.1", optional = true, default-features = false }
[dependencies.ruma]
git = "https://github.com/ruma/ruma"
rev = "6c4892664"
git = "https://github.com/ruma/ruma/"
rev = "fdbc4d6d1dd273c8a6ac95b329943ed8c68df70d"
features = ["client-api-c", "appservice-api-s", "unstable-pre-spec"]
[dev-dependencies]

View File

@@ -19,7 +19,14 @@ rustdoc-args = ["--cfg", "feature=\"docs\""]
default = []
encryption = ["matrix-sdk-crypto"]
qrcode = ["matrix-sdk-crypto/qrcode"]
sled_state_store = ["sled", "pbkdf2", "hmac", "sha2", "rand", "chacha20poly1305"]
sled_state_store = [
"sled",
"pbkdf2",
"hmac",
"sha2",
"rand",
"chacha20poly1305",
]
sled_cryptostore = ["matrix-sdk-crypto/sled_cryptostore"]
docs = ["encryption", "sled_cryptostore"]
@@ -35,7 +42,6 @@ matrix-sdk-common = { version = "0.4.0", path = "../matrix-sdk-common" }
matrix-sdk-crypto = { version = "0.4.0", path = "../matrix-sdk-crypto", optional = true }
pbkdf2 = { version = "0.9.0", default-features = false, optional = true }
rand = { version = "0.8.4", optional = true }
ruma = { git = "https://github.com/ruma/ruma", rev = "6c4892664", features = ["client-api-c", "unstable-pre-spec"] }
serde = { version = "1.0.126", features = ["rc"] }
serde_json = "1.0.64"
sha2 = { version = "0.9.5", optional = true }
@@ -44,6 +50,11 @@ thiserror = "1.0.25"
tracing = "0.1.26"
zeroize = { version = "1.3.0", features = ["zeroize_derive"] }
[dependencies.ruma]
git = "https://github.com/ruma/ruma/"
rev = "fdbc4d6d1dd273c8a6ac95b329943ed8c68df70d"
features = ["client-api-c", "unstable-pre-spec"]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.tokio]
version = "1.7.1"
default-features = false
@@ -60,7 +71,10 @@ clap = "2.33.3"
rustyline = "9.0.0"
rustyline-derive = "0.5.0"
syntect = "4.5.0"
tokio = { version = "1.7.1", default-features = false, features = ["rt-multi-thread", "macros"] }
tokio = { version = "1.7.1", default-features = false, features = [
"rt-multi-thread",
"macros",
] }
tempfile = "3.2.0"
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]

View File

@@ -650,6 +650,7 @@ impl BaseClient {
&self,
response: api::sync::sync_events::Response,
) -> Result<SyncResponse> {
#[allow(unused_variables)]
let api::sync::sync_events::Response {
next_batch,
rooms,
@@ -658,6 +659,7 @@ impl BaseClient {
to_device,
device_lists,
device_one_time_keys_count,
device_unused_fallback_key_types,
..
} = response;
@@ -679,8 +681,13 @@ impl BaseClient {
// decrypts to-device events, but leaves room events alone.
// This makes sure that we have the decryption keys for the room
// events at hand.
o.receive_sync_changes(to_device, &device_lists, &device_one_time_keys_count)
.await?
o.receive_sync_changes(
to_device,
&device_lists,
&device_one_time_keys_count,
device_unused_fallback_key_types.as_deref(),
)
.await?
} else {
to_device
}

View File

@@ -13,11 +13,18 @@ version = "0.4.1"
[dependencies]
async-trait = "0.1.50"
ruma = { git = "https://github.com/ruma/ruma", rev = "6c4892664", features = ["client-api-c"] }
serde = "1.0.126"
[dependencies.ruma]
git = "https://github.com/ruma/ruma/"
rev = "fdbc4d6d1dd273c8a6ac95b329943ed8c68df70d"
features = ["client-api-c"]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
uuid = { version = "0.8.2", default-features = false, features = ["v4", "serde"] }
uuid = { version = "0.8.2", default-features = false, features = [
"v4",
"serde",
] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.tokio]
version = "1.7.1"
@@ -36,4 +43,8 @@ features = ["now"]
async-lock = "2.4.0"
futures-util = { version = "0.3.15", default-features = false, features = ["channel"] }
wasm-bindgen-futures = "0.4.24"
uuid = { version = "0.8.2", default-features = false, features = ["v4", "wasm-bindgen", "serde"] }
uuid = { version = "0.8.2", default-features = false, features = [
"v4",
"wasm-bindgen",
"serde",
] }

View File

@@ -38,10 +38,6 @@ matrix-sdk-common = { version = "0.4.0", path = "../matrix-sdk-common" }
olm-rs = { version = "2.1", features = ["serde"] }
pbkdf2 = { version = "0.9.0", default-features = false }
rand = "0.8.4"
ruma = { git = "https://github.com/ruma/ruma", rev = "6c4892664", features = [
"client-api-c",
"unstable-pre-spec",
] }
serde = { version = "1.0.126", features = ["derive", "rc"] }
serde_json = "1.0.64"
sha2 = "0.9.5"
@@ -50,6 +46,11 @@ thiserror = "1.0.25"
tracing = "0.1.26"
zeroize = { version = "1.3.0", features = ["zeroize_derive"] }
[dependencies.ruma]
git = "https://github.com/ruma/ruma/"
rev = "fdbc4d6d1dd273c8a6ac95b329943ed8c68df70d"
features = ["client-api-c", "unstable-pre-spec"]
[dev-dependencies]
criterion = { version = "0.3.4", features = [
"async",

View File

@@ -33,12 +33,14 @@ async fn main() -> Result<(), OlmError> {
let to_device_events = ToDevice::default();
let changed_devices = DeviceLists::default();
let one_time_key_counts = BTreeMap::default();
let unused_fallback_keys = Some(Vec::new());
// Push changes that the server sent to us in a sync response.
let decrypted_to_device = machine.receive_sync_changes(
to_device_events,
&changed_devices,
&one_time_key_counts
&one_time_key_counts,
unused_fallback_keys.as_deref(),
).await?;
// Pull requests that we need to send out.

View File

@@ -30,7 +30,8 @@ use std::{
use matrix_sdk_common::{locks::RwLock, uuid::Uuid};
use ruma::{
api::client::r0::backup::RoomKeyBackup, DeviceKeyAlgorithm, DeviceKeyId, RoomId, UserId,
api::client::r0::backup::RoomKeyBackup, serde::Raw, DeviceKeyAlgorithm, DeviceKeyId, RoomId,
UserId,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
@@ -369,6 +370,11 @@ impl BackupMachine {
.or_default()
.insert(session_id.clone());
let session = Raw::from_json(
serde_json::value::to_raw_value(&session)
.expect("Can't serialize a backed up room key"),
);
backup
.entry(room_id)
.or_insert_with(|| RoomKeyBackup::new(BTreeMap::new()))

View File

@@ -213,4 +213,6 @@ pub(crate) enum SessionCreationError {
DeviceMissingCurveKey(Box<UserId>, Box<DeviceId>),
#[error("Error creating new Olm session for {0} {1}: {2:?}")]
OlmError(Box<UserId>, Box<DeviceId>, OlmSessionError),
#[error("Error deserializing the one-time key: {0}")]
InvalidJson(#[from] serde_json::Error),
}

View File

@@ -23,7 +23,7 @@ use futures_util::future::join_all;
use matrix_sdk_common::executor::spawn;
use ruma::{
api::client::r0::keys::get_keys::Response as KeysQueryResponse, encryption::DeviceKeys,
DeviceId, UserId,
serde::Raw, DeviceId, UserId,
};
use tracing::{debug, info, trace, warn};
@@ -205,7 +205,7 @@ impl IdentityManager {
own_user_id: Arc<UserId>,
own_device_id: Arc<DeviceId>,
user_id: Box<UserId>,
device_map: BTreeMap<Box<DeviceId>, DeviceKeys>,
device_map: BTreeMap<Box<DeviceId>, Raw<DeviceKeys>>,
) -> StoreResult<DeviceChanges> {
let own_device_id = (&*own_device_id).to_owned();
@@ -213,18 +213,31 @@ impl IdentityManager {
let current_devices: HashSet<Box<DeviceId>> = device_map.keys().cloned().collect();
let tasks = device_map.into_iter().filter_map(|(device_id, device_keys)| {
if user_id != device_keys.user_id || device_id != device_keys.device_id {
let tasks = device_map.into_iter().filter_map(|(device_id, device_keys)| match device_keys
.deserialize()
{
Ok(device_keys) => {
if user_id != device_keys.user_id || device_id != device_keys.device_id {
warn!(
user_id = user_id.as_str(),
device_id = device_id.as_str(),
device_key_user = device_keys.user_id.as_str(),
device_key_device_id = device_keys.device_id.as_str(),
"Mismatch in the device keys payload",
);
None
} else {
Some(spawn(Self::update_or_create_device(store.clone(), device_keys)))
}
}
Err(e) => {
warn!(
user_id = user_id.as_str(),
device_id = device_id.as_str(),
device_key_user = device_keys.user_id.as_str(),
device_key_device_id = device_keys.device_id.as_str(),
"Mismatch in the device keys payload",
error =? e,
"Device keys failed to deserialize",
);
None
} else {
Some(spawn(Self::update_or_create_device(store.clone(), device_keys)))
}
});
@@ -272,7 +285,7 @@ impl IdentityManager {
/// they are new, one of their properties has changed or they got deleted.
async fn handle_devices_from_key_query(
&self,
device_keys_map: BTreeMap<Box<UserId>, BTreeMap<Box<DeviceId>, DeviceKeys>>,
device_keys_map: BTreeMap<Box<UserId>, BTreeMap<Box<DeviceId>, Raw<DeviceKeys>>>,
) -> StoreResult<DeviceChanges> {
let mut changes = DeviceChanges::default();
@@ -312,93 +325,122 @@ impl IdentityManager {
let mut changes = IdentityChanges::default();
let mut changed_identity = None;
// TODO this is a bit chunky, refactor this into smaller methods.
for (user_id, master_key) in &response.master_keys {
let master_key = MasterPubkey::from(master_key);
match master_key.deserialize() {
Ok(master_key) => {
let master_key = MasterPubkey::from(master_key);
let self_signing = if let Some(s) = response.self_signing_keys.get(user_id) {
SelfSigningPubkey::from(s)
} else {
warn!(
user_id = user_id.as_str(),
"A user identity didn't contain a self signing pubkey"
);
continue;
};
let self_signing = if let Some(s) =
response.self_signing_keys.get(user_id).and_then(|k| k.deserialize().ok())
{
SelfSigningPubkey::from(s)
} else {
warn!(
user_id = user_id.as_str(),
"A user identity didn't contain a self signing pubkey \
or the key was invalid"
);
continue;
};
let result = if let Some(mut i) = self.store.get_user_identity(user_id).await? {
match &mut i {
ReadOnlyUserIdentities::Own(ref mut identity) => {
let user_signing = if let Some(s) = response.user_signing_keys.get(user_id)
let result = if let Some(mut i) = self.store.get_user_identity(user_id).await? {
match &mut i {
ReadOnlyUserIdentities::Own(ref mut identity) => {
let user_signing = if let Some(s) = response
.user_signing_keys
.get(user_id)
.and_then(|k| k.deserialize().ok())
{
UserSigningPubkey::from(s)
} else {
warn!(
user_id = user_id.as_str(),
"User identity for our own user didn't \
contain a user signing pubkey",
);
continue;
};
identity
.update(master_key, self_signing, user_signing)
.map(|_| (i, false))
}
ReadOnlyUserIdentities::Other(ref mut identity) => {
identity.update(master_key, self_signing).map(|_| (i, false))
}
}
} else if user_id == self.user_id() {
if let Some(s) = response
.user_signing_keys
.get(user_id)
.and_then(|k| k.deserialize().ok())
{
UserSigningPubkey::from(s)
let user_signing = UserSigningPubkey::from(s);
if master_key.user_id() != user_id
|| self_signing.user_id() != user_id
|| user_signing.user_id() != user_id
{
warn!(
user_id = user_id.as_str(),
"User ID mismatch in one of the cross signing keys",
);
continue;
}
ReadOnlyOwnUserIdentity::new(master_key, self_signing, user_signing)
.map(|i| (ReadOnlyUserIdentities::Own(i), true))
} else {
warn!(
user_id = user_id.as_str(),
"User identity for our own user didn't \
contain a user signing pubkey",
"User identity for our own user didn't contain a \
user signing pubkey or the key isn't valid",
);
continue;
};
identity.update(master_key, self_signing, user_signing).map(|_| (i, false))
}
ReadOnlyUserIdentities::Other(ref mut identity) => {
identity.update(master_key, self_signing).map(|_| (i, false))
}
}
} else if user_id == self.user_id() {
if let Some(s) = response.user_signing_keys.get(user_id) {
let user_signing = UserSigningPubkey::from(s);
if master_key.user_id() != user_id
|| self_signing.user_id() != user_id
|| user_signing.user_id() != user_id
{
}
} else if master_key.user_id() != user_id || self_signing.user_id() != user_id {
warn!(
user_id = user_id.as_str(),
user = user_id.as_str(),
"User ID mismatch in one of the cross signing keys",
);
continue;
}
ReadOnlyOwnUserIdentity::new(master_key, self_signing, user_signing)
.map(|i| (ReadOnlyUserIdentities::Own(i), true))
} else {
warn!(
user_id = user_id.as_str(),
"User identity for our own user didn't contain a \
user signing pubkey",
);
continue;
}
} else if master_key.user_id() != user_id || self_signing.user_id() != user_id {
warn!(user = user_id.as_str(), "User ID mismatch in one of the cross signing keys",);
continue;
} else {
ReadOnlyUserIdentity::new(master_key, self_signing)
.map(|i| (ReadOnlyUserIdentities::Other(i), true))
};
match result {
Ok((i, new)) => {
if let Some(identity) = i.own() {
let private_identity = self.store.private_identity();
let private_identity = private_identity.lock().await;
let result = private_identity.clear_if_differs(identity).await;
if result.any_cleared() {
changed_identity = Some((&*private_identity).clone());
info!(cleared =? result, "Removed some or all of our private cross signing keys");
}
}
if new {
trace!(user_id = user_id.as_str(), identity =? i, "Created new user identity");
changes.new.push(i);
} else {
trace!(user_id = user_id.as_str(), identity =? i, "Updated a user identity");
changes.changed.push(i);
ReadOnlyUserIdentity::new(master_key, self_signing)
.map(|i| (ReadOnlyUserIdentities::Other(i), true))
};
match result {
Ok((i, new)) => {
if let Some(identity) = i.own() {
let private_identity = self.store.private_identity();
let private_identity = private_identity.lock().await;
let result = private_identity.clear_if_differs(identity).await;
if result.any_cleared() {
changed_identity = Some((&*private_identity).clone());
info!(cleared =? result, "Removed some or all of our private cross signing keys");
}
}
if new {
trace!(user_id = user_id.as_str(), identity =? i, "Created new user identity");
changes.new.push(i);
} else {
trace!(user_id = user_id.as_str(), identity =? i, "Updated a user identity");
changes.changed.push(i);
}
}
Err(e) => {
warn!(
user_id = user_id.as_str(),
error =? e,
"Couldn't update or create new user identity"
);
continue;
}
}
}
Err(e) => {

View File

@@ -956,17 +956,19 @@ pub(crate) mod test {
fn device(response: &KeyQueryResponse) -> (ReadOnlyDevice, ReadOnlyDevice) {
let mut devices = response.device_keys.values().next().unwrap().values();
let first = ReadOnlyDevice::try_from(devices.next().unwrap()).unwrap();
let second = ReadOnlyDevice::try_from(devices.next().unwrap()).unwrap();
let first =
ReadOnlyDevice::try_from(&devices.next().unwrap().deserialize().unwrap()).unwrap();
let second =
ReadOnlyDevice::try_from(&devices.next().unwrap().deserialize().unwrap()).unwrap();
(first, second)
}
fn own_identity(response: &KeyQueryResponse) -> ReadOnlyOwnUserIdentity {
let user_id = user_id!("@example:localhost");
let master_key = response.master_keys.get(user_id).unwrap();
let user_signing = response.user_signing_keys.get(user_id).unwrap();
let self_signing = response.self_signing_keys.get(user_id).unwrap();
let master_key = response.master_keys.get(user_id).unwrap().deserialize().unwrap();
let user_signing = response.user_signing_keys.get(user_id).unwrap().deserialize().unwrap();
let self_signing = response.self_signing_keys.get(user_id).unwrap().deserialize().unwrap();
ReadOnlyOwnUserIdentity::new(master_key.into(), self_signing.into(), user_signing.into())
.unwrap()
@@ -980,8 +982,8 @@ pub(crate) mod test {
let user_id = user_id!("@example2:localhost");
let response = other_key_query();
let master_key = response.master_keys.get(user_id).unwrap();
let self_signing = response.self_signing_keys.get(user_id).unwrap();
let master_key = response.master_keys.get(user_id).unwrap().deserialize().unwrap();
let self_signing = response.self_signing_keys.get(user_id).unwrap().deserialize().unwrap();
ReadOnlyUserIdentity::new(master_key.into(), self_signing.into()).unwrap()
}
@@ -991,9 +993,9 @@ pub(crate) mod test {
let user_id = user_id!("@example:localhost");
let response = own_key_query();
let master_key = response.master_keys.get(user_id).unwrap();
let user_signing = response.user_signing_keys.get(user_id).unwrap();
let self_signing = response.self_signing_keys.get(user_id).unwrap();
let master_key = response.master_keys.get(user_id).unwrap().deserialize().unwrap();
let user_signing = response.user_signing_keys.get(user_id).unwrap().deserialize().unwrap();
let self_signing = response.self_signing_keys.get(user_id).unwrap().deserialize().unwrap();
ReadOnlyOwnUserIdentity::new(master_key.into(), self_signing.into(), user_signing.into())
.unwrap();

View File

@@ -46,9 +46,10 @@ use ruma::{
secret::request::SecretName,
AnyMessageEventContent, AnyRoomEvent, AnyToDeviceEvent, EventContent,
},
serde::Raw,
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, EventEncryptionAlgorithm, RoomId, UInt, UserId,
};
use serde_json::Value;
use serde_json::{value::to_raw_value, Value};
use tracing::{debug, error, info, trace, warn};
#[cfg(feature = "backups_v1")]
@@ -562,7 +563,13 @@ impl OlmMachine {
/// [`OlmMachine`]: struct.OlmMachine.html
async fn keys_for_upload(&self) -> Option<upload_keys::Request> {
let (device_keys, one_time_keys) = self.account.keys_for_upload().await?;
Some(assign!(upload_keys::Request::new(), { device_keys, one_time_keys }))
let device_keys = device_keys
.map(|d| Raw::from_json(to_raw_value(&d).expect("Coulnd't serialize device keys")));
Some(
assign!(upload_keys::Request::new(), { device_keys, one_time_keys, fallback_keys: BTreeMap::new(), }),
)
}
/// Decrypt a to-device event.
@@ -859,8 +866,12 @@ impl OlmMachine {
self.verification_machine.get_requests(user_id)
}
fn update_one_time_key_count(&self, key_count: &BTreeMap<DeviceKeyAlgorithm, UInt>) {
self.account.update_uploaded_key_count(key_count);
async fn update_key_counts(
&self,
one_time_key_count: &BTreeMap<DeviceKeyAlgorithm, UInt>,
#[allow(unused_variables)] unused_fallback_keys: Option<&[DeviceKeyAlgorithm]>,
) {
self.account.update_uploaded_key_count(one_time_key_count);
}
async fn handle_to_device_event(&self, event: &AnyToDeviceEvent) {
@@ -913,6 +924,7 @@ impl OlmMachine {
to_device_events: ToDevice,
changed_devices: &DeviceLists,
one_time_keys_counts: &BTreeMap<DeviceKeyAlgorithm, UInt>,
unused_fallback_keys: Option<&[DeviceKeyAlgorithm]>,
) -> OlmResult<ToDevice> {
// Remove verification objects that have expired or are done.
let mut events = self.verification_machine.garbage_collect();
@@ -922,7 +934,7 @@ impl OlmMachine {
let mut changes =
Changes { account: Some(self.account.inner.clone()), ..Default::default() };
self.update_one_time_key_count(one_time_keys_counts);
self.update_key_counts(one_time_keys_counts, unused_fallback_keys).await;
for user_id in &changed_devices.changed {
if let Err(e) = self.identity_manager.mark_user_as_changed(user_id).await {
@@ -1568,8 +1580,10 @@ pub(crate) mod test {
AnyMessageEventContent, AnySyncMessageEvent, AnySyncRoomEvent, AnyToDeviceEvent,
AnyToDeviceEventContent, SyncMessageEvent, ToDeviceEvent, Unsigned,
},
room_id, uint, user_id, DeviceId, DeviceKeyAlgorithm, DeviceKeyId,
MilliSecondsSinceUnixEpoch, UserId,
room_id,
serde::Raw,
uint, user_id, DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MilliSecondsSinceUnixEpoch,
UserId,
};
use serde_json::json;
@@ -1581,7 +1595,7 @@ pub(crate) mod test {
};
/// These keys need to be periodically uploaded to the server.
type OneTimeKeys = BTreeMap<Box<DeviceKeyId>, OneTimeKey>;
type OneTimeKeys = BTreeMap<Box<DeviceKeyId>, Raw<OneTimeKey>>;
fn alice_id() -> &'static UserId {
user_id!("@alice:example.org")
@@ -1635,7 +1649,7 @@ pub(crate) mod test {
let response = keys_upload_response();
machine.receive_keys_upload_response(&response).await.unwrap();
(machine, request.one_time_keys.unwrap())
(machine, request.one_time_keys)
}
async fn get_machine_after_query() -> (OlmMachine, OneTimeKeys) {
@@ -1836,7 +1850,7 @@ pub(crate) mod test {
&machine.user_id,
&DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, machine.device_id()),
ed25519_key,
&mut json!(&mut request.one_time_keys.as_mut().unwrap().values_mut().next()),
&mut json!(&mut request.one_time_keys.values_mut().next()),
);
assert!(ret.is_ok());
@@ -1852,7 +1866,7 @@ pub(crate) mod test {
let mut response = keys_upload_response();
response.one_time_key_counts.insert(
DeviceKeyAlgorithm::SignedCurve25519,
(request.one_time_keys.unwrap().len() as u64).try_into().unwrap(),
(request.one_time_keys.len() as u64).try_into().unwrap(),
);
machine.receive_keys_upload_response(&response).await.unwrap();

View File

@@ -43,7 +43,11 @@ use ruma::{
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, EventEncryptionAlgorithm, RoomId, UInt, UserId,
};
use serde::{Deserialize, Serialize};
use serde_json::{json, value::RawValue as RawJsonValue, Value};
use serde_json::{
json,
value::{to_raw_value, RawValue as RawJsonValue},
Value,
};
use sha2::{Digest, Sha256};
use tracing::{debug, info, trace, warn};
@@ -661,14 +665,14 @@ impl ReadOnlyAccount {
/// Returns None if no keys need to be uploaded.
pub(crate) async fn keys_for_upload(
&self,
) -> Option<(Option<DeviceKeys>, Option<BTreeMap<Box<DeviceKeyId>, OneTimeKey>>)> {
) -> Option<(Option<DeviceKeys>, BTreeMap<Box<DeviceKeyId>, Raw<OneTimeKey>>)> {
if !self.should_upload_keys().await {
return None;
}
let device_keys = if !self.shared() { Some(self.device_keys().await) } else { None };
let one_time_keys = self.signed_one_time_keys().await.ok();
let one_time_keys = self.signed_one_time_keys().await.ok().unwrap_or_default();
Some((device_keys, one_time_keys))
}
@@ -845,15 +849,20 @@ impl ReadOnlyAccount {
/// # Panic
///
/// Panics if the json value can't be serialized.
pub async fn sign_json(&self, json: Value) -> String {
pub async fn sign_json(&self, mut json: Value) -> String {
let object = json.as_object_mut().expect("Canonical json value isn't an object");
object.remove("unsigned");
object.remove("signatures");
let canonical_json: CanonicalJsonValue =
json.try_into().expect("Can't canonicalize the json value");
self.sign(&canonical_json.to_string()).await
}
pub(crate) async fn signed_one_time_keys_helper(
&self,
) -> Result<BTreeMap<Box<DeviceKeyId>, OneTimeKey>, ()> {
) -> Result<BTreeMap<Box<DeviceKeyId>, Raw<OneTimeKey>>, ()> {
let one_time_keys = self.one_time_keys().await;
let mut one_time_key_map = BTreeMap::new();
@@ -881,7 +890,10 @@ impl ReadOnlyAccount {
DeviceKeyAlgorithm::SignedCurve25519,
key_id.as_str().into(),
),
OneTimeKey::SignedKey(signed_key),
Raw::from_json(
to_raw_value(&OneTimeKey::SignedKey(signed_key))
.expect("Couldn't serialize a new signed key"),
),
);
}
@@ -893,7 +905,7 @@ impl ReadOnlyAccount {
/// If no one-time keys need to be uploaded returns an empty error.
pub(crate) async fn signed_one_time_keys(
&self,
) -> Result<BTreeMap<Box<DeviceKeyId>, OneTimeKey>, ()> {
) -> Result<BTreeMap<Box<DeviceKeyId>, Raw<OneTimeKey>>, ()> {
let _ = self.generate_one_time_keys().await?;
self.signed_one_time_keys_helper().await
}
@@ -929,6 +941,7 @@ impl ReadOnlyAccount {
inner: Arc::new(Mutex::new(session)),
session_id: session_id.into(),
sender_key: their_identity_key.into(),
created_using_fallback_key: their_one_time_key.fallback,
creation_time: Arc::new(now),
last_use_time: Arc::new(now),
})
@@ -948,7 +961,7 @@ impl ReadOnlyAccount {
pub(crate) async fn create_outbound_session(
&self,
device: ReadOnlyDevice,
key_map: &BTreeMap<Box<DeviceKeyId>, OneTimeKey>,
key_map: &BTreeMap<Box<DeviceKeyId>, Raw<OneTimeKey>>,
) -> Result<Session, SessionCreationError> {
let one_time_key = key_map.values().next().ok_or_else(|| {
SessionCreationError::OneTimeKeyMissing(
@@ -957,23 +970,24 @@ impl ReadOnlyAccount {
)
})?;
let one_time_key = match one_time_key {
OneTimeKey::SignedKey(k) => k,
OneTimeKey::Key(_) => {
let one_time_key: SignedKey = match one_time_key.deserialize() {
Ok(OneTimeKey::SignedKey(k)) => k,
Ok(OneTimeKey::Key(_)) => {
return Err(SessionCreationError::OneTimeKeyNotSigned(
device.user_id().to_owned(),
device.device_id().into(),
));
}
_ => {
Ok(_) => {
return Err(SessionCreationError::OneTimeKeyUnknown(
device.user_id().to_owned(),
device.device_id().into(),
));
}
Err(e) => return Err(SessionCreationError::InvalidJson(e)),
};
device.verify_one_time_key(one_time_key).map_err(|e| {
device.verify_one_time_key(&one_time_key).map_err(|e| {
SessionCreationError::InvalidSignature(
device.user_id().to_owned(),
device.device_id().into(),
@@ -988,7 +1002,7 @@ impl ReadOnlyAccount {
)
})?;
self.create_outbound_session_helper(curve_key, one_time_key).await.map_err(|e| {
self.create_outbound_session_helper(curve_key, &one_time_key).await.map_err(|e| {
SessionCreationError::OlmError(
device.user_id().to_owned(),
device.device_id().into(),
@@ -1029,6 +1043,7 @@ impl ReadOnlyAccount {
inner: Arc::new(Mutex::new(session)),
session_id: session_id.into(),
sender_key: their_identity_key.into(),
created_using_fallback_key: false,
creation_time: Arc::new(now),
last_use_time: Arc::new(now),
})
@@ -1178,15 +1193,19 @@ mod test {
let one_time_keys = account
.keys_for_upload()
.await
.and_then(|(_, k)| k)
.map(|(_, k)| k)
.expect("Initial keys can't be generated");
assert!(!one_time_keys.is_empty());
let second_one_time_keys = account
.keys_for_upload()
.await
.and_then(|(_, k)| k)
.map(|(_, k)| k)
.expect("Second round of one-time keys isn't generated");
assert!(!second_one_time_keys.is_empty());
let device_key_ids: BTreeSet<&DeviceKeyId> =
one_time_keys.keys().map(Deref::deref).collect();
let second_device_key_ids: BTreeSet<&DeviceKeyId> =
@@ -1197,16 +1216,16 @@ mod test {
account.mark_keys_as_published().await;
account.update_uploaded_key_count(50);
let third_one_time_keys = account.keys_for_upload().await.and_then(|(_, k)| k);
let third_one_time_keys = account.keys_for_upload().await.map(|(_, k)| k).unwrap();
assert!(third_one_time_keys.is_none());
assert!(third_one_time_keys.is_empty());
account.update_uploaded_key_count(0);
let fourth_one_time_keys = account
.keys_for_upload()
.await
.and_then(|(_, k)| k)
.map(|(_, k)| k)
.expect("Fourth round of one-time keys isn't generated");
let fourth_device_key_ids: BTreeSet<&DeviceKeyId> =

View File

@@ -379,7 +379,7 @@ impl InboundGroupSession {
);
if let Some(decrypted_content) =
decrypted_object.get_mut("content").map(|c| c.as_object_mut()).flatten()
decrypted_object.get_mut("content").and_then(|c| c.as_object_mut())
{
if !decrypted_content.contains_key("m.relates_to") {
let content = serde_json::to_value(&event.content)?;

View File

@@ -49,6 +49,7 @@ pub struct Session {
pub(crate) inner: Arc<Mutex<OlmSession>>,
pub(crate) session_id: Arc<str>,
pub(crate) sender_key: Arc<str>,
pub(crate) created_using_fallback_key: bool,
pub(crate) creation_time: Arc<Instant>,
pub(crate) last_use_time: Arc<Instant>,
}
@@ -183,6 +184,7 @@ impl Session {
PickledSession {
pickle: SessionPickle::from(pickle),
sender_key: self.sender_key.to_string(),
created_using_fallback_key: self.created_using_fallback_key,
creation_time: *self.creation_time,
last_use_time: *self.last_use_time,
}
@@ -221,6 +223,7 @@ impl Session {
our_identity_keys,
inner: Arc::new(Mutex::new(session)),
session_id: session_id.into(),
created_using_fallback_key: pickle.created_using_fallback_key,
sender_key: pickle.sender_key.into(),
creation_time: Arc::new(pickle.creation_time),
last_use_time: Arc::new(pickle.last_use_time),
@@ -244,6 +247,9 @@ pub struct PickledSession {
pub pickle: SessionPickle,
/// The curve25519 key of the other user that we share this session with.
pub sender_key: String,
/// Was the session created using a fallback key.
#[serde(default)]
pub created_using_fallback_key: bool,
/// The relative time elapsed since the session was created.
#[serde(deserialize_with = "deserialize_instant", serialize_with = "serialize_instant")]
pub creation_time: Instant,

View File

@@ -477,11 +477,10 @@ impl GroupSessionManager {
let devices: Vec<Device> = devices
.into_iter()
.map(|(_, d)| {
.flat_map(|(_, d)| {
d.into_iter()
.filter(|d| matches!(outbound.is_shared_with(d), ShareState::NotShared))
})
.flatten()
.collect();
let key_content = outbound.as_content().await;

View File

@@ -124,7 +124,7 @@ impl SessionManager {
///
/// If the device was wedged this will queue up a dummy to-device message.
async fn check_if_unwedged(&self, user_id: &UserId, device_id: &DeviceId) -> OlmResult<()> {
if self.wedged_devices.get(user_id).map(|d| d.remove(device_id)).flatten().is_some() {
if self.wedged_devices.get(user_id).and_then(|d| d.remove(device_id)).is_some() {
if let Some(device) = self.store.get_device(user_id, device_id).await? {
let content = AnyToDeviceEventContent::Dummy(ToDeviceDummyEventContent::new());
let (_, content) = device.encrypt(content).await?;
@@ -298,9 +298,6 @@ impl SessionManager {
}
};
changes.sessions.push(session);
new_sessions.entry(user_id).or_default().insert(device_id);
self.key_request_machine.retry_keyshare(user_id, device_id);
if let Err(e) = self.check_if_unwedged(user_id, device_id).await {
@@ -309,6 +306,9 @@ impl SessionManager {
user_id, device_id, e
);
}
changes.sessions.push(session);
new_sessions.entry(user_id).or_default().insert(device_id);
}
}

View File

@@ -347,8 +347,8 @@ impl Store {
let devices = self.inner.get_user_devices(user_id).await?;
let own_identity =
self.inner.get_user_identity(&self.user_id).await?.map(|i| i.own().cloned()).flatten();
let device_owner_identity = self.inner.get_user_identity(user_id).await.ok().flatten();
self.inner.get_user_identity(&self.user_id).await?.and_then(|i| i.own().cloned());
let device_owner_identity = self.inner.get_user_identity(user_id).await?;
Ok(UserDevices {
inner: devices,
@@ -364,7 +364,7 @@ impl Store {
device_id: &DeviceId,
) -> Result<Option<Device>> {
let own_identity =
self.inner.get_user_identity(&self.user_id).await?.map(|i| i.own().cloned()).flatten();
self.inner.get_user_identity(&self.user_id).await?.and_then(|i| i.own().cloned());
let device_owner_identity = self.inner.get_user_identity(user_id).await?;
Ok(self.inner.get_device(user_id, device_id).await?.map(|d| Device {

View File

@@ -18,6 +18,10 @@ appservice = []
http = "0.2.4"
lazy_static = "1.4.0"
matrix-sdk-test-macros = { version = "0.1.0", path = "../matrix-sdk-test-macros" }
ruma = { git = "https://github.com/ruma/ruma", rev = "6c4892664", features = ["client-api-c"] }
serde = "1.0.126"
serde_json = "1.0.64"
[dependencies.ruma]
git = "https://github.com/ruma/ruma/"
rev = "fdbc4d6d1dd273c8a6ac95b329943ed8c68df70d"
features = ["client-api-c"]

View File

@@ -75,8 +75,8 @@ version = "0.11.3"
default_features = false
[dependencies.ruma]
git = "https://github.com/ruma/ruma"
rev = "6c4892664"
git = "https://github.com/ruma/ruma/"
rev = "fdbc4d6d1dd273c8a6ac95b329943ed8c68df70d"
features = ["client-api-c", "compat", "unstable-pre-spec"]
[dependencies.tokio-stream]

View File

@@ -526,15 +526,21 @@ impl Client {
/// # anyhow::Result::<()>::Ok(()) });
#[cfg(feature = "encryption")]
pub async fn bootstrap_cross_signing(&self, auth_data: Option<AuthData<'_>>) -> Result<()> {
use serde_json::value::to_raw_value;
let olm = self.olm_machine().await.ok_or(Error::AuthenticationRequired)?;
let (request, signature_request) = olm.bootstrap_cross_signing(false).await?;
let to_raw = |k| {
Raw::from_json(to_raw_value(&k).expect("Can't serialize newly created cross signing keys"))
};
let request = assign!(UploadSigningKeysRequest::new(), {
auth: auth_data,
master_key: request.master_key,
self_signing_key: request.self_signing_key,
user_signing_key: request.user_signing_key,
master_key: request.master_key.map(to_raw),
self_signing_key: request.self_signing_key.map(to_raw),
user_signing_key: request.user_signing_key.map(to_raw),
});
self.send(request, None).await?;
@@ -887,9 +893,9 @@ impl Client {
request: &upload_keys::Request,
) -> Result<upload_keys::Response> {
debug!(
"Uploading encryption keys device keys: {}, one-time-keys: {}",
request.device_keys.is_some(),
request.one_time_keys.as_ref().map_or(0, |k| k.len())
device_keys = request.device_keys.is_some(),
one_time_key_count = request.one_time_keys.len(),
"Uploading public encryption keys",
);
let response = self.send(request.clone(), None).await?;