Skip to main content

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    Device as BaseDevice, DeviceData, LocalTrust, UserDevices as BaseUserDevices,
19    store::CryptoStoreError,
20};
21use ruma::{DeviceId, OwnedDeviceId, OwnedUserId, events::key::verification::VerificationMethod};
22
23use super::ManualVerifyError;
24use crate::{
25    Client,
26    encryption::verification::{SasVerification, VerificationRequest},
27    error::Result,
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 seeing
38    /// 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::types::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()`]: #method.request_verification_with_methods
141    pub async fn request_verification(&self) -> Result<VerificationRequest> {
142        let (verification, request) = self.inner.request_verification();
143        self.client.send_verification_request(request).await?;
144
145        Ok(VerificationRequest { inner: verification, client: self.client.clone() })
146    }
147
148    /// Request an interactive verification with this `Device`.
149    ///
150    /// Returns a [`VerificationRequest`] object that can be used to control the
151    /// verification flow.
152    ///
153    /// # Arguments
154    ///
155    /// - `methods` - The verification methods that we want to support. Must be
156    ///   non-empty.
157    ///
158    /// # Panics
159    ///
160    /// This method will panic if `methods` is empty.
161    ///
162    /// # Examples
163    ///
164    /// ```no_run
165    /// # use matrix_sdk::{
166    /// #    Client,
167    /// #    ruma::{
168    /// #        device_id, user_id,
169    /// #        events::key::verification::VerificationMethod,
170    /// #    }
171    /// # };
172    /// # use url::Url;
173    /// # async {
174    /// # let alice = user_id!("@alice:example.org");
175    /// # let homeserver = Url::parse("http://example.com")?;
176    /// # let client = Client::new(homeserver).await?;
177    /// let device =
178    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
179    ///
180    /// // We don't want to support showing a QR code, we only support SAS
181    /// // verification
182    /// let methods = vec![VerificationMethod::SasV1];
183    ///
184    /// if let Some(device) = device {
185    ///     let verification =
186    ///         device.request_verification_with_methods(methods).await?;
187    /// }
188    /// # anyhow::Ok(()) };
189    /// ```
190    pub async fn request_verification_with_methods(
191        &self,
192        methods: Vec<VerificationMethod>,
193    ) -> Result<VerificationRequest> {
194        assert!(!methods.is_empty(), "The list of verification methods can't be non-empty");
195
196        let (verification, request) = self.inner.request_verification_with_methods(methods);
197        self.client.send_verification_request(request).await?;
198
199        Ok(VerificationRequest { inner: verification, client: self.client.clone() })
200    }
201
202    /// Start an interactive verification with this [`Device`]
203    ///
204    /// Returns a [`SasVerification`] object that represents the interactive
205    /// verification flow.
206    ///
207    /// This method has been deprecated in the spec and the
208    /// [`request_verification()`] method should be used instead.
209    ///
210    /// # Examples
211    ///
212    /// ```no_run
213    /// # use matrix_sdk::{Client, ruma::{device_id, user_id}};
214    /// # use url::Url;
215    /// # async {
216    /// # let alice = user_id!("@alice:example.org");
217    /// # let homeserver = Url::parse("http://example.com")?;
218    /// # let client = Client::new(homeserver).await?;
219    /// let device =
220    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
221    ///
222    /// if let Some(device) = device {
223    ///     let verification = device.start_verification().await?;
224    /// }
225    /// # anyhow::Ok(()) };
226    /// ```
227    ///
228    /// [`request_verification()`]: #method.request_verification
229    #[deprecated(
230        since = "0.4.0",
231        note = "directly starting a verification is deprecated in the spec. \
232                Users should instead use request_verification()"
233    )]
234    pub async fn start_verification(&self) -> Result<SasVerification> {
235        let (sas, request) = self.inner.start_verification().await?;
236        self.client.send_to_device(&request).await?;
237
238        Ok(SasVerification { inner: Box::new(sas), client: self.client.clone() })
239    }
240
241    /// Manually verify this device.
242    ///
243    /// This method will attempt to sign the device using our private cross
244    /// signing key.
245    ///
246    /// This method will always fail if the device belongs to someone else, we
247    /// can only sign our own devices.
248    ///
249    /// It can also fail if we don't have the private part of our self-signing
250    /// key.
251    ///
252    /// The state of our private cross signing keys can be inspected using the
253    /// [`Encryption::cross_signing_status()`] method.
254    ///
255    /// [`Encryption::cross_signing_status()`]: crate::encryption::Encryption::cross_signing_status
256    ///
257    /// ### Problems of manual verification
258    ///
259    /// Manual verification may be more convenient to use, i.e. both devices
260    /// need to be online and available to interactively verify each other.
261    /// Despite the convenience, interactive verifications should be generally
262    /// preferred. Manually verifying a device won't notify the other device,
263    /// the one being verified, that they should also verify us. This means that
264    /// device `A` will consider device `B` to be verified, but not the other
265    /// way around.
266    ///
267    /// # Examples
268    ///
269    /// ```no_run
270    /// # use matrix_sdk::{
271    /// #    Client,
272    /// #    ruma::{
273    /// #        device_id, user_id,
274    /// #        events::key::verification::VerificationMethod,
275    /// #    }
276    /// # };
277    /// # use url::Url;
278    /// # async {
279    /// # let alice = user_id!("@alice:example.org");
280    /// # let homeserver = Url::parse("http://example.com")?;
281    /// # let client = Client::new(homeserver).await?;
282    /// let device =
283    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
284    ///
285    /// if let Some(device) = device {
286    ///     device.verify().await?;
287    /// }
288    /// # anyhow::Ok(()) };
289    /// ```
290    pub async fn verify(&self) -> Result<(), ManualVerifyError> {
291        let request = self.inner.verify().await?;
292        self.client.send(request).await?;
293
294        Ok(())
295    }
296
297    /// Is the device considered to be verified.
298    ///
299    /// A device is considered to be verified, either if it's locally marked as
300    /// such, or if it's signed by the appropriate cross signing key. Our own
301    /// device, is always implicitly verified.
302    ///
303    /// ## Local trust
304    ///
305    /// Local trust can be established using the [`Device::set_local_trust()`]
306    /// method or it will be established if we interactively verify the device
307    /// using [`Device::request_verification()`].
308    ///
309    /// **Note**: The concept of local trust is largely deprecated because it
310    /// can't be shared with other devices. Every device needs to verify all the
311    /// other devices it communicates to. Because this becomes quickly
312    /// unsustainable verification has migrated to cross signing verification.
313    ///
314    /// ## Cross signing verification
315    ///
316    /// Cross signing verification uses signatures over devices and user
317    /// identities to check if a device is considered to be verified. The
318    /// signatures can be uploaded to the homeserver, this allows us to share
319    /// the verification state with other devices. Devices only need to verify a
320    /// user identity, if the user identity has verified and signed the device
321    /// we can consider the device to be verified as well.
322    ///
323    /// Devices are usually cross signing verified using interactive
324    /// verification, which can be started using the
325    /// [`Device::request_verification()`] method.
326    ///
327    /// A [`Device`] can also be manually signed using the [`Device::verify()`]
328    /// method, this works only for devices belonging to our own user.
329    ///
330    /// Do note that the device that is being manually signed will not trust our
331    /// own user identity like it would if we interactively verify the device.
332    /// Such a device can mark our own user as verified using the
333    /// [`UserIdentity::verify()`] method.
334    ///
335    /// ### Verification of devices belonging to our own user
336    ///
337    /// If the device belongs to our own user, the device will be considered to
338    /// be verified if:
339    ///
340    /// - The device has been signed by our self-signing key
341    /// - Our own user identity is considered to be [verified]
342    ///
343    /// In other words we need to find a valid signature chain from our user
344    /// identity to the device:
345    ///
346    /// ```text
347    ///         ┌─────────────────────────────────────┐    ┌─────────────┐
348    ///         │           Own User Identity         │    │   Device    │
349    ///         ├──────────────────┬──────────────────┤───►├─────────────┤
350    ///         │    Master Key    │ Self-signing Key │    │ Device Keys │
351    ///         └──────────────────┴──────────────────┘    └─────────────┘
352    /// ```
353    ///
354    /// ### Verification of devices belonging to other users
355    ///
356    /// If the device belongs to some other user it will be considered to be
357    /// verified if:
358    ///
359    /// - The device has been signed by the user's self-signing key
360    /// - The user's master-signing key has been signed by our own user-signing
361    ///   key, i.e. our own identity trusts the other users identity.
362    /// - Our own user identity is considered to be [verified]
363    ///
364    /// ```text
365    ///             ┌─────────────────────────────────────┐
366    ///             │           Own User Identity         │
367    ///             ├──────────────────┬──────────────────┤─────┐
368    ///             │    Master Key    │ User-signing Key │     │
369    ///             └──────────────────┴──────────────────┘     │
370    ///     ┌───────────────────────────────────────────────────┘
371    ///     │
372    ///     │       ┌─────────────────────────────────────┐    ┌─────────────┐
373    ///     │       │             User Identity           │    │   Device    │
374    ///     └──────►├──────────────────┬──────────────────┤───►│─────────────│
375    ///             │    Master Key    │ Self-signing Key │    │ Device Keys │
376    ///             └──────────────────┴──────────────────┘    └─────────────┘
377    /// ```
378    ///
379    /// # Examples
380    ///
381    /// Let's check if a device is verified:
382    ///
383    /// ```no_run
384    /// # use matrix_sdk::{
385    /// #    Client,
386    /// #    ruma::{
387    /// #        device_id, user_id,
388    /// #        events::key::verification::VerificationMethod,
389    /// #    }
390    /// # };
391    /// # use url::Url;
392    /// # async {
393    /// # let alice = user_id!("@alice:example.org");
394    /// # let homeserver = Url::parse("http://example.com")?;
395    /// # let client = Client::new(homeserver).await?;
396    /// let device =
397    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
398    ///
399    /// if let Some(device) = device {
400    ///     if device.is_verified() {
401    ///         println!(
402    ///             "Device {} of user {} is verified",
403    ///             device.device_id(),
404    ///             device.user_id(),
405    ///         );
406    ///     } else {
407    ///         println!(
408    ///             "Device {} of user {} is not verified",
409    ///             device.device_id(),
410    ///             device.user_id(),
411    ///         );
412    ///     }
413    /// }
414    /// # anyhow::Ok(()) };
415    /// ```
416    ///
417    /// [`UserIdentity::verify()`]:
418    /// crate::encryption::identities::UserIdentity::verify
419    /// [verified]: crate::encryption::identities::UserIdentity::is_verified
420    pub fn is_verified(&self) -> bool {
421        self.inner.is_verified()
422    }
423
424    /// Is the device considered to be verified with cross-signing.
425    ///
426    /// A device is considered to be verified if it's signed by the appropriate
427    /// cross-signing key.
428    ///
429    /// ## Cross-signing verification
430    ///
431    /// Cross-signing verification uses signatures over devices and user
432    /// identities to check if a device is considered to be verified. The
433    /// signatures can be uploaded to the homeserver, this allows us to share
434    /// the verification state with other devices. Devices only need to verify a
435    /// user identity, if the user identity has verified and signed the device
436    /// we can consider the device to be verified as well.
437    ///
438    /// Devices are usually cross-signing verified using interactive
439    /// verification, which can be started using the
440    /// [`Device::request_verification()`] method.
441    ///
442    /// A [`Device`] can also be manually signed using the [`Device::verify()`]
443    /// method, this works only for devices belonging to our own user.
444    ///
445    /// Do note that the device that is being manually signed will not trust our
446    /// own user identity like it would if we interactively verify the device.
447    /// Such a device can mark our own user as verified using the
448    /// [`UserIdentity::verify()`] method.
449    ///
450    /// ### Verification of devices belonging to our own user
451    ///
452    /// If the device belongs to our own user, the device will be considered to
453    /// be verified if:
454    ///
455    /// - The device has been signed by our self-signing key
456    /// - Our own user identity is considered to be [verified]
457    ///
458    /// In other words we need to find a valid signature chain from our user
459    /// identity to the device:
460    ///
461    /// ```text
462    ///         ┌─────────────────────────────────────┐    ┌─────────────┐
463    ///         │           Own User Identity         │    │   Device    │
464    ///         ├──────────────────┬──────────────────┤───►├─────────────┤
465    ///         │    Master Key    │ Self-signing Key │    │ Device Keys │
466    ///         └──────────────────┴──────────────────┘    └─────────────┘
467    /// ```
468    ///
469    /// ### Verification of devices belonging to other users
470    ///
471    /// If the device belongs to some other user it will be considered to be
472    /// verified if:
473    ///
474    /// - The device has been signed by the user's self-signing key
475    /// - The user's master-signing key has been signed by our own user-signing
476    ///   key, i.e. our own identity trusts the other users identity.
477    /// - Our own user identity is considered to be [verified]
478    ///
479    /// ```text
480    ///             ┌─────────────────────────────────────┐
481    ///             │           Own User Identity         │
482    ///             ├──────────────────┬──────────────────┤─────┐
483    ///             │    Master Key    │ User-signing Key │     │
484    ///             └──────────────────┴──────────────────┘     │
485    ///     ┌───────────────────────────────────────────────────┘
486    ///     │
487    ///     │       ┌─────────────────────────────────────┐    ┌─────────────┐
488    ///     │       │             User Identity           │    │   Device    │
489    ///     └──────►├──────────────────┬──────────────────┤───►│─────────────│
490    ///             │    Master Key    │ Self-signing Key │    │ Device Keys │
491    ///             └──────────────────┴──────────────────┘    └─────────────┘
492    /// ```
493    ///
494    /// # Examples
495    ///
496    /// Let's check if a device is verified:
497    ///
498    /// ```no_run
499    /// # use matrix_sdk::{
500    /// #    Client,
501    /// #    ruma::{
502    /// #        device_id, user_id,
503    /// #        events::key::verification::VerificationMethod,
504    /// #    }
505    /// # };
506    /// # use url::Url;
507    /// # async {
508    /// # let alice = user_id!("@alice:example.org");
509    /// # let homeserver = Url::parse("http://example.com")?;
510    /// # let client = Client::new(homeserver).await?;
511    /// let device =
512    ///     client.encryption().get_device(alice, device_id!("DEVICEID")).await?;
513    ///
514    /// if let Some(device) = device {
515    ///     if device.is_verified_with_cross_signing() {
516    ///         println!(
517    ///             "Device {} of user {} is verified with cross-signing",
518    ///             device.device_id(),
519    ///             device.user_id()
520    ///         );
521    ///     } else {
522    ///         println!(
523    ///             "Device {} of user {} is not verified with cross-signing",
524    ///             device.device_id(),
525    ///             device.user_id()
526    ///         );
527    ///     }
528    /// }
529    /// # anyhow::Ok(()) };
530    /// ```
531    ///
532    /// [`UserIdentity::verify()`]:
533    /// crate::encryption::identities::UserIdentity::verify
534    /// [verified]: crate::encryption::identities::UserIdentity::is_verified
535    pub fn is_verified_with_cross_signing(&self) -> bool {
536        self.inner.is_cross_signing_trusted()
537    }
538
539    /// Set the local trust state of the device to the given state.
540    ///
541    /// This won't affect any cross signing verification state, this only sets a
542    /// flag marking to have the given trust state.
543    ///
544    /// # Arguments
545    ///
546    /// - `trust_state` - The new trust state that should be set for the device.
547    pub async fn set_local_trust(&self, trust_state: LocalTrust) -> Result<(), CryptoStoreError> {
548        self.inner.set_local_trust(trust_state).await
549    }
550
551    /// Is the device cross-signed by its own user.
552    pub fn is_cross_signed_by_owner(&self) -> bool {
553        self.inner.is_cross_signed_by_owner()
554    }
555}
556
557/// The collection of all the [`Device`]s a user has.
558#[derive(Debug)]
559pub struct UserDevices {
560    pub(crate) inner: BaseUserDevices,
561    pub(crate) client: Client,
562}
563
564impl UserDevices {
565    /// Get the specific device with the given device ID.
566    pub fn get(&self, device_id: &DeviceId) -> Option<Device> {
567        self.inner.get(device_id).map(|d| Device { inner: d, client: self.client.clone() })
568    }
569
570    /// Iterator over all the device ids of the user devices.
571    pub fn keys(&self) -> impl Iterator<Item = &DeviceId> {
572        self.inner.keys()
573    }
574
575    /// Iterator over all the devices of the user devices.
576    pub fn devices(&self) -> impl Iterator<Item = Device> + '_ {
577        let client = self.client.clone();
578
579        self.inner.devices().map(move |d| Device { inner: d, client: client.clone() })
580    }
581}