use std::borrow::Borrow;
use crate::Result;
use tor_bytes::SecretBuf;
pub(crate) trait ClientHandshake {
type KeyType;
type StateType;
type KeyGen;
type ClientAuxData: ?Sized;
type ServerAuxData;
fn client1<M: Borrow<Self::ClientAuxData>>(
key: &Self::KeyType,
client_aux_data: &M,
) -> Result<(Self::StateType, Vec<u8>)>;
fn client2<T: AsRef<[u8]>>(
state: Self::StateType,
msg: T,
) -> Result<(Self::ServerAuxData, Self::KeyGen)>;
}
pub(crate) trait AuxDataReply<H>
where
H: ServerHandshake + ?Sized,
{
fn reply(&mut self, msg: &H::ClientAuxData) -> Option<H::ServerAuxData>;
}
impl<F, H> AuxDataReply<H> for F
where
H: ServerHandshake + ?Sized,
F: FnMut(&H::ClientAuxData) -> Option<H::ServerAuxData>,
{
fn reply(&mut self, msg: &H::ClientAuxData) -> Option<H::ServerAuxData> {
self(msg)
}
}
pub(crate) trait ServerHandshake {
type KeyType;
type KeyGen;
type ClientAuxData: ?Sized;
type ServerAuxData;
fn server<REPLY: AuxDataReply<Self>, T: AsRef<[u8]>>(
&self,
reply_fn: &mut REPLY,
key: &[Self::KeyType],
msg: T,
) -> RelayHandshakeResult<(Self::KeyGen, Vec<u8>)>;
}
#[allow(unreachable_pub)] pub trait KeyGenerator {
fn expand(self, keylen: usize) -> Result<SecretBuf>;
}
pub(crate) struct ShakeKeyGenerator {
seed: SecretBuf,
}
impl ShakeKeyGenerator {
#[allow(dead_code)] pub(crate) fn new(seed: SecretBuf) -> Self {
ShakeKeyGenerator { seed }
}
}
impl KeyGenerator for ShakeKeyGenerator {
fn expand(self, keylen: usize) -> Result<SecretBuf> {
use crate::common::kdf::{Kdf, ShakeKdf};
ShakeKdf::new().derive(&self.seed[..], keylen)
}
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum RelayHandshakeError {
#[error("try again with updated input")]
EAgain,
#[error("Problem decoding onion handshake")]
Fmt(#[from] tor_bytes::Error),
#[error("Client asked for a key or ID that we don't have")]
MissingKey,
#[error("Bad handshake from client")]
BadClientHandshake,
#[error("Bad handshake from server")]
BadServerHandshake,
#[error("Handshake from client was seen recently -- potentially replayed.")]
ReplayedHandshake,
#[error("Problem occured while building handshake")]
FrameError(String),
#[error("Internal error")]
Internal(#[from] tor_error::Bug),
}
pub(crate) type RelayHandshakeResult<T> = std::result::Result<T, RelayHandshakeError>;