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}