Compare commits
6 Commits
0.7.0
...
0.7.1-crypto
| Author | SHA1 | Date | |
|---|---|---|---|
| c99f665766 | |||
| 8a975c8985 | |||
| 04362cdc36 | |||
| fa10bbb5dd | |||
| 4164effbf9 | |||
| 917e8c291e |
Generated
+4
-4
@@ -161,9 +161,9 @@ checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c"
|
||||
|
||||
[[package]]
|
||||
name = "aquamarine"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "074b80d14d0240b6ce94d68f059a2d26a5d77280ae142662365a21ef6e2594ef"
|
||||
checksum = "21cc1548309245035eb18aa7f0967da6bc65587005170c56e6ef2788a4cf3f4e"
|
||||
dependencies = [
|
||||
"include_dir",
|
||||
"itertools 0.10.5",
|
||||
@@ -2965,7 +2965,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "matrix-sdk"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"anymap2",
|
||||
@@ -3090,7 +3090,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "matrix-sdk-crypto"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"anyhow",
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# 0.7.1
|
||||
### Security Fixes
|
||||
|
||||
- Don't log the private part of the backup key, introduced in [#71136e4](https://github.com/matrix-org/matrix-rust-sdk/commit/71136e44c03c79f80d6d1a2446673bc4d53a2067).
|
||||
|
||||
# 0.7.0
|
||||
|
||||
- Add method to mark a list of inbound group sessions as backed up:
|
||||
|
||||
@@ -9,7 +9,7 @@ name = "matrix-sdk-crypto"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/matrix-org/matrix-rust-sdk"
|
||||
rust-version = { workspace = true }
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
@@ -626,8 +626,10 @@ mod tests {
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
olm::BackedUpRoomKey, store::BackupDecryptionKey, types::RoomKeyBackupInfo, OlmError,
|
||||
OlmMachine,
|
||||
olm::BackedUpRoomKey,
|
||||
store::{BackupDecryptionKey, Changes, CryptoStore, MemoryStore},
|
||||
types::RoomKeyBackupInfo,
|
||||
OlmError, OlmMachine,
|
||||
};
|
||||
|
||||
fn room_key() -> BackedUpRoomKey {
|
||||
@@ -850,4 +852,33 @@ mod tests {
|
||||
|
||||
assert!(result.trusted());
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_fix_backup_key_mismatch() {
|
||||
let store = MemoryStore::new();
|
||||
|
||||
let backup_decryption_key = BackupDecryptionKey::new().unwrap();
|
||||
|
||||
store
|
||||
.save_changes(Changes {
|
||||
backup_decryption_key: Some(backup_decryption_key.clone()),
|
||||
backup_version: Some("1".to_owned()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Create the machine using `with_store` and without a call to enable_backup_v1,
|
||||
// like regenerate_olm would do
|
||||
let alice = OlmMachine::with_store(alice_id(), alice_device_id(), store).await.unwrap();
|
||||
|
||||
let binding = alice.backup_machine().backup_key.read().await;
|
||||
let machine_backup_key = binding.as_ref().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
machine_backup_key.to_base64(),
|
||||
backup_decryption_key.megolm_v1_public_key().to_base64(),
|
||||
"The OlmMachine loaded the wrong backup key."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,13 +313,16 @@ impl OlmMachine {
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: This is a workaround for `regenerate_olm` clearing the backup
|
||||
// state. Ideally, backups should not get automatically enabled since
|
||||
// the `OlmMachine` doesn't get enough info from the homeserver for this
|
||||
// to work reliably.
|
||||
let saved_keys = store.load_backup_keys().await?;
|
||||
let maybe_backup_key = saved_keys.decryption_key.and_then(|k| {
|
||||
if let Some(version) = saved_keys.backup_version {
|
||||
MegolmV1BackupKey::from_base64(&k.to_base64()).ok().map(|k| {
|
||||
k.set_version(version);
|
||||
k
|
||||
})
|
||||
let megolm_v1_backup_key = k.megolm_v1_public_key();
|
||||
megolm_v1_backup_key.set_version(version);
|
||||
Some(megolm_v1_backup_key)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -2169,8 +2172,10 @@ pub(crate) mod tests {
|
||||
use crate::{
|
||||
error::EventError,
|
||||
machine::{EncryptionSyncChanges, OlmMachine},
|
||||
olm::{InboundGroupSession, OutboundGroupSession, VerifyJson},
|
||||
store::Changes,
|
||||
olm::{
|
||||
BackedUpRoomKey, ExportedRoomKey, InboundGroupSession, OutboundGroupSession, VerifyJson,
|
||||
},
|
||||
store::{BackupDecryptionKey, Changes, CryptoStore, MemoryStore},
|
||||
types::{
|
||||
events::{
|
||||
room::encrypted::{EncryptedToDeviceEvent, ToDeviceEncryptedEventContent},
|
||||
@@ -4071,4 +4076,66 @@ pub(crate) mod tests {
|
||||
// The waiting should successfully complete.
|
||||
wait.await.unwrap();
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_fix_incorrect_usage_of_backup_key_causing_decryption_errors() {
|
||||
let store = MemoryStore::new();
|
||||
|
||||
let backup_decryption_key = BackupDecryptionKey::new().unwrap();
|
||||
|
||||
store
|
||||
.save_changes(Changes {
|
||||
backup_decryption_key: Some(backup_decryption_key.clone()),
|
||||
backup_version: Some("1".to_owned()),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Some valid key data
|
||||
let data = json!({
|
||||
"algorithm": "m.megolm.v1.aes-sha2",
|
||||
"room_id": "!room:id",
|
||||
"sender_key": "FOvlmz18LLI3k/llCpqRoKT90+gFF8YhuL+v1YBXHlw",
|
||||
"session_id": "/2K+V777vipCxPZ0gpY9qcpz1DYaXwuMRIu0UEP0Wa0",
|
||||
"session_key": "AQAAAAAclzWVMeWBKH+B/WMowa3rb4ma3jEl6n5W4GCs9ue65CruzD3ihX+85pZ9hsV9Bf6fvhjp76WNRajoJYX0UIt7aosjmu0i+H+07hEQ0zqTKpVoSH0ykJ6stAMhdr6Q4uW5crBmdTTBIsqmoWsNJZKKoE2+ldYrZ1lrFeaJbjBIY/9ivle++74qQsT2dIKWPanKc9Q2Gl8LjESLtFBD9Fmt",
|
||||
"sender_claimed_keys": {
|
||||
"ed25519": "F4P7f1Z0RjbiZMgHk1xBCG3KC4/Ng9PmxLJ4hQ13sHA"
|
||||
},
|
||||
"forwarding_curve25519_key_chain": ["DBPC2zr6c9qimo9YRFK3RVr0Two/I6ODb9mbsToZN3Q", "bBc/qzZFOOKshMMT+i4gjS/gWPDoKfGmETs9yfw9430"]
|
||||
});
|
||||
|
||||
let backed_up_room_key: BackedUpRoomKey = serde_json::from_value(data).unwrap();
|
||||
|
||||
// Create the machine using `with_store` and without a call to enable_backup_v1,
|
||||
// like regenerate_olm would do
|
||||
let alice = OlmMachine::with_store(user_id(), alice_device_id(), store).await.unwrap();
|
||||
|
||||
let exported_key = ExportedRoomKey::from_backed_up_room_key(
|
||||
room_id!("!room:id").to_owned(),
|
||||
"/2K+V777vipCxPZ0gpY9qcpz1DYaXwuMRIu0UEP0Wa0".into(),
|
||||
backed_up_room_key,
|
||||
);
|
||||
|
||||
alice.store().import_exported_room_keys(vec![exported_key], |_, _| {}).await.unwrap();
|
||||
|
||||
let (_, request) = alice.backup_machine().backup().await.unwrap().unwrap();
|
||||
|
||||
let key_backup_data = request.rooms[&room_id!("!room:id").to_owned()]
|
||||
.sessions
|
||||
.get("/2K+V777vipCxPZ0gpY9qcpz1DYaXwuMRIu0UEP0Wa0")
|
||||
.unwrap()
|
||||
.deserialize()
|
||||
.unwrap();
|
||||
|
||||
let ephemeral = key_backup_data.session_data.ephemeral.encode();
|
||||
let ciphertext = key_backup_data.session_data.ciphertext.encode();
|
||||
let mac = key_backup_data.session_data.mac.encode();
|
||||
|
||||
// Prior to the fix for GHSA-9ggc-845v-gcgv, this would produce a
|
||||
// `Mac(MacError)`
|
||||
backup_decryption_key
|
||||
.decrypt_v1(&ephemeral, &mac, &ciphertext)
|
||||
.expect("The backed up key should be decrypted successfully");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ name = "matrix-sdk"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/matrix-org/matrix-rust-sdk"
|
||||
rust-version = { workspace = true }
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["docsrs"]
|
||||
@@ -62,7 +62,7 @@ docsrs = ["e2e-encryption", "sqlite", "indexeddb", "sso-login", "qrcode", "image
|
||||
[dependencies]
|
||||
anyhow = { workspace = true, optional = true }
|
||||
anymap2 = "0.13.0"
|
||||
aquamarine = "0.4.0"
|
||||
aquamarine = "0.5.0"
|
||||
as_variant = { workspace = true }
|
||||
async-channel = "2.1.0"
|
||||
async-stream = { workspace = true }
|
||||
|
||||
Reference in New Issue
Block a user