use super::config::HpkeSymCipherSuite;
use super::extension::EchExtension;
use crate::rng::RngCore;
use alloc::vec::Vec;
#[derive(Copy, Clone, Debug)]
pub struct GreaseParams {
pub cipher_suite: HpkeSymCipherSuite,
pub enc_len: usize,
pub payload_len: usize,
pub config_id_strategy: GreaseConfigIdStrategy,
}
#[derive(Copy, Clone, Debug)]
pub enum GreaseConfigIdStrategy {
Random,
Fixed(u8),
}
impl Default for GreaseParams {
fn default() -> Self {
Self {
cipher_suite: HpkeSymCipherSuite {
kdf_id: 0x0001, aead_id: 0x0001, },
enc_len: 32,
payload_len: 144,
config_id_strategy: GreaseConfigIdStrategy::Random,
}
}
}
impl GreaseParams {
pub(crate) fn build_extension<R: RngCore>(&self, rng: &mut R) -> EchExtension {
let mut enc = alloc::vec![0u8; self.enc_len];
if !enc.is_empty() {
rng.fill_bytes(&mut enc);
}
let mut payload = alloc::vec![0u8; self.payload_len];
if !payload.is_empty() {
rng.fill_bytes(&mut payload);
}
let config_id = match self.config_id_strategy {
GreaseConfigIdStrategy::Fixed(v) => v,
GreaseConfigIdStrategy::Random => {
let mut b = [0u8; 1];
rng.fill_bytes(&mut b);
b[0]
}
};
EchExtension::Outer {
cipher_suite: self.cipher_suite,
config_id,
enc,
payload,
}
}
pub fn build_extension_bytes<R: RngCore>(&self, rng: &mut R) -> Vec<u8> {
self.build_extension(rng).encode()
}
pub(crate) fn build_extension_from_seed(
&self,
seed: &[u8; 32],
ch_random: &[u8; 32],
) -> Vec<u8> {
use crate::hash::Sha256;
use crate::kdf::hkdf;
let mut out = alloc::vec![0u8; 1 + self.enc_len + self.payload_len];
hkdf::<Sha256>(ch_random, seed, b"ech grease", &mut out);
let config_id = match self.config_id_strategy {
GreaseConfigIdStrategy::Fixed(v) => v,
GreaseConfigIdStrategy::Random => out[0],
};
let (enc, payload) = out[1..].split_at(self.enc_len);
let ext = super::extension::EchExtension::Outer {
cipher_suite: self.cipher_suite,
config_id,
enc: enc.to_vec(),
payload: payload.to_vec(),
};
ext.encode()
}
}