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 tor_llcrypto::pk::ValidatableSignature;
9

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

            
30
use digest::Digest;
31

            
32
use tracing::{debug, instrument, trace};
33

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

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

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

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

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

            
108
20
        Ok(link_protocol)
109
24
    }
110

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

            
122
/// Handshake initiator base trait. All initiator handshake should implement this trait in order to
123
/// enjoy the helper functions.
124
///
125
/// It requires the base handshake trait to be implement for access to the base getters.
126
pub(crate) trait ChannelInitiatorHandshake<T>: ChannelBaseHandshake<T>
127
where
128
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
129
{
130
    /// As an initiator, we are expecting the responder's cells which are:
131
    /// - [msg::Certs]
132
    /// - [msg::AuthChallenge]
133
    /// - [msg::Netinfo]
134
    ///
135
    /// Any duplicate, missing cell or unexpected results in a protocol level error.
136
    ///
137
    /// This returns the:
138
    /// - [msg::AuthChallenge] cell
139
    /// - [msg::Certs] cell
140
    /// - [msg::Netinfo] cell
141
    /// - the instant when the netinfo cell was received (needed for the clock skew calculation)
142
    /// - the SLOG digest if `take_slog` is true (needed if we send an [msg::Authenticate] cell in the future)
143
20
    async fn recv_cells_from_responder(
144
20
        &mut self,
145
20
        take_slog: bool,
146
20
    ) -> Result<(
147
20
        msg::AuthChallenge,
148
20
        msg::Certs,
149
20
        (msg::Netinfo, coarsetime::Instant),
150
20
        // TODO: We should typedef this somewhere.
151
20
        /* the SLOG digest */
152
20
        Option<[u8; 32]>,
153
30
    )> {
154
        // IMPORTANT: Protocol wise, we MUST only allow one single cell of each type for a valid
155
        // handshake. Any duplicates lead to a failure.
156
        // They must arrive in a specific order in order for the SLOG calculation to be valid.
157

            
158
        /// Read a message from the stream.
159
        ///
160
        /// The `expecting` parameter is used for logging purposes, not filtering.
161
52
        async fn read_msg<T>(
162
52
            stream_id: UniqId,
163
52
            mut stream: impl Stream<Item = Result<AnyChanCell>> + Unpin,
164
52
        ) -> Result<T>
165
52
        where
166
52
            T: RestrictedMsg + TryFrom<AnyChanMsg, Error = AnyChanMsg>,
167
52
        {
168
52
            let Some(cell) = stream.next().await.transpose()? else {
169
                // The entire channel has ended, so nothing else to be done.
170
2
                return Err(Error::HandshakeProto("Stream ended unexpectedly".into()));
171
            };
172

            
173
46
            let (id, m) = cell.into_circid_and_msg();
174
46
            trace!(%stream_id, "received a {} cell", m.cmd());
175

            
176
            // TODO: Maybe also check this in the channel handshake codec?
177
46
            if let Some(id) = id {
178
                return Err(Error::HandshakeProto(format!(
179
                    "Expected no circ ID for {} cell, but received circ ID of {id} instead",
180
                    m.cmd(),
181
                )));
182
46
            }
183

            
184
46
            let m = m.try_into().map_err(|m: AnyChanMsg| {
185
6
                Error::HandshakeProto(format!(
186
6
                    "Expected [{}] cell, but received {} cell instead",
187
6
                    tor_basic_utils::iter_join(", ", T::cmds_for_logging().iter()),
188
6
                    m.cmd(),
189
6
                ))
190
6
            })?;
191

            
192
40
            Ok(m)
193
52
        }
194

            
195
        // Note that the `ChannelFrame` already restricts the messages due to its handshake cell
196
        // handler.
197

            
198
14
        let certs = loop {
199
            restricted_msg! {
200
                enum CertsMsg : ChanMsg {
201
                    // VPADDING cells (but not PADDING) can be sent during handshaking.
202
                    Vpadding,
203
                    Certs,
204
               }
205
            }
206

            
207
20
            break match read_msg(*self.unique_id(), self.framed_tls()).await? {
208
                CertsMsg::Vpadding(_) => continue,
209
14
                CertsMsg::Certs(msg) => msg,
210
            };
211
        };
212

            
213
        // Clients don't care about AuthChallenge,
214
        // but the responder always sends it anyways so we require it here.
215
10
        let auth_challenge = loop {
216
            restricted_msg! {
217
                enum AuthChallengeMsg : ChanMsg {
218
                    // VPADDING cells (but not PADDING) can be sent during handshaking.
219
                    Vpadding,
220
                    AuthChallenge,
221
               }
222
            }
223

            
224
18
            break match read_msg(*self.unique_id(), self.framed_tls()).await? {
225
4
                AuthChallengeMsg::Vpadding(_) => continue,
226
10
                AuthChallengeMsg::AuthChallenge(msg) => msg,
227
            };
228
        };
229

            
230
10
        let slog_digest = if take_slog {
231
            // We're the initiator, which means that the recv log is the SLOG.
232
            Some(self.framed_tls().codec_mut().take_recv_log_digest()?)
233
        } else {
234
10
            None
235
        };
236

            
237
8
        let (netinfo, netinfo_rcvd_at) = loop {
238
            restricted_msg! {
239
                enum NetinfoMsg : ChanMsg {
240
                    // VPADDING cells (but not PADDING) can be sent during handshaking.
241
                    Vpadding,
242
                    Netinfo,
243
               }
244
            }
245

            
246
14
            break match read_msg(*self.unique_id(), self.framed_tls()).await? {
247
4
                NetinfoMsg::Vpadding(_) => continue,
248
8
                NetinfoMsg::Netinfo(msg) => (msg, coarsetime::Instant::now()),
249
            };
250
        };
251

            
252
8
        Ok((
253
8
            auth_challenge,
254
8
            certs,
255
8
            (netinfo, netinfo_rcvd_at),
256
8
            slog_digest,
257
8
        ))
258
20
    }
259
}
260

            
261
/// A base channel on which versions have been negotiated and the relay's handshake has been read,
262
/// but where the certs have not been checked.
263
///
264
/// Both relay and client have specialized objects for an unverified channel which include this one
265
/// as the base in order to share functionalities.
266
pub(crate) struct UnverifiedChannel<
267
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
268
    S: CoarseTimeProvider + SleepProvider,
