diff --git a/backend/src/ds/add_clients.rs b/backend/src/ds/add_clients.rs index 3489ee5c..81e9d8ee 100644 --- a/backend/src/ds/add_clients.rs +++ b/backend/src/ds/add_clients.rs @@ -25,24 +25,20 @@ use tls_codec::DeserializeBytes; use crate::messages::intra_backend::{DsFanOutMessage, DsFanOutPayload}; -use super::{ - group_state::ClientProfile, - process::{Provider, USER_EXPIRATION_DAYS}, -}; +use super::{group_state::ClientProfile, process::USER_EXPIRATION_DAYS}; use super::group_state::DsGroupState; impl DsGroupState { pub(crate) fn add_clients( &mut self, - provider: &Provider, params: AddClientsParams, group_state_ear_key: &GroupStateEarKey, ) -> Result<(SerializedMlsMessage, Vec), ClientAdditionError> { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.commit) + .process_assisted_message(self.provider.crypto(), params.commit) .map_err(|_| ClientAdditionError::ProcessingError)?; // Perform DS-level validation @@ -127,8 +123,8 @@ impl DsGroupState { // Now we have to update the group state and distribute. // We first accept the message into the group state ... - self.group_mut().accept_processed_message( - provider.storage(), + self.group.accept_processed_message( + self.provider.storage(), processed_assisted_message_plus.processed_assisted_message, Duration::days(USER_EXPIRATION_DAYS), )?; diff --git a/backend/src/ds/add_users.rs b/backend/src/ds/add_users.rs index 808c3fed..b6285844 100644 --- a/backend/src/ds/add_users.rs +++ b/backend/src/ds/add_users.rs @@ -36,17 +36,13 @@ use crate::{ qs::QsConnector, }; -use super::{ - group_state::ClientProfile, - process::{Provider, USER_EXPIRATION_DAYS}, -}; +use super::{group_state::ClientProfile, process::USER_EXPIRATION_DAYS}; use super::group_state::DsGroupState; impl DsGroupState { pub(crate) async fn add_users( &mut self, - provider: &Provider, params: AddUsersParams, group_state_ear_key: &GroupStateEarKey, qs_provider: &Q, @@ -54,7 +50,7 @@ impl DsGroupState { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.commit) + .process_assisted_message(self.provider.crypto(), params.commit) .map_err(|e| { tracing::warn!("Error processing assisted message: {:?}", e); AddUsersError::ProcessingError @@ -219,8 +215,8 @@ impl DsGroupState { // Now we have to update the group state and distribute. // We first accept the message into the group state ... - self.group_mut().accept_processed_message( - provider.storage(), + self.group.accept_processed_message( + self.provider.storage(), processed_assisted_message_plus.processed_assisted_message, Duration::days(USER_EXPIRATION_DAYS), )?; diff --git a/backend/src/ds/delete_group.rs b/backend/src/ds/delete_group.rs index ce6c49be..f0df953c 100644 --- a/backend/src/ds/delete_group.rs +++ b/backend/src/ds/delete_group.rs @@ -10,18 +10,17 @@ use mls_assist::{ }; use phnxtypes::{errors::GroupDeletionError, messages::client_ds::DeleteGroupParams}; -use super::{group_state::DsGroupState, process::Provider}; +use super::group_state::DsGroupState; impl DsGroupState { pub(crate) fn delete_group( &mut self, - provider: &Provider, params: DeleteGroupParams, ) -> Result { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.commit) + .process_assisted_message(self.provider.crypto(), params.commit) .map_err(|_| GroupDeletionError::ProcessingError)?; // Perform DS-level validation diff --git a/backend/src/ds/group_state/mod.rs b/backend/src/ds/group_state/mod.rs index be5d586c..b448c20e 100644 --- a/backend/src/ds/group_state/mod.rs +++ b/backend/src/ds/group_state/mod.rs @@ -5,20 +5,24 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use mls_assist::{ - group::{errors::StorageError as MlsAssistStorageError, Group}, + group::Group, openmls::{ group::GroupId, prelude::{GroupEpoch, LeafNodeIndex, QueuedRemoveProposal, Sender}, treesync::RatchetTree, }, + provider_traits::MlsAssistProvider, + MlsAssistRustCrypto, }; use phnxtypes::{ + codec::PhnxCodec, credentials::EncryptedClientCredential, crypto::{ ear::{ keys::{EncryptedSignatureEarKey, GroupStateEarKey}, Ciphertext, EarDecryptable, EarEncryptable, }, + errors::{DecryptionError, EncryptionError}, signatures::keys::{UserAuthVerifyingKey, UserKeyHash}, }, errors::{CborMlsAssistStorage, UpdateQueueConfigError, ValidationError}, @@ -28,6 +32,7 @@ use phnxtypes::{ }; use serde::{Deserialize, Serialize}; use sqlx::PgExecutor; +use thiserror::Error; use uuid::Uuid; use crate::persistence::StorageError; @@ -52,62 +57,6 @@ pub(super) struct ClientProfile { pub(super) activity_epoch: GroupEpoch, } -#[derive(Serialize, Deserialize)] -pub(super) struct ProposalStore {} - -#[derive(Serialize, Deserialize)] -pub(crate) struct SerializableDsGroupState { - pub(super) group_id: GroupId, - pub(super) serialized_provider: Vec, - pub(super) user_profiles: Vec<(UserKeyHash, UserProfile)>, - pub(super) unmerged_users: Vec>, - pub(super) client_profiles: Vec<(LeafNodeIndex, ClientProfile)>, -} - -impl SerializableDsGroupState { - pub(super) fn from_group_and_provider( - group_state: DsGroupState, - provider: &CborMlsAssistStorage, - ) -> Result> { - let group_id = group_state - .group() - .group_info() - .group_context() - .group_id() - .clone(); - let user_profiles = group_state.user_profiles.into_iter().collect(); - let client_profiles = group_state.client_profiles.into_iter().collect(); - let serialized_provider = provider.serialize()?; - Ok(Self { - group_id, - serialized_provider, - user_profiles, - unmerged_users: group_state.unmerged_users, - client_profiles, - }) - } - - pub(super) fn into_group_state_and_provider( - self, - ) -> Result<(DsGroupState, CborMlsAssistStorage), MlsAssistStorageError> - { - let provider = CborMlsAssistStorage::deserialize(&self.serialized_provider)?; - // We unwrap here, because the constructor ensures that `self` always stores a group - let group = Group::load(&provider, &self.group_id)?.unwrap(); - let user_profiles = self.user_profiles.into_iter().collect(); - let client_profiles = self.client_profiles.into_iter().collect(); - Ok(( - DsGroupState { - group, - user_profiles, - unmerged_users: self.unmerged_users, - client_profiles, - }, - provider, - )) - } -} - /// The `DsGroupState` is the per-group state that the DS persists. /// It is encrypted-at-rest with a roster key. /// @@ -115,6 +64,7 @@ impl SerializableDsGroupState { /// have to store client credentials externally. pub(crate) struct DsGroupState { pub(super) group: Group, + pub(super) provider: MlsAssistRustCrypto, pub(super) user_profiles: HashMap, // Here we keep users that haven't set their user key yet. pub(super) unmerged_users: Vec>, @@ -124,6 +74,7 @@ pub(crate) struct DsGroupState { impl DsGroupState { //#[instrument(level = "trace", skip_all)] pub(crate) fn new( + provider: MlsAssistRustCrypto, group: Group, creator_user_auth_key: UserAuthVerifyingKey, creator_encrypted_client_credential: EncryptedClientCredential, @@ -149,6 +100,7 @@ impl DsGroupState { }; let client_profiles = [(LeafNodeIndex::new(0u32), creator_client_profile)].into(); Self { + provider, group, user_profiles, client_profiles, @@ -280,6 +232,41 @@ impl DsGroupState { } client_information } + + pub(super) fn encrypt( + self, + ear_key: &GroupStateEarKey, + ) -> Result { + let encrypted = + EncryptableDsGroupState::from(SerializableDsGroupState::from_group_state(self)?) + .encrypt(ear_key)?; + Ok(encrypted) + } + + pub(super) fn decrypt( + encrypted_group_state: &EncryptedDsGroupState, + ear_key: &GroupStateEarKey, + ) -> Result { + let encryptable = EncryptableDsGroupState::decrypt(ear_key, encrypted_group_state)?; + let group_state = SerializableDsGroupState::into_group_state(encryptable.into())?; + Ok(group_state) + } +} + +#[derive(Debug, Error)] +pub(super) enum DsGroupStateEncryptionError { + #[error("Error decrypting group state: {0}")] + EncryptionError(#[from] EncryptionError), + #[error("Error deserializing group state: {0}")] + DeserializationError(#[from] phnxtypes::codec::Error), +} + +#[derive(Debug, Error)] +pub(super) enum DsGroupStateDecryptionError { + #[error("Error decrypting group state: {0}")] + DecryptionError(#[from] DecryptionError), + #[error("Error deserializing group state: {0}")] + DeserializationError(#[from] phnxtypes::codec::Error), } #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] @@ -327,5 +314,72 @@ impl AsRef for EncryptedDsGroupState { } } -impl EarEncryptable for SerializableDsGroupState {} -impl EarDecryptable for SerializableDsGroupState {} +#[derive(Serialize, Deserialize)] +pub(crate) struct SerializableDsGroupState { + group_id: GroupId, + serialized_provider: Vec, + user_profiles: Vec<(UserKeyHash, UserProfile)>, + unmerged_users: Vec>, + client_profiles: Vec<(LeafNodeIndex, ClientProfile)>, +} + +impl SerializableDsGroupState { + pub(super) fn from_group_state( + group_state: DsGroupState, + ) -> Result { + let group_id = group_state + .group() + .group_info() + .group_context() + .group_id() + .clone(); + let user_profiles = group_state.user_profiles.into_iter().collect(); + let client_profiles = group_state.client_profiles.into_iter().collect(); + let serialized_provider = group_state.provider.storage().serialize()?; + Ok(Self { + group_id, + serialized_provider, + user_profiles, + unmerged_users: group_state.unmerged_users, + client_profiles, + }) + } + + pub(super) fn into_group_state(self) -> Result { + let storage = CborMlsAssistStorage::deserialize(&self.serialized_provider)?; + // We unwrap here, because the constructor ensures that `self` always stores a group + let group = Group::load(&storage, &self.group_id)?.unwrap(); + let user_profiles = self.user_profiles.into_iter().collect(); + let client_profiles = self.client_profiles.into_iter().collect(); + let provider = MlsAssistRustCrypto::from(storage); + Ok(DsGroupState { + provider, + group, + user_profiles, + unmerged_users: self.unmerged_users, + client_profiles, + }) + } +} + +#[derive(Serialize, Deserialize)] +pub(super) enum EncryptableDsGroupState { + V1(SerializableDsGroupState), +} + +impl From for SerializableDsGroupState { + fn from(encryptable: EncryptableDsGroupState) -> Self { + match encryptable { + EncryptableDsGroupState::V1(serializable) => serializable, + } + } +} + +impl From for EncryptableDsGroupState { + fn from(serializable: SerializableDsGroupState) -> Self { + EncryptableDsGroupState::V1(serializable) + } +} + +impl EarEncryptable for EncryptableDsGroupState {} +impl EarDecryptable for EncryptableDsGroupState {} diff --git a/backend/src/ds/join_connection_group.rs b/backend/src/ds/join_connection_group.rs index 9b7aecff..a7f3faab 100644 --- a/backend/src/ds/join_connection_group.rs +++ b/backend/src/ds/join_connection_group.rs @@ -15,19 +15,18 @@ use tls_codec::DeserializeBytes; use super::{ group_state::{ClientProfile, DsGroupState, UserProfile}, - process::{Provider, USER_EXPIRATION_DAYS}, + process::USER_EXPIRATION_DAYS, }; impl DsGroupState { pub(super) fn join_connection_group( &mut self, - provider: &Provider, params: JoinConnectionGroupParams, ) -> Result { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.external_commit) + .process_assisted_message(self.provider.crypto(), params.external_commit) .map_err(|e| { tracing::warn!( "Processing error: Could not process assisted message: {:?}", @@ -87,8 +86,8 @@ impl DsGroupState { let sender_credential = processed_message.credential().clone(); // Finalize processing. - self.group_mut().accept_processed_message( - provider.storage(), + self.group.accept_processed_message( + self.provider.storage(), processed_assisted_message_plus.processed_assisted_message, Duration::days(USER_EXPIRATION_DAYS), )?; diff --git a/backend/src/ds/join_group.rs b/backend/src/ds/join_group.rs index 6008a758..0295e5c1 100644 --- a/backend/src/ds/join_group.rs +++ b/backend/src/ds/join_group.rs @@ -15,19 +15,18 @@ use tls_codec::DeserializeBytes; use super::{ group_state::{ClientProfile, DsGroupState}, - process::{Provider, USER_EXPIRATION_DAYS}, + process::USER_EXPIRATION_DAYS, }; impl DsGroupState { pub(super) fn join_group( &mut self, - provider: &Provider, params: JoinGroupParams, ) -> Result { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.external_commit) + .process_assisted_message(self.provider.crypto(), params.external_commit) .map_err(|_| JoinGroupError::ProcessingError)?; // Perform DS-level validation @@ -79,8 +78,8 @@ impl DsGroupState { let sender_credential = processed_message.credential().clone(); // Finalize processing. - self.group_mut().accept_processed_message( - provider.storage(), + self.group.accept_processed_message( + self.provider.storage(), processed_assisted_message_plus.processed_assisted_message, Duration::days(USER_EXPIRATION_DAYS), )?; diff --git a/backend/src/ds/process.rs b/backend/src/ds/process.rs index e3ba0aed..0841c9d3 100644 --- a/backend/src/ds/process.rs +++ b/backend/src/ds/process.rs @@ -154,7 +154,6 @@ use mls_assist::{ prelude::{group_info::GroupInfo, GroupId, MlsMessageBodyIn, Sender}, treesync::RatchetTree, }, - provider_traits::MlsAssistProvider, MlsAssistRustCrypto, }; use tls_codec::{TlsSerialize, TlsSize}; @@ -164,7 +163,7 @@ use phnxtypes::{ codec::PhnxCodec, credentials::EncryptedClientCredential, crypto::{ - ear::{keys::EncryptedSignatureEarKey, EarDecryptable, EarEncryptable}, + ear::keys::EncryptedSignatureEarKey, signatures::{keys::LeafVerifyingKeyRef, signable::Verifiable}, }, errors::DsProcessingError, @@ -184,7 +183,7 @@ use crate::{ }; use super::{ - group_state::{DsGroupState, SerializableDsGroupState, StorableDsGroupData}, + group_state::{DsGroupState, StorableDsGroupData}, Ds, }; @@ -234,73 +233,64 @@ impl Ds { // Depending on the message, either load and decrypt an encrypted group state or // create a new one. - let (group_data, mut group_state, provider) = - if let Some(create_group_params) = message.create_group_params() { - let reserved_group_id = self - .claim_reserved_group_id(qgid.group_uuid()) - .await - .ok_or(DsProcessingError::UnreservedGroupId)?; - let CreateGroupParams { - group_id: _, - leaf_node, - encrypted_client_credential, - encrypted_signature_ear_key, - creator_client_reference: creator_queue_config, - creator_user_auth_key, - group_info, - } = create_group_params; - let MlsMessageBodyIn::GroupInfo(group_info) = group_info.clone().extract() else { - return Err(DsProcessingError::InvalidMessage); - }; - let provider = Provider::default(); - let group = Group::new(&provider, group_info.clone(), leaf_node.clone()) - .map_err(|_| DsProcessingError::InvalidMessage)?; - let group_state = DsGroupState::new( - group, - creator_user_auth_key.clone(), - encrypted_client_credential.clone(), - encrypted_signature_ear_key.clone(), - creator_queue_config.clone(), - ); - ( - GroupData::NewGroup(reserved_group_id), - group_state, - provider, - ) - } else { - let group_data = StorableDsGroupData::load(&self.db_pool, &qgid) + let (group_data, mut group_state) = if let Some(create_group_params) = + message.create_group_params() + { + let reserved_group_id = self + .claim_reserved_group_id(qgid.group_uuid()) + .await + .ok_or(DsProcessingError::UnreservedGroupId)?; + let CreateGroupParams { + group_id: _, + leaf_node, + encrypted_client_credential, + encrypted_signature_ear_key, + creator_client_reference: creator_queue_config, + creator_user_auth_key, + group_info, + } = create_group_params; + let MlsMessageBodyIn::GroupInfo(group_info) = group_info.clone().extract() else { + return Err(DsProcessingError::InvalidMessage); + }; + let provider = Provider::default(); + let group = Group::new(&provider, group_info.clone(), leaf_node.clone()) + .map_err(|_| DsProcessingError::InvalidMessage)?; + let group_state = DsGroupState::new( + provider, + group, + creator_user_auth_key.clone(), + encrypted_client_credential.clone(), + encrypted_signature_ear_key.clone(), + creator_queue_config.clone(), + ); + (GroupData::NewGroup(reserved_group_id), group_state) + } else { + let group_data = StorableDsGroupData::load(&self.db_pool, &qgid) + .await + .map_err(|e| { + tracing::warn!("Could not load group state: {:?}", e); + DsProcessingError::StorageError + })? + .ok_or(DsProcessingError::GroupNotFound)?; + + // Check if the group has expired and delete the group if that is the case. + if group_data.has_expired() { + StorableDsGroupData::delete(&self.db_pool, &qgid) .await .map_err(|e| { - tracing::warn!("Could not load group state: {:?}", e); + tracing::warn!("Could not delete expired group state: {:?}", e); DsProcessingError::StorageError - })? - .ok_or(DsProcessingError::GroupNotFound)?; - - // Check if the group has expired and delete the group if that is the case. - if group_data.has_expired() { - StorableDsGroupData::delete(&self.db_pool, &qgid) - .await - .map_err(|e| { - tracing::warn!("Could not delete expired group state: {:?}", e); - DsProcessingError::StorageError - })?; - return Err(DsProcessingError::GroupNotFound); - } + })?; + return Err(DsProcessingError::GroupNotFound); + } - let (group_state, provider) = - SerializableDsGroupState::decrypt(&ear_key, &group_data.encrypted_group_state) - .map_err(|_| DsProcessingError::CouldNotDecrypt)? - .into_group_state_and_provider() - .map_err(|e| { - tracing::error!("Could not deserialize group state: {:?}", e); - DsProcessingError::GroupNotFound - })?; - ( - GroupData::ExistingGroup(group_data), - group_state, - provider.into(), - ) - }; + let group_state = DsGroupState::decrypt(&group_data.encrypted_group_state, &ear_key) + .map_err(|e| { + tracing::error!("Could not decrypt group state: {:?}", e); + DsProcessingError::CouldNotDecrypt + })?; + (GroupData::ExistingGroup(group_data), group_state) + }; // Verify the message. let verified_message: DsRequestParams = match message.sender() { @@ -431,49 +421,48 @@ impl Ds { // needs to fetch the verifying keys from the QS of all added // users. let (group_message, welcome_bundles) = group_state - .add_users(&provider, add_users_params, &ear_key, qs_connector) + .add_users(add_users_params, &ear_key, qs_connector) .await?; prepare_result(group_message, welcome_bundles) } DsRequestParams::RemoveUsers(remove_users_params) => { - let group_message = group_state.remove_users(&provider, remove_users_params)?; + let group_message = group_state.remove_users(remove_users_params)?; prepare_result(group_message, vec![]) } DsRequestParams::UpdateClient(update_client_params) => { - let group_message = group_state.update_client(&provider, update_client_params)?; + let group_message = group_state.update_client(update_client_params)?; prepare_result(group_message, vec![]) } DsRequestParams::AddClients(add_clients_params) => { let (group_message, welcome_bundles) = - group_state.add_clients(&provider, add_clients_params, &ear_key)?; + group_state.add_clients(add_clients_params, &ear_key)?; prepare_result(group_message, welcome_bundles) } DsRequestParams::RemoveClients(remove_clients_params) => { - let group_message = group_state.remove_clients(&provider, remove_clients_params)?; + let group_message = group_state.remove_clients(remove_clients_params)?; prepare_result(group_message, vec![]) } // ======= Externally Committing Endpoints ======= DsRequestParams::JoinGroup(join_group_params) => { - let group_message = group_state.join_group(&provider, join_group_params)?; + let group_message = group_state.join_group(join_group_params)?; prepare_result(group_message, vec![]) } DsRequestParams::JoinConnectionGroup(join_connection_group_params) => { let group_message = - group_state.join_connection_group(&provider, join_connection_group_params)?; + group_state.join_connection_group(join_connection_group_params)?; prepare_result(group_message, vec![]) } DsRequestParams::ResyncClient(resync_client_params) => { - let group_message = group_state.resync_client(&provider, resync_client_params)?; + let group_message = group_state.resync_client(resync_client_params)?; prepare_result(group_message, vec![]) } DsRequestParams::DeleteGroup(delete_group) => { - let group_message = group_state.delete_group(&provider, delete_group)?; + let group_message = group_state.delete_group(delete_group)?; prepare_result(group_message, vec![]) } // ======= Proposal Endpoints ======= DsRequestParams::SelfRemoveClient(self_remove_client_params) => { - let group_message = - group_state.self_remove_client(&provider, self_remove_client_params)?; + let group_message = group_state.self_remove_client(self_remove_client_params)?; prepare_result(group_message, vec![]) } // ======= Sending messages ======= @@ -494,17 +483,10 @@ impl Ds { if group_state_has_changed { // ... before we distribute the message, we encrypt ... - let encrypted_group_state = - SerializableDsGroupState::from_group_and_provider(group_state, provider.storage()) - .map_err(|e| { - tracing::error!("Could not serialize group state: {:?}", e); - DsProcessingError::StorageError - })? - .encrypt(&ear_key) - .map_err(|e| { - tracing::error!("Could not encrypt group state: {:?}", e); - DsProcessingError::CouldNotEncrypt - })?; + let encrypted_group_state = group_state.encrypt(&ear_key).map_err(|e| { + tracing::error!("Could not serialize group state: {:?}", e); + DsProcessingError::CouldNotEncrypt + })?; // ... and store the modified group state. match group_data { diff --git a/backend/src/ds/remove_clients.rs b/backend/src/ds/remove_clients.rs index 84608bba..8993b611 100644 --- a/backend/src/ds/remove_clients.rs +++ b/backend/src/ds/remove_clients.rs @@ -12,20 +12,19 @@ use phnxtypes::{ errors::ClientRemovalError, messages::client_ds::RemoveClientsParams, time::Duration, }; -use super::process::{Provider, USER_EXPIRATION_DAYS}; +use super::process::USER_EXPIRATION_DAYS; use super::group_state::DsGroupState; impl DsGroupState { pub(crate) fn remove_clients( &mut self, - provider: &Provider, params: RemoveClientsParams, ) -> Result { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.commit) + .process_assisted_message(self.provider.crypto(), params.commit) .map_err(|_| ClientRemovalError::ProcessingError)?; // Perform DS-level validation @@ -108,8 +107,8 @@ impl DsGroupState { // Now we have to update the group state and distribute. // We first accept the message into the group state ... - self.group_mut().accept_processed_message( - provider.storage(), + self.group.accept_processed_message( + self.provider.storage(), processed_assisted_message_plus.processed_assisted_message, Duration::days(USER_EXPIRATION_DAYS), )?; diff --git a/backend/src/ds/remove_users.rs b/backend/src/ds/remove_users.rs index 648bf1ce..a5f91cf2 100644 --- a/backend/src/ds/remove_users.rs +++ b/backend/src/ds/remove_users.rs @@ -15,20 +15,19 @@ use phnxtypes::{ messages::client_ds::RemoveUsersParams, time::Duration, }; -use super::process::{Provider, USER_EXPIRATION_DAYS}; +use super::process::USER_EXPIRATION_DAYS; use super::group_state::DsGroupState; impl DsGroupState { pub(crate) fn remove_users( &mut self, - provider: &Provider, params: RemoveUsersParams, ) -> Result { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.commit) + .process_assisted_message(self.provider.crypto(), params.commit) .map_err(|_| UserRemovalError::ProcessingError)?; // Perform DS-level validation @@ -153,8 +152,8 @@ impl DsGroupState { } // We first accept the message into the group state ... - self.group_mut().accept_processed_message( - provider.storage(), + self.group.accept_processed_message( + self.provider.storage(), processed_assisted_message_plus.processed_assisted_message, Duration::days(USER_EXPIRATION_DAYS), )?; diff --git a/backend/src/ds/resync_client.rs b/backend/src/ds/resync_client.rs index 125d3f78..c1905814 100644 --- a/backend/src/ds/resync_client.rs +++ b/backend/src/ds/resync_client.rs @@ -12,20 +12,19 @@ use phnxtypes::{ errors::ResyncClientError, messages::client_ds::ResyncClientParams, time::Duration, }; -use super::process::{Provider, USER_EXPIRATION_DAYS}; +use super::process::USER_EXPIRATION_DAYS; use super::group_state::DsGroupState; impl DsGroupState { pub(crate) fn resync_client( &mut self, - provider: &Provider, params: ResyncClientParams, ) -> Result { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.external_commit) + .process_assisted_message(self.provider.crypto(), params.external_commit) .map_err(|_| ResyncClientError::ProcessingError)?; // Perform DS-level validation @@ -84,8 +83,8 @@ impl DsGroupState { // Now we have to update the group state and distribute. // We just accept the message into the group state. - self.group_mut().accept_processed_message( - provider.storage(), + self.group.accept_processed_message( + self.provider.storage(), processed_assisted_message_plus.processed_assisted_message, Duration::days(USER_EXPIRATION_DAYS), )?; diff --git a/backend/src/ds/self_remove_client.rs b/backend/src/ds/self_remove_client.rs index e25428a9..ce70bd8f 100644 --- a/backend/src/ds/self_remove_client.rs +++ b/backend/src/ds/self_remove_client.rs @@ -12,14 +12,13 @@ use phnxtypes::{ errors::ClientSelfRemovalError, messages::client_ds::SelfRemoveClientParams, time::Duration, }; -use super::process::{Provider, USER_EXPIRATION_DAYS}; +use super::process::USER_EXPIRATION_DAYS; use super::group_state::DsGroupState; impl DsGroupState { pub(crate) fn self_remove_client( &mut self, - provider: &Provider, params: SelfRemoveClientParams, ) -> Result { // Process message (but don't apply it yet). This performs @@ -28,7 +27,7 @@ impl DsGroupState { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.remove_proposal) + .process_assisted_message(self.provider.crypto(), params.remove_proposal) .map_err(|_| ClientSelfRemovalError::ProcessingError)?; // Perform DS-level validation @@ -74,8 +73,8 @@ impl DsGroupState { // Now we have to update the group state and distribute. // We first accept the message into the group state ... - self.group_mut().accept_processed_message( - provider.storage(), + self.group.accept_processed_message( + self.provider.storage(), processed_assisted_message_plus.processed_assisted_message, Duration::days(USER_EXPIRATION_DAYS), )?; diff --git a/backend/src/ds/update_client.rs b/backend/src/ds/update_client.rs index 9a9a93e7..788b9d0e 100644 --- a/backend/src/ds/update_client.rs +++ b/backend/src/ds/update_client.rs @@ -17,19 +17,18 @@ use tls_codec::DeserializeBytes; use super::{ group_state::{DsGroupState, UserProfile}, - process::{Provider, USER_EXPIRATION_DAYS}, + process::USER_EXPIRATION_DAYS, }; impl DsGroupState { pub(super) fn update_client( &mut self, - provider: &Provider, params: UpdateClientParams, ) -> Result { // Process message (but don't apply it yet). This performs mls-assist-level validations. let processed_assisted_message_plus = self .group() - .process_assisted_message(provider.crypto(), params.commit) + .process_assisted_message(self.provider.crypto(), params.commit) .map_err(|_| ClientUpdateError::ProcessingError)?; // Perform DS-level validation @@ -94,8 +93,8 @@ impl DsGroupState { }; // Finalize processing. - self.group_mut().accept_processed_message( - provider.storage(), + self.group.accept_processed_message( + self.provider.storage(), processed_assisted_message_plus.processed_assisted_message, Duration::days(USER_EXPIRATION_DAYS), )?;