1
//! Implementations for the channel handshake
2

            
3
use asynchronous_codec;
4
use futures::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
5
use futures::sink::SinkExt;
6
use futures::stream::StreamExt;
7
use tor_cell::restricted_msg;
8
use tor_error::internal;
9

            
10
use crate::channel::codec::{self, ChannelCodec, CodecError};
11
use crate::channel::UniqId;
12
use crate::memquota::ChannelAccount;
13
use crate::util::skew::ClockSkew;
14
use crate::{Error, Result};
15
use tor_cell::chancell::{msg, ChanCmd, ChanMsg};
16
use tor_rtcompat::{CoarseTimeProvider, SleepProvider, StreamOps};
17

            
18
use std::net::SocketAddr;
19
use std::sync::Arc;
20
use std::time::SystemTime;
21

            
22
use tor_bytes::Reader;
23
use tor_linkspec::{ChanTarget, ChannelMethod, OwnedChanTargetBuilder, RelayIds};
24
use tor_llcrypto as ll;
25
use tor_llcrypto::pk::ed25519::Ed25519Identity;
26
use tor_llcrypto::pk::rsa::RsaIdentity;
27

            
28
use digest::Digest;
29

            
30
use super::CellFrame;
31

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

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

            
37
/// A raw client channel on which nothing has been done.
38
pub struct OutboundClientHandshake<
39
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
40
    S: CoarseTimeProvider + SleepProvider,
41
> {
42
    /// Runtime handle (insofar as we need it)
43
    sleep_prov: S,
44

            
45
    /// Memory quota account
46
    memquota: ChannelAccount,
47

            
48
    /// Underlying TLS stream.
49
    ///
50
    /// (We don't enforce that this is actually TLS, but if it isn't, the
51
    /// connection won't be secure.)
52
    tls: T,
53

            
54
    /// Declared target method for this channel, if any.
55
    target_method: Option<ChannelMethod>,
56

            
57
    /// Logging identifier for this stream.  (Used for logging only.)
58
    unique_id: UniqId,
59
}
60

            
61
/// A client channel on which versions have been negotiated and the
62
/// relay's handshake has been read, but where the certs have not
63
/// been checked.
64
pub struct UnverifiedChannel<
65
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
66
    S: CoarseTimeProvider + SleepProvider,
67
> {
68
    /// Runtime handle (insofar as we need it)
69
    sleep_prov: S,
70
    /// Memory quota account
71
    memquota: ChannelAccount,
72
    /// The negotiated link protocol.  Must be a member of LINK_PROTOCOLS
73
    link_protocol: u16,
74
    /// The Source+Sink on which we're reading and writing cells.
75
    tls: CellFrame<T>,
76
    /// The certs cell that we got from the relay.
77
    certs_cell: msg::Certs,
78
    /// Declared target method for this channel, if any.
79
    target_method: Option<ChannelMethod>,
80
    /// The netinfo cell that we got from the relay.
81
    #[allow(dead_code)] // Relays will need this.
82
    netinfo_cell: msg::Netinfo,
83
    /// How much clock skew did we detect in this handshake?
84
    ///
85
    /// This value is _unauthenticated_, since we have not yet checked whether
86
    /// the keys in the handshake are the ones we expected.
87
    clock_skew: ClockSkew,
88
    /// Logging identifier for this stream.  (Used for logging only.)
89
    unique_id: UniqId,
90
}
91

            
92
/// A client channel on which versions have been negotiated,
93
/// relay's handshake has been read, but the client has not yet
94
/// finished the handshake.
95
///
96
/// This type is separate from UnverifiedChannel, since finishing the
97
/// handshake requires a bunch of CPU, and you might want to do it as
98
/// a separate task or after a yield.
99
pub struct VerifiedChannel<
100
    T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
101
    S: CoarseTimeProvider + SleepProvider,
102
> {
103
    /// Runtime handle (insofar as we need it)
104
    sleep_prov: S,
105
    /// Memory quota account
106
    memquota: ChannelAccount,
107
    /// The negotiated link protocol.
108
    link_protocol: u16,
109
    /// The Source+Sink on which we're reading and writing cells.
110
    tls: CellFrame<T>,
111
    /// Declared target method for this stream, if any.
112
    target_method: Option<ChannelMethod>,
113
    /// Logging identifier for this stream.  (Used for logging only.)
114
    unique_id: UniqId,
115
    /// Validated Ed25519 identity for this peer.
116
    ed25519_id: Ed25519Identity,
117
    /// Validated RSA identity for this peer.
118
    rsa_id: RsaIdentity,
119
    /// Authenticated clock skew for this peer.
120
    clock_skew: ClockSkew,
121
}
122

            
123
restricted_msg! {
124
    /// A restricted subset of ChanMsg that can arrive during a handshake.
125
    ///
126
    /// (These are messages that come after the VERSIONS cell, up to and
127
    /// including the NETINFO.)
128
    ///
129
    /// Note that unrecognized message types (ones not yet implemented in Arti)
130
    /// cause an error, rather than getting ignored.  That's intentional: if we
131
    /// start to allow them in the future, we should negotiate a new Channel
132
    /// protocol for the VERSIONS cell.
133
    #[derive(Clone,Debug)]
134
    enum HandshakeMsg : ChanMsg {
135
        Padding,
136
        Vpadding,
137
        AuthChallenge,
138
        Certs,
139
        Netinfo
140
    }
141
}
142

            
143
/// Convert a CodecError to an Error, under the context that it occurs while
144
/// doing a channel handshake.
145
4
fn codec_err_to_handshake(err: CodecError) -> Error {
146
4
    match err {
147
        CodecError::Io(e) => Error::HandshakeIoErr(Arc::new(e)),
148
4
        CodecError::DecCell(e) => {
149
4
            Error::HandshakeProto(format!("Invalid cell on handshake: {}", e))
150
        }
151
        CodecError::EncCell(e) => Error::from_cell_enc(e, "cell on handshake"),
152
    }
153
4
}
154

            
155
impl<
156
        T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
157
        S: CoarseTimeProvider + SleepProvider,
158
    > OutboundClientHandshake<T, S>
