use openmls_traits::prelude::openmls_types::Ciphersuite;
use tls_codec::{Deserialize, Serialize};
use crate::{
binary_tree::LeafNodeIndex, framing::*, group::*, key_packages::*, treesync::LeafNodeParameters,
};
use crate::group::tests_and_kats::utils::{
generate_credential_with_key, generate_key_package, CredentialWithKeyAndSigner,
};
struct ValidationTestSetup {
alice_group: MlsGroup,
bob_group: MlsGroup,
_alice_credential: CredentialWithKeyAndSigner,
_bob_credential: CredentialWithKeyAndSigner,
_alice_key_package: KeyPackage,
_bob_key_package: KeyPackage,
}
fn validation_test_setup(
wire_format_policy: WireFormatPolicy,
ciphersuite: Ciphersuite,
alice_provider: &impl crate::storage::OpenMlsProvider,
bob_provider: &impl crate::storage::OpenMlsProvider,
) -> ValidationTestSetup {
let group_id = GroupId::from_slice(b"Test Group");
let alice_credential = generate_credential_with_key(
"Alice".into(),
ciphersuite.signature_algorithm(),
alice_provider,
);
let bob_credential = generate_credential_with_key(
"Bob".into(),
ciphersuite.signature_algorithm(),
bob_provider,
);
let alice_key_package = generate_key_package(
ciphersuite,
Extensions::empty(),
alice_provider,
alice_credential.clone(),
);
let bob_key_package = generate_key_package(
ciphersuite,
Extensions::empty(),
bob_provider,
bob_credential.clone(),
);
let mls_group_create_config = MlsGroupCreateConfig::builder()
.wire_format_policy(wire_format_policy)
.ciphersuite(ciphersuite)
.build();
let mut alice_group = MlsGroup::new_with_group_id(
alice_provider,
&alice_credential.signer,
&mls_group_create_config,
group_id,
alice_credential.credential_with_key.clone(),
)
.expect("An unexpected error occurred.");
let (_message, welcome, _group_info) = alice_group
.add_members(
bob_provider,
&alice_credential.signer,
core::slice::from_ref(bob_key_package.key_package()),
)
.expect("Could not add member.");
alice_group
.merge_pending_commit(alice_provider)
.expect("error merging pending commit");
let welcome: MlsMessageIn = welcome.into();
let welcome = welcome
.into_welcome()
.expect("expected message to be a welcome");
let bob_group = StagedWelcome::new_from_welcome(
bob_provider,
mls_group_create_config.join_config(),
welcome,
Some(alice_group.export_ratchet_tree().into()),
)
.expect("error creating bob's group from welcome")
.into_group(bob_provider)
.expect("error creating bob's group from welcome");
ValidationTestSetup {
alice_group,
bob_group,
_alice_credential: alice_credential,
_bob_credential: bob_credential,
_alice_key_package: alice_key_package.key_package().clone(),
_bob_key_package: bob_key_package.key_package().clone(),
}
}
#[openmls_test::openmls_test]
fn test_valsem002() {
let alice_provider = &Provider::default();
let bob_provider = &Provider::default();
let ValidationTestSetup {
mut alice_group,
mut bob_group,
_alice_credential,
_bob_credential: _,
_alice_key_package: _,
_bob_key_package: _,
} = validation_test_setup(
PURE_PLAINTEXT_WIRE_FORMAT_POLICY,
ciphersuite,
alice_provider,
bob_provider,
);
let (message, _welcome, _group_info) = alice_group
.self_update(
alice_provider,
&_alice_credential.signer,
LeafNodeParameters::default(),
)
.expect("Could not self-update.")
.into_contents();
let serialized_message = message
.tls_serialize_detached()
.expect("Could not serialize message.");
let mut plaintext = MlsMessageIn::tls_deserialize(&mut serialized_message.as_slice())
.expect("Could not deserialize message.")
.into_plaintext()
.expect("Message was not a plaintext.");
let original_message = plaintext.clone();
plaintext.set_group_id(GroupId::from_slice(&[9, 9, 9]));
let message_in = ProtocolMessage::from(plaintext);
let err = bob_group
.process_message(bob_provider, message_in)
.expect_err("Could parse message despite wrong group ID.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::WrongGroupId)
));
bob_group
.process_message(bob_provider, ProtocolMessage::from(original_message))
.expect("Unexpected error.");
}
#[openmls_test::openmls_test]
fn test_valsem003() {
let alice_provider = &Provider::default();
let bob_provider = &Provider::default();
let ValidationTestSetup {
mut alice_group,
mut bob_group,
_alice_credential,
_bob_credential: _,
_alice_key_package: _,
_bob_key_package: _,
} = validation_test_setup(
PURE_PLAINTEXT_WIRE_FORMAT_POLICY,
ciphersuite,
alice_provider,
bob_provider,
);
let (message, _welcome, _group_info) = alice_group
.self_update(
alice_provider,
&_alice_credential.signer,
LeafNodeParameters::default(),
)
.expect("Could not self update.")
.into_contents();
alice_group.merge_pending_commit(alice_provider).unwrap();
alice_group
.merge_pending_commit(alice_provider)
.expect("Could not merge commit.");
let processed_message = bob_group
.process_message(bob_provider, message.into_protocol_message().unwrap())
.expect("Could not process message.");
if let ProcessedMessageContent::StagedCommitMessage(staged_commit) =
processed_message.into_content()
{
bob_group
.merge_staged_commit(bob_provider, *staged_commit)
.expect("Error merging commit.");
} else {
unreachable!("Expected StagedCommit.");
}
let (message, _welcome, _group_info) = alice_group
.self_update(
alice_provider,
&_alice_credential.signer,
LeafNodeParameters::default(),
)
.expect("Could not add member.")
.into_contents();
let current_epoch = alice_group.epoch();
let serialized_message = message.tls_serialize_detached().unwrap();
let mut plaintext = MlsMessageIn::tls_deserialize(&mut serialized_message.as_slice())
.expect("Could not deserialize message.")
.into_plaintext()
.expect("Message was not a plaintext.");
let original_message = plaintext.clone();
plaintext.set_epoch(current_epoch.as_u64() + 1);
let err = bob_group
.process_message(bob_provider, plaintext.clone())
.expect_err("Could parse message despite wrong epoch.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::WrongEpoch)
));
plaintext.set_epoch(current_epoch.as_u64() - 1);
let err = bob_group
.process_message(bob_provider, plaintext)
.expect_err("Could parse message despite wrong epoch.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::WrongEpoch)
));
let processed_msg = bob_group
.process_message(bob_provider, original_message.clone())
.unwrap();
if let ProcessedMessageContent::StagedCommitMessage(staged_commit) =
processed_msg.into_content()
{
bob_group
.merge_staged_commit(bob_provider, *staged_commit)
.unwrap();
} else {
unreachable!();
}
let process_twice = bob_group.process_message(bob_provider, original_message);
assert!(matches!(
process_twice.unwrap_err(),
ProcessMessageError::ValidationError(ValidationError::WrongEpoch)
));
}
#[openmls_test::openmls_test]
fn test_valsem004() {
let alice_provider = &Provider::default();
let bob_provider = &Provider::default();
let ValidationTestSetup {
mut alice_group,
mut bob_group,
_alice_credential,
_bob_credential: _,
_alice_key_package: _,
_bob_key_package: _,
} = validation_test_setup(
PURE_PLAINTEXT_WIRE_FORMAT_POLICY,
ciphersuite,
alice_provider,
bob_provider,
);
let (message, _welcome, _group_info) = alice_group
.self_update(
alice_provider,
&_alice_credential.signer,
LeafNodeParameters::default(),
)
.expect("Could not self-update.")
.into_contents();
let serialized_message = message
.tls_serialize_detached()
.expect("Could not serialize message.");
let mut plaintext = MlsMessageIn::tls_deserialize(&mut serialized_message.as_slice())
.expect("Could not deserialize message.")
.into_plaintext()
.expect("Message was not a plaintext.");
let original_message = plaintext.clone();
let random_sender = Sender::build_member(LeafNodeIndex::new(987));
plaintext.set_sender(random_sender);
plaintext
.set_membership_tag(
alice_provider.crypto(),
ciphersuite,
alice_group.message_secrets().membership_key(),
alice_group.message_secrets().serialized_context(),
)
.expect("Error setting membership tag.");
let message_in = ProtocolMessage::from(plaintext);
let err = bob_group
.process_message(bob_provider, message_in)
.expect_err("Could parse message despite wrong sender.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::UnknownMember)
));
bob_group
.process_message(bob_provider, ProtocolMessage::from(original_message))
.expect("Unexpected error.");
}
#[openmls_test::openmls_test]
fn test_valsem005() {
let alice_provider = &Provider::default();
let bob_provider = &Provider::default();
let ValidationTestSetup {
mut alice_group,
mut bob_group,
_alice_credential,
_bob_credential: _,
_alice_key_package: _,
_bob_key_package: _,
} = validation_test_setup(
PURE_PLAINTEXT_WIRE_FORMAT_POLICY,
ciphersuite,
alice_provider,
bob_provider,
);
let (message, _welcome, _group_info) = alice_group
.self_update(
alice_provider,
&_alice_credential.signer,
LeafNodeParameters::default(),
)
.expect("Could not self-update.")
.into_contents();
let serialized_message = message
.tls_serialize_detached()
.expect("Could not serialize message.");
let mut plaintext = MlsMessageIn::tls_deserialize(&mut serialized_message.as_slice())
.expect("Could not deserialize message.")
.into_plaintext()
.expect("Message was not a plaintext.");
let original_message = plaintext.clone();
plaintext.set_content(FramedContentBody::application(&[1, 2, 3]));
plaintext
.set_membership_tag(
alice_provider.crypto(),
ciphersuite,
alice_group.message_secrets().membership_key(),
alice_group.message_secrets().serialized_context(),
)
.expect("Error setting membership tag.");
let message_in = ProtocolMessage::from(plaintext);
let err = bob_group
.process_message(bob_provider, message_in)
.expect_err("Could parse message despite unencrypted application message.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::UnencryptedApplicationMessage)
));
bob_group
.process_message(bob_provider, ProtocolMessage::from(original_message))
.expect("Unexpected error.");
}
#[openmls_test::openmls_test]
fn test_valsem006() {
let alice_provider = &Provider::default();
let bob_provider = &Provider::default();
let ValidationTestSetup {
mut alice_group,
mut bob_group,
_alice_credential,
_bob_credential: _,
_alice_key_package: _,
_bob_key_package: _,
} = validation_test_setup(
PURE_CIPHERTEXT_WIRE_FORMAT_POLICY,
ciphersuite,
alice_provider,
bob_provider,
);
let message = alice_group
.create_message(alice_provider, &_alice_credential.signer, &[1, 2, 3])
.expect("An unexpected error occurred.");
let serialized_message = message
.tls_serialize_detached()
.expect("Could not serialize message.");
let mut ciphertext = MlsMessageIn::tls_deserialize(&mut serialized_message.as_slice())
.expect("Could not deserialize message.")
.into_ciphertext()
.expect("Message was not a plaintext.");
let original_message = ciphertext.clone();
ciphertext.set_ciphertext(vec![1, 2, 3]);
let message_in = ProtocolMessage::from(ciphertext);
let err = bob_group
.process_message(bob_provider, message_in)
.expect_err("Could parse message despite garbled ciphertext.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::UnableToDecrypt(
MessageDecryptionError::AeadError
))
));
bob_group
.process_message(bob_provider, ProtocolMessage::from(original_message))
.expect("Unexpected error.");
}
#[openmls_test::openmls_test]
fn test_valsem007() {
let alice_provider = &Provider::default();
let bob_provider = &Provider::default();
let ValidationTestSetup {
mut alice_group,
mut bob_group,
_alice_credential,
_bob_credential: _,
_alice_key_package: _,
_bob_key_package: _,
} = validation_test_setup(
PURE_PLAINTEXT_WIRE_FORMAT_POLICY,
ciphersuite,
alice_provider,
bob_provider,
);
let (message, _welcome, _group_info) = alice_group
.self_update(
alice_provider,
&_alice_credential.signer,
LeafNodeParameters::default(),
)
.expect("Could not self-update.")
.into_contents();
let serialized_message = message
.tls_serialize_detached()
.expect("Could not serialize message.");
let mut plaintext = MlsMessageIn::tls_deserialize(&mut serialized_message.as_slice())
.expect("Could not deserialize message.")
.into_plaintext()
.expect("Message was not a plaintext.");
let original_message = plaintext.clone();
plaintext.unset_membership_tag();
let message_in = ProtocolMessage::from(plaintext);
let err = bob_group
.process_message(bob_provider, message_in)
.expect_err("Could parse message despite missing membership tag.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::MissingMembershipTag)
));
bob_group
.process_message(bob_provider, ProtocolMessage::from(original_message))
.expect("Unexpected error.");
}
#[openmls_test::openmls_test]
fn test_valsem008() {
let alice_provider = &Provider::default();
let bob_provider = &Provider::default();
let ValidationTestSetup {
mut alice_group,
mut bob_group,
_alice_credential,
_bob_credential: _,
_alice_key_package: _,
_bob_key_package: _,
} = validation_test_setup(
PURE_PLAINTEXT_WIRE_FORMAT_POLICY,
ciphersuite,
alice_provider,
bob_provider,
);
let (message, _welcome, _group_info) = alice_group
.self_update(
alice_provider,
&_alice_credential.signer,
LeafNodeParameters::default(),
)
.expect("Could not self-update.")
.into_contents();
let serialized_message = message
.tls_serialize_detached()
.expect("Could not serialize message.");
let mut plaintext = MlsMessageIn::tls_deserialize(&mut serialized_message.as_slice())
.expect("Could not deserialize message.")
.into_plaintext()
.expect("Message was not a plaintext.");
let original_message = plaintext.clone();
plaintext.set_membership_tag_test(MembershipTag(
Mac::new(
alice_provider.crypto(),
ciphersuite,
&Secret::default(),
&[1, 2, 3],
)
.expect("Could not compute membership tag."),
));
let message_in = ProtocolMessage::from(plaintext);
let err = bob_group
.process_message(bob_provider, message_in)
.expect_err("Could process message despite wrong membership tag.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::InvalidMembershipTag)
));
bob_group
.process_message(bob_provider, ProtocolMessage::from(original_message))
.expect("Unexpected error.");
}
#[openmls_test::openmls_test]
fn test_valsem009() {
let alice_provider = &Provider::default();
let bob_provider = &Provider::default();
let ValidationTestSetup {
mut alice_group,
mut bob_group,
_alice_credential,
_bob_credential: _,
_alice_key_package: _,
_bob_key_package: _,
} = validation_test_setup(
PURE_PLAINTEXT_WIRE_FORMAT_POLICY,
ciphersuite,
alice_provider,
bob_provider,
);
let (message, _welcome, _group_info) = alice_group
.self_update(
alice_provider,
&_alice_credential.signer,
LeafNodeParameters::default(),
)
.expect("Could not self-update.")
.into_contents();
let serialized_message = message
.tls_serialize_detached()
.expect("Could not serialize message.");
let mut plaintext = MlsMessageIn::tls_deserialize(&mut serialized_message.as_slice())
.expect("Could not deserialize message.")
.into_plaintext()
.expect("Message was not a plaintext.");
let original_message = plaintext.clone();
plaintext.set_confirmation_tag(None);
plaintext
.set_membership_tag(
alice_provider.crypto(),
ciphersuite,
alice_group.message_secrets().membership_key(),
alice_group.message_secrets().serialized_context(),
)
.expect("Error setting membership tag.");
let message_in = ProtocolMessage::from(plaintext);
let err = bob_group
.process_message(bob_provider, message_in)
.expect_err("Could parse message despite missing confirmation tag.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::MissingConfirmationTag)
));
bob_group
.process_message(bob_provider, ProtocolMessage::from(original_message))
.expect("Unexpected error.");
}
#[openmls_test::openmls_test]
fn test_valsem010() {
let alice_provider = &Provider::default();
let bob_provider = &Provider::default();
let ValidationTestSetup {
mut alice_group,
mut bob_group,
_alice_credential,
_bob_credential: _,
_alice_key_package: _,
_bob_key_package: _,
} = validation_test_setup(
PURE_PLAINTEXT_WIRE_FORMAT_POLICY,
ciphersuite,
alice_provider,
bob_provider,
);
let (message, _welcome, _group_info) = alice_group
.self_update(
alice_provider,
&_alice_credential.signer,
LeafNodeParameters::default(),
)
.expect("Could not self update.")
.into_contents();
let serialized_message = message
.tls_serialize_detached()
.expect("Could not serialize message.");
let mut plaintext = MlsMessageIn::tls_deserialize(&mut serialized_message.as_slice())
.expect("Could not deserialize message.")
.into_plaintext()
.expect("Message was not a plaintext.");
let original_message = plaintext.clone();
plaintext.invalidate_signature();
plaintext
.set_membership_tag(
alice_provider.crypto(),
ciphersuite,
alice_group.message_secrets().membership_key(),
alice_group.message_secrets().serialized_context(),
)
.expect("Error setting membership tag.");
let message_in = ProtocolMessage::from(plaintext);
let err = bob_group
.process_message(bob_provider, message_in)
.expect_err("Could process message despite wrong signature.");
assert!(matches!(
err,
ProcessMessageError::ValidationError(ValidationError::InvalidSignature)
));
bob_group
.process_message(bob_provider, ProtocolMessage::from(original_message))
.expect("Unexpected error.");
}