Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crypto: Return an error when sharing a room key to a verified user, who has an unverified device (optional encryption setting) #3810

Merged

Conversation

BillCarsonFr
Copy link
Member

@BillCarsonFr BillCarsonFr commented Aug 7, 2024

Fixes #3792

Suggest review commit-by-commit.

  • Public API changes documented in changelogs (optional)

@BillCarsonFr BillCarsonFr changed the title Valere/invisible crypto/error on unsigned device of verified user Crypto: Return an error when sharing a room key to a verified user, who has an unverified device (optional encryption setting) Aug 7, 2024
@BillCarsonFr BillCarsonFr force-pushed the valere/invisible_crypto/verification_pin branch 2 times, most recently from e715223 to 1b05380 Compare August 7, 2024 13:06
@BillCarsonFr BillCarsonFr force-pushed the valere/invisible_crypto/error_on_unsigned_device_of_verified_user branch from b643839 to 6e6f71d Compare August 7, 2024 15:38
Base automatically changed from valere/invisible_crypto/verification_pin to main August 8, 2024 10:10
@BillCarsonFr BillCarsonFr force-pushed the valere/invisible_crypto/error_on_unsigned_device_of_verified_user branch from 6e6f71d to 9874e40 Compare August 8, 2024 14:18
Copy link

codecov bot commented Aug 8, 2024

Codecov Report

Attention: Patch coverage is 86.84211% with 10 lines in your changes missing coverage. Please review.

Project coverage is 84.09%. Comparing base (4ece38a) to head (5f24f8e).
Report is 13 commits behind head on main.

Files Patch % Lines
...c/session_manager/group_sessions/share_strategy.rs 85.71% 9 Missing ⚠️
crates/matrix-sdk-crypto/src/identities/device.rs 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3810      +/-   ##
==========================================
+ Coverage   84.07%   84.09%   +0.01%     
==========================================
  Files         262      262              
  Lines       27544    27581      +37     
