From 95030b623783cba04c3d07d3c0ddbc232b6aa0b7 Mon Sep 17 00:00:00 2001 From: beltram Date: Tue, 19 Mar 2024 11:48:47 +0100 Subject: [PATCH] feat: expose processed message's credential with its associated public signature key --- openmls/src/ciphersuite/signature.rs | 13 ++++++++++--- openmls/src/credentials/mod.rs | 2 +- openmls/src/framing/validation.rs | 14 +++++++------- openmls/src/group/public_group/process.rs | 11 ++++------- openmls/src/treesync/node/leaf_node.rs | 7 +++++++ openmls/tests/book_code.rs | 6 +++--- openmls/tests/test_mls_group.rs | 4 ++-- 7 files changed, 34 insertions(+), 23 deletions(-) diff --git a/openmls/src/ciphersuite/signature.rs b/openmls/src/ciphersuite/signature.rs index e60e143f4a..8366efa758 100644 --- a/openmls/src/ciphersuite/signature.rs +++ b/openmls/src/ciphersuite/signature.rs @@ -52,13 +52,20 @@ impl From<(&str, &[u8])> for SignContent { } /// A public signature key. -#[derive( - Eq, PartialEq, Hash, Debug, Clone, Serialize, Deserialize, TlsSerialize, TlsDeserialize, TlsSize, -)] +#[derive(Hash, Debug, Clone, Serialize, Deserialize, TlsSerialize, TlsDeserialize, TlsSize)] pub struct SignaturePublicKey { pub(in crate::ciphersuite) value: VLBytes, } +impl Eq for SignaturePublicKey {} + +impl PartialEq for SignaturePublicKey { + fn eq(&self, other: &Self) -> bool { + use subtle::ConstantTimeEq as _; + self.value.as_slice().ct_eq(other.value.as_slice()).into() + } +} + impl From> for SignaturePublicKey { fn from(value: Vec) -> Self { Self { diff --git a/openmls/src/credentials/mod.rs b/openmls/src/credentials/mod.rs index c7aa05774a..fa8c7be392 100644 --- a/openmls/src/credentials/mod.rs +++ b/openmls/src/credentials/mod.rs @@ -357,7 +357,7 @@ pub struct BasicCredential { identity: VLBytes, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] /// A wrapper around a credential with a corresponding public key. pub struct CredentialWithKey { /// The [`Credential`]. diff --git a/openmls/src/framing/validation.rs b/openmls/src/framing/validation.rs index 5c7dddd0b0..3da9b635a7 100644 --- a/openmls/src/framing/validation.rs +++ b/openmls/src/framing/validation.rs @@ -249,7 +249,7 @@ pub enum SenderContext { #[derive(Debug, Clone)] pub(crate) struct UnverifiedMessage { verifiable_content: VerifiableAuthenticatedContentIn, - credential: Credential, + credential: CredentialWithKey, sender_pk: OpenMlsSignaturePublicKey, sender_context: Option, } @@ -258,7 +258,7 @@ impl UnverifiedMessage { /// Construct an [UnverifiedMessage] from a [DecryptedMessage] and an optional [Credential]. pub(crate) fn from_decrypted_message( decrypted_message: DecryptedMessage, - credential: Credential, + credential: CredentialWithKey, sender_pk: OpenMlsSignaturePublicKey, sender_context: Option, ) -> Self { @@ -278,8 +278,8 @@ impl UnverifiedMessage { backend: &impl OpenMlsCryptoProvider, protocol_version: ProtocolVersion, group: &PublicGroup, - ) -> Result<(AuthenticatedContent, Credential), ProcessMessageError> { - let content: AuthenticatedContentIn = match self.credential.mls_credential() { + ) -> Result<(AuthenticatedContent, CredentialWithKey), ProcessMessageError> { + let content: AuthenticatedContentIn = match self.credential.credential.mls_credential() { MlsCredentialType::Basic(_) => self .verifiable_content .verify(backend.crypto(), &self.sender_pk) @@ -340,7 +340,7 @@ pub struct ProcessedMessage { sender: Sender, authenticated_data: Vec, content: ProcessedMessageContent, - credential: Credential, + credential: CredentialWithKey, } impl ProcessedMessage { @@ -351,7 +351,7 @@ impl ProcessedMessage { sender: Sender, authenticated_data: Vec, content: ProcessedMessageContent, - credential: Credential, + credential: CredentialWithKey, ) -> Self { Self { group_id, @@ -394,7 +394,7 @@ impl ProcessedMessage { } /// Returns the credential of the message. - pub fn credential(&self) -> &Credential { + pub fn credential(&self) -> &CredentialWithKey { &self.credential } } diff --git a/openmls/src/group/public_group/process.rs b/openmls/src/group/public_group/process.rs index 70be92f0e1..9a69ec010d 100644 --- a/openmls/src/group/public_group/process.rs +++ b/openmls/src/group/public_group/process.rs @@ -1,9 +1,9 @@ -use openmls_traits::OpenMlsCryptoProvider; use tls_codec::Serialize; +use openmls_traits::OpenMlsCryptoProvider; + use crate::{ ciphersuite::OpenMlsSignaturePublicKey, - credentials::CredentialWithKey, error::LibraryError, framing::{ mls_content::FramedContentBody, ApplicationMessage, DecryptedMessage, ProcessedMessage, @@ -72,10 +72,7 @@ impl PublicGroup { // - Prepares ValSem246 by setting the right credential. The remainder // of ValSem246 is validated as part of ValSem010. // External senders are not supported yet #106/#151. - let CredentialWithKey { - credential, - signature_key, - } = decrypted_message.credential( + let credential = decrypted_message.credential( self.treesync(), message_secrets_store_option .map(|store| store.leaves_for_epoch(decrypted_message.verifiable_content().epoch())) @@ -84,7 +81,7 @@ impl PublicGroup { )?; let signature_public_key = OpenMlsSignaturePublicKey::from_signature_key( - signature_key, + credential.signature_key.clone(), self.ciphersuite().signature_algorithm(), ); diff --git a/openmls/src/treesync/node/leaf_node.rs b/openmls/src/treesync/node/leaf_node.rs index 6caef76ea3..ebcf1f31fc 100644 --- a/openmls/src/treesync/node/leaf_node.rs +++ b/openmls/src/treesync/node/leaf_node.rs @@ -358,6 +358,13 @@ impl LeafNode { pub fn credential(&self) -> &Credential { &self.payload.credential } + /// Returns the `signature_key` as byte slice. + pub fn to_credential_with_key(&self) -> CredentialWithKey { + CredentialWithKey { + credential: self.credential().clone(), + signature_key: self.signature_key().clone(), + } + } /// Returns the `parent_hash` as byte slice or `None`. pub fn parent_hash(&self) -> Option<&[u8]> { diff --git a/openmls/tests/book_code.rs b/openmls/tests/book_code.rs index 14bc101595..346ddfb7c4 100644 --- a/openmls/tests/book_code.rs +++ b/openmls/tests/book_code.rs @@ -669,7 +669,7 @@ async fn book_operations(ciphersuite: Ciphersuite, backend: &impl OpenMlsCryptoP assert!(alice_members.any(|Member { index, .. }| index == *sender_leaf_index)); drop(alice_members); - assert_eq!(sender_credential, &charlie_credential.credential); + assert_eq!(sender_credential, &charlie_credential); let bob_processed_message = bob_group .process_message( @@ -1016,9 +1016,9 @@ async fn book_operations(ciphersuite: Ciphersuite, backend: &impl OpenMlsCryptoP // Check the message assert_eq!(application_message.into_bytes(), message_alice); // Check that Alice sent the message - assert_eq!(sender_cred_from_msg, sender_cred_from_group); + assert_eq!(sender_cred_from_msg.credential, sender_cred_from_group); assert_eq!( - &sender_cred_from_msg, + &sender_cred_from_msg.credential, alice_group.credential().expect("Expected a credential.") ); } else { diff --git a/openmls/tests/test_mls_group.rs b/openmls/tests/test_mls_group.rs index c8f49cf89b..bc12914ac0 100644 --- a/openmls/tests/test_mls_group.rs +++ b/openmls/tests/test_mls_group.rs @@ -169,7 +169,7 @@ async fn mls_group_operations(ciphersuite: Ciphersuite, backend: &impl OpenMlsCr assert_eq!(application_message.into_bytes(), message_alice); // Check that Alice sent the message assert_eq!( - &sender, + &sender.credential, alice_group .credential() .expect("An unexpected error occurred.") @@ -785,7 +785,7 @@ async fn mls_group_operations(ciphersuite: Ciphersuite, backend: &impl OpenMlsCr assert_eq!(application_message.into_bytes(), message_alice); // Check that Alice sent the message assert_eq!( - &sender, + &sender.credential, alice_group.credential().expect("Expected a credential") ); } else {