use std::sync::Arc;
use tokio::sync::RwLock;
use crate::{QsslResult};
use crate::crypto::{CipherSuite, KemAlgorithm, SignatureAlgorithm};
#[derive(Clone)]
pub struct QsslContext {
pub cipher_suites: Vec<CipherSuite>,
pub kem_algorithms: Vec<KemAlgorithm>,
pub signature_algorithms: Vec<SignatureAlgorithm>,
pub session_resumption: bool,
pub session_cache_size: usize,
pub zero_rtt: bool,
pub max_early_data: usize,
pub certificate_chain: Option<Vec<Vec<u8>>>,
pub private_key: Option<Vec<u8>>,
pub trusted_cas: Vec<Vec<u8>>,
pub alpn_protocols: Vec<String>,
pub server_name: Option<String>,
pub verify_peer: bool,
pub key_log_callback: Option<Arc<dyn Fn(&str) + Send + Sync>>,
}
impl Default for QsslContext {
fn default() -> Self {
Self {
cipher_suites: vec![
CipherSuite::SphincsKemFalcon512Aes256, CipherSuite::SphincsKemFalcon512Aes128,
CipherSuite::SphincsKemFalcon1024Aes256,
CipherSuite::Kyber768Falcon512Aes256, CipherSuite::Kyber512Falcon512Aes128,
CipherSuite::Kyber1024Falcon1024Aes256,
],
kem_algorithms: vec![
KemAlgorithm::SphincsKem, KemAlgorithm::Kyber768, KemAlgorithm::Kyber512,
KemAlgorithm::Kyber1024,
],
signature_algorithms: vec![
SignatureAlgorithm::Falcon512,
SignatureAlgorithm::Falcon1024,
SignatureAlgorithm::Dilithium3,
],
session_resumption: true,
session_cache_size: 1000,
zero_rtt: false,
max_early_data: 16384,
certificate_chain: None,
private_key: None,
trusted_cas: Vec::new(),
alpn_protocols: Vec::new(),
server_name: None,
verify_peer: true,
key_log_callback: None,
}
}
}
impl QsslContext {
pub fn new() -> Self {
Self::default()
}
pub fn client() -> Self {
let mut ctx = Self::default();
ctx.verify_peer = true;
ctx
}
pub fn server() -> Self {
let mut ctx = Self::default();
ctx.verify_peer = false; ctx
}
pub fn set_cipher_suites(&mut self, suites: Vec<CipherSuite>) -> &mut Self {
self.cipher_suites = suites;
self
}
pub fn set_certificate_chain(&mut self, chain: Vec<Vec<u8>>) -> &mut Self {
self.certificate_chain = Some(chain);
self
}
pub fn set_private_key(&mut self, key: Vec<u8>) -> &mut Self {
self.private_key = Some(key);
self
}
pub fn add_trusted_ca(&mut self, ca: Vec<u8>) -> &mut Self {
self.trusted_cas.push(ca);
self
}
pub fn set_alpn_protocols(&mut self, protocols: Vec<String>) -> &mut Self {
self.alpn_protocols = protocols;
self
}
pub fn set_server_name(&mut self, name: String) -> &mut Self {
self.server_name = Some(name);
self
}
pub fn set_verify_peer(&mut self, verify: bool) -> &mut Self {
self.verify_peer = verify;
self
}
pub fn enable_session_resumption(&mut self, cache_size: usize) -> &mut Self {
self.session_resumption = true;
self.session_cache_size = cache_size;
self
}
pub fn enable_zero_rtt(&mut self, max_early_data: usize) -> &mut Self {
self.zero_rtt = true;
self.max_early_data = max_early_data;
self
}
pub fn set_key_log_callback<F>(&mut self, callback: F) -> &mut Self
where
F: Fn(&str) + Send + Sync + 'static,
{
self.key_log_callback = Some(Arc::new(callback));
self
}
pub fn validate(&self) -> QsslResult<()> {
if self.cipher_suites.is_empty() {
return Err(crate::QsslError::Protocol(
"No cipher suites configured".to_string(),
));
}
if self.kem_algorithms.is_empty() {
return Err(crate::QsslError::Protocol(
"No KEM algorithms configured".to_string(),
));
}
if self.signature_algorithms.is_empty() {
return Err(crate::QsslError::Protocol(
"No signature algorithms configured".to_string(),
));
}
if self.certificate_chain.is_none() && self.private_key.is_some() {
return Err(crate::QsslError::Protocol(
"Private key provided without certificate".to_string(),
));
}
if self.certificate_chain.is_some() && self.private_key.is_none() {
return Err(crate::QsslError::Protocol(
"Certificate provided without private key".to_string(),
));
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_context() {
let ctx = QsslContext::default();
assert!(!ctx.cipher_suites.is_empty());
assert!(ctx.session_resumption);
assert!(!ctx.zero_rtt);
}
#[test]
fn test_client_context() {
let ctx = QsslContext::client();
assert!(ctx.verify_peer);
}
#[test]
fn test_server_context() {
let ctx = QsslContext::server();
assert!(!ctx.verify_peer);
}
#[test]
fn test_context_validation() {
let mut ctx = QsslContext::new();
assert!(ctx.validate().is_ok());
ctx.cipher_suites.clear();
assert!(ctx.validate().is_err());
}
}