Skip to content

Commit

Permalink
Support receiving own proposals without an error (#154)
Browse files Browse the repository at this point in the history
* Support receiving own proposals without an error

* Fixup

* Apply suggestions from code review

Co-authored-by: Stephane Raux <[email protected]>

* Rebase on main and unify received proposal

* Fixup

* Remove unused field

* Remove unused enum variant

---------

Co-authored-by: mulmarta <[email protected]>
Co-authored-by: Stephane Raux <[email protected]>
  • Loading branch information
3 people authored Jun 14, 2024
1 parent 73be4cb commit 9b55525
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 133 deletions.
1 change: 0 additions & 1 deletion mls-rs-uniffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@ pub enum ReceivedMessage {
sender: Arc<SigningIdentity>,
proposal: Arc<Proposal>,
},

/// Validated GroupInfo object.
GroupInfo,
/// Validated welcome message.
Expand Down
16 changes: 8 additions & 8 deletions mls-rs/src/external_client/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,22 +450,23 @@ impl<C: ExternalClientConfig + Clone> ExternalGroup<C> {
)
.await?;

self.state.proposals.insert(
ProposalRef::from_content(&self.cipher_suite_provider, &auth_content).await?,
proposal,
sender,
);
let proposal_ref =
ProposalRef::from_content(&self.cipher_suite_provider, &auth_content).await?;

let plaintext = PublicMessage {
content: auth_content.content,
auth: auth_content.auth,
membership_tag: None,
};

Ok(MlsMessage::new(
let message = MlsMessage::new(
self.group_context().version(),
MlsMessagePayload::Plain(plaintext),
))
);

self.state.proposals.insert(proposal_ref, proposal, sender);

Ok(message)
}

/// Delete all sent and received proposals cached for commit.
Expand Down Expand Up @@ -582,7 +583,6 @@ where
&self.cipher_suite_provider,
message,
None,
None,
&self.state,
)
.await?;
Expand Down
41 changes: 5 additions & 36 deletions mls-rs/src/group/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@

use alloc::vec;
use alloc::vec::Vec;
use core::fmt::{self, Debug};
use core::fmt::Debug;
use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
use mls_rs_core::{
crypto::{CipherSuiteProvider, SignatureSecretKey},
error::IntoAnyError,
};
use mls_rs_core::{crypto::SignatureSecretKey, error::IntoAnyError};

use crate::{
cipher_suite::CipherSuite,
Expand Down Expand Up @@ -43,6 +40,7 @@ use super::{
confirmation_tag::ConfirmationTag,
framing::{Content, MlsMessage, MlsMessagePayload, Sender},
key_schedule::{KeySchedule, WelcomeSecret},
message_hash::MessageHash,
message_processor::{path_update_required, MessageProcessor},
message_signature::AuthenticatedContent,
mls_rules::CommitDirection,
Expand Down Expand Up @@ -71,36 +69,7 @@ pub(super) struct CommitGeneration {
pub content: AuthenticatedContent,
pub pending_private_tree: TreeKemPrivate,
pub pending_commit_secret: PathSecret,
pub commit_message_hash: CommitHash,
}

#[derive(Clone, PartialEq, MlsEncode, MlsDecode, MlsSize)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub(crate) struct CommitHash(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "mls_rs_core::vec_serde"))]
Vec<u8>,
);

impl Debug for CommitHash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
mls_rs_core::debug::pretty_bytes(&self.0)
.named("CommitHash")
.fmt(f)
}
}

impl CommitHash {
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
pub(crate) async fn compute<CS: CipherSuiteProvider>(
cs: &CS,
commit: &MlsMessage,
) -> Result<Self, MlsError> {
cs.hash(&commit.mls_encode_to_vec()?)
.await
.map_err(|e| MlsError::CryptoProviderError(e.into_any_error()))
.map(Self)
}
pub commit_message_hash: MessageHash,
}

#[cfg_attr(
Expand Down Expand Up @@ -760,7 +729,7 @@ where
content: auth_content,
pending_private_tree: provisional_private_tree,
pending_commit_secret: commit_secret,
commit_message_hash: CommitHash::compute(&self.cipher_suite_provider, &commit_message)
commit_message_hash: MessageHash::compute(&self.cipher_suite_provider, &commit_message)
.await?,
};

Expand Down
4 changes: 1 addition & 3 deletions mls-rs/src/group/external_commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,7 @@ impl<C: ClientConfig> ExternalCommitBuilder<C> {
};

let auth_content = AuthenticatedContent::from(plaintext.clone());

