From d870e72ec6ad21a4a479e3d28988fc2785ec02b2 Mon Sep 17 00:00:00 2001 From: SimonThormeyer Date: Wed, 19 Jun 2024 18:01:29 +0200 Subject: [PATCH] feat: provide async storage interface --- Cargo.toml | 2 + openmls/Cargo.toml | 3 + openmls/src/group/core_group/mod.rs | 100 +++++++++----- .../core_group/new_from_external_init.rs | 7 +- .../src/group/core_group/new_from_welcome.rs | 6 +- openmls/src/group/core_group/process.rs | 8 +- openmls/src/group/core_group/staged_commit.rs | 13 +- openmls/src/group/public_group/mod.rs | 24 ++-- openmls/src/treesync/node/encryption_keys.rs | 12 +- traits/Cargo.toml | 4 + traits/src/storage.rs | 128 ++++++++++-------- 11 files changed, 189 insertions(+), 118 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 04e824d33e..ecac36c068 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,3 +23,5 @@ tls_codec = { version = "0.4.2-pre.1", features = [ "serde", "mls", ], git = "https://github.com/rustcrypto/formats" } +maybe-async = "0.2.10" +async-trait = "0.1.80" diff --git a/openmls/Cargo.toml b/openmls/Cargo.toml index 17a6daa946..61fc96e7cf 100644 --- a/openmls/Cargo.toml +++ b/openmls/Cargo.toml @@ -36,6 +36,8 @@ openmls_memory_storage = { path = "../memory_storage", features = [ ], optional = true } openmls_test = { path = "../openmls_test", optional = true } openmls_libcrux_crypto = { path = "../libcrux_crypto", optional = true } +maybe-async = {workspace = true} +async-trait = { workspace = true, optional = true } [features] default = ["backtrace"] @@ -60,6 +62,7 @@ js = [ "dep:getrandom", "dep:fluvio-wasm-timer", ] # enable js randomness source for provider +async = ["dep:async-trait", "openmls_traits/async"] [dev-dependencies] backtrace = "0.3" diff --git a/openmls/src/group/core_group/mod.rs b/openmls/src/group/core_group/mod.rs index 28d4c5d3aa..0a24326178 100644 --- a/openmls/src/group/core_group/mod.rs +++ b/openmls/src/group/core_group/mod.rs @@ -187,6 +187,8 @@ pub(crate) struct CoreGroupBuilder { max_past_epochs: usize, } +#[cfg_attr(feature = "async", maybe_async::must_be_async)] +#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)] impl CoreGroupBuilder { /// Create a new [`CoreGroupBuilder`]. pub(crate) fn new( @@ -266,7 +268,7 @@ impl CoreGroupBuilder { /// /// This function performs cryptographic operations and there requires an /// [`OpenMlsProvider`]. - pub(crate) fn build( + pub(crate) async fn build( self, provider: &Provider, signer: &impl Signer, @@ -347,17 +349,21 @@ impl CoreGroupBuilder { // Store the group state group .store(provider.storage()) + .await .map_err(CoreGroupBuildError::StorageError)?; // Store the private key of the own leaf in the key store as an epoch keypair. group .store_epoch_keypairs(provider.storage(), &[leaf_keypair]) + .await .map_err(CoreGroupBuildError::StorageError)?; Ok(group) } } +#[cfg_attr(feature = "async", maybe_async::must_be_async)] +#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)] impl CoreGroup { /// Get a builder for [`CoreGroup`]. pub(crate) fn builder( @@ -488,7 +494,7 @@ impl CoreGroup { } // Create application message - pub(crate) fn create_application_message( + pub(crate) async fn create_application_message( &mut self, aad: &[u8], msg: &[u8], @@ -503,11 +509,11 @@ impl CoreGroup { self.context(), signer, )?; - self.encrypt(public_message, padding_size, provider) + self.encrypt(public_message, padding_size, provider).await } // Encrypt an PublicMessage into an PrivateMessage - pub(crate) fn encrypt( + pub(crate) async fn encrypt( &mut self, public_message: AuthenticatedContent, padding_size: usize, @@ -524,6 +530,7 @@ impl CoreGroup { provider .storage() .write_message_secrets(self.group_id(), &self.message_secrets_store) + .await .map_err(MessageEncryptionError::StorageError)?; Ok(msg) @@ -726,33 +733,43 @@ impl CoreGroup { /// Stores the [`CoreGroup`]. Called from methods creating a new group and mutating an /// existing group, both inside [`CoreGroup`] and in [`MlsGroup`]. - pub(super) fn store( + pub(super) async fn store( &self, storage: &Storage, ) -> Result<(), Storage::Error> { let group_id = self.group_id(); - self.public_group.store(storage)?; - storage.write_own_leaf_index(group_id, &self.own_leaf_index())?; - storage.write_group_epoch_secrets(group_id, &self.group_epoch_secrets)?; - storage.set_use_ratchet_tree_extension(group_id, self.use_ratchet_tree_extension)?; - storage.write_message_secrets(group_id, &self.message_secrets_store)?; - storage.write_resumption_psk_store(group_id, &self.resumption_psk_store)?; + self.public_group.store(storage).await?; + storage + .write_own_leaf_index(group_id, &self.own_leaf_index()) + .await?; + storage + .write_group_epoch_secrets(group_id, &self.group_epoch_secrets) + .await?; + storage + .set_use_ratchet_tree_extension(group_id, self.use_ratchet_tree_extension) + .await?; + storage + .write_message_secrets(group_id, &self.message_secrets_store) + .await?; + storage + .write_resumption_psk_store(group_id, &self.resumption_psk_store) + .await?; Ok(()) } /// Loads a [`CoreGroup`]. Called in [`MlsGroup::load`]. - pub(super) fn load( + pub(super) async fn load( storage: &Storage, group_id: &GroupId, ) -> Result, Storage::Error> { let public_group = PublicGroup::load(storage, group_id)?; - let group_epoch_secrets = storage.group_epoch_secrets(group_id)?; - let own_leaf_index = storage.own_leaf_index(group_id)?; - let use_ratchet_tree_extension = storage.use_ratchet_tree_extension(group_id)?; - let message_secrets_store = storage.message_secrets(group_id)?; - let resumption_psk_store = storage.resumption_psk_store(group_id)?; + let group_epoch_secrets = storage.group_epoch_secrets(group_id).await?; + let own_leaf_index = storage.own_leaf_index(group_id).await?; + let use_ratchet_tree_extension = storage.use_ratchet_tree_extension(group_id).await?; + let message_secrets_store = storage.message_secrets(group_id).await?; + let resumption_psk_store = storage.resumption_psk_store(group_id).await?; let build = || -> Option { Some(Self { @@ -768,16 +785,20 @@ impl CoreGroup { Ok(build()) } - pub(super) fn delete( + pub(super) async fn delete( &self, storage: &Storage, ) -> Result<(), Storage::Error> { self.public_group.delete(storage)?; - storage.delete_own_leaf_index(self.group_id())?; - storage.delete_group_epoch_secrets(self.group_id())?; - storage.delete_use_ratchet_tree_extension(self.group_id())?; - storage.delete_message_secrets(self.group_id())?; - storage.delete_all_resumption_psk_secrets(self.group_id())?; + storage.delete_own_leaf_index(self.group_id()).await?; + storage.delete_group_epoch_secrets(self.group_id()).await?; + storage + .delete_use_ratchet_tree_extension(self.group_id()) + .await?; + storage.delete_message_secrets(self.group_id()).await?; + storage + .delete_all_resumption_psk_secrets(self.group_id()) + .await?; Ok(()) } @@ -786,17 +807,19 @@ impl CoreGroup { /// indexed by this group's [`GroupId`] and [`GroupEpoch`]. /// /// Returns an error if access to the key store fails. - pub(super) fn store_epoch_keypairs( + pub(super) async fn store_epoch_keypairs( &self, store: &Storage, keypair_references: &[EncryptionKeyPair], ) -> Result<(), Storage::Error> { - store.write_encryption_epoch_key_pairs( - self.group_id(), - &self.context().epoch(), - self.own_leaf_index().u32(), - keypair_references, - ) + store + .write_encryption_epoch_key_pairs( + self.group_id(), + &self.context().epoch(), + self.own_leaf_index().u32(), + keypair_references, + ) + .await } /// Read the [`EncryptionKeyPair`]s of this group and its current @@ -804,7 +827,7 @@ impl CoreGroup { /// /// Returns an empty vector if access to the store fails or it can't find /// any keys. - pub(super) fn read_epoch_keypairs( + pub(super) async fn read_epoch_keypairs( &self, store: &Storage, ) -> Vec { @@ -814,6 +837,7 @@ impl CoreGroup { &self.context().epoch(), self.own_leaf_index().u32(), ) + .await .unwrap_or_default() } @@ -821,15 +845,17 @@ impl CoreGroup { /// the `provider`'s key store. /// /// Returns an error if access to the key store fails. - pub(super) fn delete_previous_epoch_keypairs( + pub(super) async fn delete_previous_epoch_keypairs( &self, store: &Storage, ) -> Result<(), Storage::Error> { - store.delete_encryption_epoch_key_pairs( - self.group_id(), - &GroupEpoch::from(self.context().epoch().as_u64() - 1), - self.own_leaf_index().u32(), - ) + store + .delete_encryption_epoch_key_pairs( + self.group_id(), + &GroupEpoch::from(self.context().epoch().as_u64() - 1), + self.own_leaf_index().u32(), + ) + .await } pub(crate) fn create_commit( diff --git a/openmls/src/group/core_group/new_from_external_init.rs b/openmls/src/group/core_group/new_from_external_init.rs index 29a708405f..d3161a3ece 100644 --- a/openmls/src/group/core_group/new_from_external_init.rs +++ b/openmls/src/group/core_group/new_from_external_init.rs @@ -13,6 +13,8 @@ use crate::group::core_group::*; pub(crate) type ExternalCommitResult = (CoreGroup, CreateCommitResult); +#[cfg_attr(feature = "async", maybe_async::must_be_async)] +#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)] impl CoreGroup { /// Join a group without the help of an internal member. This function /// requires a [GroupInfo], as well as the corresponding public tree @@ -25,10 +27,10 @@ impl CoreGroup { /// /// Note: If there is a group member in the group with the same identity as us, /// this will create a remove proposal. - pub(crate) fn join_by_external_commit( + pub(crate) async fn join_by_external_commit( provider: &Provider, signer: &impl Signer, - mut params: CreateCommitParams, + mut params: CreateCommitParams<'_>, ratchet_tree: Option, verifiable_group_info: VerifiableGroupInfo, ) -> Result> { @@ -136,6 +138,7 @@ impl CoreGroup { group .store(provider.storage()) + .await .map_err(ExternalCommitError::StorageError)?; Ok(( diff --git a/openmls/src/group/core_group/new_from_welcome.rs b/openmls/src/group/core_group/new_from_welcome.rs index 7abcb62b87..c4d3ac8548 100644 --- a/openmls/src/group/core_group/new_from_welcome.rs +++ b/openmls/src/group/core_group/new_from_welcome.rs @@ -8,6 +8,8 @@ use crate::{ treesync::errors::{DerivePathError, PublicTreeError}, }; +#[cfg_attr(feature = "async", maybe_async::must_be_async)] +#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)] impl StagedCoreWelcome { /// Create a staged join from a welcome message. The purpose of this type is to be able to /// extract information, such as the identify of who created the welcome, before joining the @@ -57,7 +59,7 @@ impl StagedCoreWelcome { } /// Consumes the [`StagedCoreWelcome`] and returns the respective [`CoreGroup`]. - pub fn into_core_group( + pub async fn into_core_group( self, provider: &Provider, ) -> Result> { @@ -82,9 +84,11 @@ impl StagedCoreWelcome { group .store(provider.storage()) + .await .map_err(WelcomeError::StorageError)?; group .store_epoch_keypairs(provider.storage(), group_keypairs.as_slice()) + .await .map_err(WelcomeError::StorageError)?; Ok(group) diff --git a/openmls/src/group/core_group/process.rs b/openmls/src/group/core_group/process.rs index e203643af5..a2759835de 100644 --- a/openmls/src/group/core_group/process.rs +++ b/openmls/src/group/core_group/process.rs @@ -267,13 +267,13 @@ impl CoreGroup { } /// Helper function to read decryption keypairs. - pub(super) fn read_decryption_keypairs( + pub(super) async fn read_decryption_keypairs( &self, provider: &impl OpenMlsProvider, own_leaf_nodes: &[LeafNode], ) -> Result<(Vec, Vec), StageCommitError> { // All keys from the previous epoch are potential decryption keypairs. - let old_epoch_keypairs = self.read_epoch_keypairs(provider.storage()); + let old_epoch_keypairs = self.read_epoch_keypairs(provider.storage()).await; // If we are processing an update proposal that originally came from // us, the keypair corresponding to the leaf in the update is also a @@ -290,7 +290,7 @@ impl CoreGroup { } /// Merge a [StagedCommit] into the group after inspection - pub(crate) fn merge_staged_commit( + pub(crate) async fn merge_staged_commit( &mut self, provider: &Provider, staged_commit: StagedCommit, @@ -302,7 +302,7 @@ impl CoreGroup { let leaves = self.public_group().members().collect(); // Merge the staged commit into the group state and store the secret tree from the // previous epoch in the message secrets store. - if let Some(message_secrets) = self.merge_commit(provider, staged_commit)? { + if let Some(message_secrets) = self.merge_commit(provider, staged_commit).await? { self.message_secrets_store .add(past_epoch, message_secrets, leaves); } diff --git a/openmls/src/group/core_group/staged_commit.rs b/openmls/src/group/core_group/staged_commit.rs index 534047dbf6..66d1e223a9 100644 --- a/openmls/src/group/core_group/staged_commit.rs +++ b/openmls/src/group/core_group/staged_commit.rs @@ -13,6 +13,8 @@ use crate::{ use openmls_traits::storage::StorageProvider as _; +#[cfg_attr(feature = "async", maybe_async::must_be_async)] +#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)] impl CoreGroup { fn derive_epoch_secrets( &self, @@ -309,19 +311,20 @@ impl CoreGroup { /// /// This function should not fail and only returns a [`Result`], because it /// might throw a `LibraryError`. - pub(crate) fn merge_commit( + pub(crate) async fn merge_commit( &mut self, provider: &Provider, staged_commit: StagedCommit, ) -> Result, MergeCommitError> { // Get all keypairs from the old epoch, so we can later store the ones // that are still relevant in the new epoch. - let old_epoch_keypairs = self.read_epoch_keypairs(provider.storage()); + let old_epoch_keypairs = self.read_epoch_keypairs(provider.storage()).await; match staged_commit.state { StagedCommitState::PublicState(staged_state) => { self.public_group .merge_diff(staged_state.into_staged_diff()); self.store(provider.storage()) + .await .map_err(MergeCommitError::StorageError)?; Ok(None) } @@ -374,24 +377,30 @@ impl CoreGroup { self.public_group .store(storage) + .await .map_err(MergeCommitError::StorageError)?; storage .write_group_epoch_secrets(group_id, &self.group_epoch_secrets) + .await .map_err(MergeCommitError::StorageError)?; storage .write_message_secrets(group_id, &self.message_secrets_store) + .await .map_err(MergeCommitError::StorageError)?; // Store the relevant keys under the new epoch self.store_epoch_keypairs(storage, epoch_keypairs.as_slice()) + .await .map_err(MergeCommitError::StorageError)?; // Delete the old keys. self.delete_previous_epoch_keypairs(storage) + .await .map_err(MergeCommitError::StorageError)?; if let Some(keypair) = state.new_leaf_keypair_option { keypair .delete(storage) + .await .map_err(MergeCommitError::StorageError)?; } diff --git a/openmls/src/group/public_group/mod.rs b/openmls/src/group/public_group/mod.rs index b4ffff0810..a950ea0e92 100644 --- a/openmls/src/group/public_group/mod.rs +++ b/openmls/src/group/public_group/mod.rs @@ -294,6 +294,8 @@ impl PublicGroup { } // Getters +#[cfg_attr(feature = "async", maybe_async::must_be_async)] +#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)] impl PublicGroup { /// Get the ciphersuite. pub fn ciphersuite(&self) -> Ciphersuite { @@ -355,18 +357,24 @@ impl PublicGroup { /// existing group, both inside [`PublicGroup`] and in [`CoreGroup`]. /// /// [`CoreGroup`]: crate::group::core_group::CoreGroup - pub(crate) fn store( + pub(crate) async fn store( &self, storage: &Storage, ) -> Result<(), Storage::Error> { let group_id = self.group_context.group_id(); - storage.write_tree(group_id, self.treesync())?; - storage.write_confirmation_tag(group_id, self.confirmation_tag())?; - storage.write_context(group_id, self.group_context())?; - storage.write_interim_transcript_hash( - group_id, - &InterimTranscriptHash(self.interim_transcript_hash.clone()), - )?; + storage.write_tree(group_id, self.treesync()).await?; + storage + .write_confirmation_tag(group_id, self.confirmation_tag()) + .await?; + storage + .write_context(group_id, self.group_context()) + .await?; + storage + .write_interim_transcript_hash( + group_id, + &InterimTranscriptHash(self.interim_transcript_hash.clone()), + ) + .await?; Ok(()) } diff --git a/openmls/src/treesync/node/encryption_keys.rs b/openmls/src/treesync/node/encryption_keys.rs index 0aab483a4d..9f81117289 100644 --- a/openmls/src/treesync/node/encryption_keys.rs +++ b/openmls/src/treesync/node/encryption_keys.rs @@ -152,11 +152,15 @@ impl EncryptionKeyPair { /// This must only be used for encryption key pairs that are generated for /// update leaf nodes. All other encryption key pairs are stored as part /// of the key package or the epoch encryption key pairs. - pub(crate) fn write( + #[cfg_attr(feature = "async", maybe_async::must_be_async)] + #[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)] + pub(crate) async fn write( &self, store: &Storage, ) -> Result<(), Storage::Error> { - store.write_encryption_key_pair(self.public_key(), self) + store + .write_encryption_key_pair(self.public_key(), self) + .await } /// Read the [`EncryptionKeyPair`] from the key store of the `provider`. This @@ -184,11 +188,11 @@ impl EncryptionKeyPair { /// This must only be used for encryption key pairs that are generated for /// update leaf nodes. All other encryption key pairs are stored as part /// of the key package or the epoch encryption key pairs. - pub(crate) fn delete>( + pub(crate) async fn delete>( &self, store: &Storage, ) -> Result<(), Storage::Error> { - store.delete_encryption_key_pair(self.public_key()) + store.delete_encryption_key_pair(self.public_key()).await } pub(crate) fn public_key(&self) -> &EncryptionKey { diff --git a/traits/Cargo.toml b/traits/Cargo.toml index 440a3d64a0..7fb36dbcbb 100644 --- a/traits/Cargo.toml +++ b/traits/Cargo.toml @@ -15,7 +15,11 @@ path = "src/traits.rs" [features] default = [] test-utils = [] +async = ["dep:async-trait"] [dependencies] serde = { version = "1.0", features = ["derive"] } tls_codec = { workspace = true } +# async +maybe-async = { workspace = true } +async-trait = { workspace = true, optional = true } diff --git a/traits/src/storage.rs b/traits/src/storage.rs index e5aad83e75..3ecb89e8ff 100644 --- a/traits/src/storage.rs +++ b/traits/src/storage.rs @@ -26,6 +26,8 @@ pub const V_TEST: u16 = u16::MAX; /// loading a group. /// /// More details can be taken from the comments on the respective method. +#[cfg_attr(feature = "async", maybe_async::must_be_async)] +#[cfg_attr(not(feature = "async"), maybe_async::must_be_sync)] pub trait StorageProvider { /// An opaque error returned by all methods on this trait. type Error: core::fmt::Debug + std::error::Error + PartialEq; @@ -40,7 +42,7 @@ pub trait StorageProvider { // /// Writes the MlsGroupJoinConfig for the group with given id to storage - fn write_mls_join_config< + async fn write_mls_join_config< GroupId: traits::GroupId, MlsGroupJoinConfig: traits::MlsGroupJoinConfig, >( @@ -50,14 +52,14 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Writes the AAD for the group with given id to storage - fn write_aad>( + async fn write_aad>( &self, group_id: &GroupId, aad: &[u8], ) -> Result<(), Self::Error>; /// Adds an own leaf node for the group with given id to storage - fn append_own_leaf_node< + async fn append_own_leaf_node< GroupId: traits::GroupId, LeafNode: traits::LeafNode, >( @@ -67,7 +69,7 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Clears the own leaf node for the group with given id to storage - fn clear_own_leaf_nodes>( + async fn clear_own_leaf_nodes>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; @@ -76,7 +78,7 @@ pub trait StorageProvider { /// /// A good way to implement this could be to add a proposal to a proposal store, indexed by the /// proposal reference, and adding the reference to a per-group proposal queue list. - fn queue_proposal< + async fn queue_proposal< GroupId: traits::GroupId, ProposalRef: traits::ProposalRef, QueuedProposal: traits::QueuedProposal, @@ -88,14 +90,14 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Write the TreeSync tree. - fn write_tree, TreeSync: traits::TreeSync>( + async fn write_tree, TreeSync: traits::TreeSync>( &self, group_id: &GroupId, tree: &TreeSync, ) -> Result<(), Self::Error>; /// Write the interim transcript hash. - fn write_interim_transcript_hash< + async fn write_interim_transcript_hash< GroupId: traits::GroupId, InterimTranscriptHash: traits::InterimTranscriptHash, >( @@ -105,7 +107,7 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Write the group context. - fn write_context< + async fn write_context< GroupId: traits::GroupId, GroupContext: traits::GroupContext, >( @@ -115,7 +117,7 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Write the confirmation tag. - fn write_confirmation_tag< + async fn write_confirmation_tag< GroupId: traits::GroupId, ConfirmationTag: traits::ConfirmationTag, >( @@ -125,7 +127,7 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Writes the MlsGroupState for group with given id. - fn write_group_state< + async fn write_group_state< GroupState: traits::GroupState, GroupId: traits::GroupId, >( @@ -135,7 +137,7 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Writes the MessageSecretsStore for the group with the given id. - fn write_message_secrets< + async fn write_message_secrets< GroupId: traits::GroupId, MessageSecrets: traits::MessageSecrets, >( @@ -145,7 +147,7 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Writes the ResumptionPskStore for the group with the given id. - fn write_resumption_psk_store< + async fn write_resumption_psk_store< GroupId: traits::GroupId, ResumptionPskStore: traits::ResumptionPskStore, >( @@ -155,7 +157,7 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Writes the own leaf index inside the group for the group with the given id. - fn write_own_leaf_index< + async fn write_own_leaf_index< GroupId: traits::GroupId, LeafNodeIndex: traits::LeafNodeIndex, >( @@ -166,14 +168,14 @@ pub trait StorageProvider { /// Returns the MlsGroupState for group with given id. /// Sets whether to use the RatchetTreeExtension for the group with the given id. - fn set_use_ratchet_tree_extension>( + async fn set_use_ratchet_tree_extension>( &self, group_id: &GroupId, value: bool, ) -> Result<(), Self::Error>; /// Writes the GroupEpochSecrets for the group with the given id. - fn write_group_epoch_secrets< + async fn write_group_epoch_secrets< GroupId: traits::GroupId, GroupEpochSecrets: traits::GroupEpochSecrets, >( @@ -190,7 +192,7 @@ pub trait StorageProvider { /// /// The signature key pair is not known to OpenMLS. This may be used by the /// application - fn write_signature_key_pair< + async fn write_signature_key_pair< SignaturePublicKey: traits::SignaturePublicKey, SignatureKeyPair: traits::SignatureKeyPair, >( @@ -205,7 +207,7 @@ pub trait StorageProvider { /// This is only be used for encryption key pairs that are generated for /// update leaf nodes. All other encryption key pairs are stored as part /// of the key package or the epoch encryption key pairs. - fn write_encryption_key_pair< + async fn write_encryption_key_pair< EncryptionKey: traits::EncryptionKey, HpkeKeyPair: traits::HpkeKeyPair, >( @@ -216,7 +218,7 @@ pub trait StorageProvider { /// Store a list of HPKE encryption key pairs for a given epoch. /// This includes the private and public keys. - fn write_encryption_epoch_key_pairs< + async fn write_encryption_epoch_key_pairs< GroupId: traits::GroupId, EpochKey: traits::EpochKey, HpkeKeyPair: traits::HpkeKeyPair, @@ -237,7 +239,7 @@ pub trait StorageProvider { /// in order to iterate over key packages. OpenMLS does not have a reference /// for them. // ANCHOR: write_key_package - fn write_key_package< + async fn write_key_package< HashReference: traits::HashReference, KeyPackage: traits::KeyPackage, >( @@ -253,7 +255,7 @@ pub trait StorageProvider { /// /// PSKs are only read by OpenMLS. The application is responsible for managing /// and storing PSKs. - fn write_psk, PskBundle: traits::PskBundle>( + async fn write_psk, PskBundle: traits::PskBundle>( &self, psk_id: &PskId, psk: &PskBundle, @@ -264,7 +266,7 @@ pub trait StorageProvider { // /// Returns the MlsGroupJoinConfig for the group with given id - fn mls_group_join_config< + async fn mls_group_join_config< GroupId: traits::GroupId, MlsGroupJoinConfig: traits::MlsGroupJoinConfig, >( @@ -273,20 +275,23 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Returns the own leaf nodes for the group with given id - fn own_leaf_nodes, LeafNode: traits::LeafNode>( + async fn own_leaf_nodes< + GroupId: traits::GroupId, + LeafNode: traits::LeafNode, + >( &self, group_id: &GroupId, ) -> Result, Self::Error>; /// Returns the AAD for the group with given id /// If the value has not been set, returns an empty vector. - fn aad>( + async fn aad>( &self, group_id: &GroupId, ) -> Result, Self::Error>; /// Returns references of all queued proposals for the group with group id `group_id`, or an empty vector of none are stored. - fn queued_proposal_refs< + async fn queued_proposal_refs< GroupId: traits::GroupId, ProposalRef: traits::ProposalRef, >( @@ -295,7 +300,7 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Returns all queued proposals for the group with group id `group_id`, or an empty vector of none are stored. - fn queued_proposals< + async fn queued_proposals< GroupId: traits::GroupId, ProposalRef: traits::ProposalRef, QueuedProposal: traits::QueuedProposal, @@ -305,13 +310,13 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Returns the TreeSync tree for the group with group id `group_id`. - fn treesync, TreeSync: traits::TreeSync>( + async fn treesync, TreeSync: traits::TreeSync>( &self, group_id: &GroupId, ) -> Result, Self::Error>; /// Returns the group context for the group with group id `group_id`. - fn group_context< + async fn group_context< GroupId: traits::GroupId, GroupContext: traits::GroupContext, >( @@ -320,7 +325,7 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Returns the interim transcript hash for the group with group id `group_id`. - fn interim_transcript_hash< + async fn interim_transcript_hash< GroupId: traits::GroupId, InterimTranscriptHash: traits::InterimTranscriptHash, >( @@ -329,7 +334,7 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Returns the confirmation tag for the group with group id `group_id`. - fn confirmation_tag< + async fn confirmation_tag< GroupId: traits::GroupId, ConfirmationTag: traits::ConfirmationTag, >( @@ -338,13 +343,16 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Returns the group state for the group with group id `group_id`. - fn group_state, GroupId: traits::GroupId>( + async fn group_state< + GroupState: traits::GroupState, + GroupId: traits::GroupId, + >( &self, group_id: &GroupId, ) -> Result, Self::Error>; /// Returns the MessageSecretsStore for the group with the given id. - fn message_secrets< + async fn message_secrets< GroupId: traits::GroupId, MessageSecrets: traits::MessageSecrets, >( @@ -356,7 +364,7 @@ pub trait StorageProvider { /// /// Returning `None` here is considered an error because the store is needed /// by OpenMLS when loading a group. - fn resumption_psk_store< + async fn resumption_psk_store< GroupId: traits::GroupId, ResumptionPskStore: traits::ResumptionPskStore, >( @@ -365,7 +373,7 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Returns the own leaf index inside the group for the group with the given id. - fn own_leaf_index< + async fn own_leaf_index< GroupId: traits::GroupId, LeafNodeIndex: traits::LeafNodeIndex, >( @@ -374,13 +382,13 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Returns whether to use the RatchetTreeExtension for the group with the given id. - fn use_ratchet_tree_extension>( + async fn use_ratchet_tree_extension>( &self, group_id: &GroupId, ) -> Result, Self::Error>; /// Returns the GroupEpochSecrets for the group with the given id. - fn group_epoch_secrets< + async fn group_epoch_secrets< GroupId: traits::GroupId, GroupEpochSecrets: traits::GroupEpochSecrets, >( @@ -396,7 +404,7 @@ pub trait StorageProvider { /// /// The signature key pair is not known to OpenMLS. This may be used by the /// application - fn signature_key_pair< + async fn signature_key_pair< SignaturePublicKey: traits::SignaturePublicKey, SignatureKeyPair: traits::SignatureKeyPair, >( @@ -409,7 +417,7 @@ pub trait StorageProvider { /// This is only be used for encryption key pairs that are generated for /// update leaf nodes. All other encryption key pairs are stored as part /// of the key package or the epoch encryption key pairs. - fn encryption_key_pair< + async fn encryption_key_pair< HpkeKeyPair: traits::HpkeKeyPair, EncryptionKey: traits::EncryptionKey, >( @@ -419,7 +427,7 @@ pub trait StorageProvider { /// Get a list of HPKE encryption key pairs for a given epoch. /// This includes the private and public keys. - fn encryption_epoch_key_pairs< + async fn encryption_epoch_key_pairs< GroupId: traits::GroupId, EpochKey: traits::EpochKey, HpkeKeyPair: traits::HpkeKeyPair, @@ -431,7 +439,7 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Get a key package based on its hash reference. - fn key_package< + async fn key_package< KeyPackageRef: traits::HashReference, KeyPackage: traits::KeyPackage, >( @@ -440,7 +448,7 @@ pub trait StorageProvider { ) -> Result, Self::Error>; /// Get a PSK based on the PSK identifier. - fn psk, PskId: traits::PskId>( + async fn psk, PskId: traits::PskId>( &self, psk_id: &PskId, ) -> Result, Self::Error>; @@ -450,7 +458,7 @@ pub trait StorageProvider { // /// Removes an individual proposal from the proposal queue of the group with the provided id - fn remove_proposal< + async fn remove_proposal< GroupId: traits::GroupId, ProposalRef: traits::ProposalRef, >( @@ -460,85 +468,85 @@ pub trait StorageProvider { ) -> Result<(), Self::Error>; /// Deletes the AAD for the given id from storage - fn delete_aad>( + async fn delete_aad>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes own leaf nodes for the given id from storage - fn delete_own_leaf_nodes>( + async fn delete_own_leaf_nodes>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the MlsGroupJoinConfig for the given id from storage - fn delete_group_config>( + async fn delete_group_config>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the tree from storage - fn delete_tree>( + async fn delete_tree>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the confirmation tag from storage - fn delete_confirmation_tag>( + async fn delete_confirmation_tag>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the MlsGroupState for group with given id. - fn delete_group_state>( + async fn delete_group_state>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the group context for the group with given id - fn delete_context>( + async fn delete_context>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the interim transcript hash for the group with given id - fn delete_interim_transcript_hash>( + async fn delete_interim_transcript_hash>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the MessageSecretsStore for the group with the given id. - fn delete_message_secrets>( + async fn delete_message_secrets>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the ResumptionPskStore for the group with the given id. - fn delete_all_resumption_psk_secrets>( + async fn delete_all_resumption_psk_secrets>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the own leaf index inside the group for the group with the given id. - fn delete_own_leaf_index>( + async fn delete_own_leaf_index>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes any preference about whether to use the RatchetTreeExtension for the group with the given id. - fn delete_use_ratchet_tree_extension>( + async fn delete_use_ratchet_tree_extension>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Deletes the GroupEpochSecrets for the group with the given id. - fn delete_group_epoch_secrets>( + async fn delete_group_epoch_secrets>( &self, group_id: &GroupId, ) -> Result<(), Self::Error>; /// Clear the proposal queue for the grou pwith the given id. - fn clear_proposal_queue< + async fn clear_proposal_queue< GroupId: traits::GroupId, ProposalRef: traits::ProposalRef, >( @@ -554,7 +562,7 @@ pub trait StorageProvider { /// /// The signature key pair is not known to OpenMLS. This may be used by the /// application - fn delete_signature_key_pair>( + async fn delete_signature_key_pair>( &self, public_key: &SignaturePublicKey, ) -> Result<(), Self::Error>; @@ -564,14 +572,14 @@ pub trait StorageProvider { /// This is only be used for encryption key pairs that are generated for /// update leaf nodes. All other encryption key pairs are stored as part /// of the key package or the epoch encryption key pairs. - fn delete_encryption_key_pair>( + async fn delete_encryption_key_pair>( &self, public_key: &EncryptionKey, ) -> Result<(), Self::Error>; /// Delete a list of HPKE encryption key pairs for a given epoch. /// This includes the private and public keys. - fn delete_encryption_epoch_key_pairs< + async fn delete_encryption_epoch_key_pairs< GroupId: traits::GroupId, EpochKey: traits::EpochKey, >( @@ -585,13 +593,13 @@ pub trait StorageProvider { /// /// This function only deletes the key package. /// The corresponding encryption keys must be deleted separately. - fn delete_key_package>( + async fn delete_key_package>( &self, hash_ref: &KeyPackageRef, ) -> Result<(), Self::Error>; /// Delete a PSK based on an identifier. - fn delete_psk>( + async fn delete_psk>( &self, psk_id: &PskKey, ) -> Result<(), Self::Error>;