1
//! Implementations for the channel handshake
2

            
3
use futures::io::{AsyncRead, AsyncWrite};
4
use futures::sink::SinkExt;
5
use futures::stream::{Stream, StreamExt};
6
use std::net::IpAddr;
7
use std::sync::Arc;
8
use std::time::SystemTime;
9

            
10
use crate::channel::{Canonicity, ChannelFrame, UniqId};
11
use crate::memquota::ChannelAccount;
12
use crate::peer::PeerInfo;
13
use crate::util::skew::ClockSkew;
14
use crate::{Error, Result};
15
use safelog::{MaybeSensitive, Redacted};
16
use tor_cell::chancell::msg::AnyChanMsg;
17
use tor_cell::chancell::{AnyChanCell, ChanMsg, msg};
18
use tor_cell::restrict::{RestrictedMsg, restricted_msg};
19
use tor_error::{internal, into_internal};
20
use tor_linkspec::{
21
    ChanTarget, ChannelMethod, OwnedChanTarget, OwnedChanTargetBuilder, RelayIds, RelayIdsBuilder,
22
};
23
use tor_llcrypto as ll;
24
use tor_llcrypto::pk::ed25519::Ed25519Identity;
25
use tor_llcrypto::pk::rsa::RsaIdentity;
26
use tor_rtcompat::{CoarseTimeProvider, SleepProvider, StreamOps};
27

            
28
use digest::Digest;
29

            
30
use tracing::{debug, instrument, trace};
31

            
32
/// A list of the link protocols that we support.
33
pub(crate) static LINK_PROTOCOLS: &[u16] = &[4, 5];
34

            
35
/// Base trait that all handshake type must implement.
36
///
37
/// It has common code that all handshake share including getters for the channel frame for cell
38
/// decoding/encoding and the unique ID used for logging.
39
///
40
/// It has both a recv() and send() function for the VERSIONS cell since every handshake must start
41
/// with this cell to negotiate the link protocol version.
42
pub(crate) trait ChannelBaseHandshake<T>
43
where
44
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
45
{
46
    /// Return a mutable reference to the channel frame.
47
    fn framed_tls(&mut self) -> &mut ChannelFrame<T>;
48
    /// Return a reference to the unique ID of this handshake.
49
    fn unique_id(&self) -> &UniqId;
50

            
51
    /// Send a [msg::Versions] cell.
52
    ///
53
    /// A tuple is returned that is respectively the instant and wallclock of the send.
54
24
    async fn send_versions_cell<F>(
55
24
        &mut self,
56
24
        now_fn: F,
57
24
    ) -> Result<(coarsetime::Instant, SystemTime)>
58
24
    where
59
24
        F: FnOnce() -> SystemTime,
60
24
    {
61
24
        trace!(stream_id = %self.unique_id(), "sending versions");
62
        // Send versions cell
63
24
        let version_cell = AnyChanCell::new(
64
24
            None,
65
24
            msg::Versions::new(LINK_PROTOCOLS)
66
24
                .map_err(|e| Error::from_cell_enc(e, "versions message"))?
67
24
                .into(),
68
        );
69
24
        self.framed_tls().send(version_cell).await?;
70
24
        Ok((
71
24
            coarsetime::Instant::now(), // Flushed at instant
72
24
            now_fn(),                   // Flushed at wallclock
73
24
        ))
74
24
    }
75

            
76
    /// Receive a [msg::Versions] cell.
77
    ///
78
    /// The negotiated link protocol is returned, and also recorded in the underlying channel
79
    /// frame. This automatically transitions the frame into the "Handshake" state of the
80
    /// underlying cell handler. In other words, once the link protocol version is negotiated, the
81
    /// handler can encode and decode cells for that version in order to continue the handshake.
82
36
    async fn recv_versions_cell(&mut self) -> Result<u16> {
83
        // Get versions cell.
84
        // Get versions cell.
85
24
        trace!(stream_id = %self.unique_id(), "waiting for versions");
86
        // This can be None if we've reached EOF or any type of I/O error on the underlying TCP or
87
        // TLS stream. Either case, it is unexpected.
88
24
        let Some(cell) = self.framed_tls().next().await.transpose()? else {
89
            return Err(Error::ChanIoErr(Arc::new(std::io::Error::from(
90
                std::io::ErrorKind::UnexpectedEof,
91
            ))));
92
        };
93
22
        let AnyChanMsg::Versions(their_versions) = cell.into_circid_and_msg().1 else {
94
            return Err(Error::from(internal!(
95
                "Unexpected cell, expecting a VERSIONS cell",
96
            )));
97
        };
98
22
        trace!(stream_id = %self.unique_id(), "received their VERSIONS {:?}", their_versions);
99

            
100
        // Determine which link protocol we negotiated.
101
22
        let link_protocol = their_versions
102
22
            .best_shared_link_protocol(LINK_PROTOCOLS)
103
22
            .ok_or_else(|| Error::HandshakeProto("No shared link protocols".into()))?;
104
20
        trace!(stream_id = %self.unique_id(), "negotiated version {}", link_protocol);
105

            
106
        // Set the link protocol into our channel frame.
107
20
        self.framed_tls()
108
20
            .codec_mut()
109
20
            .set_link_version(link_protocol)?;
110
20
        Ok(link_protocol)
111
24
    }
112
}
113

            
114
/// Handshake initiator base trait. All initiator handshake should implement this trait in order to
115
/// enjoy the helper functions.
116
///
117
/// It requires the base handshake trait to be implement for access to the base getters.
118
pub(crate) trait ChannelInitiatorHandshake<T>: ChannelBaseHandshake<T>
119
where
120
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
121
{
122
    /// As an initiator, we are expecting the responder's cells which are:
123
    /// - [msg::Certs]
124
    /// - [msg::AuthChallenge]
125
    /// - [msg::Netinfo]
126
    ///
127
    /// Any duplicate, missing cell or unexpected results in a protocol level error.
128
    ///
129
    /// This returns the [msg::AuthChallenge], [msg::Certs] and [msg::Netinfo] cells along the
130
    /// instant when the netinfo cell was received. This is needed for the clock skew calculation.
131
20
    async fn recv_cells_from_responder(
132
20
        &mut self,
133
20
    ) -> Result<(
134
20
        msg::AuthChallenge,
135
20
        msg::Certs,
136
20
        (msg::Netinfo, coarsetime::Instant),
137
30
    )> {
138
        // IMPORTANT: Protocol wise, we MUST only allow one single cell of each type for a valid
139
        // handshake. Any duplicates lead to a failure.
140
        // They must arrive in a specific order in order for the SLOG calculation to be valid.
141

            
142
        /// Read a message from the stream.
143
        ///
144
        /// The `expecting` parameter is used for logging purposes, not filtering.
145
52
        async fn read_msg<T>(
146
52
            stream_id: UniqId,
147
52
            mut stream: impl Stream<Item = Result<AnyChanCell>> + Unpin,
148
52
        ) -> Result<T>
149
52
        where
150
52
            T: RestrictedMsg + TryFrom<AnyChanMsg, Error = AnyChanMsg>,
151
52
        {
152
52
            let Some(cell) = stream.next().await.transpose()? else {
153
                // The entire channel has ended, so nothing else to be done.
154
2
                return Err(Error::HandshakeProto("Stream ended unexpectedly".into()));
155
            };
156

            
157
46
            let (id, m) = cell.into_circid_and_msg();
158
46
            trace!(%stream_id, "received a {} cell", m.cmd());
159

            
160
            // TODO: Maybe also check this in the channel handshake codec?
161
46
            if let Some(id) = id {
162
                return Err(Error::HandshakeProto(format!(
163
                    "Expected no circ ID for {} cell, but received circ ID of {id} instead",
164
                    m.cmd(),
165
                )));
166
46
            }
167

            
168
46
            let m = m.try_into().map_err(|m: AnyChanMsg| {
169
6
                Error::HandshakeProto(format!(
170
6
                    "Expected [{}] cell, but received {} cell instead",
171
6
                    tor_basic_utils::iter_join(", ", T::cmds_for_logging().iter()),
172
6
                    m.cmd(),
173
6
                ))
174
6
            })?;
175

            
176
40
            Ok(m)
177
52
        }
178

            
179
        // Note that the `ChannelFrame` already restricts the messages due to its handshake cell
180
        // handler.
181

            
182
14
        let certs = loop {
183
            restricted_msg! {
184
                enum CertsMsg : ChanMsg {
185
                    // VPADDING cells (but not PADDING) can be sent during handshaking.
186
                    Vpadding,
187
                    Certs,
188
               }
189
            }
190

            
191
20
            break match read_msg(*self.unique_id(), self.framed_tls()).await? {
192
                CertsMsg::Vpadding(_) => continue,
193
14
                CertsMsg::Certs(msg) => msg,
194
            };
195
        };
196

            
197
        // Clients don't care about AuthChallenge,
198
        // but the responder always sends it anyways so we require it here.
199
10
        let auth_challenge = loop {
200
            restricted_msg! {
201
                enum AuthChallengeMsg : ChanMsg {
202
                    // VPADDING cells (but not PADDING) can be sent during handshaking.
203
                    Vpadding,
204
                    AuthChallenge,
205
               }
206
            }
207

            
208
18
            break match read_msg(*self.unique_id(), self.framed_tls()).await? {
209
4
                AuthChallengeMsg::Vpadding(_) => continue,
210
10
                AuthChallengeMsg::AuthChallenge(msg) => msg,
211
            };
212
        };
213

            
214
8
        let (netinfo, netinfo_rcvd_at) = loop {
215
            restricted_msg! {
216
                enum NetinfoMsg : ChanMsg {
217
                    // VPADDING cells (but not PADDING) can be sent during handshaking.
218
                    Vpadding,
219
                    Netinfo,
220
               }
221
            }
222

            
223
14
            break match read_msg(*self.unique_id(), self.framed_tls()).await? {
224
4
                NetinfoMsg::Vpadding(_) => continue,
225
8
                NetinfoMsg::Netinfo(msg) => (msg, coarsetime::Instant::now()),
226
            };
227
        };
228

            
229
8
        Ok((auth_challenge, certs, (netinfo, netinfo_rcvd_at)))
230
20
    }
231
}
232

            
233
/// A base channel on which versions have been negotiated and the relay's handshake has been read,
234
/// but where the certs have not been checked.
235
///
236
/// Both relay and client have specialized objects for an unverified channel which include this one
237
/// as the base in order to share functionnalities.
238
pub(crate) struct UnverifiedChannel<
239
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
240
    S: CoarseTimeProvider + SleepProvider,
