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, ChanCmd, ChanMsg, msg};
18
use tor_cell::restrict::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
            expecting: &[ChanCmd],
149
52
        ) -> Result<T>
150
52
        where
151
52
            T: TryFrom<AnyChanMsg, Error = AnyChanMsg>,
152
52
        {
153
52
            let Some(cell) = stream.next().await.transpose()? else {
154
                // The entire channel has ended, so nothing else to be done.
155
2
                return Err(Error::HandshakeProto("Stream ended unexpectedly".into()));
156
            };
157

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

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

            
169
46
            let m = m.try_into().map_err(|m: AnyChanMsg| {
170
6
                Error::HandshakeProto(format!(
171
6
                    "Expected {expecting:?} cell, but received {} cell instead",
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
            let msg = read_msg(*self.unique_id(), self.framed_tls(), &[ChanCmd::CERTS]).await?;
192

            
193
14
            break match msg {
194
                CertsMsg::Vpadding(_) => continue,
195
14
                CertsMsg::Certs(msg) => msg,
196
            };
197
        };
198

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

            
210
18
            let msg = read_msg(
211
18
                *self.unique_id(),
212
18
                self.framed_tls(),
213
18
                &[ChanCmd::AUTH_CHALLENGE],
214
18
            )
215
18
            .await?;
216

            
217
14
            break match msg {
218
4
                AuthChallengeMsg::Vpadding(_) => continue,
219
10
                AuthChallengeMsg::AuthChallenge(msg) => msg,
220
            };
221
        };
222

            
223
8
        let (netinfo, netinfo_rcvd_at) = loop {
224
            restricted_msg! {
225
                enum NetinfoMsg : ChanMsg {
226
                    // VPADDING cells (but not PADDING) can be sent during handshaking.
227
                    Vpadding,
228
                    Netinfo,
229
               }
230
            }
231

            
232
14
            let msg = read_msg(*self.unique_id(), self.framed_tls(), &[ChanCmd::NETINFO]).await?;
233

            
234
12
            break match msg {
235
4
                NetinfoMsg::Vpadding(_) => continue,
236
8
                NetinfoMsg::Netinfo(msg) => (msg, coarsetime::Instant::now()),
237
            };
238
        };
239

            
240
8
        Ok((auth_challenge, certs, (netinfo, netinfo_rcvd_at)))
241
20
    }
242
}
243

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

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

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

            
339
    /// Same as `check`, but takes the SHA256 hash of the peer certificate,
340
    /// since that is all we use.
341
24
    pub(crate) fn check_internal<U: ChanTarget + ?Sized>(
342
24
        self,
343
24
        peer: &U,
344
24
        peer_cert_digest: [u8; 32],
345
24
        now: Option<SystemTime>,
346
24
    ) -> Result<VerifiedChannel<T, S>> {
347
        use tor_cert::CertType;
348
        use tor_checkable::*;
349

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

            
378
        // We need to check the following lines of authentication:
379
        //
380
        // First, to bind the ed identity to the channel.
381
        //    peer.ed_identity() matches the key in...
382
        //    IDENTITY_V_SIGNING cert, which signs...
383
        //    SIGNING_V_TLS_CERT cert, which signs peer_cert.
384
        //
385
        // Second, to bind the rsa identity to the ed identity:
386
        //    peer.rsa_identity() matches the key in...
387
        //    the x.509 RSA identity certificate (type 2), which signs...
388
        //    the RSA->Ed25519 crosscert (type 7), which signs...
389
        //    peer.ed_identity().
390

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

            
396
        /// Helper: get a cert from a Certs cell, and convert errors appropriately.
397
114
        fn get_cert(
398
114
            certs: &tor_cell::chancell::msg::Certs,
399
114
            tp: CertType,
400
114
        ) -> Result<tor_cert::KeyUnknownCert> {
401
114
            match certs.parse_ed_cert(tp) {
402
108
                Ok(c) => Ok(c),
403
6
                Err(tor_cell::Error::ChanProto(e)) => Err(Error::HandshakeProto(e)),
404
                Err(e) => Err(Error::HandshakeProto(e.to_string())),
405
            }
406
114
        }
407

            
408
24
        let id_sk = get_cert(c, CertType::IDENTITY_V_SIGNING)?;
409
20
        let sk_tls = get_cert(c, CertType::SIGNING_V_TLS_CERT)?;
410

            
411
18
        let mut sigs = Vec::new();
412

            
413
        // Part 1: validate ed25519 stuff.
414
        //
415
        // (We are performing our timeliness checks now, but not inspecting them
416
        // until later in the function, so that we can distinguish failures that
417
        // might be caused by clock skew from failures that are definitely not
418
        // clock skew.)
419

            
420
        // Check the identity->signing cert
421
18
        let (id_sk, id_sk_sig) = id_sk
422
18
            .should_have_signing_key()
423
18
            .map_err(Error::HandshakeCertErr)?
424
18
            .dangerously_split()
425
18
            .map_err(Error::HandshakeCertErr)?;
426
18
        sigs.push(&id_sk_sig);
427
18
        let (id_sk_timeliness, id_sk) = check_timeliness(id_sk, now, self.clock_skew);
428

            
429
        // Take the identity key from the identity->signing cert
430
18
        let identity_key = id_sk.signing_key().ok_or_else(|| {
431
            Error::HandshakeProto("Missing identity key in identity->signing cert".into())
432
        })?;
433

            
434
        // Take the signing key from the identity->signing cert
435
18
        let signing_key = id_sk.subject_key().as_ed25519().ok_or_else(|| {
436
            Error::HandshakeProto("Bad key type in identity->signing cert".into())
437
        })?;
438

            
439
        // Now look at the signing->TLS cert and check it against the
440
        // peer certificate.
441
18
        let (sk_tls, sk_tls_sig) = sk_tls
442
18
            .should_be_signed_with(signing_key)
443
18
            .map_err(Error::HandshakeCertErr)?
444
18
            .dangerously_split()
445
18
            .map_err(Error::HandshakeCertErr)?;
446
18
        sigs.push(&sk_tls_sig);
447
18
        let (sk_tls_timeliness, sk_tls) = check_timeliness(sk_tls, now, self.clock_skew);
448

            
449
18
        if peer_cert_digest != sk_tls.subject_key().as_bytes() {
450
2
            return Err(Error::HandshakeProto(
451
2
                "Peer cert did not authenticate TLS cert".into(),
452
2
            ));
453
16
        }
454

            
455
        // Batch-verify the ed25519 certificates in this handshake.
456
        //
457
        // In theory we could build a list of _all_ the certificates here
458
        // and call pk::validate_all_sigs() instead, but that doesn't gain
459
        // any performance.
460
16
        if !ll::pk::ed25519::validate_batch(&sigs[..]) {
461
2
            return Err(Error::HandshakeProto(
462
2
                "Invalid ed25519 signature in handshake".into(),
463
2
            ));
464
14
        }
465

            
466
        // Part 2: validate rsa stuff.
467

            
468
        // What is the RSA identity key, according to the X.509 certificate
469
        // in which it is self-signed?
470
        //
471
        // (We don't actually check this self-signed certificate, and we use
472
        // a kludge to extract the RSA key)
473
14
        let rsa_id_cert_bytes = c
474
14
            .cert_body(CertType::RSA_ID_X509)
475
14
            .ok_or_else(|| Error::HandshakeProto("Couldn't find RSA identity cert".into()))?;
476
12
        let pkrsa =
477
12
            ll::util::x509_extract_rsa_subject_kludge(rsa_id_cert_bytes).ok_or_else(|| {
478
                Error::HandshakeProto(
479
                    "Couldn't find RSA SubjectPublicKey from RSA identity cert".into(),
480
                )
481
            })?;
482

            
483
        // Now verify the RSA identity -> Ed Identity crosscert.
484
        //
485
        // This proves that the RSA key vouches for the Ed key.  Note that
486
        // the Ed key does not vouch for the RSA key: The RSA key is too
487
        // weak.
488
12
        let rsa_cert = c
489
12
            .cert_body(CertType::RSA_ID_V_IDENTITY)
490
12
            .ok_or_else(|| Error::HandshakeProto("No RSA->Ed crosscert".into()))?;
491
10
        let rsa_cert = tor_cert::rsa::RsaCrosscert::decode(rsa_cert)
492
10
            .map_err(|e| Error::from_bytes_err(e, "RSA identity cross-certificate"))?
493
10
            .check_signature(&pkrsa)
494
10
            .map_err(|_| Error::HandshakeProto("Bad RSA->Ed crosscert signature".into()))?;
495
8
        let (rsa_cert_timeliness, rsa_cert) = check_timeliness(rsa_cert, now, self.clock_skew);
496

            
497
8
        if !rsa_cert.subject_key_matches(identity_key) {
498
            return Err(Error::HandshakeProto(
499
                "RSA->Ed crosscert certifies incorrect key".into(),
500
            ));
501
8
        }
502

            
503
8
        let rsa_id_digest: [u8; 32] = ll::d::Sha256::digest(pkrsa.to_der()).into();
504
8
        let rsa_id = pkrsa.to_rsa_identity();
505

            
506
8
        trace!(
507
            stream_id = %self.unique_id,
508
            "Validated identity as {} [{}]",
509
            identity_key,
510
            rsa_id
511
        );
512

            
513
        // Now that we've done all the verification steps on the
514
        // certificates, we know who we are talking to.  It's time to
515
        // make sure that the peer we are talking to is the peer we
516
        // actually wanted.
517
        //
518
        // We do this _last_, since "this is the wrong peer" is
519
        // usually a different situation than "this peer couldn't even
520
        // identify itself right."
521

            
522
8
        let actual_identity = RelayIds::builder()
523
8
            .ed_identity(*identity_key)
524
8
            .rsa_identity(rsa_id)
525
8
            .build()
526
8
            .expect("Unable to build RelayIds");
527

            
528
        // We enforce that the relay proved that it has every ID that we wanted:
529
        // it may also have additional IDs that we didn't ask for.
530
8
        match super::check_id_match_helper(&actual_identity, peer) {
531
4
            Err(Error::ChanMismatch(msg)) => Err(Error::HandshakeProto(msg)),
532
4
            other => other,
533
4
        }?;
534

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

            
553
4
        Ok(VerifiedChannel {
554
4
            link_protocol: self.link_protocol,
555
4
            framed_tls: self.framed_tls,
556
4
            unique_id: self.unique_id,
557
4
            target_method: self.target_method,
558
4
            ed25519_id: *identity_key,
559
4
            rsa_id,
560
4
            rsa_id_digest,
561
4
            peer_cert_digest,
562
4
            clock_skew: self.clock_skew,
563
4
            sleep_prov: self.sleep_prov,
564
4
            memquota: self.memquota,
565
4
        })
566
24
    }
567

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

            
596
        // We have finalized the handshake, move our codec to Open.
597
        self.framed_tls.codec_mut().set_open()?;
598

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

            
603
        // Grab a new handle on which we can apply StreamOps (needed for KIST).
604
        // On Unix platforms, this handle is a wrapper over the fd of the socket.
605
        //
606
        // Note: this is necessary because after `StreamExit::split()`,
607
        // we no longer have access to the underlying stream
608
        // or its StreamOps implementation.
609
        let stream_ops = self.framed_tls.new_handle();
610
        let (tls_sink, tls_stream) = self.framed_tls.split();
611

            
612
        let canonicity =
613
            Canonicity::from_netinfo(netinfo, my_addrs, peer_info.addr().netinfo_addr());
614

            
615
        let peer_id = build_filtered_chan_target(self.target_method.take(), &peer_info);
616

            
617
        debug!(
618
            stream_id = %self.unique_id,
619
            "Completed handshake without authentication to {}", Redacted::new(&peer_id)
620
        );
621

            
622
        super::Channel::new(
623
            channel_type,
624
            self.link_protocol,
625
            Box::new(tls_sink),
626
            Box::new(tls_stream),
627
            stream_ops,
628
            self.unique_id,
629
            peer_id,
630
            peer_info,
631
            self.clock_skew,
632
            self.sleep_prov,
633
            self.memquota,
634
            canonicity,
635
        )
636
    }
