From d94f415db447b096a816c4715f6026169f32a5c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 27 Apr 2022 11:05:14 +0200 Subject: [PATCH 1/5] feat(crypto): Allow unencrypted verification events to be handled --- crates/matrix-sdk-crypto/src/machine.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/matrix-sdk-crypto/src/machine.rs b/crates/matrix-sdk-crypto/src/machine.rs index add0cf4a7..df852ca3d 100644 --- a/crates/matrix-sdk-crypto/src/machine.rs +++ b/crates/matrix-sdk-crypto/src/machine.rs @@ -40,7 +40,7 @@ use ruma::{ }, room_key::ToDeviceRoomKeyEvent, secret::request::SecretName, - AnyRoomEvent, AnyToDeviceEvent, MessageLikeEventContent, + AnyMessageLikeEvent, AnyRoomEvent, AnyToDeviceEvent, MessageLikeEventContent, }, DeviceId, DeviceKeyAlgorithm, DeviceKeyId, EventEncryptionAlgorithm, OwnedDeviceId, OwnedDeviceKeyId, OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UInt, UserId, @@ -723,6 +723,20 @@ impl OlmMachine { self.group_session_manager.share_group_session(room_id, users, encryption_settings).await } + /// Receive an unencrypted verification event. + /// + /// This method can be used to pass verification events that are happening + /// in unencrypted rooms to the `OlmMachine`. + /// + /// **Note**: This does not need to be called for encrypted events since + /// those will get passed to the `OlmMachine` during decryption. + pub async fn receive_unencrypted_verification_event( + &self, + event: &AnyMessageLikeEvent, + ) -> StoreResult<()> { + self.verification_machine.receive_any_event(event).await + } + /// Receive and properly handle a decrypted to-device event. /// /// # Arguments From 4780c560e136843873c05ed8d41faa034f5699ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 27 Apr 2022 11:05:51 +0200 Subject: [PATCH 2/5] feat(base): Pass unencrypted verification events to the olm machine --- crates/matrix-sdk-base/src/client.rs | 55 +++++++++++++++++++++------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/crates/matrix-sdk-base/src/client.rs b/crates/matrix-sdk-base/src/client.rs index 59f368496..5246f9460 100644 --- a/crates/matrix-sdk-base/src/client.rs +++ b/crates/matrix-sdk-base/src/client.rs @@ -238,6 +238,22 @@ impl BaseClient { self.sync_token.read().await.clone() } + #[cfg(feature = "encryption")] + async fn handle_unenecrypted_verification_event( + &self, + event: &AnySyncMessageLikeEvent, + room_id: &RoomId, + ) -> Result<()> { + if let Some(olm) = self.olm_machine().await { + olm.receive_unencrypted_verification_event( + &event.clone().into_full_event(room_id.to_owned()), + ) + .await?; + } + + Ok(()) + } + #[allow(clippy::too_many_arguments)] async fn handle_timeline( &self, @@ -301,21 +317,34 @@ impl BaseClient { }, #[cfg(feature = "encryption")] - AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted( - SyncMessageLikeEvent::Original(encrypted), - )) => { - if let Some(olm) = self.olm_machine().await { - if let Ok(decrypted) = - olm.decrypt_room_event(encrypted, room_id).await - { - event = decrypted.into(); + AnySyncRoomEvent::MessageLike(e) => match e { + AnySyncMessageLikeEvent::RoomEncrypted( + SyncMessageLikeEvent::Original(encrypted), + ) => { + if let Some(olm) = self.olm_machine().await { + if let Ok(decrypted) = + olm.decrypt_room_event(encrypted, room_id).await + { + event = decrypted.into(); + } } } - } - // TODO if there is redacted state save the room id, - // event type and state key, add a method to get the - // requests that are needed to be called to heal this - // redacted state. + AnySyncMessageLikeEvent::RoomMessage( + SyncMessageLikeEvent::Original(original_event), + ) => match &original_event.content.msgtype { + ruma::events::room::message::MessageType::VerificationRequest( + _, + ) => { + self.handle_unenecrypted_verification_event(e, room_id).await?; + } + _ => (), + }, + _ if e.event_type().to_string().starts_with("m.key.verification") => { + self.handle_unenecrypted_verification_event(e, room_id).await?; + } + _ => (), + }, + #[cfg(not(feature = "encryption"))] _ => (), } From d8ff18322e995ed6bf5b387e2a1e2c03b9c9c24b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 27 Apr 2022 11:20:03 +0200 Subject: [PATCH 3/5] feat(crypto-ffi): Allow unencrypted verification events to be handled --- crates/matrix-crypto-ffi/src/machine.rs | 24 +++++++++++++++++++++++- crates/matrix-crypto-ffi/src/olm.udl | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/matrix-crypto-ffi/src/machine.rs b/crates/matrix-crypto-ffi/src/machine.rs index ba8208bcc..d5a569378 100644 --- a/crates/matrix-crypto-ffi/src/machine.rs +++ b/crates/matrix-crypto-ffi/src/machine.rs @@ -32,7 +32,7 @@ use ruma::{ }, events::{ key::verification::VerificationMethod, room::encrypted::OriginalSyncRoomEncryptedEvent, - AnyMessageLikeEventContent, EventContent, + AnyMessageLikeEventContent, AnySyncMessageLikeEvent, EventContent, }, DeviceKeyAlgorithm, EventId, OwnedTransactionId, OwnedUserId, RoomId, UserId, }; @@ -701,6 +701,28 @@ impl OlmMachine { Ok(()) } + /// Receive an unencrypted verification event. + /// + /// This method can be used to pass verification events that are happening + /// in unencrypted rooms to the `OlmMachine`. + /// + /// **Note**: This does not need to be called for encrypted events since + /// those will get passed to the `OlmMachine` during decryption. + pub fn receive_unencrypted_verification_event( + &self, + event: &str, + room_id: &str, + ) -> Result<(), CryptoStoreError> { + let room_id = RoomId::parse(room_id)?; + let event: AnySyncMessageLikeEvent = serde_json::from_str(event)?; + + let event = event.into_full_event(room_id); + + self.runtime.block_on(self.inner.receive_unencrypted_verification_event(&event))?; + + Ok(()) + } + /// Get all the verification requests that we share with the given user. /// /// # Arguments diff --git a/crates/matrix-crypto-ffi/src/olm.udl b/crates/matrix-crypto-ffi/src/olm.udl index f9fa5fe42..0c6d70cda 100644 --- a/crates/matrix-crypto-ffi/src/olm.udl +++ b/crates/matrix-crypto-ffi/src/olm.udl @@ -299,6 +299,8 @@ interface OlmMachine { [Throws=CryptoStoreError] sequence share_room_key([ByRef] string room_id, sequence users); + [Throws=CryptoStoreError] + void receive_unencrypted_verification_event([ByRef] string event, [ByRef] string room_id); sequence get_verification_requests([ByRef] string user_id); VerificationRequest? get_verification_request([ByRef] string user_id, [ByRef] string flow_id); Verification? get_verification([ByRef] string user_id, [ByRef] string flow_id); From 5d8c485a51d27758a2c28750b91ba15ee66f04e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 27 Apr 2022 12:58:56 +0200 Subject: [PATCH 4/5] chore: Bump most of our deps --- benchmarks/Cargo.toml | 8 +-- crates/matrix-crypto-ffi/Cargo.toml | 26 ++++---- crates/matrix-crypto-ffi/src/logger.rs | 2 +- crates/matrix-qrcode/Cargo.toml | 4 +- crates/matrix-sdk-appservice/Cargo.toml | 26 ++++---- crates/matrix-sdk-base/Cargo.toml | 38 ++++++------ crates/matrix-sdk-common/Cargo.toml | 21 ++----- crates/matrix-sdk-crypto/Cargo.toml | 49 ++++++++------- .../src/file_encryption/attachments.rs | 39 +++++++----- .../src/file_encryption/key_export.rs | 30 ++++++---- crates/matrix-sdk-indexeddb/Cargo.toml | 28 ++++----- crates/matrix-sdk-sled/Cargo.toml | 28 ++++----- crates/matrix-sdk-store-encryption/Cargo.toml | 16 ++--- crates/matrix-sdk-test-macros/Cargo.toml | 6 +- crates/matrix-sdk-test/Cargo.toml | 6 +- crates/matrix-sdk/Cargo.toml | 60 +++++++++---------- labs/sled-state-inspector/Cargo.toml | 8 +-- xtask/Cargo.toml | 2 +- 18 files changed, 202 insertions(+), 195 deletions(-) diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index 3a39e4ac5..3f43179ca 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -8,17 +8,17 @@ version = "1.0.0" publish = false [dependencies] -criterion = { version = "0.3.4", features = ["async", "async_tokio", "html_reports"] } +criterion = { version = "0.3.5", features = ["async", "async_tokio", "html_reports"] } matrix-sdk-crypto = { path = "../crates/matrix-sdk-crypto" } matrix-sdk-sled = { path = "../crates/matrix-sdk-sled", default-features = false, features = ["crypto-store"] } matrix-sdk-test = { path = "../crates/matrix-sdk-test" } ruma = { git = "https://github.com/ruma/ruma", rev = "4014e6959" } serde_json = "1.0.79" -tempfile = "3.2.0" -tokio = { version = "1.7.1", default-features = false, features = ["rt-multi-thread"] } +tempfile = "3.3.0" +tokio = { version = "1.17.0", default-features = false, features = ["rt-multi-thread"] } [target.'cfg(target_os = "linux")'.dependencies] -pprof = { version = "0.6.2", features = ["flamegraph", "criterion"] } +pprof = { version = "0.8.0", features = ["flamegraph", "criterion"] } [[bench]] name = "crypto_bench" diff --git a/crates/matrix-crypto-ffi/Cargo.toml b/crates/matrix-crypto-ffi/Cargo.toml index 51bfb4a79..87bcc3e50 100644 --- a/crates/matrix-crypto-ffi/Cargo.toml +++ b/crates/matrix-crypto-ffi/Cargo.toml @@ -9,23 +9,23 @@ crate-type = ["cdylib", "lib"] name = "matrix_crypto" [dependencies] -anyhow = "1.0.56" +anyhow = "1.0.57" base64 = "0.13.0" -hmac = "0.11.0" -http = "0.2.4" -pbkdf2 = "0.8.0" -rand = "0.8.4" -serde = "1.0.126" -serde_json = "1.0.64" -sha2 = "0.9.5" -thiserror = "1.0.25" -tracing = "0.1.26" -tracing-subscriber = "0.2.18" +hmac = "0.12.1" +http = "0.2.6" +pbkdf2 = "0.11.0" +rand = "0.8.5" +serde = "1.0.136" +serde_json = "1.0.79" +sha2 = "0.10.2" +thiserror = "1.0.30" +tracing = "0.1.34" +tracing-subscriber = { version = "0.3.11", features = ["env-filter"] } uniffi = "0.17.0" zeroize = { version = "1.3.0", features = ["zeroize_derive"] } [dependencies.js_int] -version = "0.2.1" +version = "0.2.2" features = ["lax_deserialize"] [dependencies.matrix-sdk-common] @@ -45,7 +45,7 @@ git = "https://github.com/matrix-org/vodozemac" rev = "e09c93f2c8df9770793abeec57ed984d5e1f3834" [dependencies.tokio] -version = "1.7.1" +version = "1.17.0" default_features = false features = ["rt-multi-thread"] diff --git a/crates/matrix-crypto-ffi/src/logger.rs b/crates/matrix-crypto-ffi/src/logger.rs index 993edfc32..b047784dd 100644 --- a/crates/matrix-crypto-ffi/src/logger.rs +++ b/crates/matrix-crypto-ffi/src/logger.rs @@ -27,7 +27,7 @@ impl Write for LoggerWrapper { } } -impl MakeWriter for LoggerWrapper { +impl MakeWriter<'_> for LoggerWrapper { type Writer = LoggerWrapper; fn make_writer(&self) -> Self::Writer { diff --git a/crates/matrix-qrcode/Cargo.toml b/crates/matrix-qrcode/Cargo.toml index 0ca514945..e323a2d15 100644 --- a/crates/matrix-qrcode/Cargo.toml +++ b/crates/matrix-qrcode/Cargo.toml @@ -22,11 +22,11 @@ decode_image = ["image", "rqrr", "qrcode/image", "qrcode/svg"] [dependencies] base64 = "0.13.0" byteorder = "1.4.3" -image = { version = "0.23.14", optional = true } +image = { version = "0.23.0", optional = true } qrcode = { version = "0.12.0", default-features = false } ruma-common = { git = "https://github.com/ruma/ruma", rev = "4014e6959" } rqrr = { version = "0.4.0", optional = true } -thiserror = "1.0.25" +thiserror = "1.0.30" [dependencies.vodozemac] git = "https://github.com/matrix-org/vodozemac" diff --git a/crates/matrix-sdk-appservice/Cargo.toml b/crates/matrix-sdk-appservice/Cargo.toml index 32a26986b..87212f692 100644 --- a/crates/matrix-sdk-appservice/Cargo.toml +++ b/crates/matrix-sdk-appservice/Cargo.toml @@ -24,22 +24,22 @@ sso-login = ["matrix-sdk/sso-login"] docs = [] [dependencies] -dashmap = "5.1.0" -http = "0.2" +dashmap = "5.2.0" +http = "0.2.6" matrix-sdk = { version = "0.4", path = "../matrix-sdk", default-features = false, features = ["appservice"] } percent-encoding = "2.1.0" -regex = "1" +regex = "1.5.5" ruma = { git = "https://github.com/ruma/ruma", rev = "4014e6959", features = ["client-api-c", "appservice-api-s"] } -serde = "1" -serde_json = "1" -serde_yaml = "0.8" -thiserror = "1.0" -tracing = "0.1" -url = "2" -warp = { version = "0.3.1", default-features = false } +serde = "1.0.136" +serde_json = "1.0.79" +serde_yaml = "0.8.23" +thiserror = "1.0.30" +tracing = "0.1.34" +url = "2.2.2" +warp = { version = "0.3.2", default-features = false } [dev-dependencies] matrix-sdk-test = { version = "0.4", path = "../matrix-sdk-test", features = ["appservice"] } -mockito = "0.30" -tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "macros"] } -tracing-subscriber = "0.3.7" +mockito = "0.31.0" +tokio = { version = "1.17.0", default-features = false, features = ["rt-multi-thread", "macros"] } +tracing-subscriber = "0.3.11" diff --git a/crates/matrix-sdk-base/Cargo.toml b/crates/matrix-sdk-base/Cargo.toml index b975b5b39..6476f4a85 100644 --- a/crates/matrix-sdk-base/Cargo.toml +++ b/crates/matrix-sdk-base/Cargo.toml @@ -24,33 +24,33 @@ qrcode = ["matrix-sdk-crypto/qrcode"] testing = [ "http" ] [dependencies] -async-stream = "0.3.2" +async-stream = "0.3.3" chacha20poly1305 = { version = "0.9.0", optional = true } -dashmap = "5.1.0" -futures-core = "0.3.15" -futures-util = { version = "0.3.15", default-features = false } -futures-channel = "0.3.15" -hmac = { version = "0.12.0", optional = true } -lru = "0.7.2" +dashmap = "5.2.0" +futures-core = "0.3.21" +futures-util = { version = "0.3.21", default-features = false } +futures-channel = "0.3.21" +hmac = { version = "0.12.1", optional = true } +lru = "0.7.5" 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.10.0", default-features = false, optional = true } -rand = { version = "0.8.4", optional = true } +pbkdf2 = { version = "0.11.0", default-features = false, optional = true } +rand = { version = "0.8.5", optional = true } ruma = { git = "https://github.com/ruma/ruma", rev = "4014e6959", features = ["client-api-c", "signatures"] } -serde = { version = "1.0.126", features = ["rc"] } -serde_json = "1.0.64" -sha2 = { version = "0.10.1", optional = true } -thiserror = "1.0.25" -tracing = "0.1.26" +serde = { version = "1.0.136", features = ["rc"] } +serde_json = "1.0.79" +sha2 = { version = "0.10.2", optional = true } +thiserror = "1.0.30" +tracing = "0.1.34" zeroize = { version = "1.3.0", features = ["zeroize_derive"] } -anyhow = "1" -http = { version = "0.2.4", optional = true } +anyhow = "1.0.57" +http = { version = "0.2.6", optional = true } [dev-dependencies] -futures = { version = "0.3.15", default-features = false, features = ["executor"] } -http = "0.2.4" +futures = { version = "0.3.21", default-features = false, features = ["executor"] } +http = "0.2.6" matrix-sdk-test = { version = "0.4.0", path = "../matrix-sdk-test" } -tokio = { version = "1.7.1", default-features = false, features = [ +tokio = { version = "1.17.0", default-features = false, features = [ "rt-multi-thread", "macros", ] } diff --git a/crates/matrix-sdk-common/Cargo.toml b/crates/matrix-sdk-common/Cargo.toml index c01c98bea..6dc9d037c 100644 --- a/crates/matrix-sdk-common/Cargo.toml +++ b/crates/matrix-sdk-common/Cargo.toml @@ -16,26 +16,17 @@ default-target = "x86_64-unknown-linux-gnu" targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] [dependencies] -async-trait = "0.1.50" +async-trait = "0.1.53" ruma = { git = "https://github.com/ruma/ruma", rev = "4014e6959", features = ["client-api-c"] } -serde = "1.0.126" +serde = "1.0.136" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -uuid = { version = "0.8.2", default-features = false, features = [ - "v4", - "serde", -] } -tokio = { version = "1.7.1", default-features = false, features = ["rt", "sync"] } +tokio = { version = "1.17.0", default-features = false, features = ["rt", "sync"] } instant = { version = "0.1.12", features = ["now"] } [target.'cfg(target_arch = "wasm32")'.dependencies] -async-lock = "2.4.0" +async-lock = "2.5.0" instant = { version = "0.1.12", features = ["wasm-bindgen", "inaccurate"] } -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", -] } +futures-util = { version = "0.3.21", default-features = false, features = ["channel"] } +wasm-bindgen-futures = "0.4.30" diff --git a/crates/matrix-sdk-crypto/Cargo.toml b/crates/matrix-sdk-crypto/Cargo.toml index 5e1108035..264c52e96 100644 --- a/crates/matrix-sdk-crypto/Cargo.toml +++ b/crates/matrix-sdk-crypto/Cargo.toml @@ -25,35 +25,40 @@ docsrs = [] testing = ["http"] [dependencies] -aes = { version = "0.7.4", features = ["ctr"] } -aes-gcm = "0.9.2" -atomic = "0.5.0" +aes = "0.8.1" +aes-gcm = "0.9.4" +atomic = "0.5.1" base64 = "0.13.0" bs58 = { version = "0.4.0", optional = true } byteorder = "1.4.3" -dashmap = "5.1.0" -futures-util = { version = "0.3.15", default-features = false, features = ["alloc"] } -hmac = "0.12.0" +ctr = "0.9.1" +dashmap = "5.2.0" +futures-util = { version = "0.3.21", default-features = false, features = ["alloc"] } +hmac = "0.12.1" matrix-qrcode = { version = "0.2.0", path = "../matrix-qrcode", optional = true } matrix-sdk-common = { version = "0.4.0", path = "../matrix-sdk-common" } -olm-rs = { version = "2.1", features = ["serde"], optional = true } -pbkdf2 = { version = "0.10.0", default-features = false } -rand = "0.8.4" -serde = { version = "1.0.126", features = ["derive", "rc"] } -serde_json = "1.0.64" -sha2 = "0.10.1" -thiserror = "1.0.25" -tracing = "0.1.26" +olm-rs = { version = "2.2.0", features = ["serde"], optional = true } +pbkdf2 = { version = "0.11.0", default-features = false } +rand = "0.8.5" +serde = { version = "1.0.136", features = ["derive", "rc"] } +serde_json = "1.0.79" +sha2 = "0.10.2" +thiserror = "1.0.30" +tracing = "0.1.34" zeroize = { version = "1.3.0", features = ["zeroize_derive"] } -anyhow = "1" +anyhow = "1.0.57" # feature = testing only -http = { version = "0.2.4", optional = true } +http = { version = "0.2.6", optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies.vodozemac] git = "https://github.com/matrix-org/vodozemac" rev = "e09c93f2c8df9770793abeec57ed984d5e1f3834" +[target.'cfg(target_arch = "wasm32")'.dev-dependencies.getrandom] +version = "0.2.6" +features = ["js"] + [target.'cfg(target_arch = "wasm32")'.dependencies.vodozemac] git = "https://github.com/matrix-org/vodozemac" rev = "e09c93f2c8df9770793abeec57ed984d5e1f3834" @@ -65,13 +70,11 @@ rev = "4014e6959" features = ["client-api-c", "rand", "unstable-msc2676", "unstable-msc2677"] [dev-dependencies] -futures = { version = "0.3.15", default-features = false, features = [ - "executor", -] } -http = "0.2.4" -indoc = "1.0.3" -matches = "0.1.8" +futures = { version = "0.3.21", default-features = false, features = ["executor"] } +http = "0.2.6" +indoc = "1.0.4" +matches = "0.1.9" matrix-sdk-test = { version = "0.4.0", path = "../matrix-sdk-test" } proptest = "1.0.0" # required for async_test macro -tokio = { version = "1.7.1", default-features = false, features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.17.0", default-features = false, features = ["macros", "rt-multi-thread"] } diff --git a/crates/matrix-sdk-crypto/src/file_encryption/attachments.rs b/crates/matrix-sdk-crypto/src/file_encryption/attachments.rs index 2502ccc8e..90d031cee 100644 --- a/crates/matrix-sdk-crypto/src/file_encryption/attachments.rs +++ b/crates/matrix-sdk-crypto/src/file_encryption/attachments.rs @@ -18,8 +18,8 @@ use std::{ }; use aes::{ - cipher::{generic_array::GenericArray, FromBlockCipher, NewBlockCipher, StreamCipher}, - Aes256, Aes256Ctr, + cipher::{generic_array::GenericArray, KeyIvInit, StreamCipher}, + Aes256, }; use base64::DecodeError; use rand::{thread_rng, RngCore}; @@ -30,12 +30,14 @@ use ruma::{ use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use thiserror::Error; -use zeroize::Zeroizing; +use zeroize::Zeroize; const IV_SIZE: usize = 16; const KEY_SIZE: usize = 32; const VERSION: &str = "v2"; +type Aes256Ctr = ctr::Ctr128BE; + /// A wrapper that transparently encrypts anything that implements `Read` as an /// Matrix attachment. pub struct AttachmentDecryptor<'a, R: Read> { @@ -134,13 +136,20 @@ impl<'a, R: Read + 'a> AttachmentDecryptor<'a, R> { let hash = info.hashes.get("sha256").ok_or(DecryptorError::MissingHash)?.as_bytes().to_owned(); - let key = Zeroizing::from(info.web_key.k.into_inner()); + let mut key = info.web_key.k.into_inner(); let iv = info.iv.into_inner(); + + if key.len() != KEY_SIZE { + return Err(DecryptorError::KeyNonceLength); + } + + let key_array = GenericArray::from_slice(&key); let iv = GenericArray::from_exact_iter(iv).ok_or(DecryptorError::KeyNonceLength)?; let sha = Sha256::default(); - let aes = Aes256::new_from_slice(&key).map_err(|_| DecryptorError::KeyNonceLength)?; - let aes = Aes256Ctr::from_block_cipher(aes, &iv); + + let aes = Aes256Ctr::new(key_array, &iv); + key.zeroize(); Ok(AttachmentDecryptor { inner: input, expected_hash: hash, sha, aes }) } @@ -215,12 +224,12 @@ impl<'a, R: Read + ?Sized + 'a> AttachmentEncryptor<'a, R> { /// let key = encryptor.finish(); /// ``` pub fn new(reader: &'a mut R) -> Self { - let mut key = Zeroizing::new([0u8; KEY_SIZE]); - let mut iv = Zeroizing::new([0u8; IV_SIZE]); + let mut key = [0u8; KEY_SIZE]; + let mut iv = [0u8; IV_SIZE]; let mut rng = thread_rng(); - rng.fill_bytes(&mut *key); + rng.fill_bytes(&mut key); // Only populate the first 8 bytes with randomness, the rest is 0 // initialized for the counter. rng.fill_bytes(&mut iv[0..8]); @@ -229,15 +238,15 @@ impl<'a, R: Read + ?Sized + 'a> AttachmentEncryptor<'a, R> { kty: "oct".to_owned(), key_ops: vec!["encrypt".to_owned(), "decrypt".to_owned()], alg: "A256CTR".to_owned(), - k: Base64::new((*key).to_vec()), + k: Base64::new(key.to_vec()), ext: true, }); - let encoded_iv = Base64::new((*iv).to_vec()); - let iv = GenericArray::from_slice(&*iv); - let key = GenericArray::from_slice(&*key); + let encoded_iv = Base64::new((iv).to_vec()); - let aes = Aes256::new(key); - let aes = Aes256Ctr::from_block_cipher(aes, iv); + let key_array = &key.into(); + + let aes = Aes256Ctr::new(key_array, &iv.into()); + key.zeroize(); AttachmentEncryptor { finished: false, diff --git a/crates/matrix-sdk-crypto/src/file_encryption/key_export.rs b/crates/matrix-sdk-crypto/src/file_encryption/key_export.rs index 42cdb63f1..f5adde9b0 100644 --- a/crates/matrix-sdk-crypto/src/file_encryption/key_export.rs +++ b/crates/matrix-sdk-crypto/src/file_encryption/key_export.rs @@ -15,8 +15,8 @@ use std::io::{Cursor, Read, Seek, SeekFrom}; use aes::{ - cipher::{generic_array::GenericArray, FromBlockCipher, NewBlockCipher, StreamCipher}, - Aes256, Aes256Ctr, + cipher::{generic_array::GenericArray, KeyIvInit, StreamCipher}, + Aes256, }; use byteorder::{BigEndian, ReadBytesExt}; use hmac::{Hmac, Mac}; @@ -32,6 +32,8 @@ use crate::{ utilities::{decode, encode, DecodeError}, }; +type Aes256Ctr = ctr::Ctr128BE; + const SALT_SIZE: usize = 16; const IV_SIZE: usize = 16; const MAC_SIZE: usize = 32; @@ -169,24 +171,23 @@ fn encrypt_helper(plaintext: &mut [u8], passphrase: &str, rounds: u32) -> String let mut iv = u128::from_be_bytes(iv); iv &= !(1 << 63); + let iv = iv.to_be_bytes(); pbkdf2::>(passphrase.as_bytes(), &salt, rounds, &mut derived_keys); let (key, hmac_key) = derived_keys.split_at(KEY_SIZE); - let key = GenericArray::from_slice(key); - let iv = iv.to_be_bytes(); - let iv = GenericArray::from_slice(&iv); - - let aes = Aes256::new(key); - let mut aes = Aes256Ctr::from_block_cipher(aes, iv); + // This is fine because the key is guaranteed to be 32 bytes, derive 64 + // bytes and split at the middle. + let key_array = GenericArray::from_slice(key); + let mut aes = Aes256Ctr::new(key_array, &iv.into()); aes.apply_keystream(plaintext); let mut payload: Vec = vec![]; payload.extend(&VERSION.to_be_bytes()); payload.extend(&salt); - payload.extend(&*iv); + payload.extend(&iv); payload.extend(&rounds.to_be_bytes()); payload.extend_from_slice(plaintext); @@ -196,6 +197,8 @@ fn encrypt_helper(plaintext: &mut [u8], passphrase: &str, rounds: u32) -> String payload.extend(mac.into_bytes()); + derived_keys.zeroize(); + encode(payload) } @@ -234,16 +237,17 @@ fn decrypt_helper(ciphertext: &str, passphrase: &str) -> Result Date: Wed, 27 Apr 2022 18:40:39 +0200 Subject: [PATCH 5/5] fix(crypto-ffi): Rename the error message field for MigrationError The field is called message which clashes with the field of the same name in the Kotlin Exception class. --- crates/matrix-crypto-ffi/src/lib.rs | 6 +++--- crates/matrix-crypto-ffi/src/olm.udl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/matrix-crypto-ffi/src/lib.rs b/crates/matrix-crypto-ffi/src/lib.rs index da9d1369f..7b3d166a4 100644 --- a/crates/matrix-crypto-ffi/src/lib.rs +++ b/crates/matrix-crypto-ffi/src/lib.rs @@ -123,16 +123,16 @@ pub struct PickledInboundGroupSession { #[derive(thiserror::Error, Debug)] pub enum MigrationError { /// Generic catch all error variant. - #[error("error migrating database: {message}")] + #[error("error migrating database: {error_message}")] Generic { /// The error message - message: String, + error_message: String, }, } impl From for MigrationError { fn from(e: anyhow::Error) -> MigrationError { - MigrationError::Generic { message: e.to_string() } + MigrationError::Generic { error_message: e.to_string() } } } diff --git a/crates/matrix-crypto-ffi/src/olm.udl b/crates/matrix-crypto-ffi/src/olm.udl index 0c6d70cda..d42c0499c 100644 --- a/crates/matrix-crypto-ffi/src/olm.udl +++ b/crates/matrix-crypto-ffi/src/olm.udl @@ -11,7 +11,7 @@ namespace olm { [Error] interface MigrationError { - Generic(string message); + Generic(string error_message); }; callback interface Logger {