tor_proto/channel/
handshake.rs

1//! Implementations for the channel handshake
2
3use futures::io::{AsyncRead, AsyncWrite};
4use futures::sink::SinkExt;
5use futures::stream::StreamExt;
6use tor_cell::chancell::msg::AnyChanMsg;
7use tor_error::internal;
8
9use crate::channel::{ChannelType, UniqId, new_frame};
10use crate::memquota::ChannelAccount;
11use crate::util::skew::ClockSkew;
12use crate::{Error, Result};
13use tor_cell::chancell::{AnyChanCell, ChanMsg, msg};
14use tor_rtcompat::{CoarseTimeProvider, SleepProvider, StreamOps};
15
16use std::net::SocketAddr;
17use std::sync::Arc;
18use std::time::SystemTime;
19
20use tor_linkspec::{ChanTarget, ChannelMethod, OwnedChanTargetBuilder, RelayIds};
21use tor_llcrypto as ll;
22use tor_llcrypto::pk::ed25519::Ed25519Identity;
23use tor_llcrypto::pk::rsa::RsaIdentity;
24
25use digest::Digest;
26
27use super::ChannelFrame;
28
29use tracing::{debug, instrument, trace};
30
31/// A list of the link protocols that we support.
32static LINK_PROTOCOLS: &[u16] = &[4, 5];
33
34/// Base trait that all handshake type must implement.
35///
36/// It has common code that all handshake share including getters for the channel frame for cell
37/// decoding/encoding and the unique ID used for logging.
38///
39/// It has both a recv() and send() function for the VERSIONS cell since every handshake must start
40/// with this cell to negotiate the link protocol version.
41trait ChannelBaseHandshake<T>
42where
43    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
44{
45    /// Return a mutable reference to the channel frame.
46    fn framed_tls(&mut self) -> &mut ChannelFrame<T>;
47    /// Return a reference to the unique ID of this handshake.
48    fn unique_id(&self) -> &UniqId;
49
50    /// Send a [msg::Versions] cell.
51    ///
52    /// A tuple is returned that is respectively the instant and wallclock of the send.
53    async fn send_versions_cell<F>(
54        &mut self,
55        now_fn: F,
56    ) -> Result<(coarsetime::Instant, SystemTime)>
57    where
58        F: FnOnce() -> SystemTime,
59    {
60        trace!(stream_id = %self.unique_id(), "sending versions");
61        // Send versions cell
62        let version_cell = AnyChanCell::new(
63            None,
64            msg::Versions::new(LINK_PROTOCOLS)
65                .map_err(|e| Error::from_cell_enc(e, "versions message"))?
66                .into(),
67        );
68        self.framed_tls().send(version_cell).await?;
69        Ok((
70            coarsetime::Instant::now(), // Flushed at instant
71            now_fn(),                   // Flushed at wallclock
72        ))
73    }
74
75    /// Receive a [msg::Versions] cell.
76    ///
77    /// The negotiated link protocol is returned, and also recorded in the underlying channel
78    /// frame. This automatically transitions the frame into the "Handshake" state of the
79    /// underlying cell handler. In other words, once the link protocol version is negotiated, the
80    /// handler can encode and decode cells for that version in order to continue the handshake.
81    async fn recv_versions_cell(&mut self) -> Result<u16> {
82        // Get versions cell.
83        // Get versions cell.
84        trace!(stream_id = %self.unique_id(), "waiting for versions");
85        // This can be None if we've reached EOF or any type of I/O error on the underlying TCP or
86        // TLS stream. Either case, it is unexpected.
87        let Some(cell) = self.framed_tls().next().await.transpose()? else {
88            return Err(Error::ChanIoErr(Arc::new(std::io::Error::from(
89                std::io::ErrorKind::UnexpectedEof,
90            ))));
91        };
92        let AnyChanMsg::Versions(their_versions) = cell.into_circid_and_msg().1 else {
93            return Err(Error::from(internal!(
94                "Unexpected cell, expecting a VERSIONS cell",
95            )));
96        };
97        trace!(stream_id = %self.unique_id(), "received their VERSIONS {:?}", their_versions);
98
99        // Determine which link protocol we negotiated.
100        let link_protocol = their_versions
101            .best_shared_link_protocol(LINK_PROTOCOLS)
102            .ok_or_else(|| Error::HandshakeProto("No shared link protocols".into()))?;
103        trace!(stream_id = %self.unique_id(), "negotiated version {}", link_protocol);
104
105        // Set the link protocol into our channel frame.
106        self.framed_tls()
107            .codec_mut()
108            .set_link_version(link_protocol)?;
109        Ok(link_protocol)
110    }
111}
112
113/// Handshake initiator base trait. All initiator handshake should implement this trait in order to
114/// enjoy the helper functions.
115///
116/// It requires the base handshake trait to be implement for access to the base getters.
117trait ChannelInitiatorHandshake<T>: ChannelBaseHandshake<T>
118where
119    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
120{
121    /// Return true iff this handshake is expecting to receive an AUTH_CHALLENGE from the
122    /// responder. As a handshake initiator, we always know if we expect one or not. A client or
123    /// bridge do not authenticate with the responder while relays will always do.
124    fn is_expecting_auth_challenge(&self) -> bool;
125
126    /// As an initiator, we are expecting the responder's cells which are (not in that order):
127    ///     - [msg::AuthChallenge], [msg::Certs], [msg::Netinfo]
128    ///
129    /// Any duplicate, missing cell or unexpected results in a protocol level error.
130    ///
131    /// This returns the [msg::AuthChallenge], [msg::Certs] and [msg::Netinfo] cells along the
132    /// instant when the netinfo cell was received. This is needed for the clock skew calculation.
133    async fn recv_cells_from_responder(
134        &mut self,
135    ) -> Result<(
136        Option<msg::AuthChallenge>,
137        msg::Certs,
138        (msg::Netinfo, coarsetime::Instant),
139    )> {
140        let mut auth_challenge_cell: Option<msg::AuthChallenge> = None;
141        let mut certs_cell: Option<msg::Certs> = None;
142        let mut netinfo_cell: Option<(msg::Netinfo, coarsetime::Instant)> = None;
143
144        // IMPORTANT: Protocol wise, we MUST only allow one single cell of each type for a valid
145        // handshake. Any duplicates lead to a failure. They can arrive in any order unfortunately.
146
147        // Read until we have the netinfo cell.
148        while let Some(cell) = self.framed_tls().next().await.transpose()? {
149            use super::AnyChanMsg::*;
150            let (_, m) = cell.into_circid_and_msg();
151            trace!(stream_id = %self.unique_id(), "received a {} cell.", m.cmd());
152            match m {
153                // Ignore the padding. Only VPADDING cell can be sent during handshaking.
154                Vpadding(_) => (),
155                // Clients don't care about AuthChallenge
156                AuthChallenge(ac) => {
157                    if auth_challenge_cell.replace(ac).is_some() {
158                        return Err(Error::HandshakeProto(
159                            "Duplicate AUTH_CHALLENGE cell".into(),
160                        ));
161                    }
162                }
163                Certs(c) => {
164                    if certs_cell.replace(c).is_some() {
165                        return Err(Error::HandshakeProto("Duplicate CERTS cell".into()));
166                    }
167                }
168                Netinfo(n) => {
169                    if netinfo_cell.is_some() {
170                        // This should be impossible, since we would
171                        // exit this loop on the first netinfo cell.
172                        return Err(Error::from(internal!(
173                            "Somehow tried to record a duplicate NETINFO cell"
174                        )));
175                    }
176                    netinfo_cell = Some((n, coarsetime::Instant::now()));
177                    break;
178                }
179                // This should not happen because the ChannelFrame makes sure that only allowed cell on
180                // the channel are decoded. However, Rust wants us to consider all AnyChanMsg.
181                _ => {
182                    return Err(Error::from(internal!(
183                        "Unexpected cell during initiator handshake: {m:?}"
184                    )));
185                }
186            }
187        }
188
189        // Missing any of the above means we are not connected to a Relay and so we abort the
190        // handshake protocol.
191        let Some((netinfo, netinfo_rcvd_at)) = netinfo_cell else {
192            return Err(Error::HandshakeProto("Missing NETINFO cell".into()));
193        };
194        let Some(certs) = certs_cell else {
195            return Err(Error::HandshakeProto("Missing CERTS cell".into()));
196        };
197        // If we plan to authenticate, we require an AUTH_CHALLENGE cell from the responder.
198        if self.is_expecting_auth_challenge() && auth_challenge_cell.is_none() {
199            return Err(Error::HandshakeProto("Missing AUTH_CHALLENGE cell".into()));
200        };
201
202        Ok((auth_challenge_cell, certs, (netinfo, netinfo_rcvd_at)))
203    }
204}
205
206/// A raw client channel on which nothing has been done.
207pub struct ClientInitiatorHandshake<
208    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
209    S: CoarseTimeProvider + SleepProvider,
210> {
211    /// Runtime handle (insofar as we need it)
212    sleep_prov: S,
213
214    /// Memory quota account
215    memquota: ChannelAccount,
216
217    /// Cell encoder/decoder wrapping the underlying TLS stream
218    ///
219    /// (We don't enforce that this is actually TLS, but if it isn't, the
220    /// connection won't be secure.)
221    framed_tls: ChannelFrame<T>,
222
223    /// Declared target method for this channel, if any.
224    target_method: Option<ChannelMethod>,
225
226    /// Logging identifier for this stream.  (Used for logging only.)
227    unique_id: UniqId,
228}
229
230/// Implement the base channel handshake trait.
231impl<T, S> ChannelBaseHandshake<T> for ClientInitiatorHandshake<T, S>
232where
233    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
234    S: CoarseTimeProvider + SleepProvider,
235{
236    fn framed_tls(&mut self) -> &mut ChannelFrame<T> {
237        &mut self.framed_tls
238    }
239    fn unique_id(&self) -> &UniqId {
240        &self.unique_id
241    }
242}
243
244/// Implement the initiator channel handshake trait.
245impl<T, S> ChannelInitiatorHandshake<T> for ClientInitiatorHandshake<T, S>
246where
247    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
248    S: CoarseTimeProvider + SleepProvider,
249{
250    fn is_expecting_auth_challenge(&self) -> bool {
251        // Client never authenticate with a responder, only relay do.
252        false
253    }
254}
255
256/// A client channel on which versions have been negotiated and the
257/// relay's handshake has been read, but where the certs have not
258/// been checked.
259pub struct UnverifiedChannel<
260    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
261    S: CoarseTimeProvider + SleepProvider,
262> {
263    /// Indicate what type of channel this is.
264    channel_type: ChannelType,
265    /// Runtime handle (insofar as we need it)
266    sleep_prov: S,
267    /// Memory quota account
268    memquota: ChannelAccount,
269    /// The negotiated link protocol.  Must be a member of LINK_PROTOCOLS
270    link_protocol: u16,
271    /// The Source+Sink on which we're reading and writing cells.
272    framed_tls: ChannelFrame<T>,
273    /// The certs cell that we got from the relay.
274    certs_cell: msg::Certs,
275    /// Declared target method for this channel, if any.
276    target_method: Option<ChannelMethod>,
277    /// The netinfo cell that we got from the relay.
278    #[allow(dead_code)] // Relays will need this.
279    netinfo_cell: msg::Netinfo,
280    /// How much clock skew did we detect in this handshake?
281    ///
282    /// This value is _unauthenticated_, since we have not yet checked whether
283    /// the keys in the handshake are the ones we expected.
284    clock_skew: ClockSkew,
285    /// Logging identifier for this stream.  (Used for logging only.)
286    unique_id: UniqId,
287}
288
289/// A client channel on which versions have been negotiated,
290/// relay's handshake has been read, but the client has not yet
291/// finished the handshake.
292///
293/// This type is separate from UnverifiedChannel, since finishing the
294/// handshake requires a bunch of CPU, and you might want to do it as
295/// a separate task or after a yield.
296pub struct VerifiedChannel<
297    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
298    S: CoarseTimeProvider + SleepProvider,
299> {
300    /// Indicate what type of channel this is.
301    channel_type: ChannelType,
302    /// Runtime handle (insofar as we need it)
303    sleep_prov: S,
304    /// Memory quota account
305    memquota: ChannelAccount,
306    /// The negotiated link protocol.
307    link_protocol: u16,
308    /// The Source+Sink on which we're reading and writing cells.
309    framed_tls: ChannelFrame<T>,
310    /// Declared target method for this stream, if any.
311    target_method: Option<ChannelMethod>,
312    /// Logging identifier for this stream.  (Used for logging only.)
313    unique_id: UniqId,
314    /// Validated Ed25519 identity for this peer.
315    ed25519_id: Ed25519Identity,
316    /// Validated RSA identity for this peer.
317    rsa_id: RsaIdentity,
318    /// Authenticated clock skew for this peer.
319    clock_skew: ClockSkew,
320}
321
322impl<
323    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
324    S: CoarseTimeProvider + SleepProvider,
325> ClientInitiatorHandshake<T, S>
326{
327    /// Construct a new OutboundClientHandshake.
328    pub(crate) fn new(
329        tls: T,
330        target_method: Option<ChannelMethod>,
331        sleep_prov: S,
332        memquota: ChannelAccount,
333    ) -> Self {
334        Self {
335            framed_tls: new_frame(tls, ChannelType::ClientInitiator),
336            target_method,
337            unique_id: UniqId::new(),
338            sleep_prov,
339            memquota,
340        }
341    }
342
343    /// Negotiate a link protocol version with the relay, and read
344    /// the relay's handshake information.
345    ///
346    /// Takes a function that reports the current time.  In theory, this can just be
347    /// `SystemTime::now()`.
348    #[instrument(skip_all, level = "trace")]
349    pub async fn connect<F>(mut self, now_fn: F) -> Result<UnverifiedChannel<T, S>>
350    where
351        F: FnOnce() -> SystemTime,
352    {
353        match &self.target_method {
354            Some(method) => debug!(
355                stream_id = %self.unique_id,
356                "starting Tor handshake with {:?}",
357                method
358            ),
359            None => debug!(stream_id = %self.unique_id, "starting Tor handshake"),
360        }
361        // Send versions cell.
362        let (versions_flushed_at, versions_flushed_wallclock) =
363            self.send_versions_cell(now_fn).await?;
364
365        // Receive versions cell.
366        let link_protocol = self.recv_versions_cell().await?;
367
368        // Receive the relay responder cells. Ignore the AUTH_CHALLENGE cell, we don't need it as
369        // we are not authenticating with our responder because we are a client.
370        let (_, certs_cell, (netinfo_cell, netinfo_rcvd_at)) =
371            self.recv_cells_from_responder().await?;
372
373        // Get the clock skew.
374        let clock_skew = unauthenticated_clock_skew(
375            &netinfo_cell,
376            netinfo_rcvd_at,
377            versions_flushed_at,
378            versions_flushed_wallclock,
379        );
380
381        trace!(stream_id = %self.unique_id, "received handshake, ready to verify.");
382
383        Ok(UnverifiedChannel {
384            channel_type: ChannelType::ClientInitiator,
385            link_protocol,
386            framed_tls: self.framed_tls,
387            certs_cell,
388            netinfo_cell,
389            clock_skew,
390            target_method: self.target_method.take(),
391            unique_id: self.unique_id,
392            sleep_prov: self.sleep_prov.clone(),
393            memquota: self.memquota.clone(),
394        })
395    }
396}
397
398impl<
399    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
400    S: CoarseTimeProvider + SleepProvider,
401> UnverifiedChannel<T, S>
402{
403    /// Return the reported clock skew from this handshake.
404    ///
405    /// Note that the skew reported by this function might not be "true": the
406    /// relay might have its clock set wrong, or it might be lying to us.
407    ///
408    /// The clock skew reported here is not yet authenticated; if you need to
409    /// make sure that the skew is authenticated, use
410    /// [`Channel::clock_skew`](super::Channel::clock_skew) instead.
411    pub fn clock_skew(&self) -> ClockSkew {
412        self.clock_skew
413    }
414
415    /// Validate the certificates and keys in the relay's handshake.
416    ///
417    /// 'peer' is the peer that we want to make sure we're connecting to.
418    ///
419    /// 'peer_cert' is the x.509 certificate that the peer presented during
420    /// its TLS handshake (ServerHello).
421    ///
422    /// 'now' is the time at which to check that certificates are
423    /// valid.  `None` means to use the current time. It can be used
424    /// for testing to override the current view of the time.
425    ///
426    /// This is a separate function because it's likely to be somewhat
427    /// CPU-intensive.
428    #[instrument(skip_all, level = "trace")]
429    pub fn check<U: ChanTarget + ?Sized>(
430        self,
431        peer: &U,
432        peer_cert: &[u8],
433        now: Option<std::time::SystemTime>,
434    ) -> Result<VerifiedChannel<T, S>> {
435        let peer_cert_sha256 = ll::d::Sha256::digest(peer_cert);
436        self.check_internal(peer, &peer_cert_sha256[..], now)
437    }
438
439    /// Same as `check`, but takes the SHA256 hash of the peer certificate,
440    /// since that is all we use.
441    fn check_internal<U: ChanTarget + ?Sized>(
442        self,
443        peer: &U,
444        peer_cert_sha256: &[u8],
445        now: Option<SystemTime>,
446    ) -> Result<VerifiedChannel<T, S>> {
447        use tor_cert::CertType;
448        use tor_checkable::*;
449
450        /// Helper: given a time-bound input, give a result reflecting its
451        /// validity at `now`, and the inner object.
452        ///
453        /// We use this here because we want to validate the whole handshake
454        /// regardless of whether the certs are expired, so we can determine
455        /// whether we got a plausible handshake with a skewed partner, or
456        /// whether the handshake is definitely bad.
457        fn check_timeliness<C, T>(checkable: C, now: SystemTime, skew: ClockSkew) -> (Result<()>, T)
458        where
459            C: Timebound<T, Error = TimeValidityError>,
460        {
461            let status = checkable.is_valid_at(&now).map_err(|e| match (e, skew) {
462                (TimeValidityError::Expired(expired_by), ClockSkew::Fast(skew))
463                    if expired_by < skew =>
464                {
465                    Error::HandshakeCertsExpired { expired_by }
466                }
467                // As it so happens, we don't need to check for this case, since the certs in use
468                // here only have an expiration time in them.
469                // (TimeValidityError::NotYetValid(_), ClockSkew::Slow(_)) => todo!(),
470                (_, _) => Error::HandshakeProto("Certificate expired or not yet valid".into()),
471            });
472            let cert = checkable.dangerously_assume_timely();
473            (status, cert)
474        }
475        // Replace 'now' with the real time to use.
476        let now = now.unwrap_or_else(SystemTime::now);
477
478        // We need to check the following lines of authentication:
479        //
480        // First, to bind the ed identity to the channel.
481        //    peer.ed_identity() matches the key in...
482        //    IDENTITY_V_SIGNING cert, which signs...
483        //    SIGNING_V_TLS_CERT cert, which signs peer_cert.
484        //
485        // Second, to bind the rsa identity to the ed identity:
486        //    peer.rsa_identity() matches the key in...
487        //    the x.509 RSA identity certificate (type 2), which signs...
488        //    the RSA->Ed25519 crosscert (type 7), which signs...
489        //    peer.ed_identity().
490
491        let c = &self.certs_cell;
492        /// Helper: get a cert from a Certs cell, and convert errors appropriately.
493        fn get_cert(
494            certs: &tor_cell::chancell::msg::Certs,
495            tp: CertType,
496        ) -> Result<tor_cert::KeyUnknownCert> {
497            match certs.parse_ed_cert(tp) {
498                Ok(c) => Ok(c),
499                Err(tor_cell::Error::ChanProto(e)) => Err(Error::HandshakeProto(e)),
500                Err(e) => Err(Error::HandshakeProto(e.to_string())),
501            }
502        }
503
504        let id_sk = get_cert(c, CertType::IDENTITY_V_SIGNING)?;
505        let sk_tls = get_cert(c, CertType::SIGNING_V_TLS_CERT)?;
506
507        let mut sigs = Vec::new();
508
509        // Part 1: validate ed25519 stuff.
510        //
511        // (We are performing our timeliness checks now, but not inspecting them
512        // until later in the function, so that we can distinguish failures that
513        // might be caused by clock skew from failures that are definitely not
514        // clock skew.)
515
516        // Check the identity->signing cert
517        let (id_sk, id_sk_sig) = id_sk
518            .should_have_signing_key()
519            .map_err(Error::HandshakeCertErr)?
520            .dangerously_split()
521            .map_err(Error::HandshakeCertErr)?;
522        sigs.push(&id_sk_sig);
523        let (id_sk_timeliness, id_sk) = check_timeliness(id_sk, now, self.clock_skew);
524
525        // Take the identity key from the identity->signing cert
526        let identity_key = id_sk.signing_key().ok_or_else(|| {
527            Error::HandshakeProto("Missing identity key in identity->signing cert".into())
528        })?;
529
530        // Take the signing key from the identity->signing cert
531        let signing_key = id_sk.subject_key().as_ed25519().ok_or_else(|| {
532            Error::HandshakeProto("Bad key type in identity->signing cert".into())
533        })?;
534
535        // Now look at the signing->TLS cert and check it against the
536        // peer certificate.
537        let (sk_tls, sk_tls_sig) = sk_tls
538            .should_be_signed_with(signing_key)
539            .map_err(Error::HandshakeCertErr)?
540            .dangerously_split()
541            .map_err(Error::HandshakeCertErr)?;
542        sigs.push(&sk_tls_sig);
543        let (sk_tls_timeliness, sk_tls) = check_timeliness(sk_tls, now, self.clock_skew);
544
545        if peer_cert_sha256 != sk_tls.subject_key().as_bytes() {
546            return Err(Error::HandshakeProto(
547                "Peer cert did not authenticate TLS cert".into(),
548            ));
549        }
550
551        // Batch-verify the ed25519 certificates in this handshake.
552        //
553        // In theory we could build a list of _all_ the certificates here
554        // and call pk::validate_all_sigs() instead, but that doesn't gain
555        // any performance.
556        if !ll::pk::ed25519::validate_batch(&sigs[..]) {
557            return Err(Error::HandshakeProto(
558                "Invalid ed25519 signature in handshake".into(),
559            ));
560        }
561
562        // Part 2: validate rsa stuff.
563
564        // What is the RSA identity key, according to the X.509 certificate
565        // in which it is self-signed?
566        //
567        // (We don't actually check this self-signed certificate, and we use
568        // a kludge to extract the RSA key)
569        let pkrsa = c
570            .cert_body(CertType::RSA_ID_X509)
571            .and_then(ll::util::x509_extract_rsa_subject_kludge)
572            .ok_or_else(|| Error::HandshakeProto("Couldn't find RSA identity key".into()))?;
573
574        // Now verify the RSA identity -> Ed Identity crosscert.
575        //
576        // This proves that the RSA key vouches for the Ed key.  Note that
577        // the Ed key does not vouch for the RSA key: The RSA key is too
578        // weak.
579        let rsa_cert = c
580            .cert_body(CertType::RSA_ID_V_IDENTITY)
581            .ok_or_else(|| Error::HandshakeProto("No RSA->Ed crosscert".into()))?;
582        let rsa_cert = tor_cert::rsa::RsaCrosscert::decode(rsa_cert)
583            .map_err(|e| Error::from_bytes_err(e, "RSA identity cross-certificate"))?
584            .check_signature(&pkrsa)
585            .map_err(|_| Error::HandshakeProto("Bad RSA->Ed crosscert signature".into()))?;
586        let (rsa_cert_timeliness, rsa_cert) = check_timeliness(rsa_cert, now, self.clock_skew);
587
588        if !rsa_cert.subject_key_matches(identity_key) {
589            return Err(Error::HandshakeProto(
590                "RSA->Ed crosscert certifies incorrect key".into(),
591            ));
592        }
593
594        let rsa_id = pkrsa.to_rsa_identity();
595
596        trace!(
597            stream_id = %self.unique_id,
598            "Validated identity as {} [{}]",
599            identity_key,
600            rsa_id
601        );
602
603        // Now that we've done all the verification steps on the
604        // certificates, we know who we are talking to.  It's time to
605        // make sure that the peer we are talking to is the peer we
606        // actually wanted.
607        //
608        // We do this _last_, since "this is the wrong peer" is
609        // usually a different situation than "this peer couldn't even
610        // identify itself right."
611
612        let actual_identity = RelayIds::builder()
613            .ed_identity(*identity_key)
614            .rsa_identity(rsa_id)
615            .build()
616            .expect("Unable to build RelayIds");
617
618        // We enforce that the relay proved that it has every ID that we wanted:
619        // it may also have additional IDs that we didn't ask for.
620        match super::check_id_match_helper(&actual_identity, peer) {
621            Err(Error::ChanMismatch(msg)) => Err(Error::HandshakeProto(msg)),
622            other => other,
623        }?;
624
625        // If we reach this point, the clock skew might be may now be considered
626        // authenticated: The certificates are what we wanted, and everything
627        // was well signed.
628        //
629        // The only remaining concern is certificate timeliness.  If the
630        // certificates are expired by an amount that is too large for the
631        // declared clock skew to explain, then  we'll return
632        // `Error::HandshakeProto`: in that case the clock skew is _not_
633        // authenticated.  But if the certs are only expired by a little bit,
634        // we'll reject the handshake with `Error::HandshakeCertsExpired`, and
635        // the caller can trust the clock skew.
636        //
637        // We note expired certs last, since we only want to return
638        // `HandshakeCertsExpired` when there are no other errors.
639        id_sk_timeliness?;
640        sk_tls_timeliness?;
641        rsa_cert_timeliness?;
642
643        Ok(VerifiedChannel {
644            channel_type: self.channel_type,
645            link_protocol: self.link_protocol,
646            framed_tls: self.framed_tls,
647            unique_id: self.unique_id,
648            target_method: self.target_method,
649            ed25519_id: *identity_key,
650            rsa_id,
651            clock_skew: self.clock_skew,
652            sleep_prov: self.sleep_prov,
653            memquota: self.memquota,
654        })
655    }
656}
657
658impl<
659    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
660    S: CoarseTimeProvider + SleepProvider,
661> VerifiedChannel<T, S>
662{
663    /// Send a 'Netinfo' message to the relay to finish the handshake,
664    /// and create an open channel and reactor.
665    ///
666    /// The channel is used to send cells, and to create outgoing circuits.
667    /// The reactor is used to route incoming messages to their appropriate
668    /// circuit.
669    #[instrument(skip_all, level = "trace")]
670    pub async fn finish(mut self) -> Result<(Arc<super::Channel>, super::reactor::Reactor<S>)> {
671        // We treat a completed channel -- that is to say, one where the
672        // authentication is finished -- as incoming traffic.
673        //
674        // TODO: conceivably we should remember the time when we _got_ the
675        // final cell on the handshake, and update the channel completion
676        // time to be no earlier than _that_ timestamp.
677        crate::note_incoming_traffic();
678        trace!(stream_id = %self.unique_id, "Sending netinfo cell.");
679
680        // We do indeed want the real IP here, regardless of whether the
681        // ChannelMethod is Direct connection or not.  The role of the IP in a
682        // NETINFO cell is to tell our peer what address we believe they had, so
683        // that they can better notice MITM attacks and such.
684        let peer_ip = self
685            .target_method
686            .as_ref()
687            .and_then(ChannelMethod::socket_addrs)
688            .and_then(|addrs| addrs.first())
689            .map(SocketAddr::ip);
690        let netinfo = msg::Netinfo::from_client(peer_ip);
691        self.framed_tls.send(netinfo.into()).await?;
692
693        // We have finalized the handshake, move our codec to Open.
694        self.framed_tls.codec_mut().set_open()?;
695
696        debug!(
697            stream_id = %self.unique_id,
698            "Completed handshake with {} [{}]",
699            self.ed25519_id, self.rsa_id
700        );
701
702        // Grab a new handle on which we can apply StreamOps (needed for KIST).
703        // On Unix platforms, this handle is a wrapper over the fd of the socket.
704        //
705        // Note: this is necessary because after `StreamExit::split()`,
706        // we no longer have access to the underlying stream
707        // or its StreamOps implementation.
708        let stream_ops = self.framed_tls.new_handle();
709        let (tls_sink, tls_stream) = self.framed_tls.split();
710
711        let mut peer_builder = OwnedChanTargetBuilder::default();
712        if let Some(target_method) = self.target_method {
713            if let Some(addrs) = target_method.socket_addrs() {
714                peer_builder.addrs(addrs.to_owned());
715            }
716            peer_builder.method(target_method);
717        }
718        let peer_id = peer_builder
719            .ed_identity(self.ed25519_id)
720            .rsa_identity(self.rsa_id)
721            .build()
722            .expect("OwnedChanTarget builder failed");
723
724        super::Channel::new(
725            self.channel_type,
726            self.link_protocol,
727            Box::new(tls_sink),
728            Box::new(tls_stream),
729            stream_ops,
730            self.unique_id,
731            peer_id,
732            self.clock_skew,
733            self.sleep_prov,
734            self.memquota,
735        )
736    }
737}
738
739/// Helper: Calculate a clock skew from the [msg::Netinfo] cell data and the time at which we sent
740/// the [msg::Versions] cell.
741///
742/// This is unauthenticated as in not validated with the certificates. Before using it, make sure
743/// that you have authenticated the other party.
744fn unauthenticated_clock_skew(
745    netinfo_cell: &msg::Netinfo,
746    netinfo_rcvd_at: coarsetime::Instant,
747    versions_flushed_at: coarsetime::Instant,
748    versions_flushed_wallclock: SystemTime,
749) -> ClockSkew {
750    // Try to compute our clock skew.  It won't be authenticated yet, since we haven't checked
751    // the certificates.
752    if let Some(netinfo_timestamp) = netinfo_cell.timestamp() {
753        let delay = netinfo_rcvd_at - versions_flushed_at;
754        ClockSkew::from_handshake_timestamps(
755            versions_flushed_wallclock,
756            netinfo_timestamp,
757            delay.into(),
758        )
759    } else {
760        ClockSkew::None
761    }
762}
763
764#[cfg(test)]
765pub(super) mod test {
766    #![allow(clippy::unwrap_used)]
767    use hex_literal::hex;
768    use regex::Regex;
769    use std::time::{Duration, SystemTime};
770
771    use super::*;
772    use crate::Result;
773    use crate::channel::handler::test::MsgBuf;
774    use crate::util::fake_mq;
775    use tor_cell::chancell::msg;
776    use tor_linkspec::OwnedChanTarget;
777    use tor_rtcompat::{PreferredRuntime, Runtime};
778
779    const VERSIONS: &[u8] = &hex!("0000 07 0006 0003 0004 0005");
780    // no certificates in this cell, but connect() doesn't care.
781    const NOCERTS: &[u8] = &hex!("00000000 81 0001 00");
782    const NETINFO_PREFIX: &[u8] = &hex!(
783        "00000000 08 00000000
784         04 04 7f 00 00 02
785         01
786         04 04 7f 00 00 03"
787    );
788    const NETINFO_PREFIX_WITH_TIME: &[u8] = &hex!(
789        "00000000 08 48949290
790         04 04 7f 00 00 02
791         01
792         04 04 7f 00 00 03"
793    );
794    const AUTHCHALLENGE: &[u8] = &hex!(
795        "00000000 82 0026
796         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
797         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
798         0002 0003 00ff"
799    );
800
801    const VPADDING: &[u8] = &hex!("00000000 80 0003 FF FF FF");
802
803    fn add_padded(buf: &mut Vec<u8>, cell: &[u8]) {
804        let len_prev = buf.len();
805        buf.extend_from_slice(cell);
806        buf.resize(len_prev + 514, 0);
807    }
808    fn add_netinfo(buf: &mut Vec<u8>) {
809        add_padded(buf, NETINFO_PREFIX);
810    }
811
812    #[test]
813    fn connect_ok() -> Result<()> {
814        tor_rtcompat::test_with_one_runtime!(|rt| async move {
815            let now = humantime::parse_rfc3339("2008-08-02T17:00:00Z").unwrap();
816            let mut buf = Vec::new();
817            // versions cell
818            buf.extend_from_slice(VERSIONS);
819            // certs cell -- no certs in it, but this function doesn't care.
820            buf.extend_from_slice(NOCERTS);
821            // netinfo cell -- quite minimal.
822            add_padded(&mut buf, NETINFO_PREFIX);
823            let mb = MsgBuf::new(&buf[..]);
824            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
825            let unverified = handshake.connect(|| now).await?;
826
827            assert_eq!(unverified.link_protocol, 5);
828            // No timestamp in the NETINFO, so no skew.
829            assert_eq!(unverified.clock_skew(), ClockSkew::None);
830
831            // Try again with some padding.
832            let mut buf = Vec::new();
833            buf.extend_from_slice(VERSIONS);
834            buf.extend_from_slice(NOCERTS);
835            buf.extend_from_slice(VPADDING);
836            buf.extend_from_slice(AUTHCHALLENGE);
837            buf.extend_from_slice(VPADDING);
838            add_padded(&mut buf, NETINFO_PREFIX_WITH_TIME);
839            let mb = MsgBuf::new(&buf[..]);
840            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
841            let unverified = handshake.connect(|| now).await?;
842            // Correct timestamp in the NETINFO, so no skew.
843            assert_eq!(unverified.clock_skew(), ClockSkew::None);
844
845            // Now pretend our clock is fast.
846            let now2 = now + Duration::from_secs(3600);
847            let mb = MsgBuf::new(&buf[..]);
848            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
849            let unverified = handshake.connect(|| now2).await?;
850            assert_eq!(
851                unverified.clock_skew(),
852                ClockSkew::Fast(Duration::from_secs(3600))
853            );
854
855            Ok(())
856        })
857    }
858
859    async fn connect_err<T: Into<Vec<u8>>, S>(input: T, sleep_prov: S) -> Error
860    where
861        S: CoarseTimeProvider + SleepProvider,
862    {
863        let mb = MsgBuf::new(input);
864        let handshake = ClientInitiatorHandshake::new(mb, None, sleep_prov, fake_mq());
865        handshake.connect(SystemTime::now).await.err().unwrap()
866    }
867
868    #[test]
869    fn connect_badver() {
870        tor_rtcompat::test_with_one_runtime!(|rt| async move {
871            let err = connect_err(&b"HTTP://"[..], rt.clone()).await;
872            assert!(matches!(err, Error::HandshakeProto(_)));
873            assert_eq!(
874                format!("{}", err),
875                "Handshake protocol violation: Invalid CircID in variable cell"
876            );
877
878            let err = connect_err(&hex!("0000 07 0004 1234 ffff")[..], rt.clone()).await;
879            assert!(matches!(err, Error::HandshakeProto(_)));
880            assert_eq!(
881                format!("{}", err),
882                "Handshake protocol violation: No shared link protocols"
883            );
884        });
885    }
886
887    #[test]
888    fn connect_cellparse() {
889        tor_rtcompat::test_with_one_runtime!(|rt| async move {
890            let mut buf = Vec::new();
891            buf.extend_from_slice(VERSIONS);
892            // Here's a certs cell that will fail.
893            buf.extend_from_slice(&hex!("00000000 81 0001 01")[..]);
894            let err = connect_err(buf, rt.clone()).await;
895            assert!(matches!(err, Error::HandshakeProto { .. }));
896        });
897    }
898
899    #[test]
900    fn connect_duplicates() {
901        tor_rtcompat::test_with_one_runtime!(|rt| async move {
902            let mut buf = Vec::new();
903            buf.extend_from_slice(VERSIONS);
904            buf.extend_from_slice(NOCERTS);
905            buf.extend_from_slice(NOCERTS);
906            add_netinfo(&mut buf);
907            let err = connect_err(buf, rt.clone()).await;
908            assert!(matches!(err, Error::HandshakeProto(_)));
909            assert_eq!(
910                format!("{}", err),
911                "Handshake protocol violation: Duplicate CERTS cell"
912            );
913
914            let mut buf = Vec::new();
915            buf.extend_from_slice(VERSIONS);
916            buf.extend_from_slice(NOCERTS);
917            buf.extend_from_slice(AUTHCHALLENGE);
918            buf.extend_from_slice(AUTHCHALLENGE);
919            add_netinfo(&mut buf);
920            let err = connect_err(buf, rt.clone()).await;
921            assert!(matches!(err, Error::HandshakeProto(_)));
922            assert_eq!(
923                format!("{}", err),
924                "Handshake protocol violation: Duplicate AUTH_CHALLENGE cell"
925            );
926        });
927    }
928
929    #[test]
930    fn connect_missing_certs() {
931        tor_rtcompat::test_with_one_runtime!(|rt| async move {
932            let mut buf = Vec::new();
933            buf.extend_from_slice(VERSIONS);
934            add_netinfo(&mut buf);
935            let err = connect_err(buf, rt.clone()).await;
936            assert!(matches!(err, Error::HandshakeProto(_)));
937            assert_eq!(
938                format!("{}", err),
939                "Handshake protocol violation: Missing CERTS cell"
940            );
941        });
942    }
943
944    #[test]
945    fn connect_missing_netinfo() {
946        tor_rtcompat::test_with_one_runtime!(|rt| async move {
947            let mut buf = Vec::new();
948            buf.extend_from_slice(VERSIONS);
949            buf.extend_from_slice(NOCERTS);
950            let err = connect_err(buf, rt.clone()).await;
951            assert!(matches!(err, Error::HandshakeProto(_)));
952            assert_eq!(
953                format!("{}", err),
954                "Handshake protocol violation: Missing NETINFO cell"
955            );
956        });
957    }
958
959    #[test]
960    fn connect_misplaced_cell() {
961        tor_rtcompat::test_with_one_runtime!(|rt| async move {
962            let mut buf = Vec::new();
963            buf.extend_from_slice(VERSIONS);
964            // here's a create cell.
965            add_padded(&mut buf, &hex!("00000001 01")[..]);
966            let err = connect_err(buf, rt.clone()).await;
967            assert!(matches!(err, Error::HandshakeProto(_)));
968            assert_eq!(
969                format!("{}", err),
970                "Handshake protocol violation: Decoding cell error: Error while parsing channel cell: Bad object: Unexpected command CREATE in HandshakeRelayResponderMsg"
971            );
972        });
973    }
974
975    fn make_unverified<R>(certs: msg::Certs, runtime: R) -> UnverifiedChannel<MsgBuf, R>
976    where
977        R: Runtime,
978    {
979        let localhost = std::net::IpAddr::V4(std::net::Ipv4Addr::LOCALHOST);
980        let netinfo_cell = msg::Netinfo::from_client(Some(localhost));
981        let mut framed_tls = new_frame(MsgBuf::new(&b""[..]), ChannelType::ClientInitiator);
982        let _ = framed_tls.codec_mut().set_link_version(4);
983        let _ = framed_tls.codec_mut().set_open();
984        let clock_skew = ClockSkew::None;
985        UnverifiedChannel {
986            channel_type: ChannelType::ClientInitiator,
987            link_protocol: 4,
988            framed_tls,
989            certs_cell: certs,
990            netinfo_cell,
991            clock_skew,
992            target_method: None,
993            unique_id: UniqId::new(),
994            sleep_prov: runtime,
995            memquota: fake_mq(),
996        }
997    }
998
999    // Timestamp when the example certificates were all valid.
1000    fn cert_timestamp() -> SystemTime {
1001        use humantime::parse_rfc3339;
1002        parse_rfc3339("2020-09-26T18:01:20Z").unwrap()
1003    }
1004
1005    fn certs_test<R>(
1006        certs: msg::Certs,
1007        when: Option<SystemTime>,
1008        peer_ed: &[u8],
1009        peer_rsa: &[u8],
1010        peer_cert_sha256: &[u8],
1011        runtime: &R,
1012    ) -> Result<VerifiedChannel<MsgBuf, R>>
1013    where
1014        R: Runtime,
1015    {
1016        let unver = make_unverified(certs, runtime.clone());
1017        let ed = Ed25519Identity::from_bytes(peer_ed).unwrap();
1018        let rsa = RsaIdentity::from_bytes(peer_rsa).unwrap();
1019        let chan = OwnedChanTarget::builder()
1020            .ed_identity(ed)
1021            .rsa_identity(rsa)
1022            .build()
1023            .unwrap();
1024        unver.check_internal(&chan, peer_cert_sha256, when)
1025    }
1026
1027    // no certs at all!
1028    #[test]
1029    fn certs_none() {
1030        let rt = PreferredRuntime::create().unwrap();
1031        let err = certs_test(
1032            msg::Certs::new_empty(),
1033            None,
1034            &[0_u8; 32],
1035            &[0_u8; 20],
1036            &[0_u8; 128],
1037            &rt,
1038        )
1039        .err()
1040        .unwrap();
1041        assert_eq!(
1042            format!("{}", err),
1043            "Handshake protocol violation: Missing IDENTITY_V_SIGNING certificate"
1044        );
1045    }
1046
1047    #[test]
1048    fn certs_good() {
1049        let rt = PreferredRuntime::create().unwrap();
1050        let mut certs = msg::Certs::new_empty();
1051
1052        certs.push_cert_body(2.into(), certs::CERT_T2);
1053        certs.push_cert_body(5.into(), certs::CERT_T5);
1054        certs.push_cert_body(7.into(), certs::CERT_T7);
1055        certs.push_cert_body(4.into(), certs::CERT_T4);
1056        let res = certs_test(
1057            certs,
1058            Some(cert_timestamp()),
1059            certs::PEER_ED,
1060            certs::PEER_RSA,
1061            certs::PEER_CERT_DIGEST,
1062            &rt,
1063        );
1064        let _ = res.unwrap();
1065    }
1066
1067    #[test]
1068    fn certs_missing() {
1069        let rt = PreferredRuntime::create().unwrap();
1070        let all_certs = [
1071            (2, certs::CERT_T2, "Couldn't find RSA identity key"),
1072            (7, certs::CERT_T7, "No RSA->Ed crosscert"),
1073            (4, certs::CERT_T4, "Missing IDENTITY_V_SIGNING certificate"),
1074            (5, certs::CERT_T5, "Missing SIGNING_V_TLS_CERT certificate"),
1075        ];
1076
1077        for omit_idx in 0..4 {
1078            // build a certs cell with all but one certificate
1079            let mut certs = msg::Certs::new_empty();
1080            let mut expect_err = None;
1081            for (idx, (ctype, cert, err)) in all_certs.iter().enumerate() {
1082                if idx == omit_idx {
1083                    expect_err = Some(err);
1084                    continue;
1085                }
1086
1087                certs.push_cert_body((*ctype).into(), &cert[..]);
1088            }
1089            let res = certs_test(
1090                certs,
1091                Some(cert_timestamp()),
1092                certs::PEER_ED,
1093                certs::PEER_RSA,
1094                certs::PEER_CERT_DIGEST,
1095                &rt,
1096            )
1097            .err()
1098            .unwrap();
1099
1100            assert_eq!(
1101                format!("{}", res),
1102                format!("Handshake protocol violation: {}", expect_err.unwrap())
1103            );
1104        }
1105    }
1106
1107    #[test]
1108    fn certs_wrongtarget() {
1109        let rt = PreferredRuntime::create().unwrap();
1110        let mut certs = msg::Certs::new_empty();
1111        certs.push_cert_body(2.into(), certs::CERT_T2);
1112        certs.push_cert_body(5.into(), certs::CERT_T5);
1113        certs.push_cert_body(7.into(), certs::CERT_T7);
1114        certs.push_cert_body(4.into(), certs::CERT_T4);
1115        let err = certs_test(
1116            certs.clone(),
1117            Some(cert_timestamp()),
1118            &[0x10; 32],
1119            certs::PEER_RSA,
1120            certs::PEER_CERT_DIGEST,
1121            &rt,
1122        )
1123        .err()
1124        .unwrap();
1125
1126        let re = Regex::new(
1127            // identities might be scrubbed by safelog
1128            r"Identity .* does not match target .*",
1129        )
1130        .unwrap();
1131        assert!(re.is_match(&format!("{}", err)));
1132
1133        let err = certs_test(
1134            certs.clone(),
1135            Some(cert_timestamp()),
1136            certs::PEER_ED,
1137            &[0x99; 20],
1138            certs::PEER_CERT_DIGEST,
1139            &rt,
1140        )
1141        .err()
1142        .unwrap();
1143
1144        let re = Regex::new(
1145            // identities might be scrubbed by safelog
1146            r"Identity .* does not match target .*",
1147        )
1148        .unwrap();
1149        assert!(re.is_match(&format!("{}", err)));
1150
1151        let err = certs_test(
1152            certs,
1153            Some(cert_timestamp()),
1154            certs::PEER_ED,
1155            certs::PEER_RSA,
1156            &[0; 32],
1157            &rt,
1158        )
1159        .err()
1160        .unwrap();
1161
1162        assert_eq!(
1163            format!("{}", err),
1164            "Handshake protocol violation: Peer cert did not authenticate TLS cert"
1165        );
1166    }
1167
1168    #[test]
1169    fn certs_badsig() {
1170        let rt = PreferredRuntime::create().unwrap();
1171        fn munge(inp: &[u8]) -> Vec<u8> {
1172            let mut v: Vec<u8> = inp.into();
1173            v[inp.len() - 1] ^= 0x10;
1174            v
1175        }
1176        let mut certs = msg::Certs::new_empty();
1177        certs.push_cert_body(2.into(), certs::CERT_T2);
1178        certs.push_cert_body(5.into(), munge(certs::CERT_T5)); // munge an ed signature
1179        certs.push_cert_body(7.into(), certs::CERT_T7);
1180        certs.push_cert_body(4.into(), certs::CERT_T4);
1181        let res = certs_test(
1182            certs,
1183            Some(cert_timestamp()),
1184            certs::PEER_ED,
1185            certs::PEER_RSA,
1186            certs::PEER_CERT_DIGEST,
1187            &rt,
1188        )
1189        .err()
1190        .unwrap();
1191
1192        assert_eq!(
1193            format!("{}", res),
1194            "Handshake protocol violation: Invalid ed25519 signature in handshake"
1195        );
1196
1197        let mut certs = msg::Certs::new_empty();
1198        certs.push_cert_body(2.into(), certs::CERT_T2);
1199        certs.push_cert_body(5.into(), certs::CERT_T5);
1200        certs.push_cert_body(7.into(), munge(certs::CERT_T7)); // munge an RSA signature
1201        certs.push_cert_body(4.into(), certs::CERT_T4);
1202        let res = certs_test(
1203            certs,
1204            Some(cert_timestamp()),
1205            certs::PEER_ED,
1206            certs::PEER_RSA,
1207            certs::PEER_CERT_DIGEST,
1208            &rt,
1209        )
1210        .err()
1211        .unwrap();
1212
1213        assert_eq!(
1214            format!("{}", res),
1215            "Handshake protocol violation: Bad RSA->Ed crosscert signature"
1216        );
1217    }
1218
1219    /// This module has a few certificates to play with. They're taken
1220    /// from a chutney network. They match those used in the CERTS
1221    /// cell test vector in the tor-cell crate.
1222    ///
1223    /// The names are taken from the type of the certificate.
1224    mod certs {
1225        use hex_literal::hex;
1226
1227        pub(crate) const CERT_T2: &[u8] = &hex!(
1228            "308201B930820122A0030201020208607C28BE6C390943300D06092A864886F70D01010B0500301F311D301B06035504030C147777772E74636A76356B766A646472322E636F6D301E170D3230303831303030303030305A170D3231303831303030303030305A301F311D301B06035504030C147777772E74636A76356B766A646472322E636F6D30819F300D06092A864886F70D010101050003818D0030818902818100D38B1E6CEB946E0DB0751F4CBACE3DCB9688B6C25304227B4710C35AFB73627E50500F5913E158B621802612D1C75827003703338375237552EB3CD3C12F6AB3604E60C1A2D26BB1FBAD206FF023969A90909D6A65A5458A5312C26EBD3A3DAD30302D4515CDCD264146AC18E6FC60A04BD3EC327F04294D96BA5AA25B464C3F0203010001300D06092A864886F70D01010B0500038181003BCE561EA7F95CC00B78AAB5D69573FF301C282A751D4A651921D042F1BECDBA24D918A6D8A5E138DC07BBA0B335478AE37ABD2C93A93932442AE9084329E846170FE0FC4A50AAFC804F311CC3CA4F41D845A7BA5901CBBC3E021E9794AAC70CE1F37B0A951592DB1B64F2B4AFB81AE52DBD9B6FEDE96A5FB8125EB6251EE50A"
1229        );
1230
1231        pub(crate) const CERT_T4: &[u8] = &hex!(
1232            "01040006CC2A01F82294B866A31F01FC5D0DA8572850A9B929545C3266558D7D2316E3B74172B00100200400DCB604DB2034B00FD16986D4ADB9D16B21CB4E4457A33DEC0F538903683E96E9FF1A5203FA27F86EF7528D89A0845D2520166E340754FFEA2AAE0F612B7CE5DA094A0236CDAC45034B0B6842C18E7F6B51B93A3CF7E60663B8AD061C30A62602"
1233        );
1234        pub(crate) const CERT_T5: &[u8] = &hex!(
1235            "01050006C98A03B4FD606B64E4CBD466B8D76CB131069BAE6F3AA1878857C9F624E31D77A799B8007173E5F8068431D0D3F5EE16B4C9FFD59DF373E152A87281BAE744AA5FCF72171BF4B27C4E8FC1C6A9FC5CA11058BC49647063D7903CFD9F512F89099B27BC0C"
1236        );
1237
1238        pub(crate) const CERT_T7: &[u8] = &hex!(
1239            "DCB604DB2034B00FD16986D4ADB9D16B21CB4E4457A33DEC0F538903683E96E90006DA3A805CF6006F9179066534DE6B45AD47A5C469063EE462762723396DC9F25452A0A52DA3F5087DD239F2A311F6B0D4DFEFF4ABD089DC3D0237A0ABAB19EB2045B91CDCAF04BE0A72D548A27BF2E77BD876ECFE5E1BE622350DA6BF31F6E306ED896488DD5B39409B23FC3EB7B2C9F7328EB18DA36D54D80575899EA6507CCBFCDF1F"
1240        );
1241
1242        pub(crate) const PEER_CERT_DIGEST: &[u8] =
1243            &hex!("b4fd606b64e4cbd466b8d76cb131069bae6f3aa1878857c9f624e31d77a799b8");
1244
1245        pub(crate) const PEER_ED: &[u8] =
1246            &hex!("dcb604db2034b00fd16986d4adb9d16b21cb4e4457a33dec0f538903683e96e9");
1247        pub(crate) const PEER_RSA: &[u8] = &hex!("2f1fb49bb332a9eec617e41e911c33fb3890aef3");
1248    }
1249
1250    #[test]
1251    fn test_finish() {
1252        tor_rtcompat::test_with_one_runtime!(|rt| async move {
1253            let ed25519_id = [3_u8; 32].into();
1254            let rsa_id = [4_u8; 20].into();
1255            let peer_addr = "127.1.1.2:443".parse().unwrap();
1256            let mut framed_tls = new_frame(MsgBuf::new(&b""[..]), ChannelType::ClientInitiator);
1257            let _ = framed_tls.codec_mut().set_link_version(4);
1258            let ver = VerifiedChannel {
1259                channel_type: ChannelType::ClientInitiator,
1260                link_protocol: 4,
1261                framed_tls,
1262                unique_id: UniqId::new(),
1263                target_method: Some(ChannelMethod::Direct(vec![peer_addr])),
1264                ed25519_id,
1265                rsa_id,
1266                clock_skew: ClockSkew::None,
1267                sleep_prov: rt,
1268                memquota: fake_mq(),
1269            };
1270
1271            let (_chan, _reactor) = ver.finish().await.unwrap();
1272
1273            // TODO: check contents of netinfo cell
1274        });
1275    }
1276}