637
}
638

            
639
impl<
640
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
641
    S: CoarseTimeProvider + SleepProvider,
642
> VerifiedChannel<T, S>
643
{
644
    /// Mark this channel as authenticated.
645
    pub(crate) fn set_authenticated(&mut self) -> Result<()> {
646
        self.framed_tls.codec_mut().set_authenticated()?;
647
        Ok(())
648
    }
649

            
650
    /// Build a [`RelayIds`] corresponding to this channel identities.
651
2
    pub(crate) fn relay_ids(&self) -> Result<RelayIds> {
652
2
        Ok(RelayIdsBuilder::default()
653
2
            .ed_identity(self.ed25519_id)
654
2
            .rsa_identity(self.rsa_id)
655
2
            .build()
656
2
            .map_err(into_internal!("Unable to build verified relay channel ids"))?)
657
2
    }
658

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

            
680
        // We have finalized the handshake, move our codec to Open.
681
        self.framed_tls.codec_mut().set_open()?;
682

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

            
687
        debug!(
688
            stream_id = %self.unique_id,
689
            "Completed handshake with peer: {}", peer_info
690
        );
691

            
692
        // Grab a new handle on which we can apply StreamOps (needed for KIST).
693
        // On Unix platforms, this handle is a wrapper over the fd of the socket.
694
        //
695
        // Note: this is necessary because after `StreamExit::split()`,
696
        // we no longer have access to the underlying stream
697
        // or its StreamOps implementation.
698
        let stream_ops = self.framed_tls.new_handle();
699
        let (tls_sink, tls_stream) = self.framed_tls.split();
700

            
701
        let canonicity =
702
            Canonicity::from_netinfo(netinfo, my_addrs, peer_info.addr().netinfo_addr());
703

            
704
        let peer_id = build_filtered_chan_target(self.target_method.take(), &peer_info);
705

            
706
        super::Channel::new(
707
            channel_type,
708
            self.link_protocol,
709
            Box::new(tls_sink),
710
            Box::new(tls_stream),
711
            stream_ops,
712
            self.unique_id,
713
            peer_id,
714
            peer_info,
715
            self.clock_skew,
716
            self.sleep_prov,
717
            self.memquota,
718
            canonicity,
719
        )
720
4
    }
