core_crypto/mls/session/
identifier.rs

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