1
//! Implementations for the channel handshake
2

            
3
use digest::Digest;
4
use futures::io::{AsyncRead, AsyncWrite};
5
use futures::sink::SinkExt;
6
use futures::stream::{Stream, StreamExt};
7
use std::net::IpAddr;
8
use std::sync::Arc;
9
use tracing::{debug, instrument, trace};
10

            
11
use safelog::{MaybeSensitive, Redacted};
12
use tor_cell::chancell::msg::AnyChanMsg;
13
use tor_cell::chancell::{AnyChanCell, ChanMsg, msg};
14
use tor_cell::restrict::{RestrictedMsg, restricted_msg};
15
use tor_cert::CertType;
16
use tor_checkable::{TimeValidityError, Timebound};
17
use tor_error::internal;
18
use tor_linkspec::{
19
    ChanTarget, ChannelMethod, OwnedChanTarget, OwnedChanTargetBuilder, RelayIds, RelayIdsBuilder,
20
};
21
use tor_llcrypto as ll;
22
use tor_llcrypto::pk::{ValidatableSignature, ed25519::Ed25519Identity};
23
use tor_rtcompat::{CoarseTimeProvider, Runtime, SleepProvider, StreamOps};
24
use web_time_compat::{SystemTime, SystemTimeExt};
25

            
26
use crate::channel::handler::SlogDigest;
27
use crate::channel::{Canonicity, ChannelFrame, ChannelMode, UniqId};
28
use crate::memquota::ChannelAccount;
29
use crate::peer::PeerInfo;
30
use crate::util::skew::ClockSkew;
31
use crate::{Error, Result};
32

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

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

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

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

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

            
107
38
        Ok(link_protocol)
108
46
    }
109

            
110
    /// Given a link protocol version, set it into our channel cell handler. All channel type do
111
    /// this after negotiating a [`msg::Versions`] cell.
112
    ///
113
    /// This will effectively transition the handler's state from New to Handshake.
114
38
    fn set_link_protocol(&mut self, link_protocol: u16) -> Result<()> {
115
38
        self.framed_tls()
116
38
            .codec_mut()
117
38
            .set_link_version(link_protocol)
118
38
    }
119
}
120

            
121
/// Helper: This enum is for adding semantic to the function receiving cells indicating it to
122
/// either take the auth log out or leave it in place.
123
///
124
/// With this, we avoid using a flat bool which is confusing at the call site.
125
pub(crate) enum AuthLogAction {
126
    /// Leave it in place.
127
    Leave,
128
    /// Take it out.
129
    Take,
130
}
131

            
132
impl AuthLogAction {
133
    /// Return true iff this value is [`AuthLogAction::Take`]
134
53
    fn is_take(&self) -> bool {
135
53
        matches!(self, Self::Take)
136
53
    }
137
}
138

            
139
/// Handshake initiator base trait. All initiator handshake should implement this trait in order to
140
/// enjoy the helper functions.
141
///
142
/// It requires the base handshake trait to be implement for access to the base getters.
143
pub(crate) trait ChannelInitiatorHandshake<T>: ChannelBaseHandshake<T>
144
where
145
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
146
{
147
    /// As an initiator, we are expecting the responder's cells which are:
148
    /// - [msg::Certs]
149
    /// - [msg::AuthChallenge]
150
    /// - [msg::Netinfo]
151
    ///
152
    /// Any duplicate, missing cell or unexpected results in a protocol level error.
153
    ///
154
    /// This returns the:
155
    /// - [msg::AuthChallenge] cell
156
    /// - [msg::Certs] cell
157
    /// - [msg::Netinfo] cell
158
    /// - the instant when the netinfo cell was received (needed for the clock skew calculation)
159
    /// - the SLOG digest if `auth_log_action` is [`AuthLogAction::Take`] (needed if we send an
160
    ///   [msg::Authenticate] cell in the future)
161
38
    async fn recv_cells_from_responder(
162
38
        &mut self,
163
38
        auth_log_action: AuthLogAction,
164
38
    ) -> Result<(
165
38
        msg::AuthChallenge,
166
38
        msg::Certs,
167
38
        (msg::Netinfo, coarsetime::Instant),
168
38
        Option<SlogDigest>,
169
57
    )> {
170
        // IMPORTANT: Protocol wise, we MUST only allow one single cell of each type for a valid
171
        // handshake. Any duplicates lead to a failure.
172
        // They must arrive in a specific order in order for the SLOG calculation to be valid.
173

            
174
        // Note that the `ChannelFrame` already restricts the messages due to its handshake cell
175
        // handler.
176

            
177
26
        let certs = loop {
178
            restricted_msg! {
179
                enum CertsMsg : ChanMsg {
180
                    // VPADDING cells (but not PADDING) can be sent during handshaking.
181
                    Vpadding,
182
                    Certs,
183
               }
184
            }
185

            
186
38
            break match read_msg(*self.unique_id(), self.framed_tls()).await? {
187
                CertsMsg::Vpadding(_) => continue,
188
26
                CertsMsg::Certs(msg) => msg,
189
            };
190
        };
191

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

            
203
34
            break match read_msg(*self.unique_id(), self.framed_tls()).await? {
204
8
                AuthChallengeMsg::Vpadding(_) => continue,
205
18
                AuthChallengeMsg::AuthChallenge(msg) => msg,
206
            };
207
        };
208

            
209
18
        let slog_digest = if auth_log_action.is_take() {
210
            // We're the initiator, which means that the recv log is the SLOG.
211
8
            Some(SlogDigest::new(
212
8
                self.framed_tls().codec_mut().take_recv_log_digest()?,
213
            ))
214
        } else {
215
10
            None
216
        };
217

            
218
14
        let (netinfo, netinfo_rcvd_at) = loop {
219
            restricted_msg! {
220
                enum NetinfoMsg : ChanMsg {
221
                    // VPADDING cells (but not PADDING) can be sent during handshaking.
222
                    Vpadding,
223
                    Netinfo,
224
               }
225
            }
226

            
227
26
            break match read_msg(*self.unique_id(), self.framed_tls()).await? {
228
8
                NetinfoMsg::Vpadding(_) => continue,
229
14
                NetinfoMsg::Netinfo(msg) => (msg, coarsetime::Instant::now()),
230
            };
231
        };
232

            
233
14
        Ok((
234
14
            auth_challenge,
235
14
            certs,
236
14
            (netinfo, netinfo_rcvd_at),
237
14
            slog_digest,
238
14
        ))
239
38
    }
