core_crypto/mls/session/
mod.rs1mod credential;
2pub(crate) mod e2e_identity;
3mod epoch_observer;
4mod error;
5mod history_observer;
6pub(crate) mod id;
7pub(crate) mod key_package;
8pub(crate) mod user_id;
9
10use std::sync::Arc;
11
12use async_lock::{Mutex, RwLock};
13pub use epoch_observer::EpochObserver;
14pub(crate) use error::{Error, Result};
15pub use history_observer::HistoryObserver;
16use openmls_traits::OpenMlsCryptoProvider;
17
18use crate::{
19 ClientId, HistorySecret, ImmutableDatabase, MlsTransport, OpenMlsError, RecursiveError,
20 mls::{
21 conversation::{Conversation, ConversationIdRef},
22 conversation_cache::ConversationCache,
23 },
24 mls_provider::{CryptoProvider, EntropySeed},
25};
26
27#[derive(Clone, derive_more::Debug)]
38pub struct Session {
39 id: ClientId,
40 pub(crate) crypto_provider: CryptoProvider,
41 pub(crate) transport: Arc<dyn MlsTransport + 'static>,
42 database: ImmutableDatabase,
43 #[debug("EpochObserver")]
44 pub(crate) epoch_observer: Arc<RwLock<Option<Arc<dyn EpochObserver + 'static>>>>,
45 #[debug("HistoryObserver")]
46 pub(crate) history_observer: Arc<RwLock<Option<Arc<dyn HistoryObserver + 'static>>>>,
47 pub(crate) conversation_cache: Arc<Mutex<ConversationCache>>,
52}
53
54impl Session {
55 pub fn new(
57 id: ClientId,
58 crypto_provider: CryptoProvider,
59 database: ImmutableDatabase,
60 transport: Arc<dyn MlsTransport>,
61 ) -> Self {
62 Self {
63 id,
64 crypto_provider,
65 transport,
66 database,
67 epoch_observer: Arc::new(RwLock::new(None)),
68 history_observer: Arc::new(RwLock::new(None)),
69 conversation_cache: Arc::new(Mutex::new(ConversationCache::new())),
70 }
71 }
72
73 pub async fn get_raw_conversation(&self, id: &ConversationIdRef) -> Result<Conversation> {
78 Conversation::load(self.clone(), id)
79 .await
80 .map_err(RecursiveError::context("getting raw conversation by id"))?
81 .ok_or_else(|| Error::ConversationNotFound(id.to_owned()))
82 }
83
84 pub async fn conversation_exists(&self, id: &ConversationIdRef) -> Result<bool> {
86 match self.get_raw_conversation(id).await {
87 Ok(_) => Ok(true),
88 Err(Error::ConversationNotFound(_)) => Ok(false),
89 Err(e) => Err(e),
90 }
91 }
92
93 pub fn random_bytes(&self, len: usize) -> crate::Result<Vec<u8>> {
95 use openmls_traits::random::OpenMlsRand as _;
96 self.crypto_provider
97 .rand()
98 .random_vec(len)
99 .map_err(OpenMlsError::wrap("generating random vector"))
100 .map_err(Into::into)
101 }
102
103 pub fn database(&self) -> &ImmutableDatabase {
105 &self.database
106 }
107
108 pub async fn reseed(&self, seed: Option<EntropySeed>) -> crate::Result<()> {
110 self.crypto_provider
111 .reseed(seed)
112 .map_err(OpenMlsError::wrap("reseeding mls backend"))
113 .map_err(Into::into)
114 }
115
116 pub(crate) async fn restore_from_history_secret(&self, history_secret: HistorySecret) -> Result<()> {
118 history_secret
120 .key_package
121 .store(&self.crypto_provider)
122 .await
123 .map_err(OpenMlsError::wrap("storing key package encapsulation"))?;
124
125 Ok(())
126 }
127
128 pub fn id(&self) -> ClientId {
130 self.id.clone()
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use core_crypto_keystore::{entities::*, traits::FetchFromDatabase};
137
138 use super::*;
139 use crate::transaction_context::test_utils::EntitiesCount;
140
141 impl Session {
142 pub async fn count_entities(&self) -> EntitiesCount {
144 let keystore = &self.database;
145 let buffered_commits = keystore.count::<StoredBufferedCommit>().await.unwrap();
146 let credential = keystore.count::<StoredCredential>().await.unwrap();
147 let encryption_keypair = keystore.count::<StoredEncryptionKeyPair>().await.unwrap();
148 let epoch_encryption_keypair = keystore.count::<StoredEpochEncryptionKeypair>().await.unwrap();
149 let group = keystore.count::<PersistedMlsGroup>().await.unwrap();
150 let hpke_private_key = keystore.count::<StoredHpkePrivateKey>().await.unwrap();
151 let key_package = keystore.count::<StoredKeyPackage>().await.unwrap();
152 let pending_group = keystore.count::<PersistedMlsPendingGroup>().await.unwrap();
153 let pending_messages = keystore.count::<MlsPendingMessage>().await.unwrap();
154 let psk_bundle = keystore.count::<StoredPskBundle>().await.unwrap();
155 EntitiesCount {
156 buffered_commits,
157 credential,
158 encryption_keypair,
159 epoch_encryption_keypair,
160 group,
161 hpke_private_key,
162 key_package,
163 pending_group,
164 pending_messages,
165 psk_bundle,
166 }
167 }
168 }
169}