269
> {
270
    /// Runtime handle (insofar as we need it)
271
    pub(crate) sleep_prov: S,
272
    /// Memory quota account
273
    pub(crate) memquota: ChannelAccount,
274
    /// The negotiated link protocol.  Must be a member of LINK_PROTOCOLS
275
    pub(crate) link_protocol: u16,
276
    /// The Source+Sink on which we're reading and writing cells.
277
    pub(crate) framed_tls: ChannelFrame<T>,
278
    /// Declared target method for this channel, if any.
279
    pub(crate) target_method: Option<ChannelMethod>,
280
    /// How much clock skew did we detect in this handshake?
281
    ///
282
    /// This value is _unauthenticated_, since we have not yet checked whether
283
    /// the keys in the handshake are the ones we expected.
284
    pub(crate) clock_skew: ClockSkew,
285
    /// Logging identifier for this stream.  (Used for logging only.)
286
    pub(crate) unique_id: UniqId,
287
}
288

            
289
/// A base initiator channel on which versions have been negotiated and the relay's handshake has
290
/// been read, but where the [`msg::Certs`] has not been checked.
291
///
292
/// Both relay and client have specialized objects for an unverified channel which include this one
293
/// as the base in order to share functionnalities.
294
///
295
/// We need this intermediary object between the specialized one (client/relay) and the
296
/// [`UnverifiedChannel`] because certs validation is quite different from a respodner channel.
297
/// This avoid code duplication.
298
pub(crate) struct UnverifiedInitiatorChannel<
299
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
300
    S: CoarseTimeProvider + SleepProvider,
301
> {
302
    /// Base unverified channel.
303
    pub(crate) inner: UnverifiedChannel<T, S>,
304
    /// The [`msg::Certs`] received during the handshake.
305
    pub(crate) certs_cell: msg::Certs,
306
}
307

            
308
/// A base channel on which versions have been negotiated, relay's handshake has been read, but the
309
/// client has not yet finished the handshake.
310
///
311
/// This type is separate from UnverifiedChannel, since finishing the handshake requires a bunch of
312
/// CPU, and you might want to do it as a separate task or after a yield.
313
///
314
/// Both relay and client have specialized objects for an unverified channel which include this one
315
/// as the base in order to share functionalities.
316
pub(crate) struct VerifiedChannel<
317
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
318
    S: CoarseTimeProvider + SleepProvider,