159
{
160
    /// Construct a new OutboundClientHandshake.
161
26
    pub(crate) fn new(
162
26
        tls: T,
163
26
        target_method: Option<ChannelMethod>,
164
26
        sleep_prov: S,
165
26
        memquota: ChannelAccount,
166
26
    ) -> Self {
167
26
        Self {
168
26
            tls,
169
26
            target_method,
170
26
            unique_id: UniqId::new(),
171
26
            sleep_prov,
172
26
            memquota,
173
26
        }
174
26
    }
175

            
176
    /// Negotiate a link protocol version with the relay, and read
177
    /// the relay's handshake information.
178
    ///
179
    /// Takes a function that reports the current time.  In theory, this can just be
180
    /// `SystemTime::now()`.
181
24
    pub async fn connect<F>(mut self, now_fn: F) -> Result<UnverifiedChannel<T, S>>
182
24
    where
183
24
        F: FnOnce() -> SystemTime,
184
24
    {
185
        /// Helper: wrap an IoError as a HandshakeIoErr.
186
        fn io_err_to_handshake(err: std::io::Error) -> Error {
187
            Error::HandshakeIoErr(Arc::new(err))
188
        }
189

            
190
24
        match &self.target_method {
191
2
            Some(method) => debug!(
192
                stream_id = %self.unique_id,
193
                "starting Tor handshake with {:?}",
194
                method
195
            ),
196
22
            None => debug!(stream_id = %self.unique_id, "starting Tor handshake"),
197
        }
198
24
        trace!(stream_id = %self.unique_id, "sending versions");
199
        // Send versions cell
200
        {
201
24
            let my_versions = msg::Versions::new(LINK_PROTOCOLS)
202
24
                .map_err(|e| Error::from_cell_enc(e, "versions message"))?;
203
24
            self.tls
204
24
                .write_all(
205
24
                    &my_versions
206
24
                        .encode_for_handshake()
207
24
                        .map_err(|e| Error::from_cell_enc(e.into(), "versions message"))?,
208
                )
209
24
                .await
210
24
                .map_err(io_err_to_handshake)?;
211
24
            self.tls.flush().await.map_err(io_err_to_handshake)?;
212
        }
213
24
        let versions_flushed_at = coarsetime::Instant::now();
214
24
        let versions_flushed_wallclock = now_fn();
215
24

            
216
24
        // Get versions cell.
217
24
        trace!(stream_id = %self.unique_id, "waiting for versions");
218
22
        let their_versions: msg::Versions = {
219
            // TODO: this could be turned into another function, I suppose.
220
24
            let mut hdr = [0_u8; 5];
221
24
            let not_relay = || {
222
2
                Err(Error::HandshakeProto(
223
2
                    "Doesn't seem to be a tor relay".into(),
224
2
                ))
225
2
            };
226
24
            match self.tls.read_exact(&mut hdr).await {
227
                Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => return not_relay(),
228
24
                otherwise => otherwise,
229
24
            }
230
24
            .map_err(io_err_to_handshake)?;
231
24
            if hdr[0..3] != [0, 0, ChanCmd::VERSIONS.into()] {
232
2
                return not_relay();
233
22
            }
234
22
            let msglen = u16::from_be_bytes(
235
22
                hdr[3..5]
236
22
                    .try_into()
237
22
                    .expect("Two-byte field was not two bytes!?"),
238
22
            );
239
22
            let mut msg = vec![0; msglen as usize];
240
22
            self.tls
241
22
                .read_exact(&mut msg)
242
22
                .await
243
22
                .map_err(io_err_to_handshake)?;
244
22
            let mut reader = Reader::from_slice(&msg);
245
22
            reader
246
22
                .extract()
247
22
                .map_err(|e| Error::from_bytes_err(e, "versions cell"))?
248
        };
249
22
        trace!(stream_id = %self.unique_id, "received {:?}", their_versions);
250

            
251
        // Determine which link protocol we negotiated.
252
22
        let link_protocol = their_versions
253
22
            .best_shared_link_protocol(LINK_PROTOCOLS)
254
22
            .ok_or_else(|| Error::HandshakeProto("No shared link protocols".into()))?;
255
20
        trace!(stream_id = %self.unique_id, "negotiated version {}", link_protocol);
256

            
257
        // Now we can switch to using a "Framed". We can ignore the
258
        // AsyncRead/AsyncWrite aspects of the tls, and just treat it
259
        // as a stream and a sink for cells.
260
20
        let codec = ChannelCodec::<HandshakeMsg, HandshakeMsg>::new(link_protocol);
261
20
        let mut tls = asynchronous_codec::Framed::new(self.tls, codec);
262
20

            
263
20
        // Read until we have the netinfo cells.
264
20
        let mut certs: Option<msg::Certs> = None;
265
20
        let mut netinfo: Option<(msg::Netinfo, coarsetime::Instant)> = None;
266
20
        let mut seen_authchallenge = false;
267
20

            
268
20
        // Loop: reject duplicate and unexpected cells
269
20
        trace!(stream_id = %self.unique_id, "waiting for rest of handshake.");
270
48
        while let Some(m) = tls.next().await {
271
            use HandshakeMsg::*;
272
46
            let (_, m) = m.map_err(codec_err_to_handshake)?.into_circid_and_msg();
273
42
            trace!(stream_id = %self.unique_id, "received a {} cell.", m.cmd());
274
42
            match m {
275
                // Are these technically allowed?
276
8
                Padding(_) | Vpadding(_) => (),
277
                // Clients don't care about AuthChallenge
278
                AuthChallenge(_) => {
279
8
                    if seen_authchallenge {
280
2
                        return Err(Error::HandshakeProto("Duplicate authchallenge cell".into()));
281
6
                    }
282
6
                    seen_authchallenge = true;
283
                }
284
16
                Certs(c) => {
285
16
                    if certs.is_some() {
286
2
                        return Err(Error::HandshakeProto("Duplicate certs cell".into()));
287
14
                    }
288
14
                    certs = Some(c);
289
                }
290
10
                Netinfo(n) => {
291
10
                    if netinfo.is_some() {
292
                        // This should be impossible, since we would
293
                        // exit this loop on the first netinfo cell.
294
                        return Err(Error::from(internal!(
295
                            "Somehow tried to record a duplicate NETINFO cell"
296
                        )));
297
10
                    }
298
10
                    netinfo = Some((n, coarsetime::Instant::now()));
299
10
                    break;
300
                }
301
            }
302
        }
303

            
304
        // If we have certs and netinfo, we can finish authenticating.
305
12
        match (certs, netinfo) {
306
2
            (Some(_), None) => Err(Error::HandshakeProto(
307
2
                "Missing netinfo or closed stream".into(),
308
2
            )),
309
2
            (None, _) => Err(Error::HandshakeProto("Missing certs cell".into())),
310
8
            (Some(certs_cell), Some((netinfo_cell, netinfo_rcvd_at))) => {
311
8
                trace!(stream_id = %self.unique_id, "received handshake, ready to verify.");
312
                // Try to compute our clock skew.  It won't be authenticated
313
                // yet, since we haven't checked the certificates.
314
8
                let clock_skew = if let Some(netinfo_timestamp) = netinfo_cell.timestamp() {
315
6
                    let delay = netinfo_rcvd_at - versions_flushed_at;
316
6
                    ClockSkew::from_handshake_timestamps(
317
6
                        versions_flushed_wallclock,
318
6
                        netinfo_timestamp,
319
6
                        delay.into(),
320
6
                    )
321
                } else {
322
2
                    ClockSkew::None
323
                };
324
8
                Ok(UnverifiedChannel {
325
8
                    link_protocol,
326
8
                    tls: codec::change_message_types(tls),
327
8
                    certs_cell,
328
8
                    netinfo_cell,
329
8
                    clock_skew,
330
8
                    target_method: self.target_method.take(),
331
8
                    unique_id: self.unique_id,
332
8
                    sleep_prov: self.sleep_prov.clone(),
333
8
                    memquota: self.memquota.clone(),
334
8
                })
335
            }
336
        }
337
24
    }
338
}
339

            
340
impl<
341
        T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
