1 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // Copyright by contributors to this project. 3 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 4 5 use alloc::vec::Vec; 6 use core::fmt::{self, Debug}; 7 use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize}; 8 use mls_rs_core::extension::ExtensionList; 9 10 use crate::{signer::Signable, tree_kem::node::LeafIndex}; 11 12 use super::{ConfirmationTag, GroupContext}; 13 14 #[derive(Clone, PartialEq, MlsSize, MlsEncode, MlsDecode)] 15 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] 16 #[cfg_attr( 17 all(feature = "ffi", not(test)), 18 safer_ffi_gen::ffi_type(clone, opaque) 19 )] 20 pub struct GroupInfo { 21 pub(crate) group_context: GroupContext, 22 pub(crate) extensions: ExtensionList, 23 pub(crate) confirmation_tag: ConfirmationTag, 24 pub(crate) signer: LeafIndex, 25 #[mls_codec(with = "mls_rs_codec::byte_vec")] 26 pub(crate) signature: Vec<u8>, 27 } 28 29 impl Debug for GroupInfo { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 31 f.debug_struct("GroupInfo") 32 .field("group_context", &self.group_context) 33 .field("extensions", &self.extensions) 34 .field("confirmation_tag", &self.confirmation_tag) 35 .field("signer", &self.signer) 36 .field( 37 "signature", 38 &mls_rs_core::debug::pretty_bytes(&self.signature), 39 ) 40 .finish() 41 } 42 } 43 44 #[cfg_attr(all(feature = "ffi", not(test)), ::safer_ffi_gen::safer_ffi_gen)] 45 impl GroupInfo { 46 /// Group context. group_context(&self) -> &GroupContext47 pub fn group_context(&self) -> &GroupContext { 48 &self.group_context 49 } 50 51 /// Group info extensions (not to be confused with group context extensions), 52 /// e.g. the ratchet tree. extensions(&self) -> &ExtensionList53 pub fn extensions(&self) -> &ExtensionList { 54 &self.extensions 55 } 56 57 /// Leaf index of the sender who generated and signed this group info. sender(&self) -> u3258 pub fn sender(&self) -> u32 { 59 *self.signer 60 } 61 } 62 63 #[derive(MlsEncode, MlsSize)] 64 struct SignableGroupInfo<'a> { 65 group_context: &'a GroupContext, 66 extensions: &'a ExtensionList, 67 confirmation_tag: &'a ConfirmationTag, 68 signer: LeafIndex, 69 } 70 71 impl<'a> Signable<'a> for GroupInfo { 72 const SIGN_LABEL: &'static str = "GroupInfoTBS"; 73 type SigningContext = (); 74 signature(&self) -> &[u8]75 fn signature(&self) -> &[u8] { 76 &self.signature 77 } 78 signable_content( &self, _context: &Self::SigningContext, ) -> Result<Vec<u8>, mls_rs_codec::Error>79 fn signable_content( 80 &self, 81 _context: &Self::SigningContext, 82 ) -> Result<Vec<u8>, mls_rs_codec::Error> { 83 SignableGroupInfo { 84 group_context: &self.group_context, 85 extensions: &self.extensions, 86 confirmation_tag: &self.confirmation_tag, 87 signer: self.signer, 88 } 89 .mls_encode_to_vec() 90 } 91 write_signature(&mut self, signature: Vec<u8>)92 fn write_signature(&mut self, signature: Vec<u8>) { 93 self.signature = signature 94 } 95 } 96