241
> {
242
    /// Runtime handle (insofar as we need it)
243
    pub(crate) sleep_prov: S,
244
    /// Memory quota account
245
    pub(crate) memquota: ChannelAccount,
246
    /// The negotiated link protocol.  Must be a member of LINK_PROTOCOLS
247
    pub(crate) link_protocol: u16,
248
    /// The Source+Sink on which we're reading and writing cells.
249
    pub(crate) framed_tls: ChannelFrame<T>,
250
    /// The certs cell that we might have got during the handshake.
251
    pub(crate) certs_cell: Option<msg::Certs>,
252
    /// Declared target method for this channel, if any.
253
    pub(crate) target_method: Option<ChannelMethod>,
254
    /// How much clock skew did we detect in this handshake?
255
    ///
256
    /// This value is _unauthenticated_, since we have not yet checked whether
257
    /// the keys in the handshake are the ones we expected.
258
    pub(crate) clock_skew: ClockSkew,
259
    /// Logging identifier for this stream.  (Used for logging only.)
260
    pub(crate) unique_id: UniqId,
261
}
262

            
263
/// A base channel on which versions have been negotiated, relay's handshake has been read, but the
264
/// client has not yet finished the handshake.
265
///
266
/// This type is separate from UnverifiedChannel, since finishing the handshake requires a bunch of
267
/// CPU, and you might want to do it as a separate task or after a yield.
268
///
269
/// Both relay and client have specialized objects for an unverified channel which include this one
270
/// as the base in order to share functionnalities.
271
pub(crate) struct VerifiedChannel<
272
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
273
    S: CoarseTimeProvider + SleepProvider,
274
> {
275
    /// Runtime handle (insofar as we need it)
276
    pub(crate) sleep_prov: S,
277
    /// Memory quota account
278
    pub(crate) memquota: ChannelAccount,
279
    /// The negotiated link protocol.
280
    pub(crate) link_protocol: u16,
281
    /// The Source+Sink on which we're reading and writing cells.
282
    pub(crate) framed_tls: ChannelFrame<T>,
283
    /// Declared target method for this stream, if any.
284
    pub(crate) target_method: Option<ChannelMethod>,
285
    /// Logging identifier for this stream.  (Used for logging only.)
286
    pub(crate) unique_id: UniqId,
287
    /// Validated Ed25519 identity for this peer.
288
    pub(crate) ed25519_id: Ed25519Identity,
289
    /// Validated RSA identity for this peer.
290
    pub(crate) rsa_id: RsaIdentity,
291
    /// Validated RSA identity digest of the DER format for this peer.
292
    pub(crate) rsa_id_digest: [u8; 32],
293
    /// Peer TLS certificate digest
294
    pub(crate) peer_cert_digest: [u8; 32],
295
    /// Authenticated clock skew for this peer.
296
    pub(crate) clock_skew: ClockSkew,
297
}
298

            
299
impl<
300
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
301
    S: CoarseTimeProvider + SleepProvider,