240
}
241

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

            
270
/// A base initiator channel on which versions have been negotiated and the relay's handshake has
271
/// been read, but where the [`msg::Certs`] has not been checked.
272
///
273
/// Both relay and client have specialized objects for an unverified channel which include this one
274
/// as the base in order to share functionnalities.
275
///
276
/// We need this intermediary object between the specialized one (client/relay) and the
277
/// [`UnverifiedChannel`] because certs validation is quite different from a respodner channel.
278
/// This avoid code duplication.
279
pub(crate) struct UnverifiedInitiatorChannel<
280
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
281
    S: CoarseTimeProvider + SleepProvider,
282
> {
283
    /// Base unverified channel.
284
    pub(crate) inner: UnverifiedChannel<T, S>,
285
    /// The [`msg::Certs`] received during the handshake.
286
    pub(crate) certs_cell: msg::Certs,
287
}
288

            
289
/// A base channel on which versions have been negotiated, relay's handshake has been read, but the
290
/// client has not yet finished the handshake.
291
///
292
/// This type is separate from UnverifiedChannel, since finishing the handshake requires a bunch of
293
/// CPU, and you might want to do it as a separate task or after a yield.
294
///
295
/// Both relay and client have specialized objects for an unverified channel which include this one
296
/// as the base in order to share functionalities.
297
pub(crate) struct VerifiedChannel<
298
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
299
    S: CoarseTimeProvider + SleepProvider,
300
> {
301
    /// Runtime handle (insofar as we need it)
302
    pub(crate) sleep_prov: S,
303
    /// Memory quota account
304
    pub(crate) memquota: ChannelAccount,
305
    /// The negotiated link protocol.
306
    pub(crate) link_protocol: u16,
307
    /// The Source+Sink on which we're reading and writing cells.
308
    pub(crate) framed_tls: ChannelFrame<T>,
309
    /// Declared target method for this stream, if any.
310
    pub(crate) target_method: Option<ChannelMethod>,
311
    /// Logging identifier for this stream.  (Used for logging only.)
312
    pub(crate) unique_id: UniqId,
313
    /// Authenticated clock skew for this peer.
314
    pub(crate) clock_skew: ClockSkew,
315

            
316
    /// Verified peer identities
317
    pub(crate) peer_relay_ids: RelayIds,
318
    /// Validated RSA identity digest of the DER format for this peer.
319
    pub(crate) peer_rsa_id_digest: [u8; 32],
320
}
321

            
322
impl<
323
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
324
    S: CoarseTimeProvider + SleepProvider,