342
        S: CoarseTimeProvider + SleepProvider,
343
    > UnverifiedChannel<T, S>
344
{
345
    /// Return the reported clock skew from this handshake.
346
    ///
347
    /// Note that the skew reported by this function might not be "true": the
348
    /// relay might have its clock set wrong, or it might be lying to us.
349
    ///
350
    /// The clock skew reported here is not yet authenticated; if you need to
351
    /// make sure that the skew is authenticated, use
352
    /// [`Channel::clock_skew`](super::Channel::clock_skew) instead.
353
8
    pub fn clock_skew(&self) -> ClockSkew {
354
8
        self.clock_skew
355
8
    }
356

            
357
    /// Validate the certificates and keys in the relay's handshake.
358
    ///
359
    /// 'peer' is the peer that we want to make sure we're connecting to.
360
    ///
361
    /// 'peer_cert' is the x.509 certificate that the peer presented during
362
    /// its TLS handshake (ServerHello).
363
    ///
364
    /// 'now' is the time at which to check that certificates are
365
    /// valid.  `None` means to use the current time. It can be used
366
    /// for testing to override the current view of the time.
367
    ///
368
    /// This is a separate function because it's likely to be somewhat
369
    /// CPU-intensive.
370
2
    pub fn check<U: ChanTarget + ?Sized>(
371
2
        self,
372
2
        peer: &U,
373
2
        peer_cert: &[u8],
374
2
        now: Option<std::time::SystemTime>,
375
2
    ) -> Result<VerifiedChannel<T, S>> {
376
2
        let peer_cert_sha256 = ll::d::Sha256::digest(peer_cert);
377
2
        self.check_internal(peer, &peer_cert_sha256[..], now)
378
2
    }
379

            
380
    /// Same as `check`, but takes the SHA256 hash of the peer certificate,
381
    /// since that is all we use.
382
24
    fn check_internal<U: ChanTarget + ?Sized>(
383
24
        self,
384
24
        peer: &U,
385
24
        peer_cert_sha256: &[u8],
386
24
        now: Option<SystemTime>,
387
24
    ) -> Result<VerifiedChannel<T, S>> {
388
        use tor_cert::CertType;
389
        use tor_checkable::*;
390

            
391
        /// Helper: given a time-bound input, give a result reflecting its
392
        /// validity at `now`, and the inner object.
393
        ///
394
        /// We use this here because we want to validate the whole handshake
395
        /// regardless of whether the certs are expired, so we can determine
396
        /// whether we got a plausible handshake with a skewed partner, or
397
        /// whether the handshake is definitely bad.
398
44
        fn check_timeliness<C, T>(checkable: C, now: SystemTime, skew: ClockSkew) -> (Result<()>, T)
399
44
        where
400
44
            C: Timebound<T, Error = TimeValidityError>,
401
44
        {
402
44
            let status = checkable.is_valid_at(&now).map_err(|e| match (e, skew) {
403
                (TimeValidityError::Expired(expired_by), ClockSkew::Fast(skew))
404
                    if expired_by < skew =>
405
                {
406
                    Error::HandshakeCertsExpired { expired_by }
407
                }
408
                // As it so happens, we don't need to check for this case, since the certs in use
409
                // here only have an expiration time in them.
410
                // (TimeValidityError::NotYetValid(_), ClockSkew::Slow(_)) => todo!(),
411
                (_, _) => Error::HandshakeProto("Certificate expired or not yet valid".into()),
412
44
            });
413
44
            let cert = checkable.dangerously_assume_timely();
414
44
            (status, cert)
415
44
        }
416
        // Replace 'now' with the real time to use.
417
24
        let now = now.unwrap_or_else(SystemTime::now);
418
24

            
419
24
        // We need to check the following lines of authentication:
420
24
        //
421
24
        // First, to bind the ed identity to the channel.
422
24
        //    peer.ed_identity() matches the key in...
423
24
        //    IDENTITY_V_SIGNING cert, which signs...
424
24
        //    SIGNING_V_TLS_CERT cert, which signs peer_cert.
425
24
        //
426
24
        // Second, to bind the rsa identity to the ed identity:
427
24
        //    peer.rsa_identity() matches the key in...
428
24
        //    the x.509 RSA identity certificate (type 2), which signs...
429
24
        //    the RSA->Ed25519 crosscert (type 7), which signs...
430
24
        //    peer.ed_identity().
431
24

            
432
24
        let c = &self.certs_cell;
433
        /// Helper: get a cert from a Certs cell, and convert errors appropriately.
434
114
        fn get_cert(
435
114
            certs: &tor_cell::chancell::msg::Certs,
436
114
            tp: CertType,
437
114
        ) -> Result<tor_cert::KeyUnknownCert> {
438
114
            match certs.parse_ed_cert(tp) {
439
108
                Ok(c) => Ok(c),
440
6
                Err(tor_cell::Error::ChanProto(e)) => Err(Error::HandshakeProto(e)),
441
                Err(e) => Err(Error::HandshakeProto(e.to_string())),
442
            }
443
114
        }
444

            
445
24
        let id_sk = get_cert(c, CertType::IDENTITY_V_SIGNING)?;
446
20
        let sk_tls = get_cert(c, CertType::SIGNING_V_TLS_CERT)?;
447

            
448
18
        let mut sigs = Vec::new();
449

            
450
        // Part 1: validate ed25519 stuff.
451
        //
452
        // (We are performing our timeliness checks now, but not inspecting them
453
        // until later in the function, so that we can distinguish failures that
454
        // might be caused by clock skew from failures that are definitely not
455
        // clock skew.)
456

            
457
        // Check the identity->signing cert
458
18
        let (id_sk, id_sk_sig) = id_sk
459
18
            .should_have_signing_key()
460
18
            .map_err(Error::HandshakeCertErr)?
461
18
            .dangerously_split()
462
18
            .map_err(Error::HandshakeCertErr)?;
463
18
        sigs.push(&id_sk_sig);
464
18
        let (id_sk_timeliness, id_sk) = check_timeliness(id_sk, now, self.clock_skew);
465

            
466
        // Take the identity key from the identity->signing cert
467
18
        let identity_key = id_sk.signing_key().ok_or_else(|| {
468
            Error::HandshakeProto("Missing identity key in identity->signing cert".into())
469
18
        })?;
470

            
471
        // Take the signing key from the identity->signing cert
472
18
        let signing_key = id_sk.subject_key().as_ed25519().ok_or_else(|| {
473
            Error::HandshakeProto("Bad key type in identity->signing cert".into())
474
18
        })?;
475

            
476
        // Now look at the signing->TLS cert and check it against the
477
        // peer certificate.
478
18
        let (sk_tls, sk_tls_sig) = sk_tls
479
18
            .should_be_signed_with(signing_key)
480
18
            .map_err(Error::HandshakeCertErr)?
481
18
            .dangerously_split()
482
18
            .map_err(Error::HandshakeCertErr)?;
483
18
        sigs.push(&sk_tls_sig);
484
18
        let (sk_tls_timeliness, sk_tls) = check_timeliness(sk_tls, now, self.clock_skew);
485
18

            
486
18
        if peer_cert_sha256 != sk_tls.subject_key().as_bytes() {
487
2
            return Err(Error::HandshakeProto(
488
2
                "Peer cert did not authenticate TLS cert".into(),
489
2
            ));
490
16
        }
491
16

            
492
16
        // Batch-verify the ed25519 certificates in this handshake.
493
16
        //
494
16
        // In theory we could build a list of _all_ the certificates here
495
16
        // and call pk::validate_all_sigs() instead, but that doesn't gain
496
16
        // any performance.
497
16
        if !ll::pk::ed25519::validate_batch(&sigs[..]) {
498
2
            return Err(Error::HandshakeProto(
499
2
                "Invalid ed25519 signature in handshake".into(),
500
2
            ));
501
14
        }
502

            
503
        // Part 2: validate rsa stuff.
504

            
505
        // What is the RSA identity key, according to the X.509 certificate
506
        // in which it is self-signed?
507
        //
508
        // (We don't actually check this self-signed certificate, and we use
509
        // a kludge to extract the RSA key)
510
14
        let pkrsa = c
511
14
            .cert_body(CertType::RSA_ID_X509)
512
14
            .and_then(ll::util::x509_extract_rsa_subject_kludge)
513
14
            .ok_or_else(|| Error::HandshakeProto("Couldn't find RSA identity key".into()))?;
514

            
515
        // Now verify the RSA identity -> Ed Identity crosscert.
516
        //
517
        // This proves that the RSA key vouches for the Ed key.  Note that
518
        // the Ed key does not vouch for the RSA key: The RSA key is too
519
        // weak.
520
12
        let rsa_cert = c
521
12
            .cert_body(CertType::RSA_ID_V_IDENTITY)
522
12
            .ok_or_else(|| Error::HandshakeProto("No RSA->Ed crosscert".into()))?;
523
10
        let rsa_cert = tor_cert::rsa::RsaCrosscert::decode(rsa_cert)
524
10
            .map_err(|e| Error::from_bytes_err(e, "RSA identity cross-certificate"))?
525
10
            .check_signature(&pkrsa)
526
10
            .map_err(|_| Error::HandshakeProto("Bad RSA->Ed crosscert signature".into()))?;
527
8
        let (rsa_cert_timeliness, rsa_cert) = check_timeliness(rsa_cert, now, self.clock_skew);
528
8

            
529
8
        if !rsa_cert.subject_key_matches(identity_key) {
530
            return Err(Error::HandshakeProto(
531
                "RSA->Ed crosscert certifies incorrect key".into(),
532
            ));
533
8
        }
534
8

            
535
8
        let rsa_id = pkrsa.to_rsa_identity();
536
8

            
537
8
        trace!(
538
            stream_id = %self.unique_id,
539
            "Validated identity as {} [{}]",
540
            identity_key,
541
            rsa_id
542
        );
543

            
544
        // Now that we've done all the verification steps on the
545
        // certificates, we know who we are talking to.  It's time to
546
        // make sure that the peer we are talking to is the peer we
547
        // actually wanted.
548
        //
549
        // We do this _last_, since "this is the wrong peer" is
550
        // usually a different situation than "this peer couldn't even
551
        // identify itself right."
552

            
553
8
        let actual_identity = RelayIds::builder()
554
8
            .ed_identity(*identity_key)
555
8
            .rsa_identity(rsa_id)
556
8
            .build()
557
8
            .expect("Unable to build RelayIds");
558
8

            
559
8
        // We enforce that the relay proved that it has every ID that we wanted:
560
8
        // it may also have additional IDs that we didn't ask for.
561
8
        match super::check_id_match_helper(&actual_identity, peer) {
562
4
            Err(Error::ChanMismatch(msg)) => Err(Error::HandshakeProto(msg)),
563
4
            other => other,
564
4
        }?;
565

            
566
        // If we reach this point, the clock skew might be may now be considered
567
        // authenticated: The certificates are what we wanted, and everything
568
        // was well signed.
569
        //
570
        // The only remaining concern is certificate timeliness.  If the
571
        // certificates are expired by an amount that is too large for the
572
        // declared clock skew to explain, then  we'll return
573
        // `Error::HandshakeProto`: in that case the clock skew is _not_
574
        // authenticated.  But if the certs are only expired by a little bit,
575
        // we'll reject the handshake with `Error::HandshakeCertsExpired`, and
576
        // the caller can trust the clock skew.
577
        //
578
        // We note expired certs last, since we only want to return
579
        // `HandshakeCertsExpired` when there are no other errors.
580
4
        id_sk_timeliness?;
581
4
        sk_tls_timeliness?;
582
4
        rsa_cert_timeliness?;
583

            
584
4
        Ok(VerifiedChannel {
585
4
            link_protocol: self.link_protocol,
586
4
            tls: self.tls,
587
4
            unique_id: self.unique_id,
588
4
            target_method: self.target_method,
589
4
            ed25519_id: *identity_key,
590
4
            rsa_id,
591
4
            clock_skew: self.clock_skew,
592
4
            sleep_prov: self.sleep_prov,
593
4
            memquota: self.memquota,
594
4
        })
595
24
    }
596
}
597

            
598
impl<
599
        T: AsyncRead + AsyncWrite + StreamOps + Send + Unpin + 'static,
