core_crypto/mls/conversation/immutable/
e2ei.rs1use std::{borrow::Borrow, collections::HashMap};
2
3use openmls_traits::OpenMlsCryptoProvider as _;
4use uuid::Uuid;
5
6use super::{Error, Result};
7use crate::{
8 ClientIdRef, CredentialType, E2eiConversationState, RecursiveError, Session, WireIdentity,
9 ephemeral::is_history_client, mls::credential::ext::CredentialExt as _,
10};
11
12impl super::Conversation {
13 pub async fn e2ei_conversation_state(&self) -> Result<E2eiConversationState> {
16 let backend = &self.session.crypto_provider;
17
18 let state = Session::compute_conversation_state(
19 self.group().await.members_credentials(),
20 CredentialType::X509,
21 backend.authentication_service(),
22 )
23 .await;
24 Ok(state)
25 }
26
27 pub async fn get_device_identities(
35 &self,
36 device_ids: &[impl Borrow<ClientIdRef> + Sync],
37 ) -> Result<Vec<WireIdentity>> {
38 if device_ids.is_empty() {
39 return Err(Error::CallerError(
40 "This function accepts a list of IDs as a parameter, but that list was empty.",
41 ));
42 }
43 let mls_provider = &self.session.crypto_provider;
44 let auth_service = mls_provider.authentication_service();
45
46 let pki_env = auth_service.pki_env().await;
47
48 let mut identities = vec![];
49 for (id, credential) in self.members_with_key().await? {
50 if device_ids.iter().any(|client_id| client_id.borrow() == id.as_slice()) {
51 identities.push(
52 credential
53 .extract_identity(self.cipher_suite().signature_algorithm(), pki_env.as_deref())
54 .await
55 .map_err(RecursiveError::context("extracting identity"))?,
56 );
57 }
58 }
59 Ok(identities)
60 }
61
62 pub async fn get_user_identities(&self, user_ids: &[Uuid]) -> Result<HashMap<Uuid, Vec<WireIdentity>>> {
71 if user_ids.is_empty() {
72 return Err(Error::CallerError(
73 "This function accepts a list of IDs as a parameter, but that list was empty.",
74 ));
75 }
76 let mls_provider = &self.session.crypto_provider;
77 let auth_service = mls_provider.authentication_service();
78
79 let pki_env = auth_service.pki_env().await;
80
81 let mut identities = HashMap::new();
82 for (id, credential) in self.members_with_key().await? {
83 if is_history_client(&id) {
85 continue;
86 }
87
88 let user_id = &id
89 .deserialize()
90 .map_err(RecursiveError::mls_client("deserializing client id"))?
91 .user_id;
92
93 if !user_ids.contains(user_id) {
94 continue;
95 }
96
97 let identity = credential
98 .extract_identity(self.cipher_suite().signature_algorithm(), pki_env.as_deref())
99 .await
100 .map_err(RecursiveError::context("extracting identity"))?;
101 let value = identities.entry(*user_id).or_insert_with(Vec::new);
102 value.push(identity);
103 }
104
105 Ok(identities)
106 }
107}