325
> UnverifiedChannel<T, S>
326
{
327
    /// Return a newly constructed [`VerifiedChannel`].
328
4
    pub(crate) fn into_verified(
329
4
        self,
330
4
        peer_relay_ids: RelayIds,
331
4
        peer_rsa_id_digest: [u8; 32],
332
4
    ) -> VerifiedChannel<T, S> {
333
4
        VerifiedChannel {
334
4
            link_protocol: self.link_protocol,
335
4
            framed_tls: self.framed_tls,
336
4
            unique_id: self.unique_id,
337
4
            target_method: self.target_method,
338
4
            peer_relay_ids,
339
4
            peer_rsa_id_digest,
340
4
            clock_skew: self.clock_skew,
341
4
            sleep_prov: self.sleep_prov,
342
4
            memquota: self.memquota,
343
4
        }
344
4
    }
345

            
346
    /// This validates the relay identities (Ed25519 and RSA) and signing key cert (Ed25519) found
347
    /// in the received [`msg::Certs`] cell. It also enforces that the peer claimed IDs are the one
348
    /// we expected (`peer_target`).
349
    ///
350
    /// Successful validation returns the relay ed25519 identitiy key, the ed25519 signing key and
351
    /// the RSA public key of the peer. This means that we consider the peer verified as in we've
352
    /// established that we are talking to the right target.
353
    ///
354
    /// Reason for the RSA public key is because the caller needs the SHA256 digest for the
355
    /// [`msg::Authenticate`] cell.
356
24
    pub(crate) fn check_relay_identities<U: ChanTarget + ?Sized>(
357
24
        &self,
358
24
        peer_target: &U,
359
24
        peer_certs: &msg::Certs,
360
24
        now: SystemTime,
361
24
    ) -> Result<(RelayIds, Ed25519Identity, [u8; 32])> {
362
        use tor_checkable::*;
363

            
364
        // Get the identity signing cert IDENTITY_V_SIGNING.
365
24
        let cert_signing = get_cert(peer_certs, CertType::IDENTITY_V_SIGNING)?;
366

            
367
        // Check the identity->signing cert
368
20
        let (cert_signing, cert_signing_sig) = cert_signing
369
20
            .should_have_signing_key()
370
20
            .map_err(Error::HandshakeCertErr)?
371
20
            .dangerously_split()
372
20
            .map_err(Error::HandshakeCertErr)?;
373
20
        let (cert_signing_timeliness, cert_signing) =
374
20
            check_cert_timeliness(cert_signing, now, self.clock_skew);
375

            
376
        // Make sure the ed25519 identity cert is well signed before parsing more data.
377
20
        if !cert_signing_sig.is_valid() {
378
            return Err(Error::HandshakeProto(
379
                "Invalid ed25519 identity cert signature in handshake".into(),
380
            ));
381
20
        }
382

            
383
        // Take the identity key from the identity->signing cert
384
20
        let kp_relayid_ed = cert_signing.signing_key().ok_or_else(|| {
385
            Error::HandshakeProto("Missing identity key in identity->signing cert".into())
386
        })?;
387

            
388
        // Take the signing key from the identity->signing cert
389
20
        let kp_relaysign_ed = cert_signing.subject_key().as_ed25519().ok_or_else(|| {
390
            Error::HandshakeProto("Bad key type in identity->signing cert".into())
391
        })?;
392

            
393
        // What is the RSA identity key, according to the X.509 certificate
394
        // in which it is self-signed?
395
        //
396
        // (We don't actually check this self-signed certificate, and we use
397
        // a kludge to extract the RSA key)
398
20
        let rsa_id_cert_bytes = peer_certs
399
20
            .cert_body(CertType::RSA_ID_X509)
400
20
            .ok_or_else(|| Error::HandshakeProto("Couldn't find RSA identity cert".into()))?;
401
18
        let kp_relayid_rsa = ll::util::x509_extract_rsa_subject_kludge(rsa_id_cert_bytes)
402
18
            .ok_or_else(|| {
403
                Error::HandshakeProto(
404
                    "Couldn't find RSA SubjectPublicKey from RSA identity cert".into(),
405
                )
406
            })?;
407

            
408
        // Now verify the RSA identity -> Ed Identity crosscert.
409
        //
410
        // This proves that the RSA key vouches for the Ed key.  Note that
411
        // the Ed key does not vouch for the RSA key: The RSA key is too
412
        // weak.
413
18
        let rsa_cert = peer_certs
414
18
            .cert_body(CertType::RSA_ID_V_IDENTITY)
415
18
            .ok_or_else(|| Error::HandshakeProto("No RSA->Ed crosscert".into()))?;
416
16
        let rsa_cert = tor_cert::rsa::RsaCrosscert::decode(rsa_cert)
417
16
            .map_err(|e| Error::from_bytes_err(e, "RSA identity cross-certificate"))?
418
16
            .check_signature(&kp_relayid_rsa)
419
16
            .map_err(|_| Error::HandshakeProto("Bad RSA->Ed crosscert signature".into()))?;
420
14
        let (rsa_cert_timeliness, rsa_cert) = check_cert_timeliness(rsa_cert, now, self.clock_skew);
421

            
422
14
        if !rsa_cert.subject_key_matches(kp_relayid_ed) {
423
            return Err(Error::HandshakeProto(
424
                "RSA->Ed crosscert certifies incorrect key".into(),
425
            ));
426
14
        }
427

            
428
        // The only remaining concern is certificate timeliness.  If the
429
        // certificates are expired by an amount that is too large for the
430
        // declared clock skew to explain, then  we'll return
431
        // `Error::HandshakeProto`: in that case the clock skew is _not_
432
        // authenticated.  But if the certs are only expired by a little bit,
433
        // we'll reject the handshake with `Error::HandshakeCertsExpired`, and
434
        // the caller can trust the clock skew.
435
        //
436
        // We note expired certs last, since we only want to return
437
        // `HandshakeCertsExpired` when there are no other errors.
438
14
        cert_signing_timeliness?;
439
14
        rsa_cert_timeliness?;
440

            
441
        // Now that we've done all the verification steps on the
442
        // certificates, we know who we are talking to.  It's time to
443
        // make sure that the peer we are talking to is the peer we
444
        // actually wanted.
445
        //
446
        // We do this _last_, since "this is the wrong peer" is
447
        // usually a different situation than "this peer couldn't even
448
        // identify itself right."
449
14
        let actual_identity = RelayIds::builder()
450
14
            .ed_identity(*kp_relayid_ed)
451
14
            .rsa_identity(kp_relayid_rsa.to_rsa_identity())
452
14
            .build()
453
14
            .expect("Unable to build RelayIds");
454

            
455
        // We enforce that the relay claimed to have every ID that we wanted:
456
        // it may also have additional IDs that we didn't ask for.
457
14
        match super::check_id_match_helper(&actual_identity, peer_target) {
458
4
            Err(Error::ChanMismatch(msg)) => Err(Error::HandshakeProto(msg)),
459
10
            other => other,
460
4
        }?;
461

            
462
10
        let rsa_id_digest: [u8; 32] = ll::d::Sha256::digest(kp_relayid_rsa.to_der()).into();
463

            
464
10
        Ok((actual_identity, *kp_relaysign_ed, rsa_id_digest))
465
24
    }
466

            
467
    /// Finalize this channel into an actual channel and its reactor.
468
    ///
469
    /// An unverified channel can be finalized as it skipped the cert verification and
470
    /// authentication because simply the other side is not authenticating.
471
    ///
472
    /// Two cases for this:
473
    ///     - Client <-> Relay channel
474
    ///     - Bridge <-> Relay channel
475
    ///
476
    /// `peer_netinfo` is the received [`msg::Netinfo`] cell from the peer.
477
    ///
478
    /// `my_addrs` are our advertised addresses as a relay.
479
    ///
480
    /// `peer_info` is the verified peer information (identities and addresses).
481
    ///
482
    // NOTE: Unfortunately, this function has duplicated code with the VerifiedChannel::finish()
483
    // so make sure any changes here is reflected there. A proper refactoring is welcome!
484
    #[instrument(skip_all, level = "trace")]
485
    pub(crate) fn finish(
486
        mut self,
487
        peer_netinfo: &msg::Netinfo,
488
        my_addrs: &[IpAddr],
489
        peer_info: MaybeSensitive<PeerInfo>,
490
        channel_mode: ChannelMode,
491
    ) -> Result<(Arc<super::Channel>, super::reactor::Reactor<S>)>
492
    where
493
        S: Runtime,
494
    {
495
        // We treat a completed channel as incoming traffic since all cells were exchanged.
496
        //
497
        // TODO: conceivably we should remember the time when we _got_ the
498
        // final cell on the handshake, and update the channel completion
499
        // time to be no earlier than _that_ timestamp.
500
        //
501
        // TODO: This shouldn't be here. This should be called in the trait functions that actually
502
        // receives the data (recv_*). We'll move it at a later commit.
503
        crate::note_incoming_traffic();
504

            
505
        // We have finalized the handshake, move our codec to Open.
506
        self.framed_tls.codec_mut().set_open()?;
507

            
508
        // Grab the channel type from our underlying frame as we are about to consume the
509
        // framed_tls.
510
        // Do a sanity check that the provided channel mode agrees with the type.
511
        let channel_type = self.framed_tls.codec().channel_type();
512
        channel_mode.check_agrees_with_type(channel_type)?;
513

            
514
        // Grab a new handle on which we can apply StreamOps (needed for KIST).
515
        // On Unix platforms, this handle is a wrapper over the fd of the socket.
516
        //
517
        // Note: this is necessary because after `StreamExit::split()`,
518
        // we no longer have access to the underlying stream
519
        // or its StreamOps implementation.
520
        let stream_ops = self.framed_tls.new_handle();
521
        let (tls_sink, tls_stream) = self.framed_tls.split();
522

            
523
        let canonicity =
524
            Canonicity::from_netinfo(peer_netinfo, my_addrs, peer_info.addr().netinfo_addr());
525

            
526
        // We need this because the Channel still uses a `OwnedChanTarget` in a lot of places but
527
        // the real verified truth about our connected peer is in `PeerInfo`.
528
        let peer_target = build_filtered_chan_target(self.target_method.take(), &peer_info);
529

            
530
        debug!(
531
            stream_id = %self.unique_id,
532
            "Completed handshake without authentication to {}", Redacted::new(&peer_target)
533
        );
534

            
535
        super::Channel::new(
536
            channel_mode,
537
            self.link_protocol,
538
            Box::new(tls_sink),
539
            Box::new(tls_stream),
540
            stream_ops,
541
            self.unique_id,
542
            peer_target,
543
            peer_info,
544
            self.clock_skew,
545
            self.sleep_prov,
546
            self.memquota,
547
            canonicity,
548
        )
549
    }
550
}
551

            
552
impl<
553
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
554
    S: CoarseTimeProvider + SleepProvider,
