dope-tls 0.14.0

TCP TLS streams for dope runtime, shin-backed
Documentation
use std::rc::Rc;

use shin::{
    Epoch, Event,
    client::{self, Client},
    record::CipherSuite,
    server::{self, ClientAuth, ClientCertVerifier, ClientIdentity, Server},
};

use crate::{clock::WallClock, error::Error};

pub(super) struct RcVerifier(Rc<dyn ClientCertVerifier>);

impl ClientCertVerifier for RcVerifier {
    fn verify(&self, identity: &ClientIdentity<'_>) -> bool {
        self.0.verify(identity)
    }
}

type StandardServer = server::Server<WallClock, server::NoGuard, server::NoClientAuth>;
type MutualServer = server::Server<WallClock, server::NoGuard, RcVerifier>;

pub(super) enum Side {
    Client(Box<client::Client<WallClock>>),
    Server(Box<StandardServer>),
    MutualServer(Box<MutualServer>),
}

impl Side {
    pub(super) fn client(
        config: client::Config,
        clock: WallClock,
        configure: impl FnOnce(&mut client::Client<WallClock>),
    ) -> Result<(Self, Vec<Event>), Error> {
        config.validate().map_err(Error::Handshake)?;
        let mut client = Box::new(Client::new(config, clock));
        configure(&mut client);
        let events = client.start().map_err(Error::Handshake)?;
        Ok((Self::Client(client), events))
    }

    pub(super) fn server(config: server::Config, clock: WallClock) -> Result<Self, Error> {
        config.validate().map_err(Error::Handshake)?;
        Ok(Self::Server(Box::new(Server::new(config, clock))))
    }

    pub(super) fn server_mutual(
        config: server::Config,
        clock: WallClock,
        auth: ClientAuth,
        verifier: Rc<dyn ClientCertVerifier>,
    ) -> Result<Self, Error> {
        config.validate().map_err(Error::Handshake)?;
        Ok(Self::MutualServer(Box::new(Server::with_client_auth(
            config,
            clock,
            auth,
            RcVerifier(verifier),
        ))))
    }

    pub(super) fn read(&mut self, epoch: Epoch, data: &[u8]) -> Result<Vec<Event>, shin::Error> {
        match self {
            Self::Client(client) => client.read(epoch, data),
            Self::Server(server) => server.read(epoch, data),
            Self::MutualServer(server) => server.read(epoch, data),
        }
    }

    pub(super) fn send_key_update(&mut self, request: bool) -> Result<Vec<Event>, Error> {
        match self {
            Self::Client(client) => client.send_key_update(request),
            Self::Server(server) => server.send_key_update(request),
            Self::MutualServer(server) => server.send_key_update(request),
        }
        .map_err(Error::Handshake)
    }

    pub(super) fn note_application_data(&mut self) {
        match self {
            Self::Client(client) => client.note_application_data(),
            Self::Server(server) => server.note_application_data(),
            Self::MutualServer(server) => server.note_application_data(),
        }
    }

    pub(super) fn selected_alpn(&self) -> Option<&[u8]> {
        match self {
            Self::Client(client) => client.selected_alpn(),
            Self::Server(server) => server.selected_alpn(),
            Self::MutualServer(server) => server.selected_alpn(),
        }
    }

    pub(super) fn cipher_suite(&self) -> CipherSuite {
        let negotiated = match self {
            Self::Client(client) => client.negotiated_cipher_suite(),
            Self::Server(server) => server.negotiated_cipher_suite(),
            Self::MutualServer(server) => server.negotiated_cipher_suite(),
        };
        negotiated.unwrap_or(CipherSuite::Aes128GcmSha256)
    }
}