matrix_sdk/encryption/identities/
devices.rs

1// Copyright 2021 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{collections::BTreeMap, ops::Deref};
16
17use matrix_sdk_base::crypto::{
18    store::CryptoStoreError, Device as BaseDevice, DeviceData, LocalTrust,
19    UserDevices as BaseUserDevices,
20};
21use ruma::{events::key::verification::VerificationMethod, DeviceId, OwnedDeviceId, OwnedUserId};
22
23use super::ManualVerifyError;
24use crate::{
25    encryption::verification::{SasVerification, VerificationRequest},
26    error::Result,
27    Client,
28};
29
30/// Updates about [`Device`]s which got received over the `/keys/query`
31/// endpoint.
32#[derive(Clone, Debug, Default)]
33pub struct DeviceUpdates {
34    /// The list of newly discovered devices.
35    ///
36    /// A device being in this list does not necessarily mean that the device
37    /// was just created, it just means that it's the first time we're
38    /// seeing this device.
39    pub new: BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceId, Device>>,
40    /// The list of changed devices.
41    pub changed: BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceId, Device>>,
42}
43
44impl DeviceUpdates {
45    pub(crate) fn new(
46        client: Client,
47        updates: matrix_sdk_base::crypto::store::DeviceUpdates,
48    ) -> Self {
49        let map_devices = |(user_id, devices)| {
50            // For some reason we need to tell Rust the type of `devices`.
51            let devices: BTreeMap<_, _> = devices;
52
53            (
54                user_id,
55                devices
56                    .into_iter()
57                    .map(|(device_id, device)| {
58                        (device_id, Device { inner: device, client: client.to_owned() })
59                    })
60                    .collect(),
61            )
62        };
63
64        let new = updates.new.into_iter().map(map_devices).collect();
65        let changed = updates.changed.into_iter().map(map_devices).collect();
66
67        DeviceUpdates { new, changed }
68    }
69}
70
71/// A device represents a E2EE capable client or device of an user.
72///
73/// A `Device` is backed by [device keys] that are uploaded to the server.
74///
75/// The [device keys] for our own device will be automatically uploaded by the
76/// SDK and the private parts of our device keys never leave this device.
77///
78/// Device keys consist of an Ed25519 keypair and a Curve25519 keypair. Only the
79/// public parts of those keypairs will be uploaded to the server.
80///
81/// ```text
82///                 ┌──────────────────────────────────┐
83///                 │              Device              │
84///                 ├──────────────────────────────────┤
85///                 │            Device Keys           │
86///                 ├────────────────┬─────────────────┤
87///                 │   Ed25519 Key  │  Curve25519 Key │
88///                 └────────────────┴─────────────────┘
89/// ```
90///
91/// The Ed25519 key will be used to uniquely identify the `Device` while the
92/// Curve25519 key is used to establish 1-to-1 encrypted communication channels
93/// between two devices.
94///
95/// [device keys]: https://spec.matrix.org/unstable/client-server-api/#device-keys
96#[derive(Clone, Debug)]
97pub struct Device {
98    pub(crate) inner: BaseDevice,
99    pub(crate) client: Client,
100}
101
102impl Deref for Device {
103    type Target = DeviceData;
104
105    fn deref(&self) -> &Self::Target {
106        &self.inner
107    }
108}
109
110impl Device {
111    /// Request an interactive verification with this `Device`.
112    ///
113    /// Returns a [`VerificationRequest`] object that can be used to control the
114    /// verification flow.
115    ///
116    /// The default methods that are supported are `m.sas.v1` and
117    /// `m.qr_code.show.v1`, if this isn't desirable the
118    /// [`request_verification_with_methods()`] method can be used to override
119    /// this. `m.qr_code.show.v1` is only available if the `qrcode` feature is
120    /// enabled, which it is by default.
121    ///
122    /// # Examples
123    ///
124    /// ```no_run
125    /// # use matrix_sdk::{Client, ruma::{device_id, user_id}};
126    /// # use url::Url;
127    /// # async {
128    /// # let alice = user_id!("@alice:example.org");
129    /// # let homeserver = Url::parse("http://example.com")?;
130    /// # let client = Client::new(homeserver).await?;
131    /// let device =
132    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
133    ///
134    /// if let Some(device) = device {
135    ///     let verification = device.request_verification().await?;
136    /// }
137    /// # anyhow::Ok(()) };
138    /// ```
139    ///
140    /// [`request_verification_with_methods()`]:
141    /// #method.request_verification_with_methods
142    pub async fn request_verification(&self) -> Result<VerificationRequest> {
143        let (verification, request) = self.inner.request_verification();
144        self.client.send_verification_request(request).await?;
145
146        Ok(VerificationRequest { inner: verification, client: self.client.clone() })
147    }
148
149    /// Request an interactive verification with this `Device`.
150    ///
151    /// Returns a [`VerificationRequest`] object that can be used to control the
152    /// verification flow.
153    ///
154    /// # Arguments
155    ///
156    /// * `methods` - The verification methods that we want to support. Must be
157    ///   non-empty.
158    ///
159    /// # Panics
160    ///
161    /// This method will panic if `methods` is empty.
162    ///
163    /// # Examples
164    ///
165    /// ```no_run
166    /// # use matrix_sdk::{
167    /// #    Client,
168    /// #    ruma::{
169    /// #        device_id, user_id,
170    /// #        events::key::verification::VerificationMethod,
171    /// #    }
172    /// # };
173    /// # use url::Url;
174    /// # async {
175    /// # let alice = user_id!("@alice:example.org");
176    /// # let homeserver = Url::parse("http://example.com")?;
177    /// # let client = Client::new(homeserver).await?;
178    /// let device =
179    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
180    ///
181    /// // We don't want to support showing a QR code, we only support SAS
182    /// // verification
183    /// let methods = vec![VerificationMethod::SasV1];
184    ///
185    /// if let Some(device) = device {
186    ///     let verification =
187    ///         device.request_verification_with_methods(methods).await?;
188    /// }
189    /// # anyhow::Ok(()) };
190    /// ```
191    pub async fn request_verification_with_methods(
192        &self,
193        methods: Vec<VerificationMethod>,
194    ) -> Result<VerificationRequest> {
195        assert!(!methods.is_empty(), "The list of verification methods can't be non-empty");
196
197        let (verification, request) = self.inner.request_verification_with_methods(methods);
198        self.client.send_verification_request(request).await?;
199
200        Ok(VerificationRequest { inner: verification, client: self.client.clone() })
201    }
202
203    /// Start an interactive verification with this [`Device`]
204    ///
205    /// Returns a [`SasVerification`] object that represents the interactive
206    /// verification flow.
207    ///
208    /// This method has been deprecated in the spec and the
209    /// [`request_verification()`] method should be used instead.
210    ///
211    /// # Examples
212    ///
213    /// ```no_run
214    /// # use matrix_sdk::{Client, ruma::{device_id, user_id}};
215    /// # use url::Url;
216    /// # async {
217    /// # let alice = user_id!("@alice:example.org");
218    /// # let homeserver = Url::parse("http://example.com")?;
219    /// # let client = Client::new(homeserver).await?;
220    /// let device =
221    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
222    ///
223    /// if let Some(device) = device {
224    ///     let verification = device.start_verification().await?;
225    /// }
226    /// # anyhow::Ok(()) };
227    /// ```
228    ///
229    /// [`request_verification()`]: #method.request_verification
230    #[deprecated(
231        since = "0.4.0",
232        note = "directly starting a verification is deprecated in the spec. \
233                Users should instead use request_verification()"
234    )]
235    pub async fn start_verification(&self) -> Result<SasVerification> {
236        let (sas, request) = self.inner.start_verification().await?;
237        self.client.send_to_device(&request).await?;
238
239        Ok(SasVerification { inner: sas, client: self.client.clone() })
240    }
241
242    /// Manually verify this device.
243    ///
244    /// This method will attempt to sign the device using our private cross
245    /// signing key.
246    ///
247    /// This method will always fail if the device belongs to someone else, we
248    /// can only sign our own devices.
249    ///
250    /// It can also fail if we don't have the private part of our self-signing
251    /// key.
252    ///
253    /// The state of our private cross signing keys can be inspected using the
254    /// [`Encryption::cross_signing_status()`] method.
255    ///
256    /// [`Encryption::cross_signing_status()`]: crate::encryption::Encryption::cross_signing_status
257    ///
258    /// ### Problems of manual verification
259    ///
260    /// Manual verification may be more convenient to use, i.e. both devices
261    /// need to be online and available to interactively verify each other.
262    /// Despite the convenience, interactive verifications should be
263    /// generally preferred. Manually verifying a device won't notify the
264    /// other device, the one being verified, that they should also verify
265    /// us. This means that device `A` will consider device `B` to be
266    /// verified, but not the other way around.
267    ///
268    /// # Examples
269    ///
270    /// ```no_run
271    /// # use matrix_sdk::{
272    /// #    Client,
273    /// #    ruma::{
274    /// #        device_id, user_id,
275    /// #        events::key::verification::VerificationMethod,
276    /// #    }
277    /// # };
278    /// # use url::Url;
279    /// # async {
280    /// # let alice = user_id!("@alice:example.org");
281    /// # let homeserver = Url::parse("http://example.com")?;
282    /// # let client = Client::new(homeserver).await?;
283    /// let device =
284    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
285    ///
286    /// if let Some(device) = device {
287    ///     device.verify().await?;
288    /// }
289    /// # anyhow::Ok(()) };
290    /// ```
291    pub async fn verify(&self) -> Result<(), ManualVerifyError> {
292        let request = self.inner.verify().await?;
293        self.client.send(request).await?;
294
295        Ok(())
296    }
297
298    /// Is the device considered to be verified.
299    ///
300    /// A device is considered to be verified, either if it's locally marked as
301    /// such, or if it's signed by the appropriate cross signing key. Our own
302    /// device, is always implicitly verified.
303    ///
304    /// ## Local trust
305    ///
306    /// Local trust can be established using the [`Device::set_local_trust()`]
307    /// method or it will be established if we interactively verify the device
308    /// using [`Device::request_verification()`].
309    ///
310    /// **Note**: The concept of local trust is largely deprecated because it
311    /// can't be shared with other devices. Every device needs to verify all the
312    /// other devices it communicates to. Because this becomes quickly
313    /// unsustainable verification has migrated to cross signing verification.
314    ///
315    /// ## Cross signing verification
316    ///
317    /// Cross signing verification uses signatures over devices and user
318    /// identities to check if a device is considered to be verified. The
319    /// signatures can be uploaded to the homeserver, this allows us to
320    /// share the verification state with other devices. Devices only need to
321    /// verify a user identity, if the user identity has verified and signed
322    /// the device we can consider the device to be verified as well.
323    ///
324    /// Devices are usually cross signing verified using interactive
325    /// verification, which can be started using the
326    /// [`Device::request_verification()`] method.
327    ///
328    /// A [`Device`] can also be manually signed using the [`Device::verify()`]
329    /// method, this works only for devices belonging to our own user.
330    ///
331    /// Do note that the device that is being manually signed will not trust our
332    /// own user identity like it would if we interactively verify the device.
333    /// Such a device can mark our own user as verified using the
334    /// [`UserIdentity::verify()`] method.
335    ///
336    /// ### Verification of devices belonging to our own user.
337    ///
338    /// If the device belongs to our own user, the device will be considered to
339    /// be verified if:
340    ///
341    /// * The device has been signed by our self-signing key
342    /// * Our own user identity is considered to be [verified]
343    ///
344    /// In other words we need to find a valid signature chain from our user
345    /// identity to the device:
346    ///
347    ///```text
348    ///         ┌─────────────────────────────────────┐    ┌─────────────┐
349    ///         │           Own User Identity         │    │   Device    │
350    ///         ├──────────────────┬──────────────────┤───►├─────────────┤
351    ///         │    Master Key    │ Self-signing Key │    │ Device Keys │
352    ///         └──────────────────┴──────────────────┘    └─────────────┘
353    /// ```
354    ///
355    /// ### Verification of devices belonging to other users.
356    ///
357    /// If the device belongs to some other user it will be considered to be
358    /// verified if:
359    ///
360    /// * The device has been signed by the user's self-signing key
361    /// * The user's master-signing key has been signed by our own user-signing
362    ///   key, i.e. our own identity trusts the other users identity.
363    /// * Our own user identity is considered to be [verified]
364    ///
365    /// ```text
366    ///             ┌─────────────────────────────────────┐
367    ///             │           Own User Identity         │
368    ///             ├──────────────────┬──────────────────┤─────┐
369    ///             │    Master Key    │ User-signing Key │     │
370    ///             └──────────────────┴──────────────────┘     │
371    ///     ┌───────────────────────────────────────────────────┘
372    ///     │
373    ///     │       ┌─────────────────────────────────────┐    ┌─────────────┐
374    ///     │       │             User Identity           │    │   Device    │
375    ///     └──────►├──────────────────┬──────────────────┤───►│─────────────│
376    ///             │    Master Key    │ Self-signing Key │    │ Device Keys │
377    ///             └──────────────────┴──────────────────┘    └─────────────┘
378    /// ```
379    ///
380    /// # Examples
381    ///
382    /// Let's check if a device is verified:
383    ///
384    /// ```no_run
385    /// # use matrix_sdk::{
386    /// #    Client,
387    /// #    ruma::{
388    /// #        device_id, user_id,
389    /// #        events::key::verification::VerificationMethod,
390    /// #    }
391    /// # };
392    /// # use url::Url;
393    /// # async {
394    /// # let alice = user_id!("@alice:example.org");
395    /// # let homeserver = Url::parse("http://example.com")?;
396    /// # let client = Client::new(homeserver).await?;
397    /// let device =
398    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
399    ///
400    /// if let Some(device) = device {
401    ///     if device.is_verified() {
402    ///         println!(
403    ///             "Device {} of user {} is verified",
404    ///             device.device_id(),
405    ///             device.user_id(),
406    ///         );
407    ///     } else {
408    ///         println!(
409    ///             "Device {} of user {} is not verified",
410    ///             device.device_id(),
411    ///             device.user_id(),
412    ///         );
413    ///     }
414    /// }
415    /// # anyhow::Ok(()) };
416    /// ```
417    ///
418    /// [`UserIdentity::verify()`]:
419    /// crate::encryption::identities::UserIdentity::verify
420    /// [verified]: crate::encryption::identities::UserIdentity::is_verified
421    pub fn is_verified(&self) -> bool {
422        self.inner.is_verified()
423    }
424
425    /// Is the device considered to be verified with cross-signing.
426    ///
427    /// A device is considered to be verified if it's signed by the appropriate
428    /// cross-signing key.
429    ///
430    /// ## Cross-signing verification
431    ///
432    /// Cross-signing verification uses signatures over devices and user
433    /// identities to check if a device is considered to be verified. The
434    /// signatures can be uploaded to the homeserver, this allows us to
435    /// share the verification state with other devices. Devices only need to
436    /// verify a user identity, if the user identity has verified and signed
437    /// the device we can consider the device to be verified as well.
438    ///
439    /// Devices are usually cross-signing verified using interactive
440    /// verification, which can be started using the
441    /// [`Device::request_verification()`] method.
442    ///
443    /// A [`Device`] can also be manually signed using the [`Device::verify()`]
444    /// method, this works only for devices belonging to our own user.
445    ///
446    /// Do note that the device that is being manually signed will not trust our
447    /// own user identity like it would if we interactively verify the device.
448    /// Such a device can mark our own user as verified using the
449    /// [`UserIdentity::verify()`] method.
450    ///
451    /// ### Verification of devices belonging to our own user.
452    ///
453    /// If the device belongs to our own user, the device will be considered to
454    /// be verified if:
455    ///
456    /// * The device has been signed by our self-signing key
457    /// * Our own user identity is considered to be [verified]
458    ///
459    /// In other words we need to find a valid signature chain from our user
460    /// identity to the device:
461    ///
462    ///```text
463    ///         ┌─────────────────────────────────────┐    ┌─────────────┐
464    ///         │           Own User Identity         │    │   Device    │
465    ///         ├──────────────────┬──────────────────┤───►├─────────────┤
466    ///         │    Master Key    │ Self-signing Key │    │ Device Keys │
467    ///         └──────────────────┴──────────────────┘    └─────────────┘
468    /// ```
469    ///
470    /// ### Verification of devices belonging to other users.
471    ///
472    /// If the device belongs to some other user it will be considered to be
473    /// verified if:
474    ///
475    /// * The device has been signed by the user's self-signing key
476    /// * The user's master-signing key has been signed by our own user-signing
477    ///   key, i.e. our own identity trusts the other users identity.
478    /// * Our own user identity is considered to be [verified]
479    ///
480    /// ```text
481    ///             ┌─────────────────────────────────────┐
482    ///             │           Own User Identity         │
483    ///             ├──────────────────┬──────────────────┤─────┐
484    ///             │    Master Key    │ User-signing Key │     │
485    ///             └──────────────────┴──────────────────┘     │
486    ///     ┌───────────────────────────────────────────────────┘
487    ///     │
488    ///     │       ┌─────────────────────────────────────┐    ┌─────────────┐
489    ///     │       │             User Identity           │    │   Device    │
490    ///     └──────►├──────────────────┬──────────────────┤───►│─────────────│
491    ///             │    Master Key    │ Self-signing Key │    │ Device Keys │
492    ///             └──────────────────┴──────────────────┘    └─────────────┘
493    /// ```
494    ///
495    /// # Examples
496    ///
497    /// Let's check if a device is verified:
498    ///
499    /// ```no_run
500    /// # use matrix_sdk::{
501    /// #    Client,
502    /// #    ruma::{
503    /// #        device_id, user_id,
504    /// #        events::key::verification::VerificationMethod,
505    /// #    }
506    /// # };
507    /// # use url::Url;
508    /// # async {
509    /// # let alice = user_id!("@alice:example.org");
510    /// # let homeserver = Url::parse("http://example.com")?;
511    /// # let client = Client::new(homeserver).await?;
512    /// let device =
513    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
514    ///
515    /// if let Some(device) = device {
516    ///     if device.is_verified_with_cross_signing() {
517    ///         println!(
518    ///             "Device {} of user {} is verified with cross-signing",
519    ///             device.device_id(),
520    ///             device.user_id()
521    ///         );
522    ///     } else {
523    ///         println!(
524    ///             "Device {} of user {} is not verified with cross-signing",
525    ///             device.device_id(),
526    ///             device.user_id()
527    ///         );
528    ///     }
529    /// }
530    /// # anyhow::Ok(()) };
531    /// ```
532    ///
533    /// [`UserIdentity::verify()`]:
534    /// crate::encryption::identities::UserIdentity::verify
535    /// [verified]: crate::encryption::identities::UserIdentity::is_verified
536    pub fn is_verified_with_cross_signing(&self) -> bool {
537        self.inner.is_cross_signing_trusted()
538    }
539
540    /// Set the local trust state of the device to the given state.
541    ///
542    /// This won't affect any cross signing verification state, this only sets
543    /// a flag marking to have the given trust state.
544    ///
545    /// # Arguments
546    ///
547    /// * `trust_state` - The new trust state that should be set for the device.
548    pub async fn set_local_trust(&self, trust_state: LocalTrust) -> Result<(), CryptoStoreError> {
549        self.inner.set_local_trust(trust_state).await
550    }
551
552    /// Is the device cross-signed by its own user.
553    pub fn is_cross_signed_by_owner(&self) -> bool {
554        self.inner.is_cross_signed_by_owner()
555    }
556}
557
558/// The collection of all the [`Device`]s a user has.
559#[derive(Debug)]
560pub struct UserDevices {
561    pub(crate) inner: BaseUserDevices,
562    pub(crate) client: Client,
563}
564
565impl UserDevices {
566    /// Get the specific device with the given device ID.
567    pub fn get(&self, device_id: &DeviceId) -> Option<Device> {
568        self.inner.get(device_id).map(|d| Device { inner: d, client: self.client.clone() })
569    }
570
571    /// Iterator over all the device ids of the user devices.
572    pub fn keys(&self) -> impl Iterator<Item = &DeviceId> {
573        self.inner.keys()
574    }
575
576    /// Iterator over all the devices of the user devices.
577    pub fn devices(&self) -> impl Iterator<Item = Device> + '_ {
578        let client = self.client.clone();
579
580        self.inner.devices().map(move |d| Device { inner: d, client: client.clone() })
581    }
582}