600
        S: CoarseTimeProvider + SleepProvider,
601
    > VerifiedChannel<T, S>
602
{
603
    /// Send a 'Netinfo' message to the relay to finish the handshake,
604
    /// and create an open channel and reactor.
605
    ///
606
    /// The channel is used to send cells, and to create outgoing circuits.
607
    /// The reactor is used to route incoming messages to their appropriate
608
    /// circuit.
609
4
    pub async fn finish(mut self) -> Result<(Arc<super::Channel>, super::reactor::Reactor<S>)> {
610
4
        // We treat a completed channel -- that is to say, one where the
611
4
        // authentication is finished -- as incoming traffic.
612
4
        //
613
4
        // TODO: conceivably we should remember the time when we _got_ the
614
4
        // final cell on the handshake, and update the channel completion
615
4
        // time to be no earlier than _that_ timestamp.
616
4
        crate::note_incoming_traffic();
617
4
        trace!(stream_id = %self.unique_id, "Sending netinfo cell.");
618

            
619
        // We do indeed want the real IP here, regardless of whether the
620
        // ChannelMethod is Direct connection or not.  The role of the IP in a
621
        // NETINFO cell is to tell our peer what address we believe they had, so
622
        // that they can better notice MITM attacks and such.
623
4
        let peer_ip = self
624
4
            .target_method
625
4
            .as_ref()
626
4
            .and_then(ChannelMethod::socket_addrs)
627
4
            .and_then(|addrs| addrs.first())
628
4
            .map(SocketAddr::ip);
629
4
        let netinfo = msg::Netinfo::from_client(peer_ip);
630
4
        self.tls
631
4
            .send(netinfo.into())
632
4
            .await
633
4
            .map_err(codec_err_to_handshake)?;
634

            
635
4
        debug!(
636
            stream_id = %self.unique_id,
637
            "Completed handshake with {} [{}]",
638
            self.ed25519_id, self.rsa_id
639
        );
640

            
641
        // Grab a new handle on which we can apply StreamOps (needed for KIST).
642
        // On Unix platforms, this handle is a wrapper over the fd of the socket.
643
        //
644
        // Note: this is necessary because after `StreamExit::split()`,
645
        // we no longer have access to the underlying stream
646
        // or its StreamOps implementation.
647
4
        let stream_ops = self.tls.new_handle();
648
4
        let (tls_sink, tls_stream) = self.tls.split();
649
4

            
650
4
        let mut peer_builder = OwnedChanTargetBuilder::default();
651
4
        if let Some(target_method) = self.target_method {
652
4
            if let Some(addrs) = target_method.socket_addrs() {
653
4
                peer_builder.addrs(addrs.to_owned());
654
4
            }
655
4
            peer_builder.method(target_method);
656
        }
657
4
        let peer_id = peer_builder
658
4
            .ed_identity(self.ed25519_id)
659
4
            .rsa_identity(self.rsa_id)
660
4
            .build()
661
4
            .expect("OwnedChanTarget builder failed");
662
4

            
663
4
        super::Channel::new(
664
4
            self.link_protocol,
665
4
            Box::new(tls_sink),
666
4
            Box::new(tls_stream),
667
4
            stream_ops,
668
4
            self.unique_id,
669
4
            peer_id,
670
4
            self.clock_skew,
671
4
            self.sleep_prov,
672
4
            self.memquota,
673
4
        )
674
4
    }
675
}
676

            
677
#[cfg(test)]
678
pub(super) mod test {
679
    #![allow(clippy::unwrap_used)]
680
    use hex_literal::hex;
681
    use regex::Regex;
682
    use std::time::{Duration, SystemTime};
683

            
684
    use super::*;
685
    use crate::channel::codec::test::MsgBuf;
686
    use crate::util::fake_mq;
687
    use crate::Result;
688
    use tor_cell::chancell::msg;
689
    use tor_linkspec::OwnedChanTarget;
690
    use tor_rtcompat::{PreferredRuntime, Runtime};
691

            
692
    const VERSIONS: &[u8] = &hex!("0000 07 0006 0003 0004 0005");
693
    // no certificates in this cell, but connect() doesn't care.
694
    const NOCERTS: &[u8] = &hex!("00000000 81 0001 00");
695
    const NETINFO_PREFIX: &[u8] = &hex!(
696
        "00000000 08 00000000
697
         04 04 7f 00 00 02
698
         01
699
         04 04 7f 00 00 03"
700
    );
701
    const NETINFO_PREFIX_WITH_TIME: &[u8] = &hex!(
702
        "00000000 08 48949290
703
         04 04 7f 00 00 02
704
         01
705
         04 04 7f 00 00 03"
706
    );
707
    const AUTHCHALLENGE: &[u8] = &hex!(
708
        "00000000 82 0026
709
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
710
         FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
711
         0002 0003 00ff"
712
    );
713

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

            
716
    fn add_padded(buf: &mut Vec<u8>, cell: &[u8]) {
717
        let len_prev = buf.len();
718
        buf.extend_from_slice(cell);
719
        buf.resize(len_prev + 514, 0);
720
    }
721
    fn add_netinfo(buf: &mut Vec<u8>) {
722
        add_padded(buf, NETINFO_PREFIX);
723
    }
724

            
725
    #[test]
726
    fn connect_ok() -> Result<()> {
727
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
728
            let now = humantime::parse_rfc3339("2008-08-02T17:00:00Z").unwrap();
729
            let mut buf = Vec::new();
730
            // versions cell
731
            buf.extend_from_slice(VERSIONS);
732
            // certs cell -- no certs in it, but this function doesn't care.
733
            buf.extend_from_slice(NOCERTS);
734
            // netinfo cell -- quite minimal.
735
            add_padded(&mut buf, NETINFO_PREFIX);
736
            let mb = MsgBuf::new(&buf[..]);
737
            let handshake = OutboundClientHandshake::new(mb, None, rt.clone(), fake_mq());
738
            let unverified = handshake.connect(|| now).await?;
739

            
740
            assert_eq!(unverified.link_protocol, 5);
741
            // No timestamp in the NETINFO, so no skew.
742
            assert_eq!(unverified.clock_skew(), ClockSkew::None);
743

            
744
            // Try again with an authchallenge cell and some padding.
745
            let mut buf = Vec::new();
746
            buf.extend_from_slice(VERSIONS);
747
            buf.extend_from_slice(NOCERTS);
748
            buf.extend_from_slice(VPADDING);
749
            buf.extend_from_slice(AUTHCHALLENGE);
750
            buf.extend_from_slice(VPADDING);
751
            add_padded(&mut buf, NETINFO_PREFIX_WITH_TIME);
752
            let mb = MsgBuf::new(&buf[..]);
753
            let handshake = OutboundClientHandshake::new(mb, None, rt.clone(), fake_mq());
754
            let unverified = handshake.connect(|| now).await?;
755
            // Correct timestamp in the NETINFO, so no skew.
756
            assert_eq!(unverified.clock_skew(), ClockSkew::None);
757

            
758
            // Now pretend our clock is fast.
759
            let now2 = now + Duration::from_secs(3600);
760
            let mb = MsgBuf::new(&buf[..]);
761
            let handshake = OutboundClientHandshake::new(mb, None, rt.clone(), fake_mq());
762
            let unverified = handshake.connect(|| now2).await?;
763
            assert_eq!(
764
                unverified.clock_skew(),
765
                ClockSkew::Fast(Duration::from_secs(3600))
766
            );
767

            
768
            Ok(())
769
        })
