1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use tls_codec::Serialize;
use crate::{
group::errors::ExporterError, messages::public_group_state::PublicGroupState,
schedule::AuthenticationSecret,
};
use super::*;
impl MlsGroup {
// === Export secrets ===
/// Exports a secret from the current epoch.
/// Returns [`ExportSecretError::KeyLengthTooLong`] if the requested
/// key length is too long.
/// Returns [`ExportSecretError::GroupStateError(MlsGroupStateError::UseAfterEviction)`](MlsGroupStateError::UseAfterEviction)
/// if the group is not active.
pub fn export_secret(
&self,
backend: &impl OpenMlsCryptoProvider,
label: &str,
context: &[u8],
key_length: usize,
) -> Result<Vec<u8>, ExportSecretError> {
if self.is_active() {
Ok(self
.group
.export_secret(backend, label, context, key_length)
.map_err(|e| match e {
ExporterError::LibraryError(e) => e.into(),
ExporterError::KeyLengthTooLong => ExportSecretError::KeyLengthTooLong,
})?)
} else {
Err(ExportSecretError::GroupStateError(
MlsGroupStateError::UseAfterEviction,
))
}
}
/// Returns the authentication secret of the current epoch.
pub fn authentication_secret(&self) -> &AuthenticationSecret {
self.group.authentication_secret()
}
/// Returns the resumption secret of the current epoch.
pub fn resumptionn_secret(&self) -> &ResumptionSecret {
self.group.resumption_secret()
}
/// Returns a resumption secret for a given epoch. If no resumption secret
/// is available for that epoch, `None` is returned.
pub fn get_past_resumption_secret(&self, epoch: GroupEpoch) -> Option<&ResumptionSecret> {
self.resumption_secret_store.get(epoch)
}
// === Export public group state ===
/// Exports the public group state.
pub fn export_public_group_state(
&self,
backend: &impl OpenMlsCryptoProvider,
) -> Result<PublicGroupState, ExportPublicGroupStateError> {
match self.credential() {
Ok(credential) => {
let credential_bundle: CredentialBundle = backend
.key_store()
.read(
&credential
.signature_key()
.tls_serialize_detached()
.map_err(LibraryError::missing_bound_check)?,
)
.ok_or(ExportPublicGroupStateError::NoMatchingCredentialBundle)?;
Ok(self
.group
.export_public_group_state(backend, &credential_bundle)?)
}
Err(e) => Err(e.into()),
}
}
}