| // 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<u8>, |
| } |
| |
| 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<Vec<u8>, 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<u8>) { |
| self.signature = signature |
| } |
| } |