use crate::{
hybrid::HybridMode, kdf::KdfAlgorithm, kem::KemAlgorithm, privacy_tiers::PrivacyTier,
signature::SignatureAlgorithm, wire_protocol::NodeMode,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum DefaultKem {
MlKem512,
MlKem768,
MlKem1024,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum DefaultSig {
MlDsa44,
MlDsa65,
MlDsa87,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PqcConfig {
pub kem: KemAlgorithm,
pub default_kem: DefaultKem,
pub sig: SignatureAlgorithm,
pub default_sig: DefaultSig,
pub sig_alt: Option<SignatureAlgorithm>,
pub hybrid: bool,
pub hybrid_mode: HybridMode,
pub kdf: KdfAlgorithm,
pub rng: RngSource,
pub node_mode: NodeMode,
pub min_privacy_tier: PrivacyTier,
pub fips_mode: bool,
pub verify_attestation: bool,
pub key_lifetime: u64,
pub reattestaton_interval: u64,
}
impl Default for PqcConfig {
fn default() -> Self {
Self {
kem: KemAlgorithm::MlKem768,
default_kem: DefaultKem::MlKem768,
sig: SignatureAlgorithm::MlDsa65,
default_sig: DefaultSig::MlDsa65,
sig_alt: Some(SignatureAlgorithm::SlhDsa128s),
hybrid: true,
hybrid_mode: HybridMode::MlKem768X25519,
kdf: KdfAlgorithm::HkdfSha384,
rng: RngSource::Os,
node_mode: NodeMode::SimOnly,
min_privacy_tier: PrivacyTier::AccessAtRest,
fips_mode: false,
verify_attestation: false,
key_lifetime: 86400, reattestaton_interval: 3600, }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum RngSource {
Os,
Hardware,
FipsDrbg,
}
impl PqcConfig {
pub fn maximum_security() -> Self {
Self {
kem: KemAlgorithm::MlKem1024,
default_kem: DefaultKem::MlKem1024,
sig: SignatureAlgorithm::MlDsa87,
default_sig: DefaultSig::MlDsa87,
sig_alt: Some(SignatureAlgorithm::SlhDsa256s),
hybrid: true,
hybrid_mode: HybridMode::MlKem1024X25519,
kdf: KdfAlgorithm::HkdfSha512,
rng: RngSource::FipsDrbg,
node_mode: NodeMode::SimTee,
min_privacy_tier: PrivacyTier::AccessGpuTeeIoMax,
fips_mode: true,
verify_attestation: true,
key_lifetime: 3600, reattestaton_interval: 600, }
}
pub fn performance_optimized() -> Self {
Self {
kem: KemAlgorithm::MlKem512,
default_kem: DefaultKem::MlKem512,
sig: SignatureAlgorithm::MlDsa44,
default_sig: DefaultSig::MlDsa44,
sig_alt: None,
hybrid: false,
hybrid_mode: HybridMode::MlKem512X25519,
kdf: KdfAlgorithm::HkdfSha256,
rng: RngSource::Os,
node_mode: NodeMode::SoftwareOnly,
min_privacy_tier: PrivacyTier::AccessOpen,
fips_mode: false,
verify_attestation: false,
key_lifetime: 86400 * 7, reattestaton_interval: 86400, }
}
pub fn for_privacy_tier(tier: PrivacyTier) -> Self {
let mut config = Self::default();
config.min_privacy_tier = tier;
match tier {
PrivacyTier::AccessOpen => {
config.node_mode = NodeMode::SoftwareOnly;
config.verify_attestation = false;
}
PrivacyTier::AccessAtRest => {
config.node_mode = NodeMode::SimOnly;
config.verify_attestation = false;
}
PrivacyTier::AccessCpuTee => {
config.node_mode = NodeMode::SimTee;
config.verify_attestation = true;
config.fips_mode = true;
}
PrivacyTier::AccessCpuTeePlusGpuCc | PrivacyTier::AccessGpuTeeIoMax => {
config.node_mode = NodeMode::SimTee;
config.verify_attestation = true;
config.fips_mode = true;
config.kem = KemAlgorithm::MlKem1024;
config.default_kem = DefaultKem::MlKem1024;
config.sig = SignatureAlgorithm::MlDsa87;
config.default_sig = DefaultSig::MlDsa87;
}
}
config
}
pub fn validate(&self) -> Result<(), String> {
if self.fips_mode {
if self.rng != RngSource::FipsDrbg && self.rng != RngSource::Os {
return Err("FIPS mode requires approved RNG".to_string());
}
}
if self.min_privacy_tier >= PrivacyTier::AccessCpuTee && !self.verify_attestation {
return Err("CPU TEE tier requires attestation verification".to_string());
}
match self.node_mode {
NodeMode::SoftwareOnly => {
if self.min_privacy_tier > PrivacyTier::AccessOpen {
return Err(
"Software-only mode cannot provide higher privacy tiers".to_string()
);
}
}
NodeMode::SimOnly => {
if self.min_privacy_tier > PrivacyTier::AccessAtRest {
return Err("SIM-only mode limited to at-rest protection".to_string());
}
}
NodeMode::SimTee => {
}
}
Ok(())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MigrationConfig {
pub dual_sign: bool,
pub accept_classical: bool,
pub prefer_pqc: bool,
pub deadline: Option<u64>,
}
impl Default for MigrationConfig {
fn default() -> Self {
Self {
dual_sign: true,
accept_classical: true,
prefer_pqc: true,
deadline: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_validation() {
let config = PqcConfig::default();
if let Err(e) = config.validate() {
println!("Default config validation failed: {}", e);
}
assert!(config.validate().is_ok());
let mut bad_config = PqcConfig::default();
bad_config.node_mode = NodeMode::SoftwareOnly;
bad_config.min_privacy_tier = PrivacyTier::AccessCpuTee;
assert!(bad_config.validate().is_err());
}
#[test]
fn test_tier_config() {
let config = PqcConfig::for_privacy_tier(PrivacyTier::AccessGpuTeeIoMax);
assert_eq!(config.kem, KemAlgorithm::MlKem1024);
assert!(config.verify_attestation);
assert!(config.fips_mode);
}
}