ytls-server 0.0.9

yolox sans-io TLS server context
Documentation
//! Encrypted Extensions handler for Server Handshake Ctx

use crate::{CtxError, ServerHandshakeCtx, TlsServerCtxConfig};

use ytls_traits::CryptoChaCha20Poly1305Processor;
use ytls_traits::CryptoSha256TranscriptProcessor;

use ytls_traits::CryptoConfig;
use ytls_traits::CryptoRng;
use ytls_traits::TlsLeftOut;

use ytls_traits::Tls13KeyScheduleHandshakeSha256;

use ytls_record::WrappedStaticRecordBuilder;
use ytls_traits::ServerCertificatesBuilder;
use ytls_traits::WrappedHandshakeBuilder;

impl<Config, Crypto, Rng> ServerCertificatesBuilder for ServerHandshakeCtx<Config, Crypto, Rng>
where
    Config: TlsServerCtxConfig,
    Crypto: CryptoConfig,
    Rng: CryptoRng,
{
    #[inline]
    fn server_certs_list(&self) -> &[u8] {
        self.config.server_cert_chain()
    }
    #[inline]
    fn server_cert_data(&self, id: u8) -> &[u8] {
        self.config.server_cert(id)
    }
    #[inline]
    fn server_cert_extensions(&self, _id: u8) -> &[u8] {
        &[]
    }
}

impl<Config, Crypto, Rng> ServerHandshakeCtx<Config, Crypto, Rng>
where
    Config: TlsServerCtxConfig,
    Crypto: CryptoConfig,
    Rng: CryptoRng,
{
    #[inline]
    pub(crate) fn do_server_certificates<L: TlsLeftOut, T: CryptoSha256TranscriptProcessor>(
        &mut self,
        left: &mut L,
        transcript: &mut T,
    ) -> Result<(), CtxError> {
        let key: [u8; 32] = match self.handshake_server_key {
            None => return Err(CtxError::MissingHandshakeKey),
            Some(k) => k,
        };

        let nonce: [u8; 12] = match self.handshake_server_iv {
            None => return Err(CtxError::MissingHandshakeIv),
            Some(ref mut n) => match n.use_and_incr() {
                Some(cur) => cur,
                None => return Err(CtxError::ExhaustedIv),
            },
        };

        let cipher = Crypto::aead_chaha20poly1305(&key);

        let mut server_certificates = WrappedStaticRecordBuilder::<8192>::server_certificates(self)
            .map_err(CtxError::Builder)?;

        transcript.sha256_update(server_certificates.as_hashing_context_ref());

        let tag = if let Ok([additional_data, encrypt_payload]) =
            server_certificates.as_disjoint_mut_for_aead()
        {
            cipher
                .encrypt_in_place(&nonce, &additional_data, encrypt_payload.as_mut())
                .map_err(|_| CtxError::Bug("Encrypt failure."))?
        } else {
            return Err(CtxError::Bug(
                "Disjoint for AEAD failed at certificate verify.",
            ));
        };

        server_certificates.set_auth_tag(&tag);

        left.send_record_out(server_certificates.as_encoded_bytes());
        Ok(())
    }
}