555
> VerifiedChannel<T, S>
556
{
557
    /// Mark this channel as authenticated.
558
    pub(crate) fn set_authenticated(&mut self) -> Result<()> {
559
        self.framed_tls.codec_mut().set_authenticated()?;
560
        Ok(())
561
    }
562

            
563
    /// Return our [`RelayIds`] corresponding to this channel identities.
564
2
    pub(crate) fn relay_ids(&self) -> &RelayIds {
565
2
        &self.peer_relay_ids
566
2
    }
567

            
568
    /// Finalize this channel into an actual channel and its reactor.
569
    ///
570
    /// `peer_netinfo` is the received [`msg::Netinfo`] cell from the peer.
571
    ///
572
    /// `my_addrs` are our advertised addresses as a relay.
573
    ///
574
    /// `peer_info` is the verified peer information (identities and addresses).
575
    ///
576
    // NOTE: Unfortunately, this function has duplicated code with the VerifiedChannel::finish()
577
    // so make sure any changes here is reflected there. A proper refactoring is welcome!
578
    #[instrument(skip_all, level = "trace")]
579
4
    pub(crate) async fn finish(
580
4
        mut self,
581
4
        peer_netinfo: &msg::Netinfo,
582
4
        my_addrs: &[IpAddr],
583
4
        peer_info: MaybeSensitive<PeerInfo>,
584
4
        channel_mode: ChannelMode,
585
4
    ) -> Result<(Arc<super::Channel>, super::reactor::Reactor<S>)>
586
4
    where
587
4
        S: Runtime,
588
4
    {
589
        // We treat a completed channel -- that is to say, one where the
590
        // authentication is finished -- as incoming traffic.
591
        //
592
        // TODO: conceivably we should remember the time when we _got_ the
593
        // final cell on the handshake, and update the channel completion
594
        // time to be no earlier than _that_ timestamp.
595
        //
596
        // TODO: This shouldn't be here. This should be called in the trait functions that actually
597
        // receives the data (recv_*). We'll move it at a later commit.
598
        crate::note_incoming_traffic();
599

            
600
        // We have finalized the handshake, move our codec to Open.
601
        self.framed_tls.codec_mut().set_open()?;
602

            
603
        // Grab the channel type from our underlying frame as we are about to consume the
604
        // framed_tls.
605
        // Do a sanity check that the provided channel mode agrees with the type.
606
        let channel_type = self.framed_tls.codec().channel_type();
607
        channel_mode.check_agrees_with_type(channel_type)?;
608

            
609
        debug!(
610
            stream_id = %self.unique_id,
611
            "Completed handshake with peer: {}", peer_info
612
        );
613

            
614
        // Grab a new handle on which we can apply StreamOps (needed for KIST).
615
        // On Unix platforms, this handle is a wrapper over the fd of the socket.
616
        //
617
        // Note: this is necessary because after `StreamExit::split()`,
618
        // we no longer have access to the underlying stream
619
        // or its StreamOps implementation.
620
        let stream_ops = self.framed_tls.new_handle();
621
        let (tls_sink, tls_stream) = self.framed_tls.split();
622

            
623
        let canonicity =
624
            Canonicity::from_netinfo(peer_netinfo, my_addrs, peer_info.addr().netinfo_addr());
625

            
626
        let peer_target = build_filtered_chan_target(self.target_method.take(), &peer_info);
627

            
628
        super::Channel::new(
629
            channel_mode,
630
            self.link_protocol,
631
            Box::new(tls_sink),
632
            Box::new(tls_stream),
633
            stream_ops,
634
            self.unique_id,
635
            peer_target,
636
            peer_info,
637
            self.clock_skew,
638
            self.sleep_prov,
639
            self.memquota,
640
            canonicity,
641
        )
642
4
    }
643
}
644

            
645
impl<
646
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
647
    S: CoarseTimeProvider + SleepProvider,
