core_crypto/mls/conversation/
welcome.rs1use core_crypto_keystore::{connection::FetchFromDatabase, entities::PersistedMlsPendingGroup};
2use mls_crypto_provider::MlsCryptoProvider;
3use openmls::prelude::{MlsGroup, Welcome};
4use openmls_traits::OpenMlsCryptoProvider;
5
6use super::{Error, Result};
7use crate::{
8 ConversationId, LeafError, MlsConversation, MlsConversationConfiguration, MlsError,
9 e2e_identity::NewCrlDistributionPoints, group_store::GroupStore,
10};
11
12#[derive(Debug)]
14pub struct WelcomeBundle {
15 pub id: ConversationId,
17 pub crl_new_distribution_points: NewCrlDistributionPoints,
19}
20
21impl MlsConversation {
22 pub(crate) async fn from_welcome_message(
33 welcome: Welcome,
34 configuration: MlsConversationConfiguration,
35 backend: &MlsCryptoProvider,
36 mls_groups: &mut GroupStore<MlsConversation>,
37 ) -> Result<Self> {
38 let mls_group_config = configuration.as_openmls_default_configuration()?;
39
40 let group = MlsGroup::new_from_welcome(backend, &mls_group_config, welcome, None).await;
41
42 let group = match group {
43 Err(openmls::prelude::WelcomeError::NoMatchingKeyPackage)
44 | Err(openmls::prelude::WelcomeError::NoMatchingEncryptionKey) => return Err(Error::OrphanWelcome),
45 _ => group.map_err(MlsError::wrap("group could not be created from welcome"))?,
46 };
47
48 let id = ConversationId::from(group.group_id().as_slice());
49 let existing_conversation = mls_groups.get_fetch(&id, &backend.keystore(), None).await;
50 let conversation_exists = existing_conversation.ok().flatten().is_some();
51
52 let pending_group = backend.key_store().find::<PersistedMlsPendingGroup>(id.as_ref()).await;
53 let pending_group_exists = pending_group.ok().flatten().is_some();
54
55 if conversation_exists || pending_group_exists {
56 return Err(LeafError::ConversationAlreadyExists(id).into());
57 }
58
59 Self::from_mls_group(group, configuration, backend).await
60 }
61}