770
    }
771

            
772
    async fn connect_err<T: Into<Vec<u8>>, S>(input: T, sleep_prov: S) -> Error
773
    where
774
        S: CoarseTimeProvider + SleepProvider,
775
    {
776
        let mb = MsgBuf::new(input);
777
        let handshake = OutboundClientHandshake::new(mb, None, sleep_prov, fake_mq());
778
        handshake.connect(SystemTime::now).await.err().unwrap()
779
    }
780

            
781
    #[test]
782
    fn connect_badver() {
783
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
784
            let err = connect_err(&b"HTTP://"[..], rt.clone()).await;
785
            assert!(matches!(err, Error::HandshakeProto(_)));
786
            assert_eq!(
787
                format!("{}", err),
788
                "Handshake protocol violation: Doesn't seem to be a tor relay"
789
            );
790

            
791
            let err = connect_err(&hex!("0000 07 0004 1234 ffff")[..], rt.clone()).await;
792
            assert!(matches!(err, Error::HandshakeProto(_)));
793
            assert_eq!(
794
                format!("{}", err),
795
                "Handshake protocol violation: No shared link protocols"
796
            );
797
        });
798
    }
799

            
800
    #[test]
801
    fn connect_cellparse() {
802
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
803
            let mut buf = Vec::new();
804
            buf.extend_from_slice(VERSIONS);
805
            // Here's a certs cell that will fail.
806
            buf.extend_from_slice(&hex!("00000000 81 0001 01")[..]);
807
            let err = connect_err(buf, rt.clone()).await;
808
            assert!(matches!(err, Error::HandshakeProto(_)));
809
        });