==========================================
+ Hits        23158    23193      +35     
- Misses       4386     4388       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@BillCarsonFr BillCarsonFr force-pushed the valere/invisible_crypto/error_on_unsigned_device_of_verified_user branch from 9874e40 to de4cc83 Compare August 8, 2024 14:39
@BillCarsonFr BillCarsonFr marked this pull request as ready for review August 8, 2024 14:56
@BillCarsonFr BillCarsonFr requested review from a team as code owners August 8, 2024 14:56
@BillCarsonFr BillCarsonFr requested review from poljar and richvdh and removed request for a team August 8, 2024 14:56
/// Whitelisted devices will receive group sessions regardless of their
/// verification status.
pub fn is_whitelisted(&self) -> bool {
self.local_trust_state() == LocalTrust::Ignored
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LocalTrust::Ignored actually is really Whitelist, as it says that the trust state should be ignored. Should it be renamed to Whitelisted? to be consistent with LocalTrust::BlackListed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeahh, this feels pretty confusing to me, and could do with clean up.

That said: "whitelisted"/"blacklisted" are somewhat problematic terms, and we might take the opportunity to rename both.

@@ -228,16 +313,61 @@ fn split_recipients_withhelds_for_user(
user_devices.into_values().partition_map(|d| {
if d.is_blacklisted() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if/else sequence is getting harder and harder to read with all the possible settings/outcome.
We might want to get rid of the partition/Either system.
Also the set of settings can create invalid configuration, like only_allow_trusted_devices + error_on_unsigned_device_of_verified_users doesn't really make sense.
Will get worse with more options

Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks broadly good to me. Some initial thoughts, but nothing major -- except my question about checking own_identity.is_verified().

I'll take a closer look tomorrow.

Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more, more nitpicky comments. I still need to take a closer look at the tests.

crates/matrix-sdk-crypto/src/error.rs Outdated Show resolved Hide resolved
crates/matrix-sdk-crypto/src/error.rs Outdated Show resolved Hide resolved
crates/matrix-sdk-crypto/src/error.rs Outdated Show resolved Hide resolved
crates/matrix-sdk-crypto/src/error.rs Outdated Show resolved Hide resolved
/// Once the problematic devices are blacklisted or whitelisted the
/// caller can retry to share a second time. This has to be done
/// once per problematic device.
#[serde(default)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this persisted somewhere, that makes the default necessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EncryptionSettings is persisted in the OutboundSession at least, and maybe some clients could persist the encryption settings? All the things we put as serializable could be persisted... (are we serializing things for other reasons? like for bindings to pass things back and forth?)
We really need to improve that part of the sdk, it's too easy to make a change that would break applications.
I thought about having tests with json exports of all the serializable things that are persisted, that just tries to load them back and see if it breaks. This would be minimum. Or we need to think about a specific trait for things that are expected to be serialized persisted, with a version of some form

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EncryptionSettings is persisted in the OutboundSession at least

Hrm... does that means that, once we enable the new behaviour, it won't work until megolm sessions are replaced?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. But there is something odd with the settings how they are now.

The settings persisted is used mainly (i think) in the code to detect if the session should be rotated.
I think that only part of the EncryptionSetting should be persisted (rotation_period, rotation_period_msgs, and history_visibility?).
The old only_allow_trusted_devices that was in the EncryptionSetting (replaced now by CollectStrategy) shouldn't be persisted. Because anyhow if a change on this setting change the set of devices that should receive it, then is_session_overshared_for_user will detect it and rotate the session.

history_visibility is different because you want to rotate if you decide that this session could be shared now as part of history sharing for example, event if it doesn't change right now who get the key

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really following all of this. It sounds like we shouldn't be persisting EncryptionSettings at all to me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you change the rotation_period you would want the session to be rotated immediatly instead of having to wait for the old one to be rotated based on the old rotation period. Same for history_visibility, you want to make history sharable from the point you change to that setting and not make early history available?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both of those things sound like we should be taking notice of the current EncryptionSettings, not whatever was persisted to the store.

/// Whitelisted devices will receive group sessions regardless of their
/// verification status.
pub fn is_whitelisted(&self) -> bool {
self.local_trust_state() == LocalTrust::Ignored
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeahh, this feels pretty confusing to me, and could do with clean up.

That said: "whitelisted"/"blacklisted" are somewhat problematic terms, and we might take the opportunity to rename both.

@richvdh richvdh marked this pull request as draft August 12, 2024 11:04
@richvdh richvdh force-pushed the valere/invisible_crypto/error_on_unsigned_device_of_verified_user branch 2 times, most recently from fbc66d6 to e1ad36f Compare August 13, 2024 16:53
Comment on lines +671 to +672
/// Should fail to send when a verified user has unverified devices.
pub error_on_verified_user_problem: bool,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a slightly rubbish name; ultimately I want to use it for both unverified devices (#3792) and verified users that become unverified (#3793).

@richvdh richvdh force-pushed the valere/invisible_crypto/error_on_unsigned_device_of_verified_user branch from e1ad36f to 37329ea Compare August 13, 2024 17:23
@richvdh richvdh marked this pull request as ready for review August 14, 2024 09:32
Copy link
Member

@bnjbvr bnjbvr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On request, I've just skimmed the PR and looked at Rust idioms. I've got some small suggestions to improve readability of the code, which I think should be addressed; confusing a bool for another could be particularly bad in the context of crypto, IMO. LGTM otherwise!

crates/matrix-sdk-base/src/client.rs Outdated Show resolved Hide resolved
}
match device_identity {
UserIdentityData::Own(_) => {
own_identity.is_verified() && own_identity.is_device_signed(self).is_ok()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

preexisting, and can be done in another PR: having is_device_signed return a Result when all the callers check for is_ok() makes me think it should just return a boolean instead of a Result 👀

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Let's fix that in another PR.

/// * `identity` - The identity of another user which we want to check has
/// been verified.
pub fn is_identity_verified(&self, identity: &OtherUserIdentityData) -> bool {
self.is_verified() && self.is_identity_signed(identity).is_ok()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here for is_identity_signed

crates/matrix-sdk-crypto/src/machine/tests/mod.rs Outdated Show resolved Hide resolved
@richvdh richvdh force-pushed the valere/invisible_crypto/error_on_unsigned_device_of_verified_user branch from ea1d8a2 to 5dbc599 Compare August 14, 2024 12:04
@richvdh richvdh requested a review from bnjbvr August 14, 2024 12:17
Copy link
Member

@bnjbvr bnjbvr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super nice, thanks!

richvdh and others added 11 commits August 14, 2024 14:01
Use a for loop rather than `partition_map`. We're about to add a third list, so
partition_map won't work.

(partition_map ends up using Vec::push under the hood, so this is pretty much
equivalent.)
... and use it to remove a bit of duplicated code.
The list of boolean arguments is confusing. We may as well just construct the
`DeviceBasedStrategy` directly.
Again, the list of boolean arguments is confusing.
Add (as yet unimplemented) `error_on_verified_user_problem` option
This thing was confusing. What is "legacy" about it?
@richvdh richvdh force-pushed the valere/invisible_crypto/error_on_unsigned_device_of_verified_user branch from 38a4477 to 5f24f8e Compare August 14, 2024 13:42
@richvdh richvdh removed the request for review from poljar August 14, 2024 13:54
@richvdh richvdh enabled auto-merge (rebase) August 14, 2024 13:54
@richvdh richvdh merged commit 1e8dd5d into main Aug 14, 2024
40 checks passed
@richvdh richvdh deleted the valere/invisible_crypto/error_on_unsigned_device_of_verified_user branch August 14, 2024 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Element X: Return an error when sharing a room key to a verified user, who has an unverified device
3 participants