721
}
722

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

            
748
/// Helper: Build a OwnedChanTarget that retains only the address that was actually used.
749
39
fn build_filtered_chan_target(
750
39
    target_method: Option<ChannelMethod>,
751
39
    peer_info: &MaybeSensitive<PeerInfo>,
752
39
) -> OwnedChanTarget {
753
39
    let mut peer_builder = OwnedChanTargetBuilder::default();
754
39
    if let Some(mut method) = target_method {
755
        // Retain only the address that was actually used to connect.
756
39
        if let Some(addr) = peer_info.addr().socket_addr() {
757
52
            let _ = method.retain_addrs(|socket_addr| socket_addr == &addr);
758
39
            peer_builder.addrs(vec![addr]);
759
        }
760
39
        peer_builder.method(method);
761
    }
762
39
    *peer_builder.ids() = RelayIdsBuilder::from_relay_ids(peer_info.ids());
763

            
764
39
    peer_builder
765
39
        .build()
766
39
        .expect("OwnedChanTarget builder failed")
767
39
}
768

            
769
#[cfg(test)]
770
pub(super) mod test {
771
    #![allow(clippy::unwrap_used)]
772
    use hex_literal::hex;
773
    use regex::Regex;
774
    use std::time::{Duration, SystemTime};
775

            
776
    use super::*;
777
    use crate::channel::handler::test::MsgBuf;
778
    use crate::channel::{ChannelType, new_frame};
779
    use crate::util::fake_mq;
780
    use crate::{Result, channel::ClientInitiatorHandshake};
781
    use tor_cell::chancell::msg::{self, Netinfo};
782
    use tor_linkspec::OwnedChanTarget;
783
    use tor_rtcompat::{PreferredRuntime, Runtime};
784

            
785
    const VERSIONS: &[u8] = &hex!("0000 07 0006 0003 0004 0005");
786
    // no certificates in this cell, but connect() doesn't care.
787
    const NOCERTS: &[u8] = &hex!("00000000 81 0001 00");
788
    const NETINFO_PREFIX: &[u8] = &hex!(
789
        "00000000 08 00000000
790
         04 04 7f 00 00 02
791
         01
792
         04 04 7f 00 00 03"
793
    );
794
    const NETINFO_PREFIX_WITH_TIME: &[u8] = &hex!(
795
        "00000000 08 48949290
796
         04 04 7f 00 00 02
797
         01
798
         04 04 7f 00 00 03"
799
    );
800
    const AUTHCHALLENGE: &[u8] = &hex!(
801
        "00000000 82 0026
802
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
803
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
804
         0002 0003 00ff"
805
    );
806

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

            
809
    fn add_padded(buf: &mut Vec<u8>, cell: &[u8]) {
810
        let len_prev = buf.len();
811
        buf.extend_from_slice(cell);
812
        buf.resize(len_prev + 514, 0);
813
    }
814
    fn add_netinfo(buf: &mut Vec<u8>) {
815
        add_padded(buf, NETINFO_PREFIX);
816
    }
817

            
818
    #[test]
819
    fn connect_ok() -> Result<()> {
820
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
821
            let now = humantime::parse_rfc3339("2008-08-02T17:00:00Z").unwrap();
822
            let mut buf = Vec::new();
823
            // versions cell
824
            buf.extend_from_slice(VERSIONS);
825
            // certs cell -- no certs in it, but this function doesn't care.
826
            buf.extend_from_slice(NOCERTS);
827
            // auth_challenge cell
828
            buf.extend_from_slice(AUTHCHALLENGE);
829
            // netinfo cell -- quite minimal.
830
            add_padded(&mut buf, NETINFO_PREFIX);
831
            let mb = MsgBuf::new(&buf[..]);
832
            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
833
            let unverified = handshake.connect(|| now).await?;
834

            
835
            assert_eq!(unverified.link_protocol(), 5);
836
            // No timestamp in the NETINFO, so no skew.
837
            assert_eq!(unverified.clock_skew(), ClockSkew::None);
838

            
839
            // Try again with some padding.
840
            let mut buf = Vec::new();
841
            buf.extend_from_slice(VERSIONS);
842
            buf.extend_from_slice(NOCERTS);
843
            buf.extend_from_slice(VPADDING);
844
            buf.extend_from_slice(AUTHCHALLENGE);
845
            buf.extend_from_slice(VPADDING);
846
            add_padded(&mut buf, NETINFO_PREFIX_WITH_TIME);
847
            let mb = MsgBuf::new(&buf[..]);
848
            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
849
            let unverified = handshake.connect(|| now).await?;
850
            // Correct timestamp in the NETINFO, so no skew.
851
            assert_eq!(unverified.clock_skew(), ClockSkew::None);
852

            
853
            // Now pretend our clock is fast.
854
            let now2 = now + Duration::from_secs(3600);
855
            let mb = MsgBuf::new(&buf[..]);
856
            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
857
            let unverified = handshake.connect(|| now2).await?;
858
            assert_eq!(
859
                unverified.clock_skew(),
860
                ClockSkew::Fast(Duration::from_secs(3600))
861
            );
862

            
863
            Ok(())
864
        })
