Skip to content

Commit

Permalink
Support receiving own proposals without an error
Browse files Browse the repository at this point in the history
  • Loading branch information
mulmarta committed May 2, 2024
1 parent 3662e44 commit cdf63d3
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 102 deletions.
3 changes: 3 additions & 0 deletions mls-rs-uniffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ pub enum ReceivedMessage {
proposal: Arc<Proposal>,
},

/// A proposal previously sent by this member was received.
OwnProposal,
/// Validated GroupInfo object.
GroupInfo,
/// Validated welcome message.
Expand Down Expand Up @@ -771,6 +773,7 @@ impl Group {
let proposal = Arc::new(proposal_message.proposal.into());
Ok(ReceivedMessage::ReceivedProposal { sender, proposal })
}
group::ReceivedMessage::OwnProposal => Ok(ReceivedMessage::OwnProposal),
// TODO: group::ReceivedMessage::GroupInfo does not have any
// public methods (unless the "ffi" Cargo feature is set).
// So perhaps we don't need it?
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 @@ -587,7 +588,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
36 changes: 36 additions & 0 deletions mls-rs/src/group/message_hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use core::fmt::Debug;

use core::fmt;
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)]
#[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("CommitHash")
.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)
}
}
2 changes: 2 additions & 0 deletions mls-rs/src/group/message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ pub enum ReceivedMessage {
Commit(CommitMessageDescription),
/// A proposal was received.
Proposal(ProposalMessageDescription),
/// A proposal previously sent by this member was received.
OwnProposal,
/// Validated GroupInfo object
GroupInfo(GroupInfo),
/// Validated welcome message
Expand Down
36 changes: 1 addition & 35 deletions mls-rs/src/group/message_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ pub(crate) async fn verify_plaintext_authentication<P: CipherSuiteProvider>(
cipher_suite_provider: &P,
plaintext: PublicMessage,
key_schedule: Option<&KeySchedule>,
self_index: Option<LeafIndex>,
state: &GroupState,
) -> Result<AuthenticatedContent, MlsError> {
let tag = plaintext.membership_tag.clone();
Expand All @@ -52,7 +51,7 @@ pub(crate) async fn verify_plaintext_authentication<P: CipherSuiteProvider>(

// Verify the membership tag if needed
match &auth_content.content.sender {
Sender::Member(index) => {
Sender::Member(_) => {
if let Some(key_schedule) = key_schedule {
let expected_tag = &key_schedule
.get_membership_tag(&auth_content, context, cipher_suite_provider)
Expand All @@ -64,10 +63,6 @@ pub(crate) async fn verify_plaintext_authentication<P: CipherSuiteProvider>(
return Err(MlsError::InvalidMembershipTag);
}
}

if self_index == Some(LeafIndex(*index)) {
return Err(MlsError::CantProcessMessageFromSelf);
}
}
_ => {
tag.is_none()
Expand Down Expand Up @@ -333,7 +328,6 @@ mod tests {
&env.bob.group.cipher_suite_provider,
message,
Some(&env.bob.group.key_schedule),
None,
&env.bob.group.state,
)
.await
Expand Down Expand Up @@ -381,7 +375,6 @@ mod tests {
&env.bob.group.cipher_suite_provider,
message,
Some(&env.bob.group.key_schedule),
None,
&env.bob.group.state,
)
.await;
Expand All @@ -399,7 +392,6 @@ mod tests {
&env.bob.group.cipher_suite_provider,
message,
Some(&env.bob.group.key_schedule),
None,
&env.bob.group.state,
)
.await;
Expand All @@ -417,7 +409,6 @@ mod tests {
&env.bob.group.cipher_suite_provider,
message,
Some(&env.bob.group.key_schedule),
None,
&env.bob.group.state,
)
.await;
Expand Down Expand Up @@ -485,7 +476,6 @@ mod tests {
&test_group.group.cipher_suite_provider,
message,
Some(&test_group.group.key_schedule),
None,
&test_group.group.state,
)
.await
Expand All @@ -506,7 +496,6 @@ mod tests {
&test_group.group.cipher_suite_provider,
message,
Some(&test_group.group.key_schedule),
None,
&test_group.group.state,
)
.await;
Expand All @@ -532,7 +521,6 @@ mod tests {
&test_group.group.cipher_suite_provider,
message,
Some(&test_group.group.key_schedule),
None,
&test_group.group.state,
)
.await;
Expand All @@ -556,7 +544,6 @@ mod tests {
&test_group.group.cipher_suite_provider,
message,
Some(&test_group.group.key_schedule),
None,
&test_group.group.state,
)
.await;
Expand Down Expand Up @@ -601,7 +588,6 @@ mod tests {
&test_group.group.cipher_suite_provider,
message,
Some(&test_group.group.key_schedule),
None,
&test_group.group.state,
)
.await
Expand All @@ -625,7 +611,6 @@ mod tests {
&test_group.group.cipher_suite_provider,
message,
Some(&test_group.group.key_schedule),
None,
&test_group.group.state,
)
.await;
Expand All @@ -652,29 +637,10 @@ mod tests {
&test_group.group.cipher_suite_provider,
message,
Some(&test_group.group.key_schedule),
None,
&test_group.group.state,
)
.await;

assert_matches!(res, Err(MlsError::MembershipTagForNonMember));
}

#[maybe_async::test(not(mls_build_async), async(mls_build_async, crate::futures_test))]
async fn plaintext_from_self_fails_verification() {
let mut env = TestEnv::new().await;

let message = make_signed_plaintext(&mut env.alice.group).await;

let res = verify_plaintext_authentication(
&env.alice.group.cipher_suite_provider,
message,
Some(&env.alice.group.key_schedule),
Some(LeafIndex::new(env.alice.group.current_member_index())),
&env.alice.group.state,
)
.await;

assert_matches!(res, Err(MlsError::CantProcessMessageFromSelf))
}
}
Loading

0 comments on commit cdf63d3

Please sign in to comment.