302
> UnverifiedChannel<T, S>
303
{
304
    /// Validate the certificates and keys in the relay's handshake.
305
    ///
306
    /// 'peer' is the peer that we want to make sure we're connecting to.
307
    ///
308
    /// 'peer_cert' is the x.509 certificate that the peer presented during
309
    /// its TLS handshake (ServerHello).
310
    ///
311
    /// 'now' is the time at which to check that certificates are
312
    /// valid.  `None` means to use the current time. It can be used
313
    /// for testing to override the current view of the time.
314
    ///
315
    /// This is a separate function because it's likely to be somewhat
316
    /// CPU-intensive.
317
    #[instrument(skip_all, level = "trace")]
318
2
    pub(crate) fn check<U: ChanTarget + ?Sized>(
319
2
        self,
320
2
        peer: &U,
321
2
        peer_cert: &[u8],
322
2
        now: Option<std::time::SystemTime>,
323
2
    ) -> Result<VerifiedChannel<T, S>> {
324
2
        let peer_cert_sha256 = ll::d::Sha256::digest(peer_cert).into();
325
2
        self.check_internal(peer, peer_cert_sha256, now)
326
2
    }
327

            
328
    /// Same as `check`, but takes the SHA256 hash of the peer certificate,
329
    /// since that is all we use.
330
24
    pub(crate) fn check_internal<U: ChanTarget + ?Sized>(
331
24
        self,
332
24
        peer: &U,
333
24
        peer_cert_digest: [u8; 32],
334
24
        now: Option<SystemTime>,
335
24
    ) -> Result<VerifiedChannel<T, S>> {
336
        use tor_cert::CertType;
337
        use tor_checkable::*;
338

            
339
        /// Helper: given a time-bound input, give a result reflecting its
340
        /// validity at `now`, and the inner object.
341
        ///
342
        /// We use this here because we want to validate the whole handshake
343
        /// regardless of whether the certs are expired, so we can determine
344
        /// whether we got a plausible handshake with a skewed partner, or
345
        /// whether the handshake is definitely bad.
346
44
        fn check_timeliness<C, T>(checkable: C, now: SystemTime, skew: ClockSkew) -> (Result<()>, T)
347
44
        where
348
44
            C: Timebound<T, Error = TimeValidityError>,
349
        {
350
44
            let status = checkable.is_valid_at(&now).map_err(|e| match (e, skew) {
351
                (TimeValidityError::Expired(expired_by), ClockSkew::Fast(skew))
352
                    if expired_by < skew =>
353
                {
354
                    Error::HandshakeCertsExpired { expired_by }
355
                }
356
                // As it so happens, we don't need to check for this case, since the certs in use
357
                // here only have an expiration time in them.
358
                // (TimeValidityError::NotYetValid(_), ClockSkew::Slow(_)) => todo!(),
359
                (_, _) => Error::HandshakeProto("Certificate expired or not yet valid".into()),
360
            });
361
44
            let cert = checkable.dangerously_assume_timely();
362
44
            (status, cert)
363
44
        }
364
        // Replace 'now' with the real time to use.
365
24
        let now = now.unwrap_or_else(SystemTime::now);
366

            
367
        // We need to check the following lines of authentication:
368
        //
369
        // First, to bind the ed identity to the channel.
370
        //    peer.ed_identity() matches the key in...
371
        //    IDENTITY_V_SIGNING cert, which signs...
372
        //    SIGNING_V_TLS_CERT cert, which signs peer_cert.
373
        //
374
        // Second, to bind the rsa identity to the ed identity:
375
        //    peer.rsa_identity() matches the key in...
376
        //    the x.509 RSA identity certificate (type 2), which signs...
377
        //    the RSA->Ed25519 crosscert (type 7), which signs...
378
        //    peer.ed_identity().
379

            
380
        // Evidently, without a CERTS at this point we have a code flow issue.
381
24
        let Some(c) = &self.certs_cell.as_ref() else {
382
            return Err(Error::from(internal!("No CERTS cell found to verify")));
383
        };
384

            
385
        /// Helper: get a cert from a Certs cell, and convert errors appropriately.
386
114
        fn get_cert(
387
114
            certs: &tor_cell::chancell::msg::Certs,
388
114
            tp: CertType,
389
114
        ) -> Result<tor_cert::KeyUnknownCert> {
390
114
            match certs.parse_ed_cert(tp) {
391
108
                Ok(c) => Ok(c),
392
6
                Err(tor_cell::Error::ChanProto(e)) => Err(Error::HandshakeProto(e)),
393
                Err(e) => Err(Error::HandshakeProto(e.to_string())),
394
            }
395
114
        }
396

            
397
24
        let id_sk = get_cert(c, CertType::IDENTITY_V_SIGNING)?;
398
20
        let sk_tls = get_cert(c, CertType::SIGNING_V_TLS_CERT)?;
399

            
400
18
        let mut sigs = Vec::new();
401

            
402
        // Part 1: validate ed25519 stuff.
403
        //
404
        // (We are performing our timeliness checks now, but not inspecting them
405
        // until later in the function, so that we can distinguish failures that
406
        // might be caused by clock skew from failures that are definitely not
407
        // clock skew.)
408

            
409
        // Check the identity->signing cert
410
18
        let (id_sk, id_sk_sig) = id_sk
411
18
            .should_have_signing_key()
412
18
            .map_err(Error::HandshakeCertErr)?
413
18
            .dangerously_split()
414
18
            .map_err(Error::HandshakeCertErr)?;
415
18
        sigs.push(&id_sk_sig);
416
18
        let (id_sk_timeliness, id_sk) = check_timeliness(id_sk, now, self.clock_skew);
417

            
418
        // Take the identity key from the identity->signing cert
419
18
        let identity_key = id_sk.signing_key().ok_or_else(|| {
420
            Error::HandshakeProto("Missing identity key in identity->signing cert".into())
421
        })?;
422

            
423
        // Take the signing key from the identity->signing cert
424
18
        let signing_key = id_sk.subject_key().as_ed25519().ok_or_else(|| {
425
            Error::HandshakeProto("Bad key type in identity->signing cert".into())
426
        })?;
427

            
428
        // Now look at the signing->TLS cert and check it against the
429
        // peer certificate.
430
18
        let (sk_tls, sk_tls_sig) = sk_tls
431
18
            .should_be_signed_with(signing_key)
432
18
            .map_err(Error::HandshakeCertErr)?
433
18
            .dangerously_split()
434
18
            .map_err(Error::HandshakeCertErr)?;
435
18
        sigs.push(&sk_tls_sig);
436
18
        let (sk_tls_timeliness, sk_tls) = check_timeliness(sk_tls, now, self.clock_skew);
437

            
438
18
        if peer_cert_digest != sk_tls.subject_key().as_bytes() {
439
2
            return Err(Error::HandshakeProto(
440
2
                "Peer cert did not authenticate TLS cert".into(),
441
2
            ));
442
16
        }
443

            
444
        // Batch-verify the ed25519 certificates in this handshake.
445
        //
446
        // In theory we could build a list of _all_ the certificates here
447
        // and call pk::validate_all_sigs() instead, but that doesn't gain
448
        // any performance.
449
16
        if !ll::pk::ed25519::validate_batch(&sigs[..]) {
450
2
            return Err(Error::HandshakeProto(
451
2
                "Invalid ed25519 signature in handshake".into(),
452
2
            ));
453
14
        }
454

            
455
        // Part 2: validate rsa stuff.
456

            
457
        // What is the RSA identity key, according to the X.509 certificate
458
        // in which it is self-signed?
459
        //
460
        // (We don't actually check this self-signed certificate, and we use
461
        // a kludge to extract the RSA key)
462
14
        let rsa_id_cert_bytes = c
463
14
            .cert_body(CertType::RSA_ID_X509)
464
14
            .ok_or_else(|| Error::HandshakeProto("Couldn't find RSA identity cert".into()))?;
465
12
        let pkrsa =
466
12
            ll::util::x509_extract_rsa_subject_kludge(rsa_id_cert_bytes).ok_or_else(|| {
467
                Error::HandshakeProto(
468
                    "Couldn't find RSA SubjectPublicKey from RSA identity cert".into(),
469
                )
470
            })?;
471

            
472
        // Now verify the RSA identity -> Ed Identity crosscert.
473
        //
474
        // This proves that the RSA key vouches for the Ed key.  Note that
475
        // the Ed key does not vouch for the RSA key: The RSA key is too
476
        // weak.
477
12
        let rsa_cert = c
478
12
            .cert_body(CertType::RSA_ID_V_IDENTITY)
479
12
            .ok_or_else(|| Error::HandshakeProto("No RSA->Ed crosscert".into()))?;
480
10
        let rsa_cert = tor_cert::rsa::RsaCrosscert::decode(rsa_cert)
481
10
            .map_err(|e| Error::from_bytes_err(e, "RSA identity cross-certificate"))?
482
10
            .check_signature(&pkrsa)
483
10
            .map_err(|_| Error::HandshakeProto("Bad RSA->Ed crosscert signature".into()))?;
484
8
        let (rsa_cert_timeliness, rsa_cert) = check_timeliness(rsa_cert, now, self.clock_skew);
485

            
486
8
        if !rsa_cert.subject_key_matches(identity_key) {
487
            return Err(Error::HandshakeProto(
488
                "RSA->Ed crosscert certifies incorrect key".into(),
489
            ));
490
8
        }
491

            
492
8
        let rsa_id_digest: [u8; 32] = ll::d::Sha256::digest(pkrsa.to_der()).into();
493
8
        let rsa_id = pkrsa.to_rsa_identity();
494

            
495
8
        trace!(
496
            stream_id = %self.unique_id,
497
            "Validated identity as {} [{}]",
498
            identity_key,
499
            rsa_id
500
        );
501

            
502
        // Now that we've done all the verification steps on the
503
        // certificates, we know who we are talking to.  It's time to
504
        // make sure that the peer we are talking to is the peer we
505
        // actually wanted.
506
        //
507
        // We do this _last_, since "this is the wrong peer" is
508
        // usually a different situation than "this peer couldn't even
509
        // identify itself right."
510

            
511
8
        let actual_identity = RelayIds::builder()
512
8
            .ed_identity(*identity_key)
513
8
            .rsa_identity(rsa_id)
514
8
            .build()
515
8
            .expect("Unable to build RelayIds");
516

            
517
        // We enforce that the relay proved that it has every ID that we wanted:
518
        // it may also have additional IDs that we didn't ask for.
519
8
        match super::check_id_match_helper(&actual_identity, peer) {
520
4
            Err(Error::ChanMismatch(msg)) => Err(Error::HandshakeProto(msg)),
521
4
            other => other,
522
4
        }?;
523

            
524
        // If we reach this point, the clock skew might be may now be considered
525
        // authenticated: The certificates are what we wanted, and everything
526
        // was well signed.
527
        //
528
        // The only remaining concern is certificate timeliness.  If the
529
        // certificates are expired by an amount that is too large for the
530
        // declared clock skew to explain, then  we'll return
531
        // `Error::HandshakeProto`: in that case the clock skew is _not_
532
        // authenticated.  But if the certs are only expired by a little bit,
533
        // we'll reject the handshake with `Error::HandshakeCertsExpired`, and
534
        // the caller can trust the clock skew.
535
        //
536
        // We note expired certs last, since we only want to return
537
        // `HandshakeCertsExpired` when there are no other errors.
538
4
        id_sk_timeliness?;
539
4
        sk_tls_timeliness?;
540
4
        rsa_cert_timeliness?;
541

            
542
4
        Ok(VerifiedChannel {
543
4
            link_protocol: self.link_protocol,
544
4
            framed_tls: self.framed_tls,
545
4
            unique_id: self.unique_id,
546
4
            target_method: self.target_method,
547
4
            ed25519_id: *identity_key,
548
4
            rsa_id,
549
4
            rsa_id_digest,
550
4
            peer_cert_digest,
551
4
            clock_skew: self.clock_skew,
552
4
            sleep_prov: self.sleep_prov,
553
4
            memquota: self.memquota,
554
4
        })
555
24
    }
556

            
557
    /// Finalize this channel into an actual channel and its reactor.
558
    ///
559
    /// An unverified channel can be finalized as it skipped the cert verification and
560
    /// authentication because simply the other side is not authenticating.
561
    ///
562
    /// Two cases for this:
563
    ///     - Client <-> Relay channel
564
    ///     - Bridge <-> Relay channel
565
    ///
566
    // NOTE: Unfortunately, this function has duplicated code with the VerifiedChannel::finish()
567
    // so make sure any changes here is reflected there. A proper refactoring is welcome!
568
    #[instrument(skip_all, level = "trace")]
569
    pub(crate) fn finish(
570
        mut self,
571
        netinfo: &msg::Netinfo,
572
        my_addrs: &[IpAddr],
573
        peer_info: MaybeSensitive<PeerInfo>,
574
    ) -> Result<(Arc<super::Channel>, super::reactor::Reactor<S>)> {
575
        // We treat a completed channel as incoming traffic since all cells were exchanged.
576
        //
577
        // TODO: conceivably we should remember the time when we _got_ the
578
        // final cell on the handshake, and update the channel completion
579
        // time to be no earlier than _that_ timestamp.
580
        //
581
        // TODO: This shouldn't be here. This should be called in the trait functions that actually
582
        // receives the data (recv_*). We'll move it at a later commit.
583
        crate::note_incoming_traffic();
584

            
585
        // We have finalized the handshake, move our codec to Open.
586
        self.framed_tls.codec_mut().set_open()?;
587

            
588
        // Grab the channel type from our underlying frame as we are about to consume the
589
        // framed_tls and we need the channel type to be set into the resulting Channel.
590
        let channel_type = self.framed_tls.codec().channel_type();
591

            
592
        // Grab a new handle on which we can apply StreamOps (needed for KIST).
593
        // On Unix platforms, this handle is a wrapper over the fd of the socket.
594
        //
595
        // Note: this is necessary because after `StreamExit::split()`,
596
        // we no longer have access to the underlying stream
597
        // or its StreamOps implementation.
598
        let stream_ops = self.framed_tls.new_handle();
599
        let (tls_sink, tls_stream) = self.framed_tls.split();
600

            
601
        let canonicity =
602
            Canonicity::from_netinfo(netinfo, my_addrs, peer_info.addr().netinfo_addr());
603

            
604
        let peer_id = build_filtered_chan_target(self.target_method.take(), &peer_info);
605

            
606
        debug!(
607
            stream_id = %self.unique_id,
608
            "Completed handshake without authentication to {}", Redacted::new(&peer_id)
609
        );
610

            
611
        super::Channel::new(
612
            channel_type,
613
            self.link_protocol,
614
            Box::new(tls_sink),
615
            Box::new(tls_stream),
616
            stream_ops,
617
            self.unique_id,
618
            peer_id,
619
            peer_info,
620
            self.clock_skew,
621
            self.sleep_prov,
622
            self.memquota,
623
            canonicity,
624
        )
625
    }
626
}
627

            
628
impl<
629
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
630
    S: CoarseTimeProvider + SleepProvider,