648
> UnverifiedInitiatorChannel<T, S>
649
{
650
    /// Validate all relay identities and TLS cert SIGNING_V_TLS_CERT located in the received
651
    /// `certs_cell`.
652
    ///
653
    /// `peer_target` is the relay we want to connect to.
654
    ///
655
    /// 'peer_cert_digest' is the digest of the x.509 certificate that the peer presented during
656
    /// its TLS handshake (ServerHello).
657
    ///
658
    /// 'now' is the time at which to check that certificates are valid.  `None` means to use the
659
    /// current time. It can be used for testing to override the current view of the time.
660
24
    pub(crate) fn verify<U: ChanTarget + ?Sized>(
661
24
        self,
662
24
        peer_target: &U,
663
24
        peer_cert_digest: [u8; 32],
664
24
        now: Option<std::time::SystemTime>,
665
24
    ) -> Result<VerifiedChannel<T, S>> {
666
        use tor_cert::CertType;
667

            
668
        // Replace 'now' with the real time to use.
669
24
        let now = now.unwrap_or_else(SystemTime::get);
670

            
671
        // We are a client initiating a channel to a relay or a bridge. We have received a CERTS
672
        // cell and we need to verify these certs:
673
        //
674
        //   Relay Identities:
675
        //      IDENTITY_V_SIGNING_CERT (CertType 4)
676
        //      RSA_ID_X509             (CertType 2)
677
        //      RSA_ID_V_IDENTITY       (CertType 7)
678
        //
679
        //   Connection Cert:
680
        //      SIGNING_V_TLS_CERT      (CertType 5)
681
        //
682
        // Validating the relay identities first so we can make sure we are talking to the relay
683
        // (peer) we wanted. Then, check the TLS cert validity.
684
        //
685
        // The end result is a verified channel (not authenticated yet) which guarantee that we are
686
        // talking to the right relay that we wanted. We validate so we can prove these:
687
        //
688
        // - IDENTITY_V_SIGNING proves that KP_relaysign_ed speaks on behalf of KP_relayid_ed
689
        // - SIGNING_V_TLS_CERT proves that the peer's TLS cert public key speaks on behalf of
690
        //   KP_relaysign_ed.
691
        // - The TLS handshake proved that the channel is authenticated by the peer's TLS public key.
692
        // - Therefore, we have a chain from:
693
        //   KS_relayid_ed → KP_relaysign_ed → subject key in TLS cert → the channel itself.
694
        //
695
        // As for legacy certs, they prove nothing but we can extract keys:
696
        //
697
        // - RSA_ID_X509 proves nothing; we just extract its subject key as KP_relayid_rsa.
698
        // - RSA_ID_V_IDENTITY proves that KP_relayid_ed speaks on behalf of KP_relayid_rsa.
699
        // - Therefore we have a chain from:
700
        //   KP_relayid_rsa → KS_relayid_ed → KP_relaysign_ed → subject key in TLS cert → channel.
701

            
702
        // Check the relay identities in the CERTS cell.
703
24
        let (peer_relay_ids, peer_kp_relaysign_ed, peer_rsa_id_digest) = self
704
24
            .inner
705
24
            .check_relay_identities(peer_target, &self.certs_cell, now)?;
706

            
707
        // Now look at the signing->TLS cert and check it against the
708
        // peer certificate.
709
10
        let cert_tls = get_cert(&self.certs_cell, CertType::SIGNING_V_TLS_CERT)?;
710
8
        let (cert_tls, cert_tls_sig) = cert_tls
711
8
            .should_be_signed_with(&peer_kp_relaysign_ed)
712
8
            .map_err(Error::HandshakeCertErr)?
713
8
            .dangerously_split()
714
8
            .map_err(Error::HandshakeCertErr)?;
715
8
        let (cert_tls_timeliness, cert_tls) =
716
8
            check_cert_timeliness(cert_tls, now, self.inner.clock_skew);
717

            
718
8
        if peer_cert_digest != cert_tls.subject_key().as_bytes() {
719
2
            return Err(Error::HandshakeProto(
720
2
                "Peer cert did not authenticate TLS cert".into(),
721
2
            ));
722
6
        }
723

            
724
        // Make sure the TLS cert is well signed.
725
6
        if !cert_tls_sig.is_valid() {
726
2
            return Err(Error::HandshakeProto(
727
2
                "Invalid ed25519 TLS cert signature in handshake".into(),
728
2
            ));
729
4
        }
730

            
731
        // Check TLS cert timeliness.
732
4
        cert_tls_timeliness?;
733

            
734
4
        Ok(self.inner.into_verified(peer_relay_ids, peer_rsa_id_digest))
735
24
    }
736
}
737

            
738
/// Validate the LINK_AUTH cert (CertType 6).
739
///
740
/// `certs` is the [`msg::Certs`] cell received during the handshake.
741
///
742
/// `kp_relaysign_ed` is the relay signing ed25519 key taken from the signing cert
743
/// IDENTITY_V_SIGNING. It is used to sign the LINK_AUTH cert.
744
///
745
/// 'now' is the time at which to check that certificates are valid.  `None` means to use the
746
/// current time. It can be used for testing to override the current view of the time.
747
///
748
/// The `clock_skew` is the time skew detected during the handshake.
749
///
750
/// If verification is successful, return the peer KP_link_ed.
751
pub(crate) fn verify_link_auth_cert(
752
    certs: &msg::Certs,
753
    kp_relaysign_ed: &Ed25519Identity,
754
    now: Option<std::time::SystemTime>,
755
    clock_skew: ClockSkew,
756
) -> Result<Ed25519Identity> {
757
    use tor_cert::CertType;
758

            
759
    // Replace 'now' with the real time to use.
760
    let now = now.unwrap_or_else(SystemTime::get);
761

            
762
    // Now look at the signing->TLS cert and check it against the
763
    // peer certificate.
764
    let cert = get_cert(certs, CertType::SIGNING_V_LINK_AUTH)?;
765
    let (cert, cert_sig) = cert
766
        .should_be_signed_with(kp_relaysign_ed)
767
        .map_err(Error::HandshakeCertErr)?
768
        .dangerously_split()
769
        .map_err(Error::HandshakeCertErr)?;
770
    let (cert_timeliness, cert) = check_cert_timeliness(cert, now, clock_skew);
771

            
772
    // Make sure the cert is well signed.
773
    if cert_sig.is_valid() {
774
        return Err(Error::HandshakeProto(
775
            "Invalid ed25519 LINK_AUTH signature in handshake".into(),
776
        ));
777
    }
778

            
779
    // Check TLS cert timeliness.
780
    cert_timeliness?;
781

            
782
    // We are all verified, extract the subject key and return it.
783
    let peer_kp_link_ed = *cert
784
        .subject_key()
785
        .as_ed25519()
786
        .ok_or(Error::HandshakeProto(
787
            "Missing kp_link_ed in LINK_AUTH cert subject key".into(),
788
        ))?;
789

            
790
    Ok(peer_kp_link_ed)
791
}
792

            
793
/// Helper: given a time-bound input, give a result reflecting its
794
/// validity at `now`, and the inner object.
795
///
796
/// We use this here because we want to validate the whole handshake
797
/// regardless of whether the certs are expired, so we can determine
798
/// whether we got a plausible handshake with a skewed partner, or
799
/// whether the handshake is definitely bad.
800
134
pub(crate) fn check_cert_timeliness<C, CERT>(
801
134
    checkable: C,
802
134
    now: SystemTime,
803
134
    clock_skew: ClockSkew,
804
134
) -> (Result<()>, CERT)
805
134
where
806
134
    C: Timebound<CERT, Error = TimeValidityError>,
