Revision control
Copy as Markdown
Other Tools
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Copyright by contributors to this project.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
#[cfg(feature = "psk")]
use crate::psk::PreSharedKey;
#[cfg(any(feature = "secret_tree_access", feature = "private_message"))]
use crate::tree_kem::node::NodeIndex;
#[cfg(feature = "prior_epoch")]
use crate::{crypto::SignaturePublicKey, group::GroupContext, tree_kem::node::LeafIndex};
use alloc::vec::Vec;
use core::{
fmt::{self, Debug},
ops::Deref,
};
use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
use zeroize::Zeroizing;
#[cfg(all(feature = "prior_epoch", feature = "private_message"))]
use super::ciphertext_processor::GroupStateProvider;
#[cfg(any(feature = "secret_tree_access", feature = "private_message"))]
use crate::group::secret_tree::SecretTree;
#[cfg(feature = "prior_epoch")]
#[derive(Debug, Clone, MlsEncode, MlsDecode, MlsSize, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub(crate) struct PriorEpoch {
pub(crate) context: GroupContext,
pub(crate) self_index: LeafIndex,
pub(crate) secrets: EpochSecrets,
pub(crate) signature_public_keys: Vec<Option<SignaturePublicKey>>,
}
#[cfg(feature = "prior_epoch")]
impl PriorEpoch {
#[inline(always)]
pub(crate) fn epoch_id(&self) -> u64 {
self.context.epoch
}
#[inline(always)]
pub(crate) fn group_id(&self) -> &[u8] {
&self.context.group_id
}
}
#[cfg(all(feature = "private_message", feature = "prior_epoch"))]
impl GroupStateProvider for PriorEpoch {
fn group_context(&self) -> &GroupContext {
&self.context
}
fn self_index(&self) -> LeafIndex {
self.self_index
}
fn epoch_secrets_mut(&mut self) -> &mut EpochSecrets {
&mut self.secrets
}
fn epoch_secrets(&self) -> &EpochSecrets {
&self.secrets
}
}
#[derive(Debug, Clone, PartialEq, MlsEncode, MlsDecode, MlsSize)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub(crate) struct EpochSecrets {
#[cfg(feature = "psk")]
#[mls_codec(with = "mls_rs_codec::byte_vec")]
pub(crate) resumption_secret: PreSharedKey,
#[mls_codec(with = "mls_rs_codec::byte_vec")]
pub(crate) sender_data_secret: SenderDataSecret,
#[cfg(any(feature = "secret_tree_access", feature = "private_message"))]
pub(crate) secret_tree: SecretTree<NodeIndex>,
}
#[derive(Clone, PartialEq, MlsEncode, MlsDecode, MlsSize)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub(crate) struct SenderDataSecret(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "mls_rs_core::zeroizing_serde"))]
Zeroizing<Vec<u8>>,
);
impl Debug for SenderDataSecret {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
mls_rs_core::debug::pretty_bytes(&self.0)
.named("SenderDataSecret")
.fmt(f)
}
}
impl AsRef<[u8]> for SenderDataSecret {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl Deref for SenderDataSecret {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Vec<u8>> for SenderDataSecret {
fn from(bytes: Vec<u8>) -> Self {
Self(Zeroizing::new(bytes))
}
}
impl From<Zeroizing<Vec<u8>>> for SenderDataSecret {
fn from(bytes: Zeroizing<Vec<u8>>) -> Self {
Self(bytes)
}
}
#[cfg(test)]
pub(crate) mod test_utils {
use mls_rs_core::crypto::CipherSuiteProvider;
use super::*;
use crate::cipher_suite::CipherSuite;
use crate::crypto::test_utils::test_cipher_suite_provider;
#[cfg(any(feature = "secret_tree_access", feature = "private_message"))]
use crate::group::secret_tree::test_utils::get_test_tree;
#[cfg(feature = "prior_epoch")]
use crate::group::test_utils::get_test_group_context_with_id;
use crate::group::test_utils::random_bytes;
pub(crate) fn get_test_epoch_secrets(cipher_suite: CipherSuite) -> EpochSecrets {
let cs_provider = test_cipher_suite_provider(cipher_suite);
#[cfg(any(feature = "secret_tree_access", feature = "private_message"))]
let secret_tree = get_test_tree(random_bytes(cs_provider.kdf_extract_size()), 2);
EpochSecrets {
#[cfg(feature = "psk")]
resumption_secret: random_bytes(cs_provider.kdf_extract_size()).into(),
sender_data_secret: random_bytes(cs_provider.kdf_extract_size()).into(),
#[cfg(any(feature = "secret_tree_access", feature = "private_message"))]
secret_tree,
}
}
#[cfg(feature = "prior_epoch")]
pub(crate) fn get_test_epoch_with_id(
group_id: Vec<u8>,
cipher_suite: CipherSuite,
id: u64,
) -> PriorEpoch {
PriorEpoch {
context: get_test_group_context_with_id(group_id, id, cipher_suite),
self_index: LeafIndex(0),
secrets: get_test_epoch_secrets(cipher_suite),
signature_public_keys: Default::default(),
}
}
}