631
> VerifiedChannel<T, S>
632
{
633
    /// Mark this channel as authenticated.
634
    pub(crate) fn set_authenticated(&mut self) -> Result<()> {
635
        self.framed_tls.codec_mut().set_authenticated()?;
636
        Ok(())
637
    }
638

            
639
    /// Build a [`RelayIds`] corresponding to this channel identities.
640
2
    pub(crate) fn relay_ids(&self) -> Result<RelayIds> {
641
2
        Ok(RelayIdsBuilder::default()
642
2
            .ed_identity(self.ed25519_id)
643
2
            .rsa_identity(self.rsa_id)
644
2
            .build()
645
2
            .map_err(into_internal!("Unable to build verified relay channel ids"))?)
646
2
    }
647

            
648
    /// The channel is used to send cells, and to create outgoing circuits.
649
    /// The reactor is used to route incoming messages to their appropriate
650
    /// circuit.
651
    #[instrument(skip_all, level = "trace")]
652
4
    pub(crate) async fn finish(
653
4
        mut self,
654
4
        netinfo: &msg::Netinfo,
655
4
        my_addrs: &[IpAddr],
656
4
        peer_info: MaybeSensitive<PeerInfo>,
657
4
    ) -> Result<(Arc<super::Channel>, super::reactor::Reactor<S>)> {
658
        // We treat a completed channel -- that is to say, one where the
659
        // authentication is finished -- as incoming traffic.
660
        //
661
        // TODO: conceivably we should remember the time when we _got_ the
662
        // final cell on the handshake, and update the channel completion
663
        // time to be no earlier than _that_ timestamp.
664
        //
665
        // TODO: This shouldn't be here. This should be called in the trait functions that actually
666
        // receives the data (recv_*). We'll move it at a later commit.
667
        crate::note_incoming_traffic();
668

            
669
        // We have finalized the handshake, move our codec to Open.
670
        self.framed_tls.codec_mut().set_open()?;
671

            
672
        // Grab the channel type from our underlying frame as we are about to consume the
673
        // framed_tls and we need the channel type to be set into the resulting Channel.
674
        let channel_type = self.framed_tls.codec().channel_type();
675

            
676
        debug!(
677
            stream_id = %self.unique_id,
678
            "Completed handshake with peer: {}", peer_info
679
        );
680

            
681
        // Grab a new handle on which we can apply StreamOps (needed for KIST).
682
        // On Unix platforms, this handle is a wrapper over the fd of the socket.
683
        //
684
        // Note: this is necessary because after `StreamExit::split()`,
685
        // we no longer have access to the underlying stream
686
        // or its StreamOps implementation.
687
        let stream_ops = self.framed_tls.new_handle();
688
        let (tls_sink, tls_stream) = self.framed_tls.split();
689

            
690
        let canonicity =
691
            Canonicity::from_netinfo(netinfo, my_addrs, peer_info.addr().netinfo_addr());
692

            
693
        let peer_id = build_filtered_chan_target(self.target_method.take(), &peer_info);
694

            
695
        super::Channel::new(
696
            channel_type,
697
            self.link_protocol,
698
            Box::new(tls_sink),
699
            Box::new(tls_stream),
700
            stream_ops,
701
            self.unique_id,
702
            peer_id,
703
            peer_info,
704
            self.clock_skew,
705
            self.sleep_prov,
706
            self.memquota,
707
            canonicity,
708
        )
709
4
    }
710
}
711

            
712
/// Helper: Calculate a clock skew from the [msg::Netinfo] cell data and the time at which we sent
713
/// the [msg::Versions] cell.
714
///
715
/// This is unauthenticated as in not validated with the certificates. Before using it, make sure
716
/// that you have authenticated the other party.
717
43
pub(crate) fn unauthenticated_clock_skew(
718
43
    netinfo_cell: &msg::Netinfo,
719
43
    netinfo_rcvd_at: coarsetime::Instant,
720
43
    versions_flushed_at: coarsetime::Instant,
721
43
    versions_flushed_wallclock: SystemTime,
722
43
) -> ClockSkew {
723
    // Try to compute our clock skew.  It won't be authenticated yet, since we haven't checked
724
    // the certificates.
725
43
    if let Some(netinfo_timestamp) = netinfo_cell.timestamp() {
726
41
        let delay = netinfo_rcvd_at - versions_flushed_at;
727
41
        ClockSkew::from_handshake_timestamps(
728
41
            versions_flushed_wallclock,
729
41
            netinfo_timestamp,
730
41
            delay.into(),
731
        )
732
    } else {
733
2
        ClockSkew::None
734
    }
735
43
}
736

            
737
/// Helper: Build a OwnedChanTarget that retains only the address that was actually used.
738
39
fn build_filtered_chan_target(
739
39
    target_method: Option<ChannelMethod>,
740
39
    peer_info: &MaybeSensitive<PeerInfo>,
741
39
) -> OwnedChanTarget {
742
39
    let mut peer_builder = OwnedChanTargetBuilder::default();
743
39
    if let Some(mut method) = target_method {
744
        // Retain only the address that was actually used to connect.
745
39
        if let Some(addr) = peer_info.addr().socket_addr() {
746
52
            let _ = method.retain_addrs(|socket_addr| socket_addr == &addr);
747
39
            peer_builder.addrs(vec![addr]);
748
        }
749
39
        peer_builder.method(method);
750
    }
751
39
    *peer_builder.ids() = RelayIdsBuilder::from_relay_ids(peer_info.ids());
752

            
753
39
    peer_builder
754
39
        .build()
755
39
        .expect("OwnedChanTarget builder failed")
756
39
}
757

            
758
#[cfg(test)]
759
pub(super) mod test {
760
    #![allow(clippy::unwrap_used)]
761
    use hex_literal::hex;
762
    use regex::Regex;
763
    use std::time::{Duration, SystemTime};
764

            
765
    use super::*;
766
    use crate::channel::handler::test::MsgBuf;
767
    use crate::channel::{ChannelType, new_frame};
768
    use crate::util::fake_mq;
769
    use crate::{Result, channel::ClientInitiatorHandshake};
770
    use tor_cell::chancell::msg::{self, Netinfo};
771
    use tor_linkspec::OwnedChanTarget;
772
    use tor_rtcompat::{PreferredRuntime, Runtime};
773

            
774
    const VERSIONS: &[u8] = &hex!("0000 07 0006 0003 0004 0005");
775
    // no certificates in this cell, but connect() doesn't care.
776
    const NOCERTS: &[u8] = &hex!("00000000 81 0001 00");
777
    const NETINFO_PREFIX: &[u8] = &hex!(
778
        "00000000 08 00000000
779
         04 04 7f 00 00 02
780
         01
781
         04 04 7f 00 00 03"
782
    );
783
    const NETINFO_PREFIX_WITH_TIME: &[u8] = &hex!(
784
        "00000000 08 48949290
785
         04 04 7f 00 00 02
786
         01
787
         04 04 7f 00 00 03"
788
    );
789
    const AUTHCHALLENGE: &[u8] = &hex!(
790
        "00000000 82 0026
791
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
792
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
793
         0002 0003 00ff"
794
    );
795

            
796
    const VPADDING: &[u8] = &hex!("00000000 80 0003 FF FF FF");
797

            
798
    fn add_padded(buf: &mut Vec<u8>, cell: &[u8]) {
799
        let len_prev = buf.len();
800
        buf.extend_from_slice(cell);
801
        buf.resize(len_prev + 514, 0);
802
    }
803
    fn add_netinfo(buf: &mut Vec<u8>) {
804
        add_padded(buf, NETINFO_PREFIX);
805
    }
806

            
807
    #[test]
808
    fn connect_ok() -> Result<()> {
809
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
810
            let now = humantime::parse_rfc3339("2008-08-02T17:00:00Z").unwrap();
811
            let mut buf = Vec::new();
812
            // versions cell
813
            buf.extend_from_slice(VERSIONS);
814
            // certs cell -- no certs in it, but this function doesn't care.
815
            buf.extend_from_slice(NOCERTS);
816
            // auth_challenge cell
817
            buf.extend_from_slice(AUTHCHALLENGE);
818
            // netinfo cell -- quite minimal.
819
            add_padded(&mut buf, NETINFO_PREFIX);
820
            let mb = MsgBuf::new(&buf[..]);
821
            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
822
            let unverified = handshake.connect(|| now).await?;
823

            
824
            assert_eq!(unverified.link_protocol(), 5);
825
            // No timestamp in the NETINFO, so no skew.
826
            assert_eq!(unverified.clock_skew(), ClockSkew::None);
827

            
828
            // Try again with some padding.
829
            let mut buf = Vec::new();
830
            buf.extend_from_slice(VERSIONS);
831
            buf.extend_from_slice(NOCERTS);
832
            buf.extend_from_slice(VPADDING);
833
            buf.extend_from_slice(AUTHCHALLENGE);
834
            buf.extend_from_slice(VPADDING);
835
            add_padded(&mut buf, NETINFO_PREFIX_WITH_TIME);
836
            let mb = MsgBuf::new(&buf[..]);
837
            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
838
            let unverified = handshake.connect(|| now).await?;
839
            // Correct timestamp in the NETINFO, so no skew.
840
            assert_eq!(unverified.clock_skew(), ClockSkew::None);
841

            
842
            // Now pretend our clock is fast.
843
            let now2 = now + Duration::from_secs(3600);
844
            let mb = MsgBuf::new(&buf[..]);
845
            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
846
            let unverified = handshake.connect(|| now2).await?;
847
            assert_eq!(
848
                unverified.clock_skew(),
849
                ClockSkew::Fast(Duration::from_secs(3600))
850
            );
851

            
852
            Ok(())
853
        })