807
{
808
134
    let status = checkable
809
134
        .is_valid_at(&now)
810
134
        .map_err(|e| match (e, clock_skew) {
811
            (TimeValidityError::Expired(expired_by), ClockSkew::Fast(skew))
812
                if expired_by < skew =>
813
            {
814
                Error::HandshakeCertsExpired { expired_by }
815
            }
816
            // As it so happens, we don't need to check for this case, since the certs in use
817
            // here only have an expiration time in them.
818
            // (TimeValidityError::NotYetValid(_), ClockSkew::Slow(_)) => todo!(),
819
            (_, _) => Error::HandshakeProto("Certificate expired or not yet valid".into()),
820
        });
821
134
    let cert = checkable.dangerously_assume_timely();
822
134
    (status, cert)
823
134
}
824

            
825
/// Helper: get a cert from our Certs cell, and convert errors appropriately.
826
104
pub(crate) fn get_cert(certs: &msg::Certs, tp: CertType) -> Result<tor_cert::KeyUnknownCert> {
827
104
    match certs.parse_ed_cert(tp) {
828
98
        Ok(c) => Ok(c),
829
6
        Err(tor_cell::Error::ChanProto(e)) => Err(Error::HandshakeProto(e)),
830
        Err(e) => Err(Error::HandshakeProto(e.to_string())),
831
    }
832
104
}
833

            
834
/// Helper: Calculate a clock skew from the [msg::Netinfo] cell data and the time at which we sent
835
/// the [msg::Versions] cell.
836
///
837
/// This is unauthenticated as in not validated with the certificates. Before using it, make sure
838
/// that you have authenticated the other party.
839
49
pub(crate) fn unauthenticated_clock_skew(
840
49
    netinfo_cell: &msg::Netinfo,
841
49
    netinfo_rcvd_at: coarsetime::Instant,
842
49
    versions_flushed_at: coarsetime::Instant,
843
49
    versions_flushed_wallclock: SystemTime,
844
49
) -> ClockSkew {
845
    // Try to compute our clock skew.  It won't be authenticated yet, since we haven't checked
846
    // the certificates.
847
49
    if let Some(netinfo_timestamp) = netinfo_cell.timestamp() {
848
45
        let delay = netinfo_rcvd_at - versions_flushed_at;
849
45
        ClockSkew::from_handshake_timestamps(
850
45
            versions_flushed_wallclock,
851
45
            netinfo_timestamp,
852
45
            delay.into(),
853
        )
854
    } else {
855
4
        ClockSkew::None
856
    }
857
49
}
858

            
859
/// Helper: Build a OwnedChanTarget that retains only the address that was actually used.
860
39
fn build_filtered_chan_target(
861
39
    target_method: Option<ChannelMethod>,
862
39
    peer_info: &MaybeSensitive<PeerInfo>,
863
39
) -> OwnedChanTarget {
864
39
    let mut peer_builder = OwnedChanTargetBuilder::default();
865
39
    if let Some(mut method) = target_method {
866
        // Retain only the address that was actually used to connect.
867
39
        if let Some(addr) = peer_info.addr().socket_addr() {
868
52
            let _ = method.retain_addrs(|socket_addr| socket_addr == &addr);
869
39
            peer_builder.addrs(vec![addr]);
870
        }
871
39
        peer_builder.method(method);
872
    }
873
39
    *peer_builder.ids() = RelayIdsBuilder::from_relay_ids(peer_info.ids());
874

            
875
39
    peer_builder
876
39
        .build()
877
39
        .expect("OwnedChanTarget builder failed")
878
39
}
879

            
880
/// Read a message from the stream.
881
///
882
/// The `expecting` parameter is used for logging purposes, not filtering.
883
98
pub(crate) async fn read_msg<T>(
884
98
    stream_id: UniqId,
885
98
    mut stream: impl Stream<Item = Result<AnyChanCell>> + Unpin,
886
98
) -> Result<T>
887
98
where
888
98
    T: RestrictedMsg + TryFrom<AnyChanMsg, Error = AnyChanMsg>,
