core_crypto/mls/client/
identifier.rs

1use super::CredentialBundle;
2use crate::{
3    prelude::CryptoError,
4    prelude::{CertificateBundle, Client, ClientId, CryptoResult},
5};
6use mls_crypto_provider::MlsCryptoProvider;
7use openmls_traits::types::SignatureScheme;
8use std::collections::{HashMap, HashSet};
9
10/// Used by consumers to initializes a MLS client. Encompasses all the client types available.
11/// Could be enriched later with Verifiable Presentations.
12#[derive(Debug, Clone)]
13pub enum ClientIdentifier {
14    /// Basic keypair
15    Basic(ClientId),
16    /// X509 certificate
17    X509(HashMap<SignatureScheme, CertificateBundle>),
18}
19
20impl ClientIdentifier {
21    /// Extract the unique [ClientId] from an identifier. Use with parsimony as, in case of a x509
22    /// certificate this leads to parsing the certificate
23    pub fn get_id(&self) -> CryptoResult<std::borrow::Cow<ClientId>> {
24        match self {
25            ClientIdentifier::Basic(id) => Ok(std::borrow::Cow::Borrowed(id)),
26            ClientIdentifier::X509(certs) => {
27                // since ClientId has uniqueness constraints, it is the same for all certificates.
28                // hence no need to compute it for every certificate then verify its uniqueness
29                // that's not a getter's job
30                let cert = certs.values().next().ok_or(CryptoError::ImplementationError)?;
31                let id = cert.get_client_id()?;
32                Ok(std::borrow::Cow::Owned(id))
33            }
34        }
35    }
36
37    /// Generate a new CredentialBundle (Credential + KeyPair) for each ciphersuite.
38    /// This method does not persist them in the keystore !
39    pub fn generate_credential_bundles(
40        self,
41        backend: &MlsCryptoProvider,
42        signature_schemes: HashSet<SignatureScheme>,
43    ) -> CryptoResult<Vec<(SignatureScheme, ClientId, CredentialBundle)>> {
44        match self {
45            ClientIdentifier::Basic(id) => signature_schemes.iter().try_fold(
46                Vec::with_capacity(signature_schemes.len()),
47                |mut acc, &sc| -> CryptoResult<_> {
48                    let cb = Client::new_basic_credential_bundle(&id, sc, backend)?;
49                    acc.push((sc, id.clone(), cb));
50                    Ok(acc)
51                },
52            ),
53            ClientIdentifier::X509(certs) => {
54                let cap = certs.len();
55                certs
56                    .into_iter()
57                    .try_fold(Vec::with_capacity(cap), |mut acc, (sc, cert)| -> CryptoResult<_> {
58                        let id = cert.get_client_id()?;
59                        let cb = Client::new_x509_credential_bundle(cert)?;
60                        acc.push((sc, id, cb));
61                        Ok(acc)
62                    })
63            }
64        }
65    }
66}