854
    }
855

            
856
    async fn connect_err<T: Into<Vec<u8>>, S>(input: T, sleep_prov: S) -> Error
857
    where
858
        S: CoarseTimeProvider + SleepProvider,
859
    {
860
        let mb = MsgBuf::new(input);
861
        let handshake = ClientInitiatorHandshake::new(mb, None, sleep_prov, fake_mq());
862
        handshake.connect(SystemTime::now).await.err().unwrap()
863
    }
864

            
865
    #[test]
866
    fn connect_badver() {
867
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
868
            let err = connect_err(&b"HTTP://"[..], rt.clone()).await;
869
            assert!(matches!(err, Error::HandshakeProto(_)));
870
            assert_eq!(
871
                format!("{}", err),
872
                "Handshake protocol violation: Invalid CircID in variable cell"
873
            );
874

            
875
            let err = connect_err(&hex!("0000 07 0004 1234 ffff")[..], rt.clone()).await;
876
            assert!(matches!(err, Error::HandshakeProto(_)));
877
            assert_eq!(
878
                format!("{}", err),
879
                "Handshake protocol violation: No shared link protocols"
880
            );
881
        });
882
    }
883

            
884
    #[test]
885
    fn connect_cellparse() {
886
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
887
            let mut buf = Vec::new();
888
            buf.extend_from_slice(VERSIONS);
889
            // Here's a certs cell that will fail.
890
            buf.extend_from_slice(&hex!("00000000 81 0001 01")[..]);
891
            let err = connect_err(buf, rt.clone()).await;
892
            assert!(matches!(err, Error::HandshakeProto { .. }));
893
        });