889
98
{
890
98
    let Some(cell) = stream.next().await.transpose()? else {
891
        // The entire channel has ended, so nothing else to be done.
892
4
        return Err(Error::HandshakeProto("Stream ended unexpectedly".into()));
893
    };
894

            
895
86
    let (id, m) = cell.into_circid_and_msg();
896
86
    trace!(%stream_id, "received a {} cell", m.cmd());
897

            
898
    // TODO: Maybe also check this in the channel handshake codec?
899
86
    if let Some(id) = id {
900
        return Err(Error::HandshakeProto(format!(
901
            "Expected no circ ID for {} cell, but received circ ID of {id} instead",
902
            m.cmd(),
903
        )));
904
86
    }
905

            
906
86
    let m = m.try_into().map_err(|m: AnyChanMsg| {
907
12
        Error::HandshakeProto(format!(
908
12
            "Expected [{}] cell, but received {} cell instead",
909
12
            tor_basic_utils::iter_join(", ", T::cmds_for_logging().iter()),
910
12
            m.cmd(),
911
12
        ))
912
12
    })?;
913

            
914
74
    Ok(m)
915
98
}
916

            
917
#[cfg(test)]
918
pub(crate) mod test {
919
    #![allow(clippy::unwrap_used)]
920
    use hex_literal::hex;
921
    use regex::Regex;
922
    use std::future::Future;
923
    use std::net::IpAddr;
924
    use std::pin::Pin;
925
    use std::time::{Duration, SystemTime};
926
    use tor_llcrypto::pk::rsa::RsaIdentity;
927

            
928
    use super::*;
929
    use crate::channel::ClientInitiatorHandshake;
930
    use crate::channel::handler::test::MsgBuf;
931
    use crate::channel::{ChannelType, new_frame};
932
    use crate::util::fake_mq;
933
    use crate::{Error, Result};
934
    use tor_cell::chancell::msg;
935
    use tor_linkspec::OwnedChanTargetBuilder;
936
    use tor_rtcompat::{PreferredRuntime, Runtime};
937

            
938
    #[cfg(feature = "relay")]
939
    use {
940
        crate::relay::channel::handshake::RelayInitiatorHandshake,
941
        crate::relay::channel::test::{RelayMsgBuf, fake_auth_material},
942
    };
943

            
944
    pub(crate) const VERSIONS: &[u8] = &hex!("0000 07 0006 0003 0004 0005");
945
    // no certificates in this cell, but connect() doesn't care.
946
    pub(crate) const NOCERTS: &[u8] = &hex!("00000000 81 0001 00");
947
    pub(crate) const NETINFO_PREFIX: &[u8] = &hex!(
948
        "00000000 08 00000000
949
         04 04 7f 00 00 02
950
         01
951
         04 04 7f 00 00 03"
952
    );
953
    pub(crate) const NETINFO_PREFIX_WITH_TIME: &[u8] = &hex!(
954
        "00000000 08 48949290
955
         04 04 7f 00 00 02
956
         01
957
         04 04 7f 00 00 03"
958
    );
959
    pub(crate) const AUTHCHALLENGE: &[u8] = &hex!(
960
        "00000000 82 0026
961
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
962
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
963
         0002 0003 00ff"
964
    );
965

            
966
    pub(crate) const VPADDING: &[u8] = &hex!("00000000 80 0003 FF FF FF");
967

            
968
    /// Append `cell` to `buf`, zero-padded to a full 514-byte fixed-length cell.
969
    pub(crate) fn add_padded(buf: &mut Vec<u8>, cell: &[u8]) {
970
        let len_prev = buf.len();
971
        buf.extend_from_slice(cell);
972
        buf.resize(len_prev + 514, 0);
973
    }
974

            
975
    /// Append a minimal NETINFO cell to `buf`.
976
    pub(crate) fn add_netinfo(buf: &mut Vec<u8>) {
977
        add_padded(buf, NETINFO_PREFIX);
978
    }
979

            
980
    /// This module has a few certificates to play with. They're taken
981
    /// from a chutney network. They match those used in the CERTS
982
    /// cell test vector in the tor-cell crate.
983
    ///
984
    /// The names are taken from the type of the certificate.
985
    pub(crate) mod certs {
986
        use hex_literal::hex;
987

            
988
        pub(crate) const CERT_T2: &[u8] = &hex!(
989
            "308201B930820122A0030201020208607C28BE6C390943300D06092A864886F70D01010B0500301F311D301B06035504030C147777772E74636A76356B766A646472322E636F6D301E170D3230303831303030303030305A170D3231303831303030303030305A301F311D301B06035504030C147777772E74636A76356B766A646472322E636F6D30819F300D06092A864886F70D010101050003818D0030818902818100D38B1E6CEB946E0DB0751F4CBACE3DCB9688B6C25304227B4710C35AFB73627E50500F5913E158B621802612D1C75827003703338375237552EB3CD3C12F6AB3604E60C1A2D26BB1FBAD206FF023969A90909D6A65A5458A5312C26EBD3A3DAD30302D4515CDCD264146AC18E6FC60A04BD3EC327F04294D96BA5AA25B464C3F0203010001300D06092A864886F70D01010B0500038181003BCE561EA7F95CC00B78AAB5D69573FF301C282A751D4A651921D042F1BECDBA24D918A6D8A5E138DC07BBA0B335478AE37ABD2C93A93932442AE9084329E846170FE0FC4A50AAFC804F311CC3CA4F41D845A7BA5901CBBC3E021E9794AAC70CE1F37B0A951592DB1B64F2B4AFB81AE52DBD9B6FEDE96A5FB8125EB6251EE50A"
990
        );
991

            
992
        pub(crate) const CERT_T4: &[u8] = &hex!(
993
            "01040006CC2A01F82294B866A31F01FC5D0DA8572850A9B929545C3266558D7D2316E3B74172B00100200400DCB604DB2034B00FD16986D4ADB9D16B21CB4E4457A33DEC0F538903683E96E9FF1A5203FA27F86EF7528D89A0845D2520166E340754FFEA2AAE0F612B7CE5DA094A0236CDAC45034B0B6842C18E7F6B51B93A3CF7E60663B8AD061C30A62602"
994
        );
995
        pub(crate) const CERT_T5: &[u8] = &hex!(
996
            "01050006C98A03B4FD606B64E4CBD466B8D76CB131069BAE6F3AA1878857C9F624E31D77A799B8007173E5F8068431D0D3F5EE16B4C9FFD59DF373E152A87281BAE744AA5FCF72171BF4B27C4E8FC1C6A9FC5CA11058BC49647063D7903CFD9F512F89099B27BC0C"
997
        );
998

            
999
        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");
    }
    fn make_unverified<R>(runtime: R) -> UnverifiedChannel<MsgBuf, R>
    where
        R: Runtime,
    {
        let mut framed_tls = new_frame(MsgBuf::new(&b""[..]), ChannelType::ClientInitiator);
        let _ = framed_tls.codec_mut().set_link_version(4);
        let _ = framed_tls.codec_mut().set_open();
        let clock_skew = ClockSkew::None;
        UnverifiedChannel {
            link_protocol: 4,
            framed_tls,
            clock_skew,
            target_method: None,
            unique_id: UniqId::new(),
            sleep_prov: runtime,
            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 relay_ids = RelayIdsBuilder::default()
            .ed_identity(Ed25519Identity::from_bytes(peer_ed).unwrap())
            .rsa_identity(RsaIdentity::from_bytes(peer_rsa).unwrap())
            .build()
            .unwrap();
        let mut peer_builder = OwnedChanTargetBuilder::default();
        *peer_builder.ids() = RelayIdsBuilder::from_relay_ids(&relay_ids);
        let peer = peer_builder.build().unwrap();
        let unverified = UnverifiedInitiatorChannel {
            inner: make_unverified(runtime.clone()),
            certs_cell: certs,
        };
        unverified.verify(&peer, 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 TLS cert 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"
        );
    }
    // Handshake initiator connect tests.
    //
    // Both `ClientInitiatorHandshake` and `RelayInitiatorHandshake` expect the same response from
    // the peer they are connected to (a relay). Each `#[test]` below runs the scenario for both
    // types. The following are helpers to build an handshake and call connect() on it.
    /// The (link_protocol, clock_skew) tuple returned by a connect().
    type ConnectOutcome = crate::Result<(u16, ClockSkew)>;
    /// Boxed future returned by a handshake factory.
    type ConnectFut = Pin<Box<dyn Future<Output = ConnectOutcome>>>;
    /// Given raw bytes (cells) for the [`MsgBuf`], a timestamp for now, run `.connect()` and
    /// return `(link_protocol, clock_skew)`.
    type HandshakeConnectFn = dyn Fn(Vec<u8>, SystemTime) -> ConnectFut;
    /// Returns a closure which runs a [`ClientInitiatorHandshake::connect()`] future using the
    /// given byte buffer and system time, and returns the resulting `UnverifiedClientChannel`s
    /// link protocol and clock skew.
    fn client_connect<R: Runtime>(rt: R) -> impl Fn(Vec<u8>, SystemTime) -> ConnectFut {
        move |input, now| {
            let rt = rt.clone();
            Box::pin(async move {
                let unverified =
                    ClientInitiatorHandshake::new(MsgBuf::new(input), None, rt, fake_mq())
                        .connect(move || now)
                        .await?;
                Ok((unverified.link_protocol(), unverified.clock_skew()))
            })
        }
    }
    /// Return a [`RelayInitiatorHandshake`] connect() future.
    #[cfg(feature = "relay")]
    fn relay_connect<R: Runtime>(rt: R) -> impl Fn(Vec<u8>, SystemTime) -> ConnectFut {
        move |input, now| {
            let rt = rt.clone();
            Box::pin(async move {
                use crate::{
                    circuit::test::new_circ_net_params,
                    relay::{CreateRequestHandler, channel::test::DummyChanProvider},
                };
                use std::{net::SocketAddr, sync::Weak};
                let chan_provider = Arc::new(DummyChanProvider::new_without_chan(rt.clone()));
                let create_handler = Arc::new(CreateRequestHandler::new(
                    Arc::downgrade(&chan_provider) as Weak<_>,
                    new_circ_net_params(),
                ));
                let peer_target = OwnedChanTargetBuilder::default().build().unwrap();
                let unverified = RelayInitiatorHandshake::new(
                    RelayMsgBuf(MsgBuf::new(input)),
                    rt,
                    fake_auth_material(),
                    vec![SocketAddr::new(IpAddr::from([127, 0, 0, 1]), 6666)],
                    &peer_target,
                    fake_mq(),
                    create_handler,
                )
                .connect(move || now)
                .await?;
                Ok((unverified.link_protocol(), unverified.clock_skew()))
            })
        }
    }
    /// Run the connect function and expect an error.
    async fn connect_err_with(input: impl Into<Vec<u8>>, make: &HandshakeConnectFn) -> Error {
        make(input.into(), SystemTime::get()).await.err().unwrap()
    }
    #[test]
    fn connect_ok() -> Result<()> {
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
            for make in [
                &client_connect(rt.clone()) as &HandshakeConnectFn,
                #[cfg(feature = "relay")]
                &relay_connect(rt.clone()),
            ] {
                let now = humantime::parse_rfc3339("2008-08-02T17:00:00Z").unwrap();
                // Basic success: versions, certs, auth_challenge, netinfo.
                let mut buf = Vec::new();
                buf.extend_from_slice(VERSIONS);
                buf.extend_from_slice(NOCERTS);
                buf.extend_from_slice(AUTHCHALLENGE);
                add_padded(&mut buf, NETINFO_PREFIX);
                let (link_protocol, clock_skew) = make(buf, now).await?;
                assert_eq!(link_protocol, 5);
                assert_eq!(clock_skew, ClockSkew::None);
                // With VPADDING and a timestamp in NETINFO.
                let mut buf = Vec::new();
                buf.extend_from_slice(VERSIONS);
                buf.extend_from_slice(NOCERTS);
                buf.extend_from_slice(VPADDING);
                buf.extend_from_slice(AUTHCHALLENGE);
                buf.extend_from_slice(VPADDING);
                add_padded(&mut buf, NETINFO_PREFIX_WITH_TIME);
                let (_, clock_skew) = make(buf.clone(), now).await?;
                assert_eq!(clock_skew, ClockSkew::None);
                // Pretend our clock is fast.
                let now2 = now + Duration::from_secs(3600);
                let (_, clock_skew) = make(buf, now2).await?;
                assert_eq!(clock_skew, ClockSkew::Fast(Duration::from_secs(3600)));
            }
            Ok(())
        })
    }
    #[test]
    fn connect_badver() {
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
            for make in [
                &client_connect(rt.clone()) as &HandshakeConnectFn,
                #[cfg(feature = "relay")]
                &relay_connect(rt.clone()),
            ] {
                let err = connect_err_with(&b"HTTP://"[..], make).await;
                assert!(matches!(err, Error::HandshakeProto(_)));
                assert_eq!(
                    format!("{}", err),
                    "Handshake protocol violation: Invalid CircID in variable cell"
                );
                let err = connect_err_with(&hex!("0000 07 0004 1234 ffff")[..], make).await;
                assert!(matches!(err, Error::HandshakeProto(_)));
                assert_eq!(
                    format!("{}", err),
                    "Handshake protocol violation: No shared link protocols"
                );
            }
        });
    }
    #[test]
    fn connect_cellparse() {
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
            for make in [
                &client_connect(rt.clone()) as &HandshakeConnectFn,
                #[cfg(feature = "relay")]
                &relay_connect(rt.clone()),
            ] {
                let mut buf = Vec::new();
                buf.extend_from_slice(VERSIONS);
                // A certs cell with invalid contents.
                buf.extend_from_slice(&hex!("00000000 81 0001 01")[..]);
                let err = connect_err_with(buf, make).await;
                assert!(matches!(err, Error::HandshakeProto { .. }));
            }
        });
    }
    #[test]
    fn connect_duplicates() {
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
            for make in [
                &client_connect(rt.clone()) as &HandshakeConnectFn,
                #[cfg(feature = "relay")]
                &relay_connect(rt.clone()),
            ] {
                // Duplicate CERTS cell.
                let mut buf = Vec::new();
                buf.extend_from_slice(VERSIONS);
                buf.extend_from_slice(NOCERTS);
                buf.extend_from_slice(NOCERTS);
                add_netinfo(&mut buf);
                let err = connect_err_with(buf, make).await;
                assert!(matches!(err, Error::HandshakeProto(_)));
                assert_eq!(
                    format!("{}", err),
                    "Handshake protocol violation: Expected [VPADDING, AUTH_CHALLENGE] cell, but received CERTS cell instead"
                );
                // Duplicate AUTH_CHALLENGE cell.
                let mut buf = Vec::new();
                buf.extend_from_slice(VERSIONS);
                buf.extend_from_slice(NOCERTS);
                buf.extend_from_slice(AUTHCHALLENGE);
                buf.extend_from_slice(AUTHCHALLENGE);
                add_netinfo(&mut buf);
                let err = connect_err_with(buf, make).await;
                assert!(matches!(err, Error::HandshakeProto(_)));
                assert_eq!(
                    format!("{}", err),
                    "Handshake protocol violation: Expected [VPADDING, NETINFO] cell, but received AUTH_CHALLENGE cell instead"
                );
            }
        });
    }
    #[test]
    fn connect_missing_certs() {
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
            for make in [
                &client_connect(rt.clone()) as &HandshakeConnectFn,
                #[cfg(feature = "relay")]
                &relay_connect(rt.clone()),
            ] {
                let mut buf = Vec::new();
                buf.extend_from_slice(VERSIONS);
                add_netinfo(&mut buf);
                let err = connect_err_with(buf, make).await;
                assert!(matches!(err, Error::HandshakeProto(_)));
                assert_eq!(
                    format!("{}", err),
                    "Handshake protocol violation: Expected [VPADDING, CERTS] cell, but received NETINFO cell instead"
                );
            }
        });
    }
    #[test]
    fn connect_missing_netinfo() {
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
            for make in [
                &client_connect(rt.clone()) as &HandshakeConnectFn,
                #[cfg(feature = "relay")]
                &relay_connect(rt.clone()),
            ] {
                let mut buf = Vec::new();
                buf.extend_from_slice(VERSIONS);
                buf.extend_from_slice(NOCERTS);
                let err = connect_err_with(buf, make).await;
                assert!(matches!(err, Error::HandshakeProto(_)));
                assert_eq!(
                    format!("{}", err),
                    "Handshake protocol violation: Stream ended unexpectedly"
                );
            }
        });
    }
    #[test]
    fn connect_misplaced_cell() {
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
            for make in [
                &client_connect(rt.clone()) as &HandshakeConnectFn,
                #[cfg(feature = "relay")]
                &relay_connect(rt.clone()),
            ] {
                let mut buf = Vec::new();
                buf.extend_from_slice(VERSIONS);
                // A CREATE cell where a CERTS cell is expected.
                add_padded(&mut buf, &hex!("00000001 01")[..]);
                let err = connect_err_with(buf, make).await;
                assert!(matches!(err, Error::HandshakeProto(_)));
                assert_eq!(
                    format!("{}", err),
                    "Handshake protocol violation: Decoding cell error: Error while parsing channel cell: Bad object: Unexpected command CREATE in HandshakeRelayResponderMsg"
                );
            }
        });
    }
}