810
    }
811

            
812
    #[test]
813
    fn connect_duplicates() {
814
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
815
            let mut buf = Vec::new();
816
            buf.extend_from_slice(VERSIONS);
817
            buf.extend_from_slice(NOCERTS);
818
            buf.extend_from_slice(NOCERTS);
819
            add_netinfo(&mut buf);
820
            let err = connect_err(buf, rt.clone()).await;
821
            assert!(matches!(err, Error::HandshakeProto(_)));
822
            assert_eq!(
823
                format!("{}", err),
824
                "Handshake protocol violation: Duplicate certs cell"
825
            );
826

            
827
            let mut buf = Vec::new();
828
            buf.extend_from_slice(VERSIONS);
829
            buf.extend_from_slice(NOCERTS);
830
            buf.extend_from_slice(AUTHCHALLENGE);
831
            buf.extend_from_slice(AUTHCHALLENGE);
832
            add_netinfo(&mut buf);
833
            let err = connect_err(buf, rt.clone()).await;
834
            assert!(matches!(err, Error::HandshakeProto(_)));
835
            assert_eq!(
836
                format!("{}", err),
837
                "Handshake protocol violation: Duplicate authchallenge cell"
838
            );
839
        });
840
    }
841

            
842
    #[test]
843
    fn connect_missing_certs() {
844
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
845
            let mut buf = Vec::new();
846
            buf.extend_from_slice(VERSIONS);
847
            add_netinfo(&mut buf);
848
            let err = connect_err(buf, rt.clone()).await;
849
            assert!(matches!(err, Error::HandshakeProto(_)));
850
            assert_eq!(
851
                format!("{}", err),
852
                "Handshake protocol violation: Missing certs cell"
853
            );
854
        });
855
    }
856

            
857
    #[test]
858
    fn connect_missing_netinfo() {
859
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
860
            let mut buf = Vec::new();
861
            buf.extend_from_slice(VERSIONS);
862
            buf.extend_from_slice(NOCERTS);
863
            let err = connect_err(buf, rt.clone()).await;
864
            assert!(matches!(err, Error::HandshakeProto(_)));
865
            assert_eq!(
866
                format!("{}", err),
867
                "Handshake protocol violation: Missing netinfo or closed stream"
868
            );
869
        });
870
    }
871

            
872
    #[test]
873
    fn connect_misplaced_cell() {
874
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
875
            let mut buf = Vec::new();
876
            buf.extend_from_slice(VERSIONS);
877
            // here's a create cell.
878
            add_padded(&mut buf, &hex!("00000001 01")[..]);
879
            let err = connect_err(buf, rt.clone()).await;
880
            assert!(matches!(err, Error::HandshakeProto(_)));
881
            assert_eq!(
882
                format!("{}", err),
883
                "Handshake protocol violation: Invalid cell on handshake: Error while parsing channel cell"
884
            );
885
        });