865
    }
866

            
867
    async fn connect_err<T: Into<Vec<u8>>, S>(input: T, sleep_prov: S) -> Error
868
    where
869
        S: CoarseTimeProvider + SleepProvider,
870
    {
871
        let mb = MsgBuf::new(input);
872
        let handshake = ClientInitiatorHandshake::new(mb, None, sleep_prov, fake_mq());
873
        handshake.connect(SystemTime::now).await.err().unwrap()
874
    }
875

            
876
    #[test]
877
    fn connect_badver() {
878
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
879
            let err = connect_err(&b"HTTP://"[..], rt.clone()).await;
880
            assert!(matches!(err, Error::HandshakeProto(_)));
881
            assert_eq!(
882
                format!("{}", err),
883
                "Handshake protocol violation: Invalid CircID in variable cell"
884
            );
885

            
886
            let err = connect_err(&hex!("0000 07 0004 1234 ffff")[..], rt.clone()).await;
887
            assert!(matches!(err, Error::HandshakeProto(_)));
888
            assert_eq!(
889
                format!("{}", err),
890
                "Handshake protocol violation: No shared link protocols"
891
            );
892
        });
893
    }
894

            
895
    #[test]
896
    fn connect_cellparse() {
897
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
898
            let mut buf = Vec::new();
899
            buf.extend_from_slice(VERSIONS);
900
            // Here's a certs cell that will fail.
901
            buf.extend_from_slice(&hex!("00000000 81 0001 01")[..]);
902
            let err = connect_err(buf, rt.clone()).await;
903
            assert!(matches!(err, Error::HandshakeProto { .. }));
904
        });