894
    }
895

            
896
    #[test]
897
    fn connect_duplicates() {
898
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
899
            let mut buf = Vec::new();
900
            buf.extend_from_slice(VERSIONS);
901
            buf.extend_from_slice(NOCERTS);
902
            buf.extend_from_slice(NOCERTS);
903
            add_netinfo(&mut buf);
904
            let err = connect_err(buf, rt.clone()).await;
905
            assert!(matches!(err, Error::HandshakeProto(_)));
906
            assert_eq!(
907
                format!("{}", err),
908
                "Handshake protocol violation: Expected [VPADDING, AUTH_CHALLENGE] cell, but received CERTS cell instead"
909
            );
910

            
911
            let mut buf = Vec::new();
912
            buf.extend_from_slice(VERSIONS);
913
            buf.extend_from_slice(NOCERTS);
914
            buf.extend_from_slice(AUTHCHALLENGE);
915
            buf.extend_from_slice(AUTHCHALLENGE);
916
            add_netinfo(&mut buf);
917
            let err = connect_err(buf, rt.clone()).await;
918
            assert!(matches!(err, Error::HandshakeProto(_)));
919
            assert_eq!(
920
                format!("{}", err),
921
                "Handshake protocol violation: Expected [VPADDING, NETINFO] cell, but received AUTH_CHALLENGE cell instead"
922
            );
923
        });
924
    }
925

            
926
    #[test]
927
    fn connect_missing_certs() {
928
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
929
            let mut buf = Vec::new();
930
            buf.extend_from_slice(VERSIONS);
931
            add_netinfo(&mut buf);
932
            let err = connect_err(buf, rt.clone()).await;
933
            assert!(matches!(err, Error::HandshakeProto(_)));
934
            assert_eq!(
935
                format!("{}", err),
936
                "Handshake protocol violation: Expected [VPADDING, CERTS] cell, but received NETINFO cell instead"
937
            );
938
        });
