core_crypto/e2e_identity/
identity.rs

1use crate::{
2    e2e_identity::{device_status::DeviceStatus, id::WireQualifiedClientId},
3    prelude::MlsCredentialType,
4};
5use std::str::FromStr;
6use x509_cert::der::pem::LineEnding;
7
8use super::{Error, Result};
9
10/// Represents the identity claims identifying a client
11/// Those claims are verifiable by any member in the group
12#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
13pub struct WireIdentity {
14    /// Unique client identifier e.g. `T4Coy4vdRzianwfOgXpn6A:6add501bacd1d90e@whitehouse.gov`
15    pub client_id: String,
16    /// MLS thumbprint
17    pub thumbprint: String,
18    /// Status of the Credential at the moment T when this object is created
19    pub status: DeviceStatus,
20    /// Indicates whether the credential is Basic or X509
21    pub credential_type: MlsCredentialType,
22    /// In case 'credential_type' is [MlsCredentialType::X509] this is populated
23    pub x509_identity: Option<X509Identity>,
24}
25
26/// Represents the parts of [WireIdentity] that are specific to a X509 certificate (and not a Basic one).
27///
28/// We don't use an enum here since the sole purpose of this is to be exposed through the FFI (and
29/// union types are impossible to carry over the FFI boundary)
30#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
31pub struct X509Identity {
32    /// user handle e.g. `john_wire`
33    pub handle: String,
34    /// Name as displayed in the messaging application e.g. `John Fitzgerald Kennedy`
35    pub display_name: String,
36    /// DNS domain for which this identity proof was generated e.g. `whitehouse.gov`
37    pub domain: String,
38    /// X509 certificate identifying this client in the MLS group ; PEM encoded
39    pub certificate: String,
40    /// X509 certificate serial number
41    pub serial_number: String,
42    /// X509 certificate not before as Unix timestamp
43    pub not_before: u64,
44    /// X509 certificate not after as Unix timestamp
45    pub not_after: u64,
46}
47
48impl<'a> TryFrom<(wire_e2e_identity::prelude::WireIdentity, &'a [u8])> for WireIdentity {
49    type Error = Error;
50
51    fn try_from((i, cert): (wire_e2e_identity::prelude::WireIdentity, &'a [u8])) -> Result<Self> {
52        use x509_cert::der::Decode as _;
53        let document = x509_cert::der::Document::from_der(cert)?;
54        let certificate = document.to_pem("CERTIFICATE", LineEnding::LF)?;
55
56        let client_id = WireQualifiedClientId::from_str(&i.client_id)?;
57
58        Ok(Self {
59            client_id: client_id.try_into()?,
60            status: i.status.into(),
61            thumbprint: i.thumbprint,
62            credential_type: MlsCredentialType::X509,
63            x509_identity: Some(X509Identity {
64                handle: i.handle.to_string(),
65                display_name: i.display_name,
66                domain: i.domain,
67                certificate,
68                serial_number: i.serial_number,
69                not_before: i.not_before,
70                not_after: i.not_after,
71            }),
72        })
73    }
74}