Skip to main content

tor_proto/relay/channel/
initiator.rs

1//! Relay initiator channel.
2//!
3//! Code only related to a relay channel opened as an initiator. The handshake code is responsible
4//! for creating an [`UnverifiedInitiatorRelayChannel`] when connecting to another relay in order
5//! to build a tor channel.
6//!
7//! The [`UnverifiedInitiatorRelayChannel::verify`] function needs to be called to verify the
8//! underlying channel and build a [`VerifiedInitiatorRelayChannel`] channel which needs to be
9//! finished with [`VerifiedInitiatorRelayChannel::finish`] to get a Channel/Reactor.
10//!
11//! Note that channel cells are sent in the handshake upon connection. And then in the finish()
12//! process. The verify can be CPU intensive and thus in its own function.
13
14use digest::Digest;
15use futures::{AsyncRead, AsyncWrite, SinkExt};
16use safelog::MaybeSensitive;
17use std::{net::IpAddr, ops::Deref, sync::Arc};
18use tracing::trace;
19
20use tor_cell::chancell::msg;
21use tor_linkspec::OwnedChanTarget;
22use tor_rtcompat::{CertifiedConn, CoarseTimeProvider, Runtime, SleepProvider, StreamOps};
23
24use crate::{
25    ClockSkew, RelayChannelAuthMaterial, Result,
26    channel::{
27        Channel, ChannelMode, ClogDigest, Reactor, SlogDigest,
28        circmap::CircIdRange,
29        handshake::{UnverifiedInitiatorChannel, VerifiedChannel},
30    },
31    peer::{PeerAddr, PeerInfo},
32    relay::CreateRequestHandler,
33    relay::channel::ChannelAuthenticationData,
34};
35
36/// An unverified relay initiator channel.
37///
38/// This is built by the [`crate::relay::channel::handshake::RelayInitiatorHandshake`] upon a
39/// connect. It has everything needed to verify in order to get a verified channel.
40pub struct UnverifiedInitiatorRelayChannel<
41    T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
42    S: CoarseTimeProvider + SleepProvider,
43> {
44    /// The common unverified channel that both client and relays use.
45    pub(crate) inner: UnverifiedInitiatorChannel<T, S>,
46    /// AUTH_CHALLENGE cell received from the responder.
47    pub(crate) auth_challenge_cell: msg::AuthChallenge,
48    /// The SLOG digest.
49    pub(crate) slog_digest: SlogDigest,
50    /// The netinfo cell received from the responder.
51    pub(crate) netinfo_cell: msg::Netinfo,
52    /// Our channel key material needed for authentication.
53    pub(crate) auth_material: Arc<RelayChannelAuthMaterial>,
54    /// Our advertised IP addresses for the final NETINFO
55    pub(crate) my_addrs: Vec<IpAddr>,
56    /// Provided to each new channel so that they can handle CREATE* requests.
57    pub(crate) create_request_handler: Arc<CreateRequestHandler>,
58}
59
60impl<T, S> UnverifiedInitiatorRelayChannel<T, S>
61where
62    T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
63    S: CoarseTimeProvider + SleepProvider,
64{
65    /// Validate the certificates and keys in the relay's handshake. As an initiator, we always
66    /// authenticate no matter what.
67    ///
68    /// 'peer_target' is the peer that we want to make sure we're connecting to.
69    ///
70    /// 'peer_tls_cert' is the x.509 certificate that the peer presented during its TLS handshake
71    /// (ServerHello).
72    ///
73    /// 'now' is the time at which to check that certificates are valid.  `None` means to use the
74    /// current time. It can be used for testing to override the current view of the time.
75    ///
76    /// This is a separate function because it's likely to be somewhat CPU-intensive.
77    pub fn verify(
78        self,
79        peer_target: &OwnedChanTarget,
80        peer_tls_cert: &[u8],
81        now: Option<std::time::SystemTime>,
82    ) -> Result<VerifiedInitiatorRelayChannel<T, S>> {
83        // Get these object out as we consume "self" in the inner check().
84        let auth_challenge_cell = self.auth_challenge_cell;
85        let identities = self.auth_material;
86        let my_addrs = self.my_addrs;
87        let netinfo_cell = self.netinfo_cell;
88
89        let peer_tls_cert_digest = tor_llcrypto::d::Sha256::digest(peer_tls_cert).into();
90
91        // Verify our inner channel and then proceed to handle the authentication challenge if any.
92        let verified = self.inner.verify(peer_target, peer_tls_cert_digest, now)?;
93
94        Ok(VerifiedInitiatorRelayChannel {
95            inner: verified,
96            auth_material: identities,
97            netinfo_cell,
98            auth_challenge_cell,
99            peer_tls_cert_digest,
100            slog_digest: self.slog_digest,
101            my_addrs,
102            create_request_handler: self.create_request_handler,
103        })
104    }
105
106    /// Return the clock skew of this channel.
107    pub fn clock_skew(&self) -> ClockSkew {
108        self.inner.inner.clock_skew
109    }
110
111    /// Return the link protocol version of this channel.
112    #[cfg(test)]
113    pub(crate) fn link_protocol(&self) -> u16 {
114        self.inner.inner.link_protocol
115    }
116}
117
118/// A verified relay initiator channel.
119///
120/// Holding this object means the channel TLS layer has been verified against the received CERTS
121/// cell and we now believe that we are talking to the right relay end point.
122///
123/// The finish() function needs to be called in order to finalize this channel into a generic
124/// Channel/Reactor.
125pub struct VerifiedInitiatorRelayChannel<
126    T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
127    S: CoarseTimeProvider + SleepProvider,
128> {
129    /// The common unverified channel that both client and relays use.
130    inner: VerifiedChannel<T, S>,
131    /// Relay channel authentication material.
132    auth_material: Arc<RelayChannelAuthMaterial>,
133    /// The netinfo cell that we got from the relay.
134    netinfo_cell: msg::Netinfo,
135    /// The AUTH_CHALLENGE cell that we got from the relay.
136    auth_challenge_cell: msg::AuthChallenge,
137    /// The peer TLS certificate digest.
138    peer_tls_cert_digest: [u8; 32],
139    /// The SLOG digest.
140    slog_digest: SlogDigest,
141    /// Our advertised IP addresses.
142    my_addrs: Vec<IpAddr>,
143    /// Provided to each new channel so that they can handle CREATE* requests.
144    create_request_handler: Arc<CreateRequestHandler>,
145}
146
147impl<T, S> VerifiedInitiatorRelayChannel<T, S>
148where
149    T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
150    S: CoarseTimeProvider + SleepProvider,
151{
152    /// Send our [`msg::Certs`], [`msg::Authenticate`] and [`msg::Netinfo`] to the relay to finish
153    /// the handshake, which will create an open channel and reactor.
154    ///
155    /// The resulting channel is considered, by Tor protocol standard, an authenticated relay
156    /// channel on which circuits can be opened.
157    pub async fn finish(mut self, peer_addr: PeerAddr) -> Result<(Arc<Channel>, Reactor<S>)>
158    where
159        S: Runtime,
160    {
161        // Send the CERTS cell.
162        let certs = super::build_certs_cell(&self.auth_material, /* is_responder */ false);
163        trace!(channel_id = %self.inner.unique_id, "Sending CERTS as initiator cell.");
164        self.inner.framed_tls.send(certs.into()).await?;
165
166        // We're the initiator, which means that the send log is the CLOG.
167        //
168        // We can finalize the CLOG now that we're about to send the AUTHENTICATE cell.
169        //
170        // > The CLOG field is computed as the SHA-256 digest of all bytes sent within
171        // > the TLS channel up to but not including the AUTHENTICATE cell.
172        let clog_digest =
173            ClogDigest::new(self.inner.framed_tls.codec_mut().take_send_log_digest()?);
174
175        // Build the AUTHENTICATE cell.
176        //
177        // By building the ChannelAuthenticationData, we are certain that the authentication
178        // type requested by the responder is supported by us.
179        let auth_cell = ChannelAuthenticationData::build_initiator(
180            &self.auth_challenge_cell,
181            &self.auth_material,
182            clog_digest,
183            self.slog_digest,
184            &mut self.inner,
185            self.peer_tls_cert_digest,
186        )?
187        .into_authenticate(
188            self.inner.framed_tls.deref(),
189            &self.auth_material.link_sign_kp,
190        )?;
191
192        // Send the AUTHENTICATE cell.
193        trace!(channel_id = %self.inner.unique_id, "Sending AUTHENTICATE as initiator cell.");
194        self.inner.framed_tls.send(auth_cell.into()).await?;
195
196        // Send our NETINFO cell. This will indicate the end of the handshake.
197        let netinfo = super::build_netinfo_cell(
198            peer_addr.netinfo_addr(),
199            self.my_addrs.clone(),
200            &self.inner.sleep_prov,
201        )?;
202        trace!(channel_id = %self.inner.unique_id, "Sending NETINFO as initiator cell.");
203        self.inner.framed_tls.send(netinfo.into()).await?;
204
205        // Relay only initiate to another relay so NOT sensitive.
206        let peer_info =
207            MaybeSensitive::not_sensitive(PeerInfo::new(peer_addr, self.inner.relay_ids().clone()));
208
209        let channel_mode = ChannelMode::Relay {
210            circ_id_range: CircIdRange::High,
211            our_ed25519_id: self.auth_material.ed_id,
212            our_rsa_id: self.auth_material.rsa_id,
213            create_request_handler: self.create_request_handler,
214        };
215
216        // Get a Channel and a Reactor.
217        self.inner
218            .finish(&self.netinfo_cell, &self.my_addrs, peer_info, channel_mode)
219            .await
220    }
221}