Skip to main content

tor_proto/relay/
channel.rs

1//! Relay channel code.
2//!
3//! This contains relay specific channel code. In other words, everyting that a relay needs to
4//! establish a channel according to the Tor protocol.
5
6pub(crate) mod handshake;
7pub(crate) mod initiator;
8pub(crate) mod responder;
9
10pub use responder::MaybeVerifiableRelayResponderChannel;
11
12use digest::Digest;
13use futures::{AsyncRead, AsyncWrite};
14use rand::Rng;
15use safelog::Sensitive;
16use std::net::IpAddr;
17use std::sync::Arc;
18use std::time::UNIX_EPOCH;
19
20use tor_cell::chancell::msg;
21use tor_cert::rsa::EncodedRsaCrosscert;
22use tor_cert::x509::TlsKeyAndCert;
23use tor_cert::{CertType, EncodedEd25519Cert};
24use tor_error::internal;
25use tor_linkspec::{HasRelayIds, OwnedChanTarget, RelayIdRef, RelayIdType};
26use tor_llcrypto as ll;
27use tor_llcrypto::pk::{
28    ed25519::{Ed25519Identity, Ed25519SigningKey},
29    rsa,
30    rsa::RsaIdentity,
31};
32use tor_relay_crypto::pk::RelayLinkSigningKeypair;
33use tor_rtcompat::{CertifiedConn, CoarseTimeProvider, SleepProvider, StreamOps};
34
35use crate::channel::handshake::VerifiedChannel;
36use crate::relay::channel::handshake::{AUTHTYPE_ED25519_SHA256_RFC5705, RelayResponderHandshake};
37use crate::{Error, Result, channel::RelayInitiatorHandshake, memquota::ChannelAccount};
38
39// TODO(relay): We should probably get those values from protover crate or some other
40// crate that have all "network parameters" we support?
41/// A list of link authentication that we support (LinkAuth).
42pub(crate) static LINK_AUTH: &[u16] = &[AUTHTYPE_ED25519_SHA256_RFC5705];
43
44/// Object containing the key and certificate that basically identifies us as a relay. They are
45/// used for channel authentication.
46///
47/// We use this intermediary object in order to not have tor-proto crate have access to the KeyMgr
48/// meaning access to all keys. This restricts the view to what is needed.
49pub struct RelayIdentities {
50    /// The SHA256(DER(KP_relayid_rsa)) digest for the AUTHENTICATE cell CID.
51    pub(crate) rsa_id_der_digest: [u8; 32],
52    /// Our RSA identity `KP_relayid_rsa` (SHA1). Needed for HasRelayIds which is required to
53    /// compare this with a [`tor_linkspec::ChanTarget`].
54    pub(crate) rsa_id: RsaIdentity,
55    /// Our Ed identity key (KP_relayid_ed). For the [`msg::Authenticate`] cell CID_ED field.
56    pub(crate) ed_id: Ed25519Identity,
57    /// Our link signing keypair. Used to sign the [`msg::Authenticate`] cell.
58    pub(crate) link_sign_kp: RelayLinkSigningKeypair,
59    /// The Ed25519 identity signing cert (CertType 4) for the [`msg::Certs`] cell.
60    pub(crate) cert_id_sign_ed: EncodedEd25519Cert,
61    /// The Ed25519 signing TLS cert (CertType 5) for the [`msg::Certs`] cell.
62    pub(crate) cert_sign_tls_ed: EncodedEd25519Cert,
63    /// The Ed25519 signing link auth cert (CertType 6) for the [`msg::Certs`] cell.
64    pub(crate) cert_sign_link_auth_ed: EncodedEd25519Cert,
65    /// Legacy: the RSA identity X509 cert (CertType 2) for the [`msg::Certs`] cell.
66    ///
67    /// We only have the bytes here as create_legacy_rsa_id_cert() takes a key and gives us back
68    /// the encoded cert.
69    pub(crate) cert_id_x509_rsa: Vec<u8>,
70    /// Legacy: the RSA identity cert (CertType 7) for the [`msg::Certs`] cell.
71    pub(crate) cert_id_rsa: EncodedRsaCrosscert,
72    /// Tls key and cert. This is for the TLS acceptor object needed to be a responder (TLS server
73    /// side).
74    pub(crate) tls_key_and_cert: TlsKeyAndCert,
75}
76
77impl RelayIdentities {
78    /// Constructor.
79    #[allow(clippy::too_many_arguments)] // Yes, plethora of keys...
80    pub fn new(
81        rsa_id_pk: &rsa::PublicKey,
82        ed_id: Ed25519Identity,
83        link_sign_kp: RelayLinkSigningKeypair,
84        cert_id_sign_ed: EncodedEd25519Cert,
85        cert_sign_tls_ed: EncodedEd25519Cert,
86        cert_sign_link_auth_ed: EncodedEd25519Cert,
87        cert_id_x509_rsa: Vec<u8>,
88        cert_id_rsa: EncodedRsaCrosscert,
89        tls_key_and_cert: TlsKeyAndCert,
90    ) -> Self {
91        Self {
92            rsa_id_der_digest: ll::d::Sha256::digest(rsa_id_pk.to_der()).into(),
93            rsa_id: rsa_id_pk.to_rsa_identity(),
94            ed_id,
95            link_sign_kp,
96            cert_id_sign_ed,
97            cert_sign_tls_ed,
98            cert_sign_link_auth_ed,
99            cert_id_x509_rsa,
100            cert_id_rsa,
101            tls_key_and_cert,
102        }
103    }
104
105    /// Return the TLS key and certificate to use for the underlying TLS provider.
106    ///
107    /// This is used by the TLS acceptor that acts as the TLS server provider.
108    pub fn tls_key_and_cert(&self) -> &TlsKeyAndCert {
109        &self.tls_key_and_cert
110    }
111
112    /// Return our Ed identity key (KP_relayid_ed) as bytes.
113    pub(crate) fn ed_id_bytes(&self) -> [u8; 32] {
114        self.ed_id.into()
115    }
116}
117
118impl HasRelayIds for RelayIdentities {
119    fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
120        match key_type {
121            RelayIdType::Ed25519 => Some(RelayIdRef::from(&self.ed_id)),
122            RelayIdType::Rsa => Some(RelayIdRef::from(&self.rsa_id)),
123            _ => None, // Non-exhaustive...
124        }
125    }
126}
127
128/// Structure for building and launching a relay Tor channel.
129#[derive(Default)]
130#[non_exhaustive]
131pub struct RelayChannelBuilder;
132
133impl RelayChannelBuilder {
134    /// Constructor.
135    pub fn new() -> Self {
136        Self::default()
137    }
138
139    /// Launch a new handshake over a TLS stream.
140    ///
141    /// After calling this function, you'll need to call `connect()` on the result to start the
142    /// handshake.  If that succeeds, you'll have authentication info from the relay: call
143    /// `check()` on the result to check that.  Finally, to finish the handshake, call `finish()`
144    /// on the result of _that_.
145    #[allow(clippy::too_many_arguments)] // TODO consider if we want a builder
146    pub fn launch<T, S>(
147        self,
148        tls: T,
149        sleep_prov: S,
150        identities: Arc<RelayIdentities>,
151        my_addrs: Vec<IpAddr>,
152        peer: &OwnedChanTarget,
153        memquota: ChannelAccount,
154    ) -> RelayInitiatorHandshake<T, S>
155    where
156        T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
157        S: CoarseTimeProvider + SleepProvider,
158    {
159        RelayInitiatorHandshake::new(tls, sleep_prov, identities, my_addrs, peer, memquota)
160    }
161
162    /// Accept a new handshake over a TLS stream.
163    pub fn accept<T, S>(
164        self,
165        peer: Sensitive<std::net::SocketAddr>,
166        my_addrs: Vec<IpAddr>,
167        tls: T,
168        sleep_prov: S,
169        identities: Arc<RelayIdentities>,
170        memquota: ChannelAccount,
171    ) -> RelayResponderHandshake<T, S>
172    where
173        T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
174        S: CoarseTimeProvider + SleepProvider,
175    {
176        RelayResponderHandshake::new(
177            peer.into_inner().into(),
178            my_addrs,
179            tls,
180            sleep_prov,
181            identities,
182            memquota,
183        )
184    }
185}
186
187/// Channel authentication data. This is only relevant for a Relay to Relay channel which are
188/// authenticated using this buffet of bytes.
189#[derive(Debug)]
190pub(crate) struct ChannelAuthenticationData {
191    /// Authentication method to use.
192    pub(crate) link_auth: u16,
193    /// SHA256 digest of the initiator KP_relayid_rsa.
194    pub(crate) cid: [u8; 32],
195    /// SHA256 digest of the responder KP_relayid_rsa.
196    pub(crate) sid: [u8; 32],
197    /// The initiator KP_relayid_ed.
198    pub(crate) cid_ed: [u8; 32],
199    /// The responder KP_relayid_ed.
200    pub(crate) sid_ed: [u8; 32],
201    /// Initiator log SHA256 digest.
202    pub(crate) clog: [u8; 32],
203    /// Responder log SHA256 digest.
204    pub(crate) slog: [u8; 32],
205    /// SHA256 of responder's TLS certificate.
206    pub(crate) scert: [u8; 32],
207}
208
209impl ChannelAuthenticationData {
210    /// Helper: return the authentication type string from the given link auth version.
211    const fn auth_type_bytes(link_auth: u16) -> Result<&'static [u8]> {
212        match link_auth {
213            3 => Ok(b"AUTH0003"),
214            _ => Err(Error::BadCellAuth),
215        }
216    }
217
218    /// Helper: return the keying material label from the given link auth version.
219    const fn keying_material_label_bytes(link_auth: u16) -> Result<&'static [u8]> {
220        match link_auth {
221            3 => Ok(b"EXPORTER FOR TOR TLS CLIENT BINDING AUTH0003"),
222            _ => Err(Error::BadCellAuth),
223        }
224    }
225
226    /// Consume ourself and return an AUTHENTICATE cell from the data we hold.
227    pub(crate) fn into_authenticate<C: CertifiedConn>(
228        self,
229        tls: &C,
230        link_ed: &RelayLinkSigningKeypair,
231    ) -> Result<msg::Authenticate> {
232        // The body is exactly 352 bytes so optimize a bit memory.
233        let mut body = Vec::with_capacity(352);
234
235        // Obviously, ordering matteres. See tor-spec section Ed25519-SHA256-RFC5705
236        body.extend_from_slice(Self::auth_type_bytes(self.link_auth)?);
237        body.extend_from_slice(&self.cid);
238        body.extend_from_slice(&self.sid);
239        body.extend_from_slice(&self.cid_ed);
240        body.extend_from_slice(&self.sid_ed);
241        body.extend_from_slice(&self.slog);
242        body.extend_from_slice(&self.clog);
243        body.extend_from_slice(&self.scert);
244
245        // TLSSECRETS is built from the CID.
246        let tls_secrets = tls.export_keying_material(
247            32,
248            Self::keying_material_label_bytes(self.link_auth)?,
249            Some(&self.cid[..]),
250        )?;
251        body.extend_from_slice(tls_secrets.as_slice());
252
253        // Add the random bytes.
254        let random: [u8; 24] = rand::rng().random();
255        body.extend_from_slice(&random);
256
257        // Create signature with our KP_link_ed and append it to body. We hard expect the
258        // KP_link_ed because this would be a code flow error.
259        let sig = link_ed.sign(&body);
260        body.extend_from_slice(&sig.to_bytes());
261
262        // Lets go with the AUTHENTICATE cell.
263        Ok(msg::Authenticate::new(self.link_auth, body))
264    }
265
266    /// Build the [`ChannelAuthenticationData`] given a [`VerifiedChannel`].
267    ///
268    /// We should never check or build authentication data if the channel is not verified thus the
269    /// requirement to pass the verified channel to this function.
270    ///
271    /// The `our_cert` parameter is for the responder case only that is it contains our certificate
272    /// that we presented as the TLS server side. This MUST be Some() if auth_challenge_cell is
273    /// None.
274    ///
275    /// Both initiator and responder handshake build this data in order to authenticate.
276    ///
277    /// IMPORTANT: The CLOG and SLOG from the framed_tls codec is consumed here so calling twice
278    /// build_auth_data() will result in different AUTHENTICATE cells.
279    pub(crate) fn build<T, S>(
280        auth_challenge_cell: Option<&msg::AuthChallenge>,
281        identities: &Arc<RelayIdentities>,
282        verified: &mut VerifiedChannel<T, S>,
283        our_cert: Option<[u8; 32]>,
284    ) -> Result<ChannelAuthenticationData>
285    where
286        T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
287        S: CoarseTimeProvider + SleepProvider,
288    {
289        // With an AUTH_CHALLENGE, we are the Initiator. With an AUTHENTICATE, we are the
290        // Responder. See tor-spec for a diagram of messages.
291        let is_responder = auth_challenge_cell.is_none();
292
293        // Without an AUTH_CHALLENGE, we use our known link protocol value. Else, we only keep what
294        // we know from the AUTH_CHALLENGE and we max() on it.
295        let link_auth = *LINK_AUTH
296            .iter()
297            .filter(|m| auth_challenge_cell.is_none_or(|cell| cell.methods().contains(m)))
298            .max()
299            .ok_or(Error::BadCellAuth)?;
300        // The ordering matter based on if initiator or responder.
301        let cid = identities.rsa_id_der_digest;
302        let sid = verified.rsa_id_digest;
303        let cid_ed = identities.ed_id_bytes();
304        let sid_ed = verified.ed25519_id.into();
305        // Both values are consumed from the underlying codec.
306        let clog = verified.framed_tls.codec_mut().get_clog_digest()?;
307        let slog = verified.framed_tls.codec_mut().get_slog_digest()?;
308
309        let (cid, sid, cid_ed, sid_ed) = if is_responder {
310            // Reverse when responder as in CID becomes SID, and so on.
311            (sid, cid, sid_ed, cid_ed)
312        } else {
313            // Keep it that way if we are initiator.
314            (cid, sid, cid_ed, sid_ed)
315        };
316
317        let (clog, slog) = if is_responder {
318            // Reverse as the SLOG is the responder log digest meaning the clog as a responder.
319            (slog, clog)
320        } else {
321            // Keep ordering.
322            (clog, slog)
323        };
324
325        let scert = if is_responder {
326            our_cert.ok_or(internal!("Responder channel without own certificate"))?
327        } else {
328            verified.peer_cert_digest
329        };
330
331        Ok(Self {
332            link_auth,
333            cid,
334            sid,
335            cid_ed,
336            sid_ed,
337            clog,
338            slog,
339            scert,
340        })
341    }
342}
343
344/// Helper: Build a [`msg::Certs`] cell for the given relay identities and channel type.
345///
346/// Both relay initiator and responder handshake use this.
347pub(crate) fn build_certs_cell(
348    identities: &Arc<RelayIdentities>,
349    is_responder: bool,
350) -> msg::Certs {
351    let mut certs = msg::Certs::new_empty();
352    // Push into the cell the CertType 2 RSA
353    certs.push_cert_body(
354        tor_cert::CertType::RSA_ID_X509,
355        identities.cert_id_x509_rsa.clone(),
356    );
357
358    // Push into the cell the CertType 7 RSA
359    certs.push_cert_body(CertType::RSA_ID_V_IDENTITY, identities.cert_id_rsa.clone());
360
361    // Push into the cell the CertType 4 Ed25519
362    certs.push_cert_body(
363        CertType::IDENTITY_V_SIGNING,
364        identities.cert_id_sign_ed.clone(),
365    );
366    // Push into the cell the CertType 5/6 Ed25519
367    if is_responder {
368        // Responder has CertType 5
369        certs.push_cert_body(
370            CertType::SIGNING_V_TLS_CERT,
371            identities.cert_sign_tls_ed.clone(),
372        );
373    } else {
374        // Initiator has CertType 6
375        certs.push_cert_body(
376            CertType::SIGNING_V_LINK_AUTH,
377            identities.cert_sign_link_auth_ed.clone(),
378        );
379    }
380    certs
381}
382
383/// Build a [`msg::Netinfo`] cell from the given peer IPs and our advertised addresses.
384///
385/// Both relay initiator and responder handshake use this.
386pub(crate) fn build_netinfo_cell<S>(
387    peer_ip: Option<IpAddr>,
388    my_addrs: Vec<IpAddr>,
389    sleep_prov: &S,
390) -> Result<msg::Netinfo>
391where
392    S: CoarseTimeProvider + SleepProvider,
393{
394    // Unix timestamp but over 32bit. This will be sad in 2038 but proposal 338 addresses this
395    // issue with a change to 64bit.
396    let timestamp = sleep_prov
397        .wallclock()
398        .duration_since(UNIX_EPOCH)
399        .map_err(|e| internal!("Wallclock may have gone backwards: {e}"))?
400        .as_secs()
401        .try_into()
402        .map_err(|e| internal!("Wallclock secs fail to convert to 32bit: {e}"))?;
403    Ok(msg::Netinfo::from_relay(timestamp, peer_ip, my_addrs))
404}