use super::msg::{self, Body};
use crate::relaycell::extlist::{ExtList, decl_extension_group};
use caret::caret_int;
use derive_deftly::Deftly;
use tor_bytes::{EncodeError, EncodeResult, Error as BytesError, Result};
use tor_bytes::{Reader, Writer};
use tor_hscrypto::RendCookie;
use tor_llcrypto::pk::rsa::RsaIdentity;
use tor_memquota::derive_deftly_template_HasMemoryCost;
pub mod est_intro;
pub mod intro_payload;
pub mod pow;
pub use crate::relaycell::extlist::UnrecognizedExt;
caret_int! {
#[derive(Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct AuthKeyType(u8) {
ED25519_SHA3_256 = 2,
}
}
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct EstablishRendezvous {
cookie: RendCookie,
}
impl EstablishRendezvous {
pub fn new(cookie: RendCookie) -> Self {
Self { cookie }
}
}
impl msg::Body for EstablishRendezvous {
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let cookie = r.extract()?;
r.take_rest();
Ok(Self { cookie })
}
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
w.write(&self.cookie)
}
}
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Introduce1(Introduce);
impl msg::Body for Introduce1 {
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let (intro, _) = Introduce::decode_from_reader(r)?;
Ok(Self(intro))
}
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
self.0.encode_onto(w)
}
}
impl Introduce1 {
pub fn new(auth_key_type: AuthKeyType, auth_key: Vec<u8>, encrypted: Vec<u8>) -> Self {
Self(Introduce::new(auth_key_type, auth_key, encrypted))
}
}
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Introduce2 {
encoded_header: Vec<u8>,
msg: Introduce,
}
impl msg::Body for Introduce2 {
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let (msg, header) = Introduce::decode_from_reader(r)?;
let encoded_header = header.to_vec();
Ok(Self {
encoded_header,
msg,
})
}
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
self.msg.encode_onto(w)
}
}
impl Introduce2 {
#[cfg(test)] pub fn new(auth_key_type: AuthKeyType, auth_key: Vec<u8>, encrypted: Vec<u8>) -> Self {
use tor_bytes::Writeable as _;
let msg = Introduce::new(auth_key_type, auth_key, encrypted);
let mut encoded_header = Vec::new();
msg.header
.write_onto(&mut encoded_header)
.expect("Generated a header that we could not encode");
Self {
encoded_header,
msg,
}
}
pub fn encoded_header(&self) -> &[u8] {
&self.encoded_header[..]
}
pub fn header(&self) -> &IntroduceHeader {
&self.msg.header
}
pub fn encrypted_body(&self) -> &[u8] {
&self.msg.encrypted[..]
}
}
caret_int! {
#[derive(Ord,PartialOrd)]
pub struct IntroduceExtType(u8) {
}
}
decl_extension_group! {
#[derive(Debug,Clone,Deftly)]
#[derive_deftly(HasMemoryCost)]
enum IntroduceExt [ IntroduceExtType ] {
}
}
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct IntroduceHeader {
auth_key_type: AuthKeyType,
auth_key: Vec<u8>,
extensions: ExtList<IntroduceExt>,
}
impl tor_bytes::Readable for IntroduceHeader {
fn take_from(r: &mut Reader<'_>) -> Result<Self> {
let legacy_key_id: RsaIdentity = r.extract()?;
if !legacy_key_id.is_zero() {
return Err(BytesError::InvalidMessage(
"legacy key id in Introduce1.".into(),
));
}
let auth_key_type = r.take_u8()?.into();
let auth_key_len = r.take_u16()?;
let auth_key = r.take(auth_key_len as usize)?.into();
let extensions = r.extract()?;
Ok(Self {
auth_key_type,
auth_key,
extensions,
})
}
}
impl tor_bytes::Writeable for IntroduceHeader {
fn write_onto<W: Writer + ?Sized>(&self, w: &mut W) -> EncodeResult<()> {
w.write_all(&[0_u8; 20]);
w.write_u8(self.auth_key_type.get());
w.write_u16(u16::try_from(self.auth_key.len()).map_err(|_| EncodeError::BadLengthValue)?);
w.write_all(&self.auth_key[..]);
w.write(&self.extensions)?;
Ok(())
}
}
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
struct Introduce {
header: IntroduceHeader,
encrypted: Vec<u8>,
}
impl Introduce {
fn new(auth_key_type: AuthKeyType, auth_key: Vec<u8>, encrypted: Vec<u8>) -> Self {
Self {
header: IntroduceHeader {
auth_key_type,
auth_key,
extensions: Default::default(),
},
encrypted,
}
}
fn decode_from_reader<'a>(r: &mut Reader<'a>) -> Result<(Self, &'a [u8])> {
let header_start = r.cursor();
let header = r.extract()?;
let header_end = r.cursor();
let encrypted = r.take_rest().into();
Ok((
Self { header, encrypted },
r.range(header_start, header_end),
))
}
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
w.write(&self.header)?;
w.write_all(&self.encrypted[..]);
Ok(())
}
}
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Rendezvous1 {
cookie: RendCookie,
handshake_info: Vec<u8>,
}
impl Body for Rendezvous1 {
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let cookie = r.extract()?;
let handshake_info = r.take_rest().into();
Ok(Self {
cookie,
handshake_info,
})
}
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
w.write(&self.cookie)?;
w.write_all(&self.handshake_info[..]);
Ok(())
}
}
impl Rendezvous1 {
pub fn new(cookie: RendCookie, handshake_info: impl Into<Vec<u8>>) -> Self {
Self {
cookie,
handshake_info: handshake_info.into(),
}
}
}
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Rendezvous2 {
handshake_info: Vec<u8>,
}
impl Rendezvous2 {
pub fn new(handshake_info: impl Into<Vec<u8>>) -> Self {
Self {
handshake_info: handshake_info.into(),
}
}
pub fn handshake_info(&self) -> &[u8] {
&self.handshake_info
}
}
impl From<Rendezvous1> for Rendezvous2 {
fn from(value: Rendezvous1) -> Self {
Self {
handshake_info: value.handshake_info,
}
}
}
impl Body for Rendezvous2 {
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let handshake_info = r.take_rest().into();
Ok(Self { handshake_info })
}
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
w.write_all(&self.handshake_info[..]);
Ok(())
}
}
caret_int! {
#[derive(Ord, PartialOrd)]
pub struct IntroEstablishedExtType(u8) {
}
}
decl_extension_group! {
#[derive(Debug,Clone,Deftly)]
#[derive_deftly(HasMemoryCost)]
#[non_exhaustive]
pub enum IntroEstablishedExt [ IntroEstablishedExtType ] {
}
}
#[derive(Debug, Clone, Default, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct IntroEstablished {
extensions: ExtList<IntroEstablishedExt>,
}
impl IntroEstablished {
pub fn new() -> Self {
Self::default()
}
pub fn iter_extensions(&self) -> impl Iterator<Item = &IntroEstablishedExt> {
self.extensions.iter()
}
}
impl Body for IntroEstablished {
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let extensions = r.extract()?;
Ok(Self { extensions })
}
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
w.write(&self.extensions)?;
Ok(())
}
}
caret_int! {
#[derive(Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct IntroduceAckStatus(u16) {
SUCCESS = 0x0000,
NOT_RECOGNIZED = 0x0001,
BAD_MESSAGE_FORMAT = 0x0002,
CANT_RELAY = 0x0003,
}
}
caret_int! {
#[derive(Ord, PartialOrd, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct IntroduceAckExtType(u8) {
}
}
decl_extension_group! {
#[derive(Debug,Clone,Deftly)]
#[derive_deftly(HasMemoryCost)]
enum IntroduceAckExt [ IntroduceAckExtType ] {
}
}
#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct IntroduceAck {
status_code: IntroduceAckStatus,
extensions: ExtList<IntroduceAckExt>,
}
impl IntroduceAck {
pub fn new(status_code: IntroduceAckStatus) -> Self {
Self {
status_code,
extensions: Default::default(),
}
}
pub fn status(&self) -> IntroduceAckStatus {
self.status_code
}
pub fn success(self) -> std::result::Result<IntroduceAck, IntroduceAckStatus> {
if self.status() == IntroduceAckStatus::SUCCESS {
Ok(self)
} else {
Err(self.status())
}
}
}
impl Body for IntroduceAck {
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let status_code = r.take_u16()?.into();
let extensions = r.extract()?;
Ok(IntroduceAck {
status_code,
extensions,
})
}
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
w.write_u16(self.status_code.into());
w.write(&self.extensions)?;
Ok(())
}
}
impl tor_error::HasRetryTime for IntroduceAckStatus {
fn retry_time(&self) -> tor_error::RetryTime {
use IntroduceAckStatus as S;
use tor_error::RetryTime as RT;
match *self {
S::SUCCESS => RT::Never, S::NOT_RECOGNIZED => RT::AfterWaiting,
S::BAD_MESSAGE_FORMAT => RT::Never,
S::CANT_RELAY => RT::AfterWaiting,
_ => RT::AfterWaiting, }
}
}
super::msg::empty_body! {
pub struct RendezvousEstablished {}
}