319
> {
320
    /// Runtime handle (insofar as we need it)
321
    pub(crate) sleep_prov: S,
322
    /// Memory quota account
323
    pub(crate) memquota: ChannelAccount,
324
    /// The negotiated link protocol.
325
    pub(crate) link_protocol: u16,
326
    /// The Source+Sink on which we're reading and writing cells.
327
    pub(crate) framed_tls: ChannelFrame<T>,
328
    /// Declared target method for this stream, if any.
329
    pub(crate) target_method: Option<ChannelMethod>,
330
    /// Logging identifier for this stream.  (Used for logging only.)
331
    pub(crate) unique_id: UniqId,
332
    /// Verified peer identities
333
    pub(crate) relay_ids: RelayIds,
334
    /// Validated RSA identity digest of the DER format for this peer.
335
    pub(crate) rsa_id_digest: [u8; 32],
336
    /// Authenticated clock skew for this peer.
337
    pub(crate) clock_skew: ClockSkew,
338
}
339

            
340
impl<
341
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
342
    S: CoarseTimeProvider + SleepProvider,
343
> UnverifiedChannel<T, S>
344
{
345
    /// Return a newly constructed [`VerifiedChannel`].
346
4
    pub(crate) fn into_verified(
347
4
        self,
348
4
        relay_ids: RelayIds,
349
4
        rsa_id_digest: [u8; 32],
350
4
    ) -> VerifiedChannel<T, S> {
351
4
        VerifiedChannel {
352
4
            link_protocol: self.link_protocol,
353
4
            framed_tls: self.framed_tls,
354
4
            unique_id: self.unique_id,
355
4
            target_method: self.target_method,
356
4
            relay_ids,
357
4
            rsa_id_digest,
358
4
            clock_skew: self.clock_skew,
359
4
            sleep_prov: self.sleep_prov,
360
4
            memquota: self.memquota,
361
4
        }
362
4
    }
363

            
364
    /// This validates the relay identities (Ed25519 and RSA) and signing key cert (Ed25519).
365
    /// Successful validation returns the relay ed25519 identitiy key, the ed25519 signing key and
366
    /// the RSA public key.
367
    ///
368
    /// Reason for the RSA public key is because the caller needs to the SHA256 digest for the
369
    /// [`msg::Authenticate`] cell.
370
24
    pub(crate) fn check_relay_identities<U: ChanTarget + ?Sized>(
371
24
        &self,
372
24
        peer: &U,
373
24
        certs: &msg::Certs,
374
24
        now: SystemTime,
375
24
    ) -> Result<(RelayIds, Ed25519Identity, [u8; 32])> {
376
        use tor_checkable::*;
377

            
378
        // Get the identity signing cert (CertType 4).
379
24
        let id_sk = get_cert(certs, CertType::IDENTITY_V_SIGNING)?;
380

            
381
        // Check the identity->signing cert
382
20
        let (id_sk, id_sk_sig) = id_sk
383
20
            .should_have_signing_key()
384
20
            .map_err(Error::HandshakeCertErr)?
385
20
            .dangerously_split()
386
20
            .map_err(Error::HandshakeCertErr)?;
387
20
        let (id_sk_timeliness, id_sk) = check_cert_timeliness(id_sk, now, self.clock_skew);
388

            
389
        // Make sure the ed25519 identity cert is well signed before parsing more data.
390
20
        if !id_sk_sig.is_valid() {
391
            return Err(Error::HandshakeProto(
392
                "Invalid ed25519 identity cert signature in handshake".into(),
393
            ));
394
20
        }
395

            
396
        // Take the identity key from the identity->signing cert
397
20
        let identity_key = id_sk.signing_key().ok_or_else(|| {
398
            Error::HandshakeProto("Missing identity key in identity->signing cert".into())
399
        })?;
400

            
401
        // Take the signing key from the identity->signing cert
402
20
        let signing_key = id_sk.subject_key().as_ed25519().ok_or_else(|| {
403
            Error::HandshakeProto("Bad key type in identity->signing cert".into())
404
        })?;
405

            
406
        // What is the RSA identity key, according to the X.509 certificate
407
        // in which it is self-signed?
408
        //
409
        // (We don't actually check this self-signed certificate, and we use
410
        // a kludge to extract the RSA key)
411
20
        let rsa_id_cert_bytes = certs
412
20
            .cert_body(CertType::RSA_ID_X509)
413
20
            .ok_or_else(|| Error::HandshakeProto("Couldn't find RSA identity cert".into()))?;
414
18
        let pkrsa =
415
18
            ll::util::x509_extract_rsa_subject_kludge(rsa_id_cert_bytes).ok_or_else(|| {
416
                Error::HandshakeProto(
417
                    "Couldn't find RSA SubjectPublicKey from RSA identity cert".into(),
418
                )
419
            })?;
420

            
421
        // Now verify the RSA identity -> Ed Identity crosscert.
422
        //
423
        // This proves that the RSA key vouches for the Ed key.  Note that
424
        // the Ed key does not vouch for the RSA key: The RSA key is too
425
        // weak.
426
18
        let rsa_cert = certs
427
18
            .cert_body(CertType::RSA_ID_V_IDENTITY)
428
18
            .ok_or_else(|| Error::HandshakeProto("No RSA->Ed crosscert".into()))?;
429
16
        let rsa_cert = tor_cert::rsa::RsaCrosscert::decode(rsa_cert)
430
16
            .map_err(|e| Error::from_bytes_err(e, "RSA identity cross-certificate"))?
431
16
            .check_signature(&pkrsa)
432
16
            .map_err(|_| Error::HandshakeProto("Bad RSA->Ed crosscert signature".into()))?;
433
14
        let (rsa_cert_timeliness, rsa_cert) = check_cert_timeliness(rsa_cert, now, self.clock_skew);
434

            
435
14
        if !rsa_cert.subject_key_matches(identity_key) {
436
            return Err(Error::HandshakeProto(
437
                "RSA->Ed crosscert certifies incorrect key".into(),
438
            ));
439
14
        }
440

            
441
        // The only remaining concern is certificate timeliness.  If the
442
        // certificates are expired by an amount that is too large for the
443
        // declared clock skew to explain, then  we'll return
444
        // `Error::HandshakeProto`: in that case the clock skew is _not_
445
        // authenticated.  But if the certs are only expired by a little bit,
446
        // we'll reject the handshake with `Error::HandshakeCertsExpired`, and
447
        // the caller can trust the clock skew.
448
        //
449
        // We note expired certs last, since we only want to return
450
        // `HandshakeCertsExpired` when there are no other errors.
451
14
        id_sk_timeliness?;
452
14
        rsa_cert_timeliness?;
453

            
454
        // Now that we've done all the verification steps on the
455
        // certificates, we know who we are talking to.  It's time to
456
        // make sure that the peer we are talking to is the peer we
457
        // actually wanted.
458
        //
459
        // We do this _last_, since "this is the wrong peer" is
460
        // usually a different situation than "this peer couldn't even
461
        // identify itself right."
462
14
        let actual_identity = RelayIds::builder()
463
14
            .ed_identity(*identity_key)
464
14
            .rsa_identity(pkrsa.to_rsa_identity())
465
14
            .build()
466
14
            .expect("Unable to build RelayIds");
467

            
468
        // We enforce that the relay proved that it has every ID that we wanted:
469
        // it may also have additional IDs that we didn't ask for.
470
14
        match super::check_id_match_helper(&actual_identity, peer) {
471
4
            Err(Error::ChanMismatch(msg)) => Err(Error::HandshakeProto(msg)),
472
10
            other => other,
473
4
        }?;
474

            
475
10
        let rsa_id_digest: [u8; 32] = ll::d::Sha256::digest(pkrsa.to_der()).into();
476

            
477
10
        Ok((actual_identity, *signing_key, rsa_id_digest))
478
24
    }
479

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

            
508
        // We have finalized the handshake, move our codec to Open.
509
        self.framed_tls.codec_mut().set_open()?;
510

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

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

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

            
527
        let peer_id = build_filtered_chan_target(self.target_method.take(), &peer_info);
528

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

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

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

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

            
567
    /// The channel is used to send cells, and to create outgoing circuits.
568
    /// The reactor is used to route incoming messages to their appropriate
569
    /// circuit.
570
    #[instrument(skip_all, level = "trace")]
571
4
    pub(crate) async fn finish(
572
4
        mut self,
573
4
        netinfo: &msg::Netinfo,
574
4
        my_addrs: &[IpAddr],
575
4
        peer_info: MaybeSensitive<PeerInfo>,
576
4
    ) -> Result<(Arc<super::Channel>, super::reactor::Reactor<S>)> {
577
        // We treat a completed channel -- that is to say, one where the
578
        // authentication is finished -- as incoming traffic.
579
        //
580
        // TODO: conceivably we should remember the time when we _got_ the
581
        // final cell on the handshake, and update the channel completion
582
        // time to be no earlier than _that_ timestamp.
583
        //
584
        // TODO: This shouldn't be here. This should be called in the trait functions that actually
585
        // receives the data (recv_*). We'll move it at a later commit.
586
        crate::note_incoming_traffic();
587

            
588
        // We have finalized the handshake, move our codec to Open.
589
        self.framed_tls.codec_mut().set_open()?;
590

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

            
595
        debug!(
596
            stream_id = %self.unique_id,
597
            "Completed handshake with peer: {}", peer_info
598
        );
599

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

            
609
        let canonicity =
610
            Canonicity::from_netinfo(netinfo, my_addrs, peer_info.addr().netinfo_addr());
611

            
612
        let peer_id = build_filtered_chan_target(self.target_method.take(), &peer_info);
613

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

            
631
impl<
632
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
633
    S: CoarseTimeProvider + SleepProvider,
634
> UnverifiedInitiatorChannel<T, S>
635
{
636
    /// Validate the TLS cert (CertType 5) located in our `certs_cell`.
637
    ///
638
    /// `peer` is the relay we want to connect to.
639
    ///
640
    /// 'peer_cert_digest' is the digest of the x.509 certificate that the peer presented during
641
    /// its TLS handshake (ServerHello).
642
    ///
643
    /// `kp_relaysign_ed` is the relay signing key taken from the signing cert (CertType 4). It is used
644
    /// to sign the TLS cert and so we use it to validate.
645
    ///
646
    /// 'now' is the time at which to check that certificates are valid.  `None` means to use the
647
    /// current time. It can be used for testing to override the current view of the time.
648
    ///
649
    /// The `clock_skew` is the time skew detected during the handshake.
650
24
    pub(crate) fn verify<U: ChanTarget + ?Sized>(
651
24
        self,
652
24
        peer: &U,
653
24
        peer_cert_digest: [u8; 32],
654
24
        now: Option<std::time::SystemTime>,
655
24
    ) -> Result<VerifiedChannel<T, S>> {
656
        use tor_cert::CertType;
657

            
658
        // Replace 'now' with the real time to use.
659
24
        let now = now.unwrap_or_else(SystemTime::get);
660

            
661
        // We are a client initiating a channel to a relay or a bridge. We have received a CERTS
662
        // cell and we need to verify these certs:
663
        //
664
        //   Relay Identities:
665
        //      IDENTITY_V_SIGNING_CERT (CertType 4)
666
        //      RSA_ID_X509             (CertType 2)
667
        //      RSA_ID_V_IDENTITY       (CertType 7)
668
        //
669
        //   Connection Cert:
670
        //      SIGNING_V_TLS_CERT      (CertType 5)
671
        //
672
        // Validating the relay identities first so we can make sure we are talking to the relay
673
        // (peer) we wanted. Then, check the TLS cert validity.
674
        //
675
        // The end result is a verified channel (not authenticated yet) which guarantee that we are
676
        // talking to the right relay that we wanted.
677

            
678
        // Check the relay identities in the CERTS cell.
679
10
        let (relay_ids, kp_relaysign_ed, rsa_id_digest) =
680
24
            self.inner
681
24
                .check_relay_identities(peer, &self.certs_cell, now)?;
682

            
683
        // Now look at the signing->TLS cert and check it against the
684
        // peer certificate.
685
10
        let sk_tls = get_cert(&self.certs_cell, CertType::SIGNING_V_TLS_CERT)?;
686
8
        let (sk_tls, sk_tls_sig) = sk_tls
687
8
            .should_be_signed_with(&kp_relaysign_ed)
688
8
            .map_err(Error::HandshakeCertErr)?
689
8
            .dangerously_split()
690
8
            .map_err(Error::HandshakeCertErr)?;
691
8
        let (sk_tls_timeliness, sk_tls) = check_cert_timeliness(sk_tls, now, self.inner.clock_skew);
692

            
693
8
        if peer_cert_digest != sk_tls.subject_key().as_bytes() {
694
2
            return Err(Error::HandshakeProto(
695
2
                "Peer cert did not authenticate TLS cert".into(),
696
2
            ));
697
6
        }
698

            
699
        // Make sure the TLS cert is well signed.
700
6
        if !sk_tls_sig.is_valid() {
701
2
            return Err(Error::HandshakeProto(
702
2
                "Invalid ed25519 TLS cert signature in handshake".into(),
703
2
            ));
704
4
        }
705

            
706
        // Check TLS cert timeliness.
707
4
        sk_tls_timeliness?;
708

            
709
4
        Ok(self.inner.into_verified(relay_ids, rsa_id_digest))
710
24
    }
711
}
712

            
713
/// Validate the LINK_AUTH cert (CertType 6).
714
///
715
/// `certs` is the [`msg::Certs`] cell received during the handshake.
716
///
717
/// `kp_relaysign_ed` is the relay signing ed25519 key taken from the signing cert (CertType 4). It
718
/// is used to sign the LINK_AUTH cert.
719
///
720
/// 'now' is the time at which to check that certificates are valid.  `None` means to use the
721
/// current time. It can be used for testing to override the current view of the time.
722
///
723
/// The `clock_skew` is the time skew detected during the handshake.
724
///
725
/// If verification is successful, return the peer KP_link_ed.
726
pub(crate) fn verify_link_auth_cert(
727
    certs: &msg::Certs,
728
    kp_relaysign_ed: &Ed25519Identity,
729
    now: Option<std::time::SystemTime>,
730
    clock_skew: ClockSkew,
731
) -> Result<Ed25519Identity> {
732
    use tor_cert::CertType;
733

            
734
    // Replace 'now' with the real time to use.
735
    let now = now.unwrap_or_else(SystemTime::get);
736

            
737
    // Now look at the signing->TLS cert and check it against the
738
    // peer certificate.
739
    let cert = get_cert(certs, CertType::SIGNING_V_LINK_AUTH)?;
740
    let (cert, cert_sig) = cert
741
        .should_be_signed_with(kp_relaysign_ed)
742
        .map_err(Error::HandshakeCertErr)?
743
        .dangerously_split()
744
        .map_err(Error::HandshakeCertErr)?;
745
    let (cert_timeliness, cert) = check_cert_timeliness(cert, now, clock_skew);
746

            
747
    // Make sure the cert is well signed.
748
    if cert_sig.is_valid() {
749
        return Err(Error::HandshakeProto(
750
            "Invalid ed25519 LINK_AUTH signature in handshake".into(),
751
        ));
752
    }
753

            
754
    // Check TLS cert timeliness.
755
    cert_timeliness?;
756

            
757
    // We are all verified, extract the subject key and return it.
758
    let peer_kp_link_ed = *cert
759
        .subject_key()
760
        .as_ed25519()
761
        .ok_or(Error::HandshakeProto(
762
            "Missing kp_link_ed in LINK_AUTH cert subject key".into(),
763
        ))?;
764

            
765
    Ok(peer_kp_link_ed)
766
}
767

            
768
/// Helper: given a time-bound input, give a result reflecting its
769
/// validity at `now`, and the inner object.
770
///
771
/// We use this here because we want to validate the whole handshake
772
/// regardless of whether the certs are expired, so we can determine
773
/// whether we got a plausible handshake with a skewed partner, or
774
/// whether the handshake is definitely bad.
775
134
pub(crate) fn check_cert_timeliness<C, CERT>(
776
134
    checkable: C,
777
134
    now: SystemTime,
778
134
    clock_skew: ClockSkew,
779
134
) -> (Result<()>, CERT)
780
134
where
781
134
    C: Timebound<CERT, Error = TimeValidityError>,
782
{
783
134
    let status = checkable
784
134
        .is_valid_at(&now)
785
134
        .map_err(|e| match (e, clock_skew) {
786
            (TimeValidityError::Expired(expired_by), ClockSkew::Fast(skew))
787
                if expired_by < skew =>
788
            {
789
                Error::HandshakeCertsExpired { expired_by }
790
            }
791
            // As it so happens, we don't need to check for this case, since the certs in use
792
            // here only have an expiration time in them.
793
            // (TimeValidityError::NotYetValid(_), ClockSkew::Slow(_)) => todo!(),
794
            (_, _) => Error::HandshakeProto("Certificate expired or not yet valid".into()),
795
        });
796
134
    let cert = checkable.dangerously_assume_timely();
797
134
    (status, cert)
798
134
}
799

            
800
/// Helper: get a cert from our Certs cell, and convert errors appropriately.
801
104
pub(crate) fn get_cert(certs: &msg::Certs, tp: CertType) -> Result<tor_cert::KeyUnknownCert> {
802
104
    match certs.parse_ed_cert(tp) {
803
98
        Ok(c) => Ok(c),
804
6
        Err(tor_cell::Error::ChanProto(e)) => Err(Error::HandshakeProto(e)),
805
        Err(e) => Err(Error::HandshakeProto(e.to_string())),
806
    }
807
104
}
808

            
809
/// Helper: Calculate a clock skew from the [msg::Netinfo] cell data and the time at which we sent
810
/// the [msg::Versions] cell.
811
///
812
/// This is unauthenticated as in not validated with the certificates. Before using it, make sure
813
/// that you have authenticated the other party.
814
43
pub(crate) fn unauthenticated_clock_skew(
815
43
    netinfo_cell: &msg::Netinfo,
816
43
    netinfo_rcvd_at: coarsetime::Instant,
817
43
    versions_flushed_at: coarsetime::Instant,
818
43
    versions_flushed_wallclock: SystemTime,
819
43
) -> ClockSkew {
820
    // Try to compute our clock skew.  It won't be authenticated yet, since we haven't checked
821
    // the certificates.
822
43
    if let Some(netinfo_timestamp) = netinfo_cell.timestamp() {
823
41
        let delay = netinfo_rcvd_at - versions_flushed_at;
824
41
        ClockSkew::from_handshake_timestamps(
825
41
            versions_flushed_wallclock,
826
41
            netinfo_timestamp,
827
41
            delay.into(),
828
        )
829
    } else {
830
2
        ClockSkew::None
831
    }
832
43
}
833

            
834
/// Helper: Build a OwnedChanTarget that retains only the address that was actually used.
835
39
fn build_filtered_chan_target(
836
39
    target_method: Option<ChannelMethod>,
837
39
    peer_info: &MaybeSensitive<PeerInfo>,
838
39
) -> OwnedChanTarget {
839
39
    let mut peer_builder = OwnedChanTargetBuilder::default();
840
39
    if let Some(mut method) = target_method {
841
        // Retain only the address that was actually used to connect.
842
39
        if let Some(addr) = peer_info.addr().socket_addr() {
843
52
            let _ = method.retain_addrs(|socket_addr| socket_addr == &addr);
844
39
            peer_builder.addrs(vec![addr]);
845
        }
846
39
        peer_builder.method(method);
847
    }
848
39
    *peer_builder.ids() = RelayIdsBuilder::from_relay_ids(peer_info.ids());
849

            
850
39
    peer_builder
851
39
        .build()
852
39
        .expect("OwnedChanTarget builder failed")
853
39
}
854

            
855
#[cfg(test)]
856
pub(super) mod test {
857
    #![allow(clippy::unwrap_used)]
858
    use hex_literal::hex;
859
    use regex::Regex;
860
    use std::time::{Duration, SystemTime};
861
    use tor_llcrypto::pk::rsa::RsaIdentity;
862

            
863
    use super::*;
864
    use crate::channel::handler::test::MsgBuf;
865
    use crate::channel::{ChannelType, new_frame};
866
    use crate::util::fake_mq;
867
    use crate::{Result, channel::ClientInitiatorHandshake};
868
    use tor_cell::chancell::msg::{self, Netinfo};
869
    use tor_rtcompat::{PreferredRuntime, Runtime};
870

            
871
    const VERSIONS: &[u8] = &hex!("0000 07 0006 0003 0004 0005");
872
    // no certificates in this cell, but connect() doesn't care.
873
    const NOCERTS: &[u8] = &hex!("00000000 81 0001 00");
874
    const NETINFO_PREFIX: &[u8] = &hex!(
875
        "00000000 08 00000000
876
         04 04 7f 00 00 02
877
         01
878
         04 04 7f 00 00 03"
879
    );
880
    const NETINFO_PREFIX_WITH_TIME: &[u8] = &hex!(
881
        "00000000 08 48949290
882
         04 04 7f 00 00 02
883
         01
884
         04 04 7f 00 00 03"
885
    );
886
    const AUTHCHALLENGE: &[u8] = &hex!(
887
        "00000000 82 0026
888
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
889
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
890
         0002 0003 00ff"
891
    );
892

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

            
895
    fn add_padded(buf: &mut Vec<u8>, cell: &[u8]) {
896
        let len_prev = buf.len();
897
        buf.extend_from_slice(cell);
898
        buf.resize(len_prev + 514, 0);
899
    }
900
    fn add_netinfo(buf: &mut Vec<u8>) {
901
        add_padded(buf, NETINFO_PREFIX);
902
    }
903

            
904
    #[test]
905
    fn connect_ok() -> Result<()> {
906
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
907
            let now = humantime::parse_rfc3339("2008-08-02T17:00:00Z").unwrap();
908
            let mut buf = Vec::new();
909
            // versions cell
910
            buf.extend_from_slice(VERSIONS);
911
            // certs cell -- no certs in it, but this function doesn't care.
912
            buf.extend_from_slice(NOCERTS);
913
            // auth_challenge cell
914
            buf.extend_from_slice(AUTHCHALLENGE);
915
            // netinfo cell -- quite minimal.
916
            add_padded(&mut buf, NETINFO_PREFIX);
917
            let mb = MsgBuf::new(&buf[..]);
918
            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
919
            let unverified = handshake.connect(|| now).await?;
920

            
921
            assert_eq!(unverified.link_protocol(), 5);
922
            // No timestamp in the NETINFO, so no skew.
923
            assert_eq!(unverified.clock_skew(), ClockSkew::None);
924

            
925
            // Try again with some padding.
926
            let mut buf = Vec::new();
927
            buf.extend_from_slice(VERSIONS);
928
            buf.extend_from_slice(NOCERTS);
929
            buf.extend_from_slice(VPADDING);
930
            buf.extend_from_slice(AUTHCHALLENGE);
931
            buf.extend_from_slice(VPADDING);
932
            add_padded(&mut buf, NETINFO_PREFIX_WITH_TIME);
933
            let mb = MsgBuf::new(&buf[..]);
934
            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
935
            let unverified = handshake.connect(|| now).await?;
936
            // Correct timestamp in the NETINFO, so no skew.
937
            assert_eq!(unverified.clock_skew(), ClockSkew::None);
938

            
939
            // Now pretend our clock is fast.
940
            let now2 = now + Duration::from_secs(3600);
941
            let mb = MsgBuf::new(&buf[..]);
942
            let handshake = ClientInitiatorHandshake::new(mb, None, rt.clone(), fake_mq());
943
            let unverified = handshake.connect(|| now2).await?;
944
            assert_eq!(
945
                unverified.clock_skew(),
946
                ClockSkew::Fast(Duration::from_secs(3600))
947
            );
948

            
949
            Ok(())
950
        })
951
    }
952

            
953
    async fn connect_err<T: Into<Vec<u8>>, S>(input: T, sleep_prov: S) -> Error
954
    where
955
        S: CoarseTimeProvider + SleepProvider,
956
    {
957
        let mb = MsgBuf::new(input);
958
        let handshake = ClientInitiatorHandshake::new(mb, None, sleep_prov, fake_mq());
959
        handshake.connect(SystemTime::get).await.err().unwrap()
960
    }
961

            
962
    #[test]
963
    fn connect_badver() {
964
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
965
            let err = connect_err(&b"HTTP://"[..], rt.clone()).await;
966
            assert!(matches!(err, Error::HandshakeProto(_)));
967
            assert_eq!(
968
                format!("{}", err),
969
                "Handshake protocol violation: Invalid CircID in variable cell"
970
            );
971

            
972
            let err = connect_err(&hex!("0000 07 0004 1234 ffff")[..], rt.clone()).await;
973
            assert!(matches!(err, Error::HandshakeProto(_)));
974
            assert_eq!(
975
                format!("{}", err),
976
                "Handshake protocol violation: No shared link protocols"
977
            );
978
        });
