#[cfg(feature = "alloc")]
use alloc::sync::Arc;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::fmt;
use crate::providers::traits::HpkeCryptoProvider;
use crate::types::{
HpkeAead,
HpkeCipherSuite,
HpkeContextState,
SecretBytes,
};
pub struct HpkeSenderContext {
pub shared_secret: SecretBytes,
pub exporter_secret: SecretBytes,
pub key: SecretBytes,
pub nonce: SecretBytes,
pub cipher_suite: HpkeCipherSuite,
pub aead: HpkeAead,
pub encapsulated_key: Vec<u8>,
pub sequence_number: u32,
pub max_sequence_number: u32,
pub state: HpkeContextState,
pub(crate) hpke_crypto: Arc<dyn HpkeCryptoProvider + Send + Sync>,
}
impl fmt::Debug for HpkeSenderContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HpkeSenderContext")
.field("shared_secret", &"<redacted>")
.field("exporter_secret", &"<redacted>")
.field("key", &"<redacted>")
.field("nonce", &"<redacted>")
.field("cipher_suite", &self.cipher_suite)
.field("aead", &self.aead)
.field("encapsulated_key_len", &self.encapsulated_key.len())
.field("sequence_number", &self.sequence_number)
.field("max_sequence_number", &self.max_sequence_number)
.field("state", &self.state)
.field("hpke_crypto", &self.hpke_crypto.name())
.finish()
}
}
impl HpkeSenderContext {
#[allow(clippy::too_many_arguments)] pub fn new(
shared_secret: SecretBytes,
exporter_secret: SecretBytes,
key: SecretBytes,
nonce: SecretBytes,
encapsulated_key: Vec<u8>,
cipher_suite: HpkeCipherSuite,
aead: HpkeAead,
hpke_crypto: Arc<dyn HpkeCryptoProvider + Send + Sync>,
) -> Self {
Self {
shared_secret,
exporter_secret,
key,
nonce,
cipher_suite,
aead,
encapsulated_key,
sequence_number: 0,
max_sequence_number: u32::MAX - 1,
state: HpkeContextState::Active,
hpke_crypto,
}
}
pub fn hpke_crypto(&self) -> &(dyn HpkeCryptoProvider + Send + Sync) {
self.hpke_crypto.as_ref()
}
pub fn can_encrypt(&self) -> bool {
self.aead != HpkeAead::Export &&
self.state == HpkeContextState::Active &&
self.sequence_number < self.max_sequence_number
}
pub fn increment_sequence(&mut self) -> Result<(), crate::error::HpkeError> {
if self.sequence_number >= self.max_sequence_number {
self.state = HpkeContextState::NeedsRekey;
return Err(crate::error::HpkeError::CryptoError(
"Sequence number overflow: context needs rekeying".into(),
));
}
self.sequence_number = self.sequence_number.wrapping_add(1);
Ok(())
}
pub fn close(&mut self) {
self.state = HpkeContextState::Closed;
}
pub fn encapsulated_key(&self) -> &[u8] {
&self.encapsulated_key
}
}
pub struct HpkeReceiverContext {
pub shared_secret: SecretBytes,
pub exporter_secret: SecretBytes,
pub key: SecretBytes,
pub nonce: SecretBytes,
pub cipher_suite: HpkeCipherSuite,
pub aead: HpkeAead,
pub sequence_number: u32,
pub max_sequence_number: u32,
pub state: HpkeContextState,
pub(crate) hpke_crypto: Arc<dyn HpkeCryptoProvider + Send + Sync>,
}
impl fmt::Debug for HpkeReceiverContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HpkeReceiverContext")
.field("shared_secret", &"<redacted>")
.field("exporter_secret", &"<redacted>")
.field("key", &"<redacted>")
.field("nonce", &"<redacted>")
.field("cipher_suite", &self.cipher_suite)
.field("aead", &self.aead)
.field("sequence_number", &self.sequence_number)
.field("max_sequence_number", &self.max_sequence_number)
.field("state", &self.state)
.field("hpke_crypto", &self.hpke_crypto.name())
.finish()
}
}
impl HpkeReceiverContext {
pub fn new(
shared_secret: SecretBytes,
exporter_secret: SecretBytes,
key: SecretBytes,
nonce: SecretBytes,
cipher_suite: HpkeCipherSuite,
aead: HpkeAead,
hpke_crypto: Arc<dyn HpkeCryptoProvider + Send + Sync>,
) -> Self {
Self {
shared_secret,
exporter_secret,
key,
nonce,
cipher_suite,
aead,
sequence_number: 0,
max_sequence_number: u32::MAX - 1,
state: HpkeContextState::Active,
hpke_crypto,
}
}
pub fn hpke_crypto(&self) -> &(dyn HpkeCryptoProvider + Send + Sync) {
self.hpke_crypto.as_ref()
}
pub fn can_decrypt(&self) -> bool {
self.aead != HpkeAead::Export &&
self.state == HpkeContextState::Active &&
self.sequence_number < self.max_sequence_number
}
pub fn increment_sequence(&mut self) -> Result<(), crate::error::HpkeError> {
if self.sequence_number >= self.max_sequence_number {
self.state = HpkeContextState::NeedsRekey;
return Err(crate::error::HpkeError::CryptoError(
"Sequence number overflow: context needs rekeying".into(),
));
}
self.sequence_number = self.sequence_number.wrapping_add(1);
Ok(())
}
pub fn close(&mut self) {
self.state = HpkeContextState::Closed;
}
}