qssh 0.4.4

Post-quantum secure shell with NIST PQC algorithms (Falcon, SPHINCS+, ML-KEM), configurable security tiers, and quantum-resistant protocol design
Documentation
//! QSSL-based transport for QSSH
//!
//! This module provides a QSSL transport layer that can be used
//! instead of the custom transport implementation.

use std::sync::Arc;
use tokio::net::TcpStream;
use tokio::io::{AsyncRead, AsyncWrite, AsyncReadExt, AsyncWriteExt};
use serde::{Serialize, Deserialize};

use crate::{QsshError, Result};

// Import QSSL types when available
// For now, we'll define a trait that can be implemented by QSSL

/// QSSL Transport trait for QSSH integration
#[async_trait::async_trait]
pub trait QsslTransportLayer: Send + Sync {
    /// Perform handshake
    async fn handshake(&mut self) -> Result<()>;

    /// Send encrypted message
    async fn send_message<T: Serialize + Send + Sync>(&self, message: &T) -> Result<()>;

    /// Receive encrypted message
    async fn recv_message<T: for<'de> Deserialize<'de>>(&self) -> Result<T>;

    /// Get negotiated cipher suite
    fn cipher_suite(&self) -> String;

    /// Check if connection is established
    async fn is_established(&self) -> bool;

    /// Close connection
    async fn close(&self) -> Result<()>;
}

/// QSSL-based transport implementation for QSSH
pub struct QsslTransport {
    inner: Option<Arc<dyn QsslTransportLayer>>,
    stream: Option<TcpStream>,
    is_client: bool,
}

impl QsslTransport {
    /// Create new QSSL transport
    pub fn new(stream: TcpStream, is_client: bool) -> Self {
        Self {
            inner: None,
            stream: Some(stream),
            is_client,
        }
    }

    /// Initialize with QSSL connection
    pub async fn init_with_qssl(&mut self) -> Result<()> {
        // This will be implemented when QSSL is linked
        // For now, we prepare the interface

        if let Some(stream) = self.stream.take() {
            // When QSSL is available:
            // if self.is_client {
            //     let conn = qssl::QsslConnection::connect_from_stream(stream).await?;
            //     self.inner = Some(Arc::new(QsslConnectionWrapper::new(conn)));
            // } else {
            //     let conn = qssl::QsslConnection::accept(stream).await?;
            //     self.inner = Some(Arc::new(QsslConnectionWrapper::new(conn)));
            // }

            // Placeholder for now
            return Err(QsshError::Protocol("QSSL not yet linked".to_string()));
        }

        Ok(())
    }

    /// Send message using QSSL
    pub async fn send<T: Serialize + Send + Sync>(&self, message: &T) -> Result<()> {
        if let Some(inner) = &self.inner {
            inner.send_message(message).await
        } else {
            Err(QsshError::Protocol("QSSL transport not initialized".to_string()))
        }
    }

    /// Receive message using QSSL
    pub async fn recv<T: for<'de> Deserialize<'de>>(&self) -> Result<T> {
        if let Some(inner) = &self.inner {
            inner.recv_message().await
        } else {
            Err(QsshError::Protocol("QSSL transport not initialized".to_string()))
        }
    }
}

/// Configuration for QSSL transport
#[derive(Debug, Clone)]
pub struct QsslConfig {
    /// Preferred cipher suites
    pub cipher_suites: Vec<String>,

    /// Enable session resumption
    pub session_resumption: bool,

    /// Enable 0-RTT
    pub zero_rtt: bool,

    /// Certificate path
    pub cert_path: Option<String>,

    /// Private key path
    pub key_path: Option<String>,

    /// Trusted CA path
    pub ca_path: Option<String>,
}

impl Default for QsslConfig {
    fn default() -> Self {
        Self {
            cipher_suites: vec![
                "QSSL_KYBER768_FALCON512_AES256_SHA384".to_string(),
                "QSSL_KYBER512_FALCON512_AES128_SHA256".to_string(),
            ],
            session_resumption: true,
            zero_rtt: false,
            cert_path: None,
            key_path: None,
            ca_path: None,
        }
    }
}

/// Factory for creating QSSL transports
pub struct QsslTransportFactory {
    config: QsslConfig,
}

impl QsslTransportFactory {
    /// Create new factory with config
    pub fn new(config: QsslConfig) -> Self {
        Self { config }
    }

    /// Create client transport
    pub async fn create_client(&self, addr: &str) -> Result<QsslTransport> {
        let stream = TcpStream::connect(addr).await.map_err(QsshError::Io)?;
        let mut transport = QsslTransport::new(stream, true);
        transport.init_with_qssl().await?;
        Ok(transport)
    }

    /// Create server transport from accepted connection
    pub async fn create_server(&self, stream: TcpStream) -> Result<QsslTransport> {
        let mut transport = QsslTransport::new(stream, false);
        transport.init_with_qssl().await?;
        Ok(transport)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_qssl_config() {
        let config = QsslConfig::default();
        assert!(!config.cipher_suites.is_empty());
        assert!(config.session_resumption);
        assert!(!config.zero_rtt);
    }

    #[test]
    fn test_qssl_transport_factory() {
        let config = QsslConfig::default();
        let factory = QsslTransportFactory::new(config);
        // Factory is ready for use when QSSL is linked
    }
}