886
    }
887

            
888
    fn make_unverified<R>(certs: msg::Certs, runtime: R) -> UnverifiedChannel<MsgBuf, R>
889
    where
890
        R: Runtime,
891
    {
892
        let localhost = std::net::IpAddr::V4(std::net::Ipv4Addr::LOCALHOST);
893
        let netinfo_cell = msg::Netinfo::from_client(Some(localhost));
894
        let clock_skew = ClockSkew::None;
895
        UnverifiedChannel {
896
            link_protocol: 4,
897
            tls: asynchronous_codec::Framed::new(MsgBuf::new(&b""[..]), ChannelCodec::new(4)),
898
            certs_cell: certs,
899
            netinfo_cell,
900
            clock_skew,
901
            target_method: None,
902
            unique_id: UniqId::new(),
903
            sleep_prov: runtime,
904
            memquota: fake_mq(),
905
        }
906
    }
907

            
908
    // Timestamp when the example certificates were all valid.
909
    fn cert_timestamp() -> SystemTime {
910
        use humantime::parse_rfc3339;
911
        parse_rfc3339("2020-09-26T18:01:20Z").unwrap()
912
    }
913

            
914
    fn certs_test<R>(
915
        certs: msg::Certs,
916
        when: Option<SystemTime>,
917
        peer_ed: &[u8],
918
        peer_rsa: &[u8],
919
        peer_cert_sha256: &[u8],
920
        runtime: &R,
921
    ) -> Result<VerifiedChannel<MsgBuf, R>>
922
    where
923
        R: Runtime,
924
    {
925
        let unver = make_unverified(certs, runtime.clone());
926
        let ed = Ed25519Identity::from_bytes(peer_ed).unwrap();
927
        let rsa = RsaIdentity::from_bytes(peer_rsa).unwrap();
928
        let chan = OwnedChanTarget::builder()
929
            .ed_identity(ed)
930
            .rsa_identity(rsa)
931
            .build()
932
            .unwrap();
933
        unver.check_internal(&chan, peer_cert_sha256, when)
934
    }
935

            
936
    // no certs at all!
937
    #[test]
938
    fn certs_none() {
939
        let rt = PreferredRuntime::create().unwrap();
940
        let err = certs_test(
941
            msg::Certs::new_empty(),
942
            None,
943
            &[0_u8; 32],
944
            &[0_u8; 20],
945
            &[0_u8; 128],
946
            &rt,
947
        )
948
        .err()
949
        .unwrap();
950
        assert_eq!(
951
            format!("{}", err),
952
            "Handshake protocol violation: Missing IDENTITY_V_SIGNING certificate"
953
        );
954
    }
955

            
956
    #[test]
957
    fn certs_good() {
958
        let rt = PreferredRuntime::create().unwrap();
959
        let mut certs = msg::Certs::new_empty();
960

            
961
        certs.push_cert_body(2.into(), certs::CERT_T2);
962
        certs.push_cert_body(5.into(), certs::CERT_T5);
963
        certs.push_cert_body(7.into(), certs::CERT_T7);
964
        certs.push_cert_body(4.into(), certs::CERT_T4);
965
        let res = certs_test(
966
            certs,
967
            Some(cert_timestamp()),
968
            certs::PEER_ED,
969
            certs::PEER_RSA,
970
            certs::PEER_CERT_DIGEST,
971
            &rt,
972
        );
973
        let _ = res.unwrap();
974
    }
975

            
976
    #[test]
