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