1use crate::{
2 SensitiveBytes,
3 credential::Credential,
4 crypto::SignaturePublicKey,
5 defs::{CredentialType, ExtensionType, ProposalType},
6};
7
8pub mod commits;
9pub mod extensions;
10pub mod group_info;
11pub mod proposals;
12pub mod welcome;
13
14pub type HashReference = SensitiveBytes;
15pub type ProposalRef = HashReference;
16pub type KeyPackageRef = HashReference;
17#[cfg(feature = "draft-kohbrok-mls-leaf-operation-intents")]
18pub type LeafNodeRef = HashReference;
19
20pub type GroupId = Vec<u8>;
21pub type GroupIdRef<'a> = &'a [u8];
22
23#[derive(
24 Debug,
25 Clone,
26 Copy,
27 PartialEq,
28 Eq,
29 Hash,
30 tls_codec::TlsSerialize,
31 tls_codec::TlsDeserialize,
32 tls_codec::TlsSize,
33)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
35pub struct KeyPackageLifetime {
36 pub not_before: u64,
37 pub not_after: u64,
38}
39
40impl KeyPackageLifetime {
41 pub const LIFETIME_WIGGLE_ROOM: u64 = 50_400;
43 #[cfg(not(feature = "test-vectors"))]
44 pub const MAX_LEAF_NODE_ACCEPTABLE_RANGE: u64 = 8_035_200;
46 #[cfg(feature = "test-vectors")]
47 pub const MAX_LEAF_NODE_ACCEPTABLE_RANGE: u64 = u64::MAX - Self::LIFETIME_WIGGLE_ROOM;
48
49 pub fn validate_range(&self) -> bool {
53 if self.not_after < self.not_before {
54 return false;
55 }
56
57 let kp_range = self.not_after.saturating_sub(self.not_before);
58 let acceptable_range =
59 Self::MAX_LEAF_NODE_ACCEPTABLE_RANGE.saturating_add(Self::LIFETIME_WIGGLE_ROOM);
60 kp_range <= acceptable_range
61 }
62
63 pub fn validate_expiration(&self) -> bool {
65 let now = now();
66 self.not_before < now && now < self.not_after
67 }
68}
69
70#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
71fn now() -> u64 {
72 let val = js_sys::Date::now();
73 std::time::Duration::from_millis(val as u64).as_secs()
74}
75
76#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
77fn now() -> u64 {
78 let now = std::time::SystemTime::now();
79 now.duration_since(std::time::SystemTime::UNIX_EPOCH)
80 .expect("System clock is before UNIX_EPOCH")
81 .as_secs()
82}
83
84impl Default for KeyPackageLifetime {
85 fn default() -> Self {
86 let now = now();
87 let not_before = now.saturating_sub(Self::LIFETIME_WIGGLE_ROOM);
88 let not_after = now.saturating_add(Self::MAX_LEAF_NODE_ACCEPTABLE_RANGE);
89 Self {
90 not_before,
91 not_after,
92 }
93 }
94}
95
96#[derive(
97 Debug,
98 Clone,
99 PartialEq,
100 Eq,
101 Hash,
102 tls_codec::TlsSerialize,
103 tls_codec::TlsDeserialize,
104 tls_codec::TlsSize,
105)]
106#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
107pub struct ExternalSender {
108 pub signature_key: SignaturePublicKey,
109 pub credential: Credential,
110}
111
112#[derive(
113 Debug,
114 Clone,
115 Default,
116 PartialEq,
117 Eq,
118 Hash,
119 tls_codec::TlsSerialize,
120 tls_codec::TlsDeserialize,
121 tls_codec::TlsSize,
122)]
123#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
124pub struct RequiredCapabilities {
125 pub extension_types: Vec<ExtensionType>,
126 pub proposal_types: Vec<ProposalType>,
127 pub credential_types: Vec<CredentialType>,
128}