977
    fn certs_missing() {
978
        let rt = PreferredRuntime::create().unwrap();
979
        let all_certs = [
980
            (2, certs::CERT_T2, "Couldn't find RSA identity key"),
981
            (7, certs::CERT_T7, "No RSA->Ed crosscert"),
982
            (4, certs::CERT_T4, "Missing IDENTITY_V_SIGNING certificate"),
983
            (5, certs::CERT_T5, "Missing SIGNING_V_TLS_CERT certificate"),
984
        ];
985

            
986
        for omit_idx in 0..4 {
987
            // build a certs cell with all but one certificate
988
            let mut certs = msg::Certs::new_empty();
989
            let mut expect_err = None;
990
            for (idx, (ctype, cert, err)) in all_certs.iter().enumerate() {
991
                if idx == omit_idx {
992
                    expect_err = Some(err);
993
                    continue;
994
                }
995

            
996
                certs.push_cert_body((*ctype).into(), &cert[..]);
997
            }
998
            let res = certs_test(
999
                certs,
                Some(cert_timestamp()),
                certs::PEER_ED,
                certs::PEER_RSA,
                certs::PEER_CERT_DIGEST,
                &rt,
            )
            .err()
            .unwrap();
            assert_eq!(
                format!("{}", res),
                format!("Handshake protocol violation: {}", expect_err.unwrap())
            );
        }
    }
    #[test]
    fn certs_wrongtarget() {
        let rt = PreferredRuntime::create().unwrap();
        let mut certs = msg::Certs::new_empty();
        certs.push_cert_body(2.into(), certs::CERT_T2);
        certs.push_cert_body(5.into(), certs::CERT_T5);
        certs.push_cert_body(7.into(), certs::CERT_T7);
        certs.push_cert_body(4.into(), certs::CERT_T4);
        let err = certs_test(
            certs.clone(),
            Some(cert_timestamp()),
            &[0x10; 32],
            certs::PEER_RSA,
            certs::PEER_CERT_DIGEST,
            &rt,
        )
        .err()
        .unwrap();
        let re = Regex::new(
            // identities might be scrubbed by safelog
            r"Identity .* does not match target .*",
        )
        .unwrap();
        assert!(re.is_match(&format!("{}", err)));
        let err = certs_test(
            certs.clone(),
            Some(cert_timestamp()),
            certs::PEER_ED,
            &[0x99; 20],
            certs::PEER_CERT_DIGEST,
            &rt,
        )
        .err()
        .unwrap();
        let re = Regex::new(
            // identities might be scrubbed by safelog
            r"Identity .* does not match target .*",
        )
        .unwrap();
        assert!(re.is_match(&format!("{}", err)));
        let err = certs_test(
            certs,
            Some(cert_timestamp()),
            certs::PEER_ED,
            certs::PEER_RSA,
            &[0; 32],
            &rt,
        )
        .err()
        .unwrap();
        assert_eq!(
            format!("{}", err),
            "Handshake protocol violation: Peer cert did not authenticate TLS cert"
        );
    }
    #[test]
    fn certs_badsig() {
        let rt = PreferredRuntime::create().unwrap();
        fn munge(inp: &[u8]) -> Vec<u8> {
            let mut v: Vec<u8> = inp.into();
            v[inp.len() - 1] ^= 0x10;
            v
        }
        let mut certs = msg::Certs::new_empty();
        certs.push_cert_body(2.into(), certs::CERT_T2);
        certs.push_cert_body(5.into(), munge(certs::CERT_T5)); // munge an ed signature
        certs.push_cert_body(7.into(), certs::CERT_T7);
        certs.push_cert_body(4.into(), certs::CERT_T4);
        let res = certs_test(
            certs,
            Some(cert_timestamp()),
            certs::PEER_ED,
            certs::PEER_RSA,
            certs::PEER_CERT_DIGEST,
            &rt,
        )
        .err()
        .unwrap();
        assert_eq!(
            format!("{}", res),
            "Handshake protocol violation: Invalid ed25519 signature in handshake"
        );
        let mut certs = msg::Certs::new_empty();
        certs.push_cert_body(2.into(), certs::CERT_T2);
        certs.push_cert_body(5.into(), certs::CERT_T5);
        certs.push_cert_body(7.into(), munge(certs::CERT_T7)); // munge an RSA signature
        certs.push_cert_body(4.into(), certs::CERT_T4);
        let res = certs_test(
            certs,
            Some(cert_timestamp()),
            certs::PEER_ED,
            certs::PEER_RSA,
            certs::PEER_CERT_DIGEST,
            &rt,
        )
        .err()
        .unwrap();
        assert_eq!(
            format!("{}", res),
            "Handshake protocol violation: Bad RSA->Ed crosscert signature"
        );
    }
    /// This module has a few certificates to play with. They're taken
    /// from a chutney network. They match those used in the CERTS
    /// cell test vector in the tor-cell crate.
    ///
    /// The names are taken from the type of the certificate.
    mod certs {
        use hex_literal::hex;
        pub(crate) const CERT_T2: &[u8] = &hex!("308201B930820122A0030201020208607C28BE6C390943300D06092A864886F70D01010B0500301F311D301B06035504030C147777772E74636A76356B766A646472322E636F6D301E170D3230303831303030303030305A170D3231303831303030303030305A301F311D301B06035504030C147777772E74636A76356B766A646472322E636F6D30819F300D06092A864886F70D010101050003818D0030818902818100D38B1E6CEB946E0DB0751F4CBACE3DCB9688B6C25304227B4710C35AFB73627E50500F5913E158B621802612D1C75827003703338375237552EB3CD3C12F6AB3604E60C1A2D26BB1FBAD206FF023969A90909D6A65A5458A5312C26EBD3A3DAD30302D4515CDCD264146AC18E6FC60A04BD3EC327F04294D96BA5AA25B464C3F0203010001300D06092A864886F70D01010B0500038181003BCE561EA7F95CC00B78AAB5D69573FF301C282A751D4A651921D042F1BECDBA24D918A6D8A5E138DC07BBA0B335478AE37ABD2C93A93932442AE9084329E846170FE0FC4A50AAFC804F311CC3CA4F41D845A7BA5901CBBC3E021E9794AAC70CE1F37B0A951592DB1B64F2B4AFB81AE52DBD9B6FEDE96A5FB8125EB6251EE50A");
        pub(crate) const CERT_T4: &[u8] = &hex!("01040006CC2A01F82294B866A31F01FC5D0DA8572850A9B929545C3266558D7D2316E3B74172B00100200400DCB604DB2034B00FD16986D4ADB9D16B21CB4E4457A33DEC0F538903683E96E9FF1A5203FA27F86EF7528D89A0845D2520166E340754FFEA2AAE0F612B7CE5DA094A0236CDAC45034B0B6842C18E7F6B51B93A3CF7E60663B8AD061C30A62602");
        pub(crate) const CERT_T5: &[u8] = &hex!("01050006C98A03B4FD606B64E4CBD466B8D76CB131069BAE6F3AA1878857C9F624E31D77A799B8007173E5F8068431D0D3F5EE16B4C9FFD59DF373E152A87281BAE744AA5FCF72171BF4B27C4E8FC1C6A9FC5CA11058BC49647063D7903CFD9F512F89099B27BC0C");
        pub(crate) const CERT_T7: &[u8] = &hex!("DCB604DB2034B00FD16986D4ADB9D16B21CB4E4457A33DEC0F538903683E96E90006DA3A805CF6006F9179066534DE6B45AD47A5C469063EE462762723396DC9F25452A0A52DA3F5087DD239F2A311F6B0D4DFEFF4ABD089DC3D0237A0ABAB19EB2045B91CDCAF04BE0A72D548A27BF2E77BD876ECFE5E1BE622350DA6BF31F6E306ED896488DD5B39409B23FC3EB7B2C9F7328EB18DA36D54D80575899EA6507CCBFCDF1F");
        pub(crate) const PEER_CERT_DIGEST: &[u8] =
            &hex!("b4fd606b64e4cbd466b8d76cb131069bae6f3aa1878857c9f624e31d77a799b8");
        pub(crate) const PEER_ED: &[u8] =
            &hex!("dcb604db2034b00fd16986d4adb9d16b21cb4e4457a33dec0f538903683e96e9");
        pub(crate) const PEER_RSA: &[u8] = &hex!("2f1fb49bb332a9eec617e41e911c33fb3890aef3");
    }
    #[test]
    fn test_finish() {
        tor_rtcompat::test_with_one_runtime!(|rt| async move {
            let ed25519_id = [3_u8; 32].into();
            let rsa_id = [4_u8; 20].into();
            let peer_addr = "127.1.1.2:443".parse().unwrap();
            let ver = VerifiedChannel {
                link_protocol: 4,
                tls: asynchronous_codec::Framed::new(MsgBuf::new(&b""[..]), ChannelCodec::new(4)),
                unique_id: UniqId::new(),
                target_method: Some(ChannelMethod::Direct(vec![peer_addr])),
                ed25519_id,
                rsa_id,
                clock_skew: ClockSkew::None,
                sleep_prov: rt,
                memquota: fake_mq(),
            };
            let (_chan, _reactor) = ver.finish().await.unwrap();
            // TODO: check contents of netinfo cell
        });
    }
}