1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
|
//! Relay responder channel.
//!
//! Code related to the relay channel opened as a responder. The handshake code is responsible for
//! creating an [`MaybeVerifiableRelayResponderChannel`] when accepting an inbound connection.
//!
//! It can then be used to get a fully working channel.
use digest::Digest;
use futures::{AsyncRead, AsyncWrite};
use safelog::{MaybeSensitive, Sensitive};
use std::{net::IpAddr, ops::Deref, sync::Arc};
use subtle::ConstantTimeEq;
use tracing::instrument;
use tor_cell::chancell::msg;
use tor_linkspec::{HasRelayIds, OwnedChanTarget, RelayIds};
use tor_llcrypto as ll;
use tor_llcrypto::pk::ed25519::Ed25519Identity;
use tor_llcrypto::pk::rsa::RsaIdentity;
use tor_rtcompat::{CertifiedConn, CoarseTimeProvider, Runtime, SleepProvider, StreamOps};
use web_time_compat::{SystemTime, SystemTimeExt};
use crate::{
ClockSkew, Error, RelayChannelAuthMaterial, Result,
channel::{
Channel, ChannelMode, ClogDigest, Reactor, SlogDigest,
circmap::CircIdRange,
handshake::{UnverifiedChannel, VerifiedChannel},
},
peer::{PeerAddr, PeerInfo},
relay::CreateRequestHandler,
relay::channel::ChannelAuthenticationData,
};
/// An enum combining both the possibility of a verifiable (relay) or non verifiable channel
/// (client/bridge).
#[allow(clippy::exhaustive_enums)]
pub enum MaybeVerifiableRelayResponderChannel<
T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
S: CoarseTimeProvider + SleepProvider,
> {
/// Verifiable channel (relay).
Verifiable(UnverifiedResponderRelayChannel<T, S>),
/// Non verifiable channel (client/bridge).
NonVerifiable(NonVerifiableResponderRelayChannel<T, S>),
}
/// A channel that can NOT be verified. This is solely either a client or bridge on the other end.
///
/// This can only be built if no [`msg::Authenticate`] was ever received.
pub struct NonVerifiableResponderRelayChannel<
T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
S: CoarseTimeProvider + SleepProvider,
> {
/// The common unverified channel that both client and relays use.
pub(crate) inner: UnverifiedChannel<T, S>,
/// The netinfo cell received from the initiator.
pub(crate) netinfo_cell: msg::Netinfo,
/// Our advertised addresses.
pub(crate) my_addrs: Vec<IpAddr>,
/// The peer address which is sensitive considering it is either client or bridge.
pub(crate) peer_addr: Sensitive<PeerAddr>,
/// Provided to each new channel so that they can handle CREATE* requests.
pub(crate) create_request_handler: Arc<CreateRequestHandler>,
/// Our Ed25519 identity.
///
/// Needed for ntor-v3 handshakes.
pub(crate) our_ed25519_id: Ed25519Identity,
/// Our RSA identity.
///
/// Needed for ntor handshakes.
pub(crate) our_rsa_id: RsaIdentity,
}
/// A verifiable relay responder channel that is currently unverified. This can only be a relay on
/// the other end.
///
/// The verify() and then finish() functions are to be used to get a final Channel/Reactor.
pub struct UnverifiedResponderRelayChannel<
T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
S: CoarseTimeProvider + SleepProvider,
> {
/// The common unverified channel that both client and relays use.
pub(crate) inner: UnverifiedChannel<T, S>,
/// AUTHENTICATE cell received from the initiator.
pub(crate) auth_cell: msg::Authenticate,
/// The netinfo cell received from the initiator.
pub(crate) netinfo_cell: msg::Netinfo,
/// The [`msg::Certs`] cell received from the initiator.
pub(crate) certs_cell: msg::Certs,
/// Our authentication key material.
pub(crate) auth_material: Arc<RelayChannelAuthMaterial>,
/// Our advertised addresses.
pub(crate) my_addrs: Vec<IpAddr>,
/// The peer address which we know is a relay.
pub(crate) peer_addr: PeerAddr,
/// The CLOG digest.
pub(crate) clog_digest: ClogDigest,
/// The SLOG digest.
pub(crate) slog_digest: SlogDigest,
/// Provided to each new channel so that they can handle CREATE* requests.
pub(crate) create_request_handler: Arc<CreateRequestHandler>,
}
/// A verified relay responder channel.
///
/// Only finish() remains to transform this into a fully usable [`crate::channel::Channel`] and
/// [`crate::channel::Reactor`].
pub struct VerifiedResponderRelayChannel<
T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
S: CoarseTimeProvider + SleepProvider,
> {
/// The common unverified channel that both client and relays use.
inner: VerifiedChannel<T, S>,
/// The netinfo cell that we got from the relay. Canonicity decision.
netinfo_cell: msg::Netinfo,
/// Our advertised addresses.
my_addrs: Vec<IpAddr>,
/// The peer address which we know is a relay.
peer_addr: PeerAddr,
/// Provided to each new channel so that they can handle CREATE* requests.
create_request_handler: Arc<CreateRequestHandler>,
/// Our Ed25519 identity.
///
/// Needed for ntor-v3 handshakes.
our_ed25519_id: Ed25519Identity,
/// Our RSA identity.
///
/// Needed for ntor handshakes.
our_rsa_id: RsaIdentity,
}
impl<T, S> UnverifiedResponderRelayChannel<T, S>
where
T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
S: CoarseTimeProvider + SleepProvider,
{
/// Validate the certificates and keys in the relay's handshake.
///
/// 'peer_target_no_ids' is the peer, without identities as we are accepting a connection and thus
/// don't have expectations on any identity, that we want to make sure we're connecting to.
///
/// 'our_tls_cert' is the x.509 certificate that we presented during the TLS handshake.
///
/// 'now' is the time at which to check that certificates are valid. `None` means to use the
/// current time. It can be used for testing to override the current view of the time.
///
/// This is a separate function because it's likely to be somewhat CPU-intensive.
#[instrument(skip_all, level = "trace")]
pub fn verify(
self,
peer_target_no_ids: &OwnedChanTarget,
our_tls_cert: &[u8],
now: Option<std::time::SystemTime>,
) -> Result<VerifiedResponderRelayChannel<T, S>> {
// Get these object out as we consume "self" in the inner check().
let identities = self.auth_material;
let peer_netinfo_cell = self.netinfo_cell;
let peer_auth_cell = self.auth_cell;
let my_addrs = self.my_addrs;
let now = now.unwrap_or_else(SystemTime::get);
// We are a relay responder. We have received a CERTS cell and we need to verify these
// certs:
//
// Relay Identities:
// IDENTITY_V_SIGNING_CERT (CertType 4)
// RSA_ID_X509 (CertType 2)
// RSA_ID_V_IDENTITY (CertType 7)
//
// Connection Cert:
// SIGNING_V_LINK_AUTH (CertType 6)
//
// Validating the relay identities first so we can make sure we are talking to the relay
// (peer) we wanted. Then, check the AUTHENTICATE cell.
//
// The end result is a verified channel (not authenticated yet) which guarantee that we are
// talking to the right relay that we wanted. We validate so we can prove these:
//
// - IDENTITY_V_SIGNING proves that KP_relaysign_ed speaks on behalf of KP_relayid_ed
// - SIGNING_V_LINK_AUTH proves that KP_link_ed speaks on behalf of KP_relaysign_ed
// - The AUTHENTICATE cell proves that the TLS session's key material is known by the
// owner of KP_link_ed
// - Therefore, we have a chain from:
// KS_relayid_ed → KP_relaysign_ed → KP_link_ed → AUTHENTICATE cell → the channel itself.
//
// As for legacy certs, they prove nothing but we can extract keys:
//
// - RSA_ID_X509 proves nothing; we just extract its subject key as KP_relayid_rsa.
// - RSA_ID_V_IDENTITY proves that KP_relayid_ed speaks on behalf of KP_relayid_rsa.
// - Therefore we have a chain from:
// KP_relayid_rsa → KS_relayid_ed → KP_relaysign_ed → KP_link_ed → AUTHENTICATE cell →
// the channel itself.
// Check the relay identities in the CERTS cell.
let (peer_relay_ids, peer_kp_relaysign_ed, peer_rsa_id_digest) = self
.inner
.check_relay_identities(peer_target_no_ids, &self.certs_cell, now)?;
// Next, verify the LINK_AUTH cert (CertType 6).
let peer_kp_link_ed = crate::channel::handshake::verify_link_auth_cert(
&self.certs_cell,
&peer_kp_relaysign_ed,
Some(now),
self.inner.clock_skew,
)?;
let our_tls_cert_digest = ll::d::Sha256::digest(our_tls_cert).into();
let peer_relayid_ed = *peer_relay_ids
.ed_identity()
.expect("Validated relay channel without Ed25519 identity");
// By building the ChannelAuthenticationData, we are certain that the authentication type
// of the initiator is supported by us.
let expected_auth_body = ChannelAuthenticationData::build_responder(
peer_auth_cell.auth_type(),
&identities,
self.clog_digest,
self.slog_digest,
peer_rsa_id_digest,
peer_relayid_ed,
our_tls_cert_digest,
)?
.as_body_no_rand(self.inner.framed_tls.deref())?;
// CRITICAL: This if is what authenticates a channel on the responder side. We compare
// what we expected to what we received.
let peer_auth_cell_body_no_rand = peer_auth_cell
.body_no_rand()
.map_err(|e| Error::ChanProto(format!("AUTHENTICATE body_no_rand malformed: {e}")))?;
// This equality is in constant-time to avoid timing attack oracle.
if (!peer_auth_cell_body_no_rand.ct_eq(&expected_auth_body)).into() {
return Err(Error::ChanProto(
"AUTHENTICATE was unexpected. Failing authentication".into(),
));
}
// CRITICAL: Verify the signature of the AUTHENTICATE cell with the peer KP_link_ed.
let peer_link_ed_pubkey: tor_llcrypto::pk::ed25519::PublicKey = peer_kp_link_ed
.try_into()
.expect("Peer KP_link_ed fails to convert to PublicKey");
let peer_auth_cell_sig =
tor_llcrypto::pk::ed25519::Signature::from_bytes(peer_auth_cell.sig().map_err(
|e| Error::ChanProto(format!("AUTHENTICATE sig field is invalid: {e}")),
)?);
let peer_body = peer_auth_cell
.body()
.map_err(|e| Error::ChanProto(format!("AUTHENTICATE body malformed: {e}")))?;
peer_link_ed_pubkey
.verify(peer_body, &peer_auth_cell_sig)
.map_err(|e| {
Error::ChanProto(format!("AUTHENTICATE cell signature failed to verify: {e}"))
})?;
// Transform our inner into a verified channel now that we are verified.
let mut verified = self.inner.into_verified(peer_relay_ids, peer_rsa_id_digest);
// This part is very important as we now flag that we are verified and thus authenticated.
//
// At this point, the underlying cell handler is in the Handshake state. Setting the
// channel type here as authenticated means that once the handler transition to the Open
// state, it will carry this authenticated flag leading to the message filter of the
// channel codec to adapt its restricted message sets (meaning R2R only).
//
// After this call, it is considered a R2R channel.
verified.set_authenticated()?;
Ok(VerifiedResponderRelayChannel {
inner: verified,
netinfo_cell: peer_netinfo_cell,
my_addrs,
peer_addr: self.peer_addr,
create_request_handler: self.create_request_handler,
our_ed25519_id: identities.ed_id,
our_rsa_id: identities.rsa_id,
})
}
/// Return the clock skew of this channel.
pub fn clock_skew(&self) -> ClockSkew {
self.inner.clock_skew
}
}
impl<T, S> VerifiedResponderRelayChannel<T, S>
where
T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
S: CoarseTimeProvider + SleepProvider,
{
/// Finish the handhshake which will create an open channel and reactor.
///
/// The resulting channel is considered, by Tor protocol standard, an authenticated relay
/// channel on which circuits can be opened.
#[instrument(skip_all, level = "trace")]
pub async fn finish(self) -> Result<(Arc<Channel>, Reactor<S>)>
where
S: Runtime,
{
// Relay<->Relay channels are NOT sensitive as we need their info in the log.
let peer_info = MaybeSensitive::not_sensitive(PeerInfo::new(
self.peer_addr,
self.inner.relay_ids().clone(),
));
let channel_mode = ChannelMode::Relay {
circ_id_range: CircIdRange::Low,
our_ed25519_id: self.our_ed25519_id,
our_rsa_id: self.our_rsa_id,
create_request_handler: self.create_request_handler,
};
self.inner
.finish(&self.netinfo_cell, &self.my_addrs, peer_info, channel_mode)
.await
}
}
impl<T, S> NonVerifiableResponderRelayChannel<T, S>
where
T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
S: CoarseTimeProvider + SleepProvider,
{
/// Finish the handhshake which will create an open channel and reactor.
///
/// The resulting channel is considered, by Tor protocol standard, a client/bridge relay
/// channel meaning not authenticated. Circuit can be opened on it.
#[instrument(skip_all, level = "trace")]
pub fn finish(self) -> Result<(Arc<Channel>, Reactor<S>)>
where
S: Runtime,
{
// This is either a client or a bridge so very sensitive.
let peer_info = MaybeSensitive::sensitive(PeerInfo::new(
self.peer_addr.into_inner(),
RelayIds::empty(),
));
let channel_mode = ChannelMode::Relay {
circ_id_range: CircIdRange::Low,
our_ed25519_id: self.our_ed25519_id,
our_rsa_id: self.our_rsa_id,
create_request_handler: self.create_request_handler,
};
// Non verifiable responder channel, we simply finalize our underlying channel and we are
// done. We are connected to a client or bridge.
self.inner
.finish(&self.netinfo_cell, &self.my_addrs, peer_info, channel_mode)
}
}
|