// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // Copyright by contributors to this project. // SPDX-License-Identifier: (Apache-2.0 OR MIT) use alloc::vec::Vec; use core::fmt::{self, Debug}; use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize}; use mls_rs_core::extension::ExtensionList; use crate::{signer::Signable, tree_kem::node::LeafIndex}; use super::{ConfirmationTag, GroupContext}; #[derive(Clone, PartialEq, MlsSize, MlsEncode, MlsDecode)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[cfg_attr( all(feature = "ffi", not(test)), safer_ffi_gen::ffi_type(clone, opaque) )] pub struct GroupInfo { pub(crate) group_context: GroupContext, pub(crate) extensions: ExtensionList, pub(crate) confirmation_tag: ConfirmationTag, pub(crate) signer: LeafIndex, #[mls_codec(with = "mls_rs_codec::byte_vec")] pub(crate) signature: Vec, } impl Debug for GroupInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("GroupInfo") .field("group_context", &self.group_context) .field("extensions", &self.extensions) .field("confirmation_tag", &self.confirmation_tag) .field("signer", &self.signer) .field( "signature", &mls_rs_core::debug::pretty_bytes(&self.signature), ) .finish() } } #[cfg_attr(all(feature = "ffi", not(test)), ::safer_ffi_gen::safer_ffi_gen)] impl GroupInfo { /// Group context. pub fn group_context(&self) -> &GroupContext { &self.group_context } /// Group info extensions (not to be confused with group context extensions), /// e.g. the ratchet tree. pub fn extensions(&self) -> &ExtensionList { &self.extensions } /// Leaf index of the sender who generated and signed this group info. pub fn sender(&self) -> u32 { *self.signer } } #[derive(MlsEncode, MlsSize)] struct SignableGroupInfo<'a> { group_context: &'a GroupContext, extensions: &'a ExtensionList, confirmation_tag: &'a ConfirmationTag, signer: LeafIndex, } impl<'a> Signable<'a> for GroupInfo { const SIGN_LABEL: &'static str = "GroupInfoTBS"; type SigningContext = (); fn signature(&self) -> &[u8] { &self.signature } fn signable_content( &self, _context: &Self::SigningContext, ) -> Result, mls_rs_codec::Error> { SignableGroupInfo { group_context: &self.group_context, extensions: &self.extensions, confirmation_tag: &self.confirmation_tag, signer: self.signer, } .mls_encode_to_vec() } fn write_signature(&mut self, signature: Vec) { self.signature = signature } }