verify_plaintext_authentication(&cipher_suite, plaintext, None, None, &group.state)
.await?;
verify_plaintext_authentication(&cipher_suite, plaintext, None, &group.state).await?;

group
.process_event_or_content(EventOrContent::Content(auth_content), true, None)
Expand Down
37 changes: 37 additions & 0 deletions mls-rs/src/group/message_hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use alloc::vec::Vec;
use core::fmt;
use core::fmt::Debug;

use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
use mls_rs_core::crypto::CipherSuiteProvider;

use crate::{client::MlsError, error::IntoAnyError, MlsMessage};

#[derive(Clone, PartialEq, Eq, MlsEncode, MlsDecode, MlsSize, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub(crate) struct MessageHash(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "mls_rs_core::vec_serde"))]
Vec<u8>,
);

impl Debug for MessageHash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
mls_rs_core::debug::pretty_bytes(&self.0)
.named("MessageHash")
.fmt(f)
}
}

impl MessageHash {
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
pub(crate) async fn compute<CS: CipherSuiteProvider>(
cs: &CS,
message: &MlsMessage,
) -> Result<Self, MlsError> {
cs.hash(&message.mls_encode_to_vec()?)
.await
.map_err(|e| MlsError::CryptoProviderError(e.into_any_error()))
.map(Self)
}
}
53 changes: 33 additions & 20 deletions mls-rs/src/group/message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use crate::{
},
CipherSuiteProvider, KeyPackage,
};
use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};

#[cfg(mls_build_async)]
use alloc::boxed::Box;
use alloc::vec::Vec;
Expand Down Expand Up @@ -68,9 +70,6 @@ use super::proposal::CustomProposal;
#[cfg(feature = "private_message")]
use crate::group::framing::PrivateMessage;

#[cfg(feature = "by_ref_proposal")]
use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};

#[derive(Debug)]
pub(crate) struct ProvisionalState {
pub(crate) public_tree: TreeKemPublic,
Expand Down Expand Up @@ -300,16 +299,18 @@ impl Debug for CommitMessageDescription {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, MlsEncode, MlsDecode, MlsSize)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
/// Proposal sender type.
pub enum ProposalSender {
/// A current member of the group by index in the group state.
Member(u32),
Member(u32) = 1u8,
/// An external entity by index within an
/// [`ExternalSendersExt`](crate::extension::built_in::ExternalSendersExt).
External(u32),
External(u32) = 2u8,
/// A new member proposing their addition to the group.
NewMember,
NewMember = 3u8,
}

impl TryFrom<Sender> for ProposalSender {
Expand All @@ -332,7 +333,8 @@ impl TryFrom<Sender> for ProposalSender {
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[derive(Clone)]
#[derive(Clone, MlsEncode, MlsDecode, MlsSize, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
/// Description of a processed MLS proposal message.
pub struct ProposalMessageDescription {
Expand Down Expand Up @@ -401,6 +403,20 @@ impl ProposalMessageDescription {
pub fn proposal_ref(&self) -> Vec<u8> {
self.proposal_ref.to_vec()
}

#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
pub(crate) async fn new<C: CipherSuiteProvider>(
cs: &C,
content: &AuthenticatedContent,
proposal: Proposal,
) -> Result<Self, MlsError> {
Ok(ProposalMessageDescription {
authenticated_data: content.content.authenticated_data.clone(),
proposal,
sender: content.content.sender.try_into()?,
proposal_ref: ProposalRef::from_content(cs, content).await?,
})
}
}

#[cfg(not(feature = "by_ref_proposal"))]
Expand Down Expand Up @@ -587,27 +603,24 @@ pub(crate) trait MessageProcessor: Send + Sync {
proposal: &Proposal,
cache_proposal: bool,
) -> Result<ProposalMessageDescription, MlsError> {
let proposal_ref =
ProposalRef::from_content(self.cipher_suite_provider(), auth_content).await?;
let proposal = ProposalMessageDescription::new(
self.cipher_suite_provider(),
auth_content,
proposal.clone(),
)
.await?;

let group_state = self.group_state_mut();

if cache_proposal {
let proposal_ref = proposal_ref.clone();

group_state.proposals.insert(
proposal_ref.clone(),
proposal.clone(),
proposal.proposal_ref.clone(),
proposal.proposal.clone(),
auth_content.content.sender,
);
}

Ok(ProposalMessageDescription {
authenticated_data: auth_content.content.authenticated_data.clone(),
proposal: proposal.clone(),
sender: auth_content.content.sender.try_into()?,
proposal_ref,
})
Ok(proposal)
}

#[cfg(feature = "state_update")]
Expand Down
Loading

0 comments on commit 9b55525

Please sign in to comment.