Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions bindings/matrix-sdk-crypto-ffi/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ pub enum DecryptionError {
Store { error: String },
}

#[derive(Debug, thiserror::Error, uniffi::Error)]
pub enum BootstrapCrossSigningError {
#[error(transparent)]
CryptoStore(CryptoStoreError),
#[error(transparent)]
Signature(SignatureError),
}

/// Error describing what went wrong when exporting a [`SecretsBundle`].
///
/// The [`SecretsBundle`] can only be exported if we have all cross-signing
Expand Down Expand Up @@ -149,6 +157,16 @@ impl From<InnerStoreError> for DecryptionError {
}
}

impl From<matrix_sdk_crypto::BootstrapCrossSigningError> for BootstrapCrossSigningError {
fn from(err: matrix_sdk_crypto::BootstrapCrossSigningError) -> Self {
use matrix_sdk_crypto::BootstrapCrossSigningError as BCSE;
match err {
BCSE::CryptoStore(e) => Self::CryptoStore(e.into()),
BCSE::Signature(e) => Self::Signature(e.into()),
}
}
}

#[cfg(test)]
mod tests {
use assert_matches2::assert_let;
Expand Down
3 changes: 2 additions & 1 deletion bindings/matrix-sdk-crypto-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ pub use backup_recovery_key::{
};
pub use device::Device;
pub use error::{
CryptoStoreError, DecryptionError, KeyImportError, SecretImportError, SignatureError,
BootstrapCrossSigningError, CryptoStoreError, DecryptionError, KeyImportError,
SecretImportError, SignatureError,
};
use js_int::UInt;
pub use logger::{Logger, set_logger};
Expand Down
15 changes: 9 additions & 6 deletions bindings/matrix-sdk-crypto-ffi/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ use tokio::runtime::Runtime;
use zeroize::Zeroize;

use crate::{
BackupKeys, BackupRecoveryKey, BootstrapCrossSigningResult, CrossSigningKeyExport,
CrossSigningStatus, DecodeError, DecryptedEvent, Device, DeviceLists, EncryptionSettings,
EventEncryptionAlgorithm, KeyImportError, KeysImportResult, MegolmV1BackupKey,
ProgressListener, Request, RequestType, RequestVerificationResult, RoomKeyCounts, RoomSettings,
Sas, SignatureUploadRequest, StartSasResult, UserIdentity, Verification, VerificationRequest,
BackupKeys, BackupRecoveryKey, BootstrapCrossSigningError, BootstrapCrossSigningResult,
CrossSigningKeyExport, CrossSigningStatus, DecodeError, DecryptedEvent, Device, DeviceLists,
EncryptionSettings, EventEncryptionAlgorithm, KeyImportError, KeysImportResult,
MegolmV1BackupKey, ProgressListener, Request, RequestType, RequestVerificationResult,
RoomKeyCounts, RoomSettings, Sas, SignatureUploadRequest, StartSasResult, UserIdentity,
Verification, VerificationRequest,
dehydrated_devices::DehydratedDevices,
error::{
CryptoStoreError, DecryptionError, SecretImportError, SecretsBundleExportError,
Expand Down Expand Up @@ -1376,7 +1377,9 @@ impl OlmMachine {

/// Create a new private cross signing identity and create a request to
/// upload the public part of it to the server.
pub fn bootstrap_cross_signing(&self) -> Result<BootstrapCrossSigningResult, CryptoStoreError> {
pub fn bootstrap_cross_signing(
&self,
) -> Result<BootstrapCrossSigningResult, BootstrapCrossSigningError> {
Comment thread
kaylendog marked this conversation as resolved.
Ok(self.runtime.block_on(self.inner.bootstrap_cross_signing(true))?.into())
}

Expand Down
4 changes: 4 additions & 0 deletions bindings/matrix-sdk-ffi/changelog.d/6715.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[**breaking**] Adjust `OlmMachine::bootstrap_cross_signing` to return
a new `BootstrapCrossSigningError` enum covering both crypto store
and signing failures. This replaces the previous `CryptoStoreError`
return type.
9 changes: 9 additions & 0 deletions crates/matrix-sdk-crypto/changelog.d/6715.changed
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Accept `impl Into<Signature>` in `Signatures::add_signature`.

[**breaking**] Make `OlmMachine::bootstrap_cross_signing` fallible to
allow future signing implementations to produce errors. Further
introduces `CrossSigningBootstrapError` to enumerate possible failure
cases.

[**breaking**] Removed `Account::sign_master_key`, as the master key
is signed automatically when calling `OwnUserIdentity::verify`
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,7 @@ mod tests {
let account = Account::with_device_id(user_id, &device_id);

let private_identity =
Arc::new(Mutex::new(PrivateCrossSigningIdentity::for_account(&account)));
Arc::new(Mutex::new(PrivateCrossSigningIdentity::for_account(&account).unwrap()));

let other_user_identity_data =
OtherUserIdentityData::from_private(&*private_identity.lock().await).await;
Expand Down Expand Up @@ -1152,7 +1152,7 @@ mod tests {
let account = Account::with_device_id(user_id, &device_id);

let private_identity =
Arc::new(Mutex::new(PrivateCrossSigningIdentity::for_account(&account)));
Arc::new(Mutex::new(PrivateCrossSigningIdentity::for_account(&account).unwrap()));

let own_user_identity_data =
OwnUserIdentityData::from_private(&*private_identity.lock().await).await;
Expand Down
25 changes: 21 additions & 4 deletions crates/matrix-sdk-crypto/src/identities/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use as_variant::as_variant;
use matrix_sdk_common::locks::RwLock;
use ruma::{
DeviceId, EventId, OwnedDeviceId, OwnedUserId, RoomId, UserId,
api::client::keys::upload_signatures::v3::Request as SignatureUploadRequest,
api::client::keys::upload_signatures::v3::{Request as SignatureUploadRequest, SignedKeys},
events::{key::verification::VerificationMethod, room::message::MessageType},
};
use serde::{Deserialize, Deserializer, Serialize};
Expand All @@ -40,7 +40,8 @@ use crate::{
types::{Changes, IdentityChanges},
},
types::{
MasterPubkey, SelfSigningPubkey, UserSigningPubkey, requests::OutgoingVerificationRequest,
CrossSigningKey, MasterPubkey, SelfSigningPubkey, UserSigningPubkey,
requests::OutgoingVerificationRequest,
},
verification::VerificationMachine,
};
Expand Down Expand Up @@ -230,7 +231,23 @@ impl OwnUserIdentity {

let cache = self.store.cache().await?;
let account = cache.account().await?;
account.sign_master_key(&self.master_key)

let public_key = self
.master_key
.get_first_key()
.ok_or(SignatureError::MissingSigningKey)?
.to_base64()
.into();

let mut cross_signing_key: CrossSigningKey = (*self.master_key).as_ref().clone();
cross_signing_key.signatures.clear();
account.sign_cross_signing_key(&mut cross_signing_key)?;

let mut user_signed_keys = SignedKeys::new();
user_signed_keys.add_cross_signing_keys(public_key, cross_signing_key.to_raw());

let signed_keys = [(self.user_id().to_owned(), user_signed_keys)].into();
Ok(SignatureUploadRequest::new(signed_keys))
}

/// Send a verification request to our other devices.
Expand Down Expand Up @@ -2023,7 +2040,7 @@ pub(crate) mod tests {
* Creates a new private user identity for the account.
*/
fn get_verification_machine(account: &Account) -> VerificationMachine {
let private_identity = PrivateCrossSigningIdentity::for_account(account);
let private_identity = PrivateCrossSigningIdentity::for_account(account).unwrap();
VerificationMachine::new(
account.static_data().clone(),
Arc::new(Mutex::new(private_identity)),
Expand Down
3 changes: 2 additions & 1 deletion crates/matrix-sdk-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ pub use identities::{
OwnUserIdentityData, UserDevices, UserIdentity, UserIdentityData,
};
pub use machine::{
CrossSigningBootstrapRequests, EncryptionSyncChanges, OlmMachine, OlmMachineBuilder,
BootstrapCrossSigningError, CrossSigningBootstrapRequests, EncryptionSyncChanges, OlmMachine,
OlmMachineBuilder,
};
use matrix_sdk_common::deserialized_responses::{DecryptedRoomEvent, UnableToDecryptInfo};
#[cfg(feature = "qrcode")]
Expand Down
20 changes: 18 additions & 2 deletions crates/matrix-sdk-crypto/src/machine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ impl OlmMachine {
pub async fn bootstrap_cross_signing(
&self,
reset: bool,
) -> StoreResult<CrossSigningBootstrapRequests> {
) -> Result<CrossSigningBootstrapRequests, BootstrapCrossSigningError> {
// Don't hold the lock, otherwise we might deadlock in
// `bootstrap_cross_signing()` on `account` if a sync task is already
// running (which locks `account`), or we will deadlock
Expand All @@ -731,7 +731,7 @@ impl OlmMachine {
let (identity, upload_signing_keys_req, upload_signatures_req) = {
let cache = self.inner.store.cache().await?;
let account = cache.account().await?;
account.bootstrap_cross_signing().await
account.bootstrap_cross_signing().await?
};

let public = identity.to_public_identity().await.expect(
Expand Down Expand Up @@ -3193,6 +3193,22 @@ pub struct CrossSigningBootstrapRequests {
pub upload_signatures_req: UploadSignaturesRequest,
}

/// An error that can occur during [`OlmMachine::bootstrap_cross_signing`]:
///
/// * because a failure with the store occurred, or
///
/// * because the new cross-signing identity could not be signed.
#[derive(Debug, thiserror::Error)]
pub enum BootstrapCrossSigningError {
/// A failure with the store occurred.
#[error(transparent)]
CryptoStore(#[from] CryptoStoreError),

/// The new cross-signing identity could not be signed
#[error(transparent)]
Signature(#[from] SignatureError),
}

/// Data contained from a sync response and that needs to be processed by the
/// OlmMachine.
#[derive(Debug)]
Expand Down
40 changes: 9 additions & 31 deletions crates/matrix-sdk-crypto/src/olm/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ use ruma::{
OwnedUserId, RoomId, SecondsSinceUnixEpoch, UInt, UserId,
api::client::{
dehydrated_device::{DehydratedDeviceData, DehydratedDeviceV2},
keys::{
upload_keys,
upload_signatures::v3::{Request as SignatureUploadRequest, SignedKeys},
},
keys::{upload_keys, upload_signatures::v3::Request as SignatureUploadRequest},
},
canonical_json::to_canonical_value,
events::{AnyToDeviceEvent, room::history_visibility::HistoryVisibility},
Expand Down Expand Up @@ -70,7 +67,7 @@ use crate::{
types::{Changes, DeviceChanges},
},
types::{
CrossSigningKey, DeviceKeys, EventEncryptionAlgorithm, MasterPubkey, OneTimeKey, SignedKey,
CrossSigningKey, DeviceKeys, EventEncryptionAlgorithm, OneTimeKey, SignedKey,
events::{
olm_v1::AnyDecryptedOlmEvent,
room::encrypted::{
Expand Down Expand Up @@ -817,17 +814,17 @@ impl Account {
/// this device to the server.
pub async fn bootstrap_cross_signing(
&self,
) -> (PrivateCrossSigningIdentity, UploadSigningKeysRequest, SignatureUploadRequest) {
let identity = PrivateCrossSigningIdentity::for_account(self);
) -> Result<
(PrivateCrossSigningIdentity, UploadSigningKeysRequest, SignatureUploadRequest),
SignatureError,
> {
let identity = PrivateCrossSigningIdentity::for_account(self)?;

let signature_request = identity
.sign_account(self.static_data())
.await
.expect("Can't sign own device with new cross signing keys");
let signature_request = identity.sign_account(self.static_data()).await?;

let upload_request = identity.as_upload_request().await;

(identity, upload_request, signature_request)
Ok((identity, upload_request, signature_request))
}

/// Sign the given CrossSigning Key in place
Expand All @@ -846,25 +843,6 @@ impl Account {
Ok(())
}

/// Sign the given Master Key
pub fn sign_master_key(
&self,
master_key: &MasterPubkey,
) -> Result<SignatureUploadRequest, SignatureError> {
let public_key =
master_key.get_first_key().ok_or(SignatureError::MissingSigningKey)?.to_base64().into();

let mut cross_signing_key: CrossSigningKey = master_key.as_ref().clone();
cross_signing_key.signatures.clear();
self.sign_cross_signing_key(&mut cross_signing_key)?;

let mut user_signed_keys = SignedKeys::new();
user_signed_keys.add_cross_signing_keys(public_key, cross_signing_key.to_raw());

let signed_keys = [(self.user_id().to_owned(), user_signed_keys)].into();
Ok(SignatureUploadRequest::new(signed_keys))
}

/// Convert a JSON value to the canonical representation and sign the JSON
/// string.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ mod tests {
async fn test_from_device_for_verified_user() {
let alice_account =
Account::with_device_id(user_id!("@alice:example.com"), device_id!("ALICE_DEVICE"));
let alice_identity = PrivateCrossSigningIdentity::for_account(&alice_account);
let alice_identity = PrivateCrossSigningIdentity::for_account(&alice_account).unwrap();

let bob_identity = PrivateCrossSigningIdentity::new(owned_user_id!("@bob:example.com"));
let bob_account =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ mod tests {
let account = Account::with_device_id(user_id, device_id);
let user_id = user_id.to_owned();
let private_identity =
Arc::new(Mutex::new(PrivateCrossSigningIdentity::for_account(&account)));
Arc::new(Mutex::new(PrivateCrossSigningIdentity::for_account(&account).unwrap()));

let user_identity =
create_user_identity(&*private_identity.lock().await, is_me, is_verified, signer)
Expand Down
18 changes: 9 additions & 9 deletions crates/matrix-sdk-crypto/src/olm/signing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,14 +564,14 @@ impl PrivateCrossSigningIdentity {
*
* * `account` - The Olm account that is creating the new identity.
*/
pub(crate) fn for_account(account: &Account) -> PrivateCrossSigningIdentity {
pub(crate) fn for_account(
account: &Account,
) -> Result<PrivateCrossSigningIdentity, SignatureError> {
let mut master = MasterSigning::new(account.user_id().into());

account
.sign_cross_signing_key(master.public_key_mut().as_mut())
.expect("Can't sign our freshly created master key with our account");
account.sign_cross_signing_key(master.public_key_mut().as_mut())?;

Self::new_helper(account.user_id(), master)
Ok(Self::new_helper(account.user_id(), master))
}

#[cfg(any(test, feature = "testing"))]
Expand Down Expand Up @@ -749,7 +749,7 @@ mod tests {
#[async_test]
async fn test_private_identity_signed_by_account() {
let account = Account::with_device_id(user_id(), device_id!("DEVICEID"));
let identity = PrivateCrossSigningIdentity::for_account(&account);
let identity = PrivateCrossSigningIdentity::for_account(&account).unwrap();
let master = identity.master_key.lock().await;
let master = master.as_ref().unwrap();

Expand All @@ -772,7 +772,7 @@ mod tests {
#[async_test]
async fn test_sign_device() {
let account = Account::with_device_id(user_id(), device_id!("DEVICEID"));
let identity = PrivateCrossSigningIdentity::for_account(&account);
let identity = PrivateCrossSigningIdentity::for_account(&account).unwrap();

let mut device = DeviceData::from_account(&account);
let self_signing = identity.self_signing_key.lock().await;
Expand All @@ -789,11 +789,11 @@ mod tests {
#[async_test]
async fn test_sign_user_identity() {
let account = Account::with_device_id(user_id(), device_id!("DEVICEID"));
let identity = PrivateCrossSigningIdentity::for_account(&account);
let identity = PrivateCrossSigningIdentity::for_account(&account).unwrap();

let bob_account =
Account::with_device_id(user_id!("@bob:localhost"), device_id!("DEVICEID"));
let bob_private = PrivateCrossSigningIdentity::for_account(&bob_account);
let bob_private = PrivateCrossSigningIdentity::for_account(&bob_account).unwrap();
let mut bob_public = OtherUserIdentityData::from_private(&bob_private).await;

let user_signing = identity.user_signing_key.lock().await;
Expand Down
2 changes: 1 addition & 1 deletion crates/matrix-sdk-crypto/src/types/signatures/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl Signatures {
&mut self,
signer: OwnedUserId,
key_id: OwnedDeviceKeyId,
signature: Ed25519Signature,
signature: impl Into<Signature>,
) -> Option<Result<Signature, InvalidSignature>> {
self.0.entry(signer).or_default().insert(key_id, Ok(signature.into()))
}
Expand Down
4 changes: 2 additions & 2 deletions crates/matrix-sdk-crypto/src/verification/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,12 +830,12 @@ pub(crate) mod tests {
pub(crate) async fn setup_stores() -> (Account, VerificationStore, Account, VerificationStore) {
let alice = Account::with_device_id(alice_id(), alice_device_id());
let alice_store = MemoryStore::new();
let alice_private_identity = PrivateCrossSigningIdentity::for_account(&alice);
let alice_private_identity = PrivateCrossSigningIdentity::for_account(&alice).unwrap();
let alice_private_identity = Mutex::new(alice_private_identity);

let bob = Account::with_device_id(bob_id(), bob_device_id());
let bob_store = MemoryStore::new();
let bob_private_identity = PrivateCrossSigningIdentity::for_account(&bob);
let bob_private_identity = PrivateCrossSigningIdentity::for_account(&bob).unwrap();
let bob_private_identity = Mutex::new(bob_private_identity);

let alice_public_identity =
Expand Down
2 changes: 2 additions & 0 deletions crates/matrix-sdk/changelog.d/6715.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Added a new top-level `Error` variant, `SignatureError` representing
errors that occurred signing or verifying cryptographic data.
Loading
Loading