905
    }
906

            
907
    #[test]
908
    fn connect_duplicates() {
909
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
910
            let mut buf = Vec::new();
911
            buf.extend_from_slice(VERSIONS);
912
            buf.extend_from_slice(NOCERTS);
913
            buf.extend_from_slice(NOCERTS);
914
            add_netinfo(&mut buf);
915
            let err = connect_err(buf, rt.clone()).await;
916
            assert!(matches!(err, Error::HandshakeProto(_)));
917
            assert_eq!(
918
                format!("{}", err),
919
                "Handshake protocol violation: Expected [ChanCmd(AUTH_CHALLENGE)] cell, but received CERTS cell instead"
920
            );
921

            
922
            let mut buf = Vec::new();
923
            buf.extend_from_slice(VERSIONS);
924
            buf.extend_from_slice(NOCERTS);
925
            buf.extend_from_slice(AUTHCHALLENGE);
926
            buf.extend_from_slice(AUTHCHALLENGE);
927
            add_netinfo(&mut buf);
928
            let err = connect_err(buf, rt.clone()).await;
929
            assert!(matches!(err, Error::HandshakeProto(_)));
930
            assert_eq!(
931
                format!("{}", err),
932
                "Handshake protocol violation: Expected [ChanCmd(NETINFO)] cell, but received AUTH_CHALLENGE cell instead"
933
            );
934
        });
