mls_rs/group/
group_info.rs

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
5use alloc::vec::Vec;
6use core::fmt::{self, Debug};
7use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
8use mls_rs_core::extension::ExtensionList;
9
10use crate::{signer::Signable, tree_kem::node::LeafIndex};
11
12use 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)]
20pub 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
29impl Debug for GroupInfo {
30    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
44impl GroupInfo {
45    /// Group context.
46    pub fn group_context(&self) -> &GroupContext {
47        &self.group_context
48    }
49
50    /// Group info extensions (not to be confused with group context extensions),
51    /// e.g. the ratchet tree.
52    pub fn extensions(&self) -> &ExtensionList {
53        &self.extensions
54    }
55
56    /// Leaf index of the sender who generated and signed this group info.
57    pub fn sender(&self) -> u32 {
58        *self.signer
59    }
60}
61
62#[derive(MlsEncode, MlsSize)]
63struct SignableGroupInfo<'a> {
64    group_context: &'a GroupContext,
65    extensions: &'a ExtensionList,
66    confirmation_tag: &'a ConfirmationTag,
67    signer: LeafIndex,
68}
69
70impl Signable<'_> for GroupInfo {
71    const SIGN_LABEL: &'static str = "GroupInfoTBS";
72    type SigningContext = ();
73
74    fn signature(&self) -> &[u8] {
75        &self.signature
76    }
77
78    fn signable_content(
79        &self,
80        _context: &Self::SigningContext,
81    ) -> Result<Vec<u8>, mls_rs_codec::Error> {
82        SignableGroupInfo {
83            group_context: &self.group_context,
84            extensions: &self.extensions,
85            confirmation_tag: &self.confirmation_tag,
86            signer: self.signer,
87        }
88        .mls_encode_to_vec()
89    }
90
91    fn write_signature(&mut self, signature: Vec<u8>) {
92        self.signature = signature
93    }
94}