939
    }
940

            
941
    #[test]
942
    fn connect_missing_netinfo() {
943
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
944
            let mut buf = Vec::new();
945
            buf.extend_from_slice(VERSIONS);
946
            buf.extend_from_slice(NOCERTS);
947
            let err = connect_err(buf, rt.clone()).await;
948
            assert!(matches!(err, Error::HandshakeProto(_)));
949
            assert_eq!(
950
                format!("{}", err),
951
                "Handshake protocol violation: Stream ended unexpectedly"
952
            );
953
        });
954
    }
955

            
956
    #[test]
957
    fn connect_misplaced_cell() {
958
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
959
            let mut buf = Vec::new();
960
            buf.extend_from_slice(VERSIONS);
961
            // here's a create cell.
962
            add_padded(&mut buf, &hex!("00000001 01")[..]);
963
            let err = connect_err(buf, rt.clone()).await;
964
            assert!(matches!(err, Error::HandshakeProto(_)));
965
            assert_eq!(
966
                format!("{}", err),
967
                "Handshake protocol violation: Decoding cell error: Error while parsing channel cell: Bad object: Unexpected command CREATE in HandshakeRelayResponderMsg"
968
            );
969
        });
970
    }
971

            
972
    fn make_unverified<R>(certs: msg::Certs, runtime: R) -> UnverifiedChannel<MsgBuf, R>
973
    where
974
        R: Runtime,
975
    {
976
        let mut framed_tls = new_frame(MsgBuf::new(&b""[..]), ChannelType::ClientInitiator);
977
        let _ = framed_tls.codec_mut().set_link_version(4);
978
        let _ = framed_tls.codec_mut().set_open();
979
        let clock_skew = ClockSkew::None;
980
        UnverifiedChannel {
981
            link_protocol: 4,
982
            framed_tls,
983
            certs_cell: Some(certs),
984
            clock_skew,
985
            target_method: None,
986
            unique_id: UniqId::new(),
987
            sleep_prov: runtime,
988
            memquota: fake_mq(),
989
        }
990
    }
991

            
992
    // Timestamp when the example certificates were all valid.
993
    fn cert_timestamp() -> SystemTime {
994
        use humantime::parse_rfc3339;
995
        parse_rfc3339("2020-09-26T18:01:20Z").unwrap()
996
    }