979
    }
980

            
981
    #[test]
982
    fn connect_cellparse() {
983
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
984
            let mut buf = Vec::new();
985
            buf.extend_from_slice(VERSIONS);
986
            // Here's a certs cell that will fail.
987
            buf.extend_from_slice(&hex!("00000000 81 0001 01")[..]);
988
            let err = connect_err(buf, rt.clone()).await;
989
            assert!(matches!(err, Error::HandshakeProto { .. }));
990
        });
991
    }
992

            
993
    #[test]
994
    fn connect_duplicates() {
995
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
996
            let mut buf = Vec::new();
997
            buf.extend_from_slice(VERSIONS);
998
            buf.extend_from_slice(NOCERTS);
999
            buf.extend_from_slice(NOCERTS);
            add_netinfo(&mut buf);
            let err = connect_err(buf, rt.clone()).await;
            assert!(matches!(err, Error::HandshakeProto(_)));
            assert_eq!(
                format!("{}", err),
                "Handshake protocol violation: Expected [VPADDING, AUTH_CHALLENGE] cell, but received CERTS cell instead"
            );
            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(buf, rt.clone()).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 {
            let mut buf = Vec::new();
            buf.extend_from_slice(VERSIONS);
            add_netinfo(&mut buf);
            let err = connect_err(buf, rt.clone()).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 {
            let mut buf = Vec::new();
            buf.extend_from_slice(VERSIONS);
            buf.extend_from_slice(NOCERTS);
            let err = connect_err(buf, rt.clone()).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 {
            let mut buf = Vec::new();
            buf.extend_from_slice(VERSIONS);
            // here's a create cell.
            add_padded(&mut buf, &hex!("00000001 01")[..]);
            let err = connect_err(buf, rt.clone()).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"
            );
        });
    }
    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"
        );
    }
    /// 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 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])),
                relay_ids: RelayIds::empty(),
                rsa_id_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
        });
    }
}