935
    }
936

            
937
    #[test]
938
    fn connect_missing_certs() {
939
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
940
            let mut buf = Vec::new();
941
            buf.extend_from_slice(VERSIONS);
942
            add_netinfo(&mut buf);
943
            let err = connect_err(buf, rt.clone()).await;
944
            assert!(matches!(err, Error::HandshakeProto(_)));
945
            assert_eq!(
946
                format!("{}", err),
947
                "Handshake protocol violation: Expected [ChanCmd(CERTS)] cell, but received NETINFO cell instead"
948
            );
949
        });
950
    }
951

            
952
    #[test]
953
    fn connect_missing_netinfo() {
954
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
955
            let mut buf = Vec::new();
956
            buf.extend_from_slice(VERSIONS);
957
            buf.extend_from_slice(NOCERTS);
958
            let err = connect_err(buf, rt.clone()).await;
959
            assert!(matches!(err, Error::HandshakeProto(_)));
960
            assert_eq!(
961
                format!("{}", err),
962
                "Handshake protocol violation: Stream ended unexpectedly"
963
            );
964
        });
965
    }
966

            
967
    #[test]
968
    fn connect_misplaced_cell() {
969
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
970
            let mut buf = Vec::new();
971
            buf.extend_from_slice(VERSIONS);
972
            // here's a create cell.
973
            add_padded(&mut buf, &hex!("00000001 01")[..]);
974
            let err = connect_err(buf, rt.clone()).await;
975
            assert!(matches!(err, Error::HandshakeProto(_)));
976
            assert_eq!(
977
                format!("{}", err),
978
                "Handshake protocol violation: Decoding cell error: Error while parsing channel cell: Bad object: Unexpected command CREATE in HandshakeRelayResponderMsg"
979
            );
980
        });
981
    }
982

            
983
    fn make_unverified<R>(certs: msg::Certs, runtime: R) -> UnverifiedChannel<MsgBuf, R>
984
    where
985
        R: Runtime,
986
    {
987
        let mut framed_tls = new_frame(MsgBuf::new(&b""[..]), ChannelType::ClientInitiator);
988
        let _ = framed_tls.codec_mut().set_link_version(4);
989
        let _ = framed_tls.codec_mut().set_open();
990
        let clock_skew = ClockSkew::None;
991
        UnverifiedChannel {
992
            link_protocol: 4,
993
            framed_tls,
994
            certs_cell: Some(certs),
995
            clock_skew,
996
            target_method: None,
997
            unique_id: UniqId::new(),
998
            sleep_prov: runtime,
999
            memquota: fake_mq(),
        }
    }
    // Timestamp when the example certificates were all valid.
    fn cert_timestamp() -> SystemTime {
        use humantime::parse_rfc3339;
        parse_rfc3339("2020-09-26T18:01:20Z").unwrap()
    }
    fn certs_test<R>(
        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
        });
    }
}