997

            
998
    fn certs_test<R>(
999
        certs: msg::Certs,
        when: Option<SystemTime>,
        peer_ed: &[u8],
        peer_rsa: &[u8],
        peer_cert_sha256: [u8; 32],
        runtime: &R,
    ) -> Result<VerifiedChannel<MsgBuf, R>>
    where
        R: Runtime,
    {
        let unver = make_unverified(certs, runtime.clone());
        let ed = Ed25519Identity::from_bytes(peer_ed).unwrap();
        let rsa = RsaIdentity::from_bytes(peer_rsa).unwrap();
        let chan = OwnedChanTarget::builder()
            .ed_identity(ed)
            .rsa_identity(rsa)
            .build()
            .unwrap();
        unver.check_internal(&chan, peer_cert_sha256, when)
    }
    // no certs at all!
    #[test]
    fn certs_none() {
        let rt = PreferredRuntime::create().unwrap();
        let err = certs_test(
            msg::Certs::new_empty(),
            None,
            &[0_u8; 32],
            &[0_u8; 20],
            [0_u8; 32],
            &rt,
        )
        .err()
        .unwrap();
        assert_eq!(
            format!("{}", err),
            "Handshake protocol violation: Missing IDENTITY_V_SIGNING certificate"
        );
    }
    #[test]
    fn certs_good() {
        let rt = PreferredRuntime::create().unwrap();
        let mut certs = msg::Certs::new_empty();
        certs.push_cert_body(2.into(), certs::CERT_T2);
        certs.push_cert_body(5.into(), certs::CERT_T5);
        certs.push_cert_body(7.into(), certs::CERT_T7);
        certs.push_cert_body(4.into(), certs::CERT_T4);
        let res = certs_test(
            certs,
            Some(cert_timestamp()),
            certs::PEER_ED,
            certs::PEER_RSA,
            *certs::PEER_CERT_DIGEST,
            &rt,
        );
        let _ = res.unwrap();
    }
    #[test]
    fn certs_missing() {
        let rt = PreferredRuntime::create().unwrap();
        let all_certs = [
            (2, certs::CERT_T2, "Couldn't find RSA identity cert"),
            (7, certs::CERT_T7, "No RSA->Ed crosscert"),
            (4, certs::CERT_T4, "Missing IDENTITY_V_SIGNING certificate"),
            (5, certs::CERT_T5, "Missing SIGNING_V_TLS_CERT certificate"),
        ];
        for omit_idx in 0..4 {
            // build a certs cell with all but one certificate
            let mut certs = msg::Certs::new_empty();
            let mut expect_err = None;
            for (idx, (ctype, cert, err)) in all_certs.iter().enumerate() {
                if idx == omit_idx {
                    expect_err = Some(err);
                    continue;
                }
                certs.push_cert_body((*ctype).into(), &cert[..]);
            }
            let res = certs_test(
                certs,
                Some(cert_timestamp()),
                certs::PEER_ED,
                certs::PEER_RSA,
                *certs::PEER_CERT_DIGEST,
                &rt,
            )
            .err()
            .unwrap();
            assert_eq!(
                format!("{}", res),
                format!("Handshake protocol violation: {}", expect_err.unwrap())
            );
        }
    }
    #[test]
    fn certs_wrongtarget() {
        let rt = PreferredRuntime::create().unwrap();
        let mut certs = msg::Certs::new_empty();
        certs.push_cert_body(2.into(), certs::CERT_T2);
        certs.push_cert_body(5.into(), certs::CERT_T5);
        certs.push_cert_body(7.into(), certs::CERT_T7);
        certs.push_cert_body(4.into(), certs::CERT_T4);
        let err = certs_test(
            certs.clone(),
            Some(cert_timestamp()),
            &[0x10; 32],
            certs::PEER_RSA,
            *certs::PEER_CERT_DIGEST,
            &rt,
        )
        .err()
        .unwrap();
        let re = Regex::new(
            // identities might be scrubbed by safelog
            r"Identity .* does not match target .*",
        )
        .unwrap();
        assert!(re.is_match(&format!("{}", err)));
        let err = certs_test(
            certs.clone(),
            Some(cert_timestamp()),
            certs::PEER_ED,
            &[0x99; 20],
            *certs::PEER_CERT_DIGEST,
            &rt,
        )
        .err()
        .unwrap();
        let re = Regex::new(
            // identities might be scrubbed by safelog
            r"Identity .* does not match target .*",
        )
        .unwrap();
        assert!(re.is_match(&format!("{}", err)));
        let err = certs_test(
            certs,
            Some(cert_timestamp()),
            certs::PEER_ED,
            certs::PEER_RSA,
            [0; 32],
            &rt,
        )
        .err()
        .unwrap();
        assert_eq!(
            format!("{}", err),
            "Handshake protocol violation: Peer cert did not authenticate TLS cert"
        );
    }
    #[test]
    fn certs_badsig() {
        let rt = PreferredRuntime::create().unwrap();
        fn munge(inp: &[u8]) -> Vec<u8> {
            let mut v: Vec<u8> = inp.into();
            v[inp.len() - 1] ^= 0x10;
            v
        }
        let mut certs = msg::Certs::new_empty();
        certs.push_cert_body(2.into(), certs::CERT_T2);
        certs.push_cert_body(5.into(), munge(certs::CERT_T5)); // munge an ed signature
        certs.push_cert_body(7.into(), certs::CERT_T7);
        certs.push_cert_body(4.into(), certs::CERT_T4);
        let res = certs_test(
            certs,
            Some(cert_timestamp()),
            certs::PEER_ED,
            certs::PEER_RSA,
            *certs::PEER_CERT_DIGEST,
            &rt,
        )
        .err()
        .unwrap();
        assert_eq!(
            format!("{}", res),
            "Handshake protocol violation: Invalid ed25519 signature in handshake"
        );
        let mut certs = msg::Certs::new_empty();
        certs.push_cert_body(2.into(), certs::CERT_T2);
        certs.push_cert_body(5.into(), certs::CERT_T5);
        certs.push_cert_body(7.into(), munge(certs::CERT_T7)); // munge an RSA signature
        certs.push_cert_body(4.into(), certs::CERT_T4);
        let res = certs_test(
            certs,
            Some(cert_timestamp()),
            certs::PEER_ED,
            certs::PEER_RSA,
            *certs::PEER_CERT_DIGEST,
            &rt,
        )
        .err()
        .unwrap();
        assert_eq!(
            format!("{}", res),
            "Handshake protocol violation: Bad RSA->Ed crosscert signature"
        );
    }
    /// This module has a few certificates to play with. They're taken
    /// from a chutney network. They match those used in the CERTS
    /// cell test vector in the tor-cell crate.
    ///
    /// The names are taken from the type of the certificate.
    mod certs {
        use hex_literal::hex;
        pub(crate) const CERT_T2: &[u8] = &hex!(
            "308201B930820122A0030201020208607C28BE6C390943300D06092A864886F70D01010B0500301F311D301B06035504030C147777772E74636A76356B766A646472322E636F6D301E170D3230303831303030303030305A170D3231303831303030303030305A301F311D301B06035504030C147777772E74636A76356B766A646472322E636F6D30819F300D06092A864886F70D010101050003818D0030818902818100D38B1E6CEB946E0DB0751F4CBACE3DCB9688B6C25304227B4710C35AFB73627E50500F5913E158B621802612D1C75827003703338375237552EB3CD3C12F6AB3604E60C1A2D26BB1FBAD206FF023969A90909D6A65A5458A5312C26EBD3A3DAD30302D4515CDCD264146AC18E6FC60A04BD3EC327F04294D96BA5AA25B464C3F0203010001300D06092A864886F70D01010B0500038181003BCE561EA7F95CC00B78AAB5D69573FF301C282A751D4A651921D042F1BECDBA24D918A6D8A5E138DC07BBA0B335478AE37ABD2C93A93932442AE9084329E846170FE0FC4A50AAFC804F311CC3CA4F41D845A7BA5901CBBC3E021E9794AAC70CE1F37B0A951592DB1B64F2B4AFB81AE52DBD9B6FEDE96A5FB8125EB6251EE50A"
        );
        pub(crate) const CERT_T4: &[u8] = &hex!(
            "01040006CC2A01F82294B866A31F01FC5D0DA8572850A9B929545C3266558D7D2316E3B74172B00100200400DCB604DB2034B00FD16986D4ADB9D16B21CB4E4457A33DEC0F538903683E96E9FF1A5203FA27F86EF7528D89A0845D2520166E340754FFEA2AAE0F612B7CE5DA094A0236CDAC45034B0B6842C18E7F6B51B93A3CF7E60663B8AD061C30A62602"
        );
        pub(crate) const CERT_T5: &[u8] = &hex!(
            "01050006C98A03B4FD606B64E4CBD466B8D76CB131069BAE6F3AA1878857C9F624E31D77A799B8007173E5F8068431D0D3F5EE16B4C9FFD59DF373E152A87281BAE744AA5FCF72171BF4B27C4E8FC1C6A9FC5CA11058BC49647063D7903CFD9F512F89099B27BC0C"
        );
        pub(crate) const CERT_T7: &[u8] = &hex!(
            "DCB604DB2034B00FD16986D4ADB9D16B21CB4E4457A33DEC0F538903683E96E90006DA3A805CF6006F9179066534DE6B45AD47A5C469063EE462762723396DC9F25452A0A52DA3F5087DD239F2A311F6B0D4DFEFF4ABD089DC3D0237A0ABAB19EB2045B91CDCAF04BE0A72D548A27BF2E77BD876ECFE5E1BE622350DA6BF31F6E306ED896488DD5B39409B23FC3EB7B2C9F7328EB18DA36D54D80575899EA6507CCBFCDF1F"
        );
        pub(crate) const PEER_CERT_DIGEST: &[u8; 32] =
            &hex!("b4fd606b64e4cbd466b8d76cb131069bae6f3aa1878857c9f624e31d77a799b8");
        pub(crate) const PEER_ED: &[u8] =
            &hex!("dcb604db2034b00fd16986d4adb9d16b21cb4e4457a33dec0f538903683e96e9");
        pub(crate) const PEER_RSA: &[u8] = &hex!("2f1fb49bb332a9eec617e41e911c33fb3890aef3");
    }
    #[test]
    fn test_finish() {
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
            let ed25519_id = [3_u8; 32].into();
            let rsa_id = [4_u8; 20].into();
            let peer_addr = "127.1.1.2:443".parse().unwrap();
            let mut framed_tls = new_frame(MsgBuf::new(&b""[..]), ChannelType::ClientInitiator);
            let _ = framed_tls.codec_mut().set_link_version(4);
            let ver = VerifiedChannel {
                link_protocol: 4,
                framed_tls,
                unique_id: UniqId::new(),
                target_method: Some(ChannelMethod::Direct(vec![peer_addr])),
                ed25519_id,
                rsa_id,
                rsa_id_digest: [0; 32],
                peer_cert_digest: [0; 32],
                clock_skew: ClockSkew::None,
                sleep_prov: rt,
                memquota: fake_mq(),
            };
            let peer_ip = peer_addr.ip();
            let netinfo = Netinfo::from_client(Some(peer_ip));
            let (_chan, _reactor) = ver
                .finish(
                    &netinfo,
                    &[],
                    MaybeSensitive::not_sensitive(PeerInfo::EMPTY),
                )
                .await
                .unwrap();
            // TODO: check contents of netinfo cell
        });
    }
}