core_crypto/mls/conversation/
welcome.rs

1use 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/// Contains everything client needs to know after decrypting an (encrypted) Welcome message
13#[derive(Debug)]
14pub struct WelcomeBundle {
15    /// MLS Group Id
16    pub id: ConversationId,
17    /// New CRL distribution points that appeared by the introduction of a new credential
18    pub crl_new_distribution_points: NewCrlDistributionPoints,
19}
20
21impl MlsConversation {
22    // ? Do we need to provide the ratchet_tree to the MlsGroup? Does everything crumble down if we can't actually get
23    // it?
24    /// Create the MLS conversation from an MLS Welcome message
25    ///
26    /// # Arguments
27    /// * `welcome` - welcome message to create the group from
28    /// * `config` - group configuration
29    /// * `backend` - the KeyStore to persist the group
30    ///
31    /// # Errors
32    /// Errors can happen from OpenMls or from the KeyStore
33    pub(crate) async fn from_welcome_message(
34        welcome: Welcome,
35        configuration: MlsConversationConfiguration,
36        backend: &MlsCryptoProvider,
37        mls_groups: &mut GroupStore<MlsConversation>,
38    ) -> Result<Self> {
39        let mls_group_config = configuration.as_openmls_default_configuration()?;
40
41        let group = MlsGroup::new_from_welcome(backend, &mls_group_config, welcome, None).await;
42
43        let group = match group {
44            Err(openmls::prelude::WelcomeError::NoMatchingKeyPackage)
45            | Err(openmls::prelude::WelcomeError::NoMatchingEncryptionKey) => return Err(Error::OrphanWelcome),
46            _ => group.map_err(MlsError::wrap("group could not be created from welcome"))?,
47        };
48
49        let id = ConversationId::from(group.group_id().as_slice());
50        let existing_conversation = mls_groups.get_fetch(&id, &backend.keystore(), None).await;
51        let conversation_exists = existing_conversation.ok().flatten().is_some();
52
53        let pending_group = backend.key_store().find::<PersistedMlsPendingGroup>(id.as_ref()).await;
54        let pending_group_exists = pending_group.ok().flatten().is_some();
55
56        if conversation_exists || pending_group_exists {
57            return Err(LeafError::ConversationAlreadyExists(id).into());
58        }
59
60        Self::from_mls_group(group, configuration, backend).await
61    }
62}