1pub(crate) mod handshake;
7pub(crate) mod initiator;
8pub(crate) mod responder;
9
10pub use responder::MaybeVerifiableRelayResponderChannel;
11
12use digest::Digest;
13use futures::{AsyncRead, AsyncWrite};
14use rand::Rng;
15use safelog::Sensitive;
16use std::net::IpAddr;
17use std::sync::Arc;
18use std::time::UNIX_EPOCH;
19
20use tor_cell::chancell::msg;
21use tor_cert::rsa::EncodedRsaCrosscert;
22use tor_cert::x509::TlsKeyAndCert;
23use tor_cert::{CertType, EncodedEd25519Cert};
24use tor_error::internal;
25use tor_linkspec::{HasRelayIds, OwnedChanTarget, RelayIdRef, RelayIdType};
26use tor_llcrypto as ll;
27use tor_llcrypto::pk::{
28 ed25519::{Ed25519Identity, Ed25519SigningKey},
29 rsa,
30 rsa::RsaIdentity,
31};
32use tor_relay_crypto::pk::RelayLinkSigningKeypair;
33use tor_rtcompat::{CertifiedConn, CoarseTimeProvider, SleepProvider, StreamOps};
34
35use crate::channel::handshake::VerifiedChannel;
36use crate::relay::channel::handshake::{AUTHTYPE_ED25519_SHA256_RFC5705, RelayResponderHandshake};
37use crate::{Error, Result, channel::RelayInitiatorHandshake, memquota::ChannelAccount};
38
39pub(crate) static LINK_AUTH: &[u16] = &[AUTHTYPE_ED25519_SHA256_RFC5705];
43
44pub struct RelayIdentities {
50 pub(crate) rsa_id_der_digest: [u8; 32],
52 pub(crate) rsa_id: RsaIdentity,
55 pub(crate) ed_id: Ed25519Identity,
57 pub(crate) link_sign_kp: RelayLinkSigningKeypair,
59 pub(crate) cert_id_sign_ed: EncodedEd25519Cert,
61 pub(crate) cert_sign_tls_ed: EncodedEd25519Cert,
63 pub(crate) cert_sign_link_auth_ed: EncodedEd25519Cert,
65 pub(crate) cert_id_x509_rsa: Vec<u8>,
70 pub(crate) cert_id_rsa: EncodedRsaCrosscert,
72 pub(crate) tls_key_and_cert: TlsKeyAndCert,
75}
76
77impl RelayIdentities {
78 #[allow(clippy::too_many_arguments)] pub fn new(
81 rsa_id_pk: &rsa::PublicKey,
82 ed_id: Ed25519Identity,
83 link_sign_kp: RelayLinkSigningKeypair,
84 cert_id_sign_ed: EncodedEd25519Cert,
85 cert_sign_tls_ed: EncodedEd25519Cert,
86 cert_sign_link_auth_ed: EncodedEd25519Cert,
87 cert_id_x509_rsa: Vec<u8>,
88 cert_id_rsa: EncodedRsaCrosscert,
89 tls_key_and_cert: TlsKeyAndCert,
90 ) -> Self {
91 Self {
92 rsa_id_der_digest: ll::d::Sha256::digest(rsa_id_pk.to_der()).into(),
93 rsa_id: rsa_id_pk.to_rsa_identity(),
94 ed_id,
95 link_sign_kp,
96 cert_id_sign_ed,
97 cert_sign_tls_ed,
98 cert_sign_link_auth_ed,
99 cert_id_x509_rsa,
100 cert_id_rsa,
101 tls_key_and_cert,
102 }
103 }
104
105 pub fn tls_key_and_cert(&self) -> &TlsKeyAndCert {
109 &self.tls_key_and_cert
110 }
111
112 pub(crate) fn ed_id_bytes(&self) -> [u8; 32] {
114 self.ed_id.into()
115 }
116}
117
118impl HasRelayIds for RelayIdentities {
119 fn identity(&self, key_type: RelayIdType) -> Option<RelayIdRef<'_>> {
120 match key_type {
121 RelayIdType::Ed25519 => Some(RelayIdRef::from(&self.ed_id)),
122 RelayIdType::Rsa => Some(RelayIdRef::from(&self.rsa_id)),
123 _ => None, }
125 }
126}
127
128#[derive(Default)]
130#[non_exhaustive]
131pub struct RelayChannelBuilder;
132
133impl RelayChannelBuilder {
134 pub fn new() -> Self {
136 Self::default()
137 }
138
139 #[allow(clippy::too_many_arguments)] pub fn launch<T, S>(
147 self,
148 tls: T,
149 sleep_prov: S,
150 identities: Arc<RelayIdentities>,
151 my_addrs: Vec<IpAddr>,
152 peer: &OwnedChanTarget,
153 memquota: ChannelAccount,
154 ) -> RelayInitiatorHandshake<T, S>
155 where
156 T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
157 S: CoarseTimeProvider + SleepProvider,
158 {
159 RelayInitiatorHandshake::new(tls, sleep_prov, identities, my_addrs, peer, memquota)
160 }
161
162 pub fn accept<T, S>(
164 self,
165 peer: Sensitive<std::net::SocketAddr>,
166 my_addrs: Vec<IpAddr>,
167 tls: T,
168 sleep_prov: S,
169 identities: Arc<RelayIdentities>,
170 memquota: ChannelAccount,
171 ) -> RelayResponderHandshake<T, S>
172 where
173 T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
174 S: CoarseTimeProvider + SleepProvider,
175 {
176 RelayResponderHandshake::new(
177 peer.into_inner().into(),
178 my_addrs,
179 tls,
180 sleep_prov,
181 identities,
182 memquota,
183 )
184 }
185}
186
187#[derive(Debug)]
190pub(crate) struct ChannelAuthenticationData {
191 pub(crate) link_auth: u16,
193 pub(crate) cid: [u8; 32],
195 pub(crate) sid: [u8; 32],
197 pub(crate) cid_ed: [u8; 32],
199 pub(crate) sid_ed: [u8; 32],
201 pub(crate) clog: [u8; 32],
203 pub(crate) slog: [u8; 32],
205 pub(crate) scert: [u8; 32],
207}
208
209impl ChannelAuthenticationData {
210 const fn auth_type_bytes(link_auth: u16) -> Result<&'static [u8]> {
212 match link_auth {
213 3 => Ok(b"AUTH0003"),
214 _ => Err(Error::BadCellAuth),
215 }
216 }
217
218 const fn keying_material_label_bytes(link_auth: u16) -> Result<&'static [u8]> {
220 match link_auth {
221 3 => Ok(b"EXPORTER FOR TOR TLS CLIENT BINDING AUTH0003"),
222 _ => Err(Error::BadCellAuth),
223 }
224 }
225
226 pub(crate) fn into_authenticate<C: CertifiedConn>(
228 self,
229 tls: &C,
230 link_ed: &RelayLinkSigningKeypair,
231 ) -> Result<msg::Authenticate> {
232 let mut body = Vec::with_capacity(352);
234
235 body.extend_from_slice(Self::auth_type_bytes(self.link_auth)?);
237 body.extend_from_slice(&self.cid);
238 body.extend_from_slice(&self.sid);
239 body.extend_from_slice(&self.cid_ed);
240 body.extend_from_slice(&self.sid_ed);
241 body.extend_from_slice(&self.slog);
242 body.extend_from_slice(&self.clog);
243 body.extend_from_slice(&self.scert);
244
245 let tls_secrets = tls.export_keying_material(
247 32,
248 Self::keying_material_label_bytes(self.link_auth)?,
249 Some(&self.cid[..]),
250 )?;
251 body.extend_from_slice(tls_secrets.as_slice());
252
253 let random: [u8; 24] = rand::rng().random();
255 body.extend_from_slice(&random);
256
257 let sig = link_ed.sign(&body);
260 body.extend_from_slice(&sig.to_bytes());
261
262 Ok(msg::Authenticate::new(self.link_auth, body))
264 }
265
266 pub(crate) fn build<T, S>(
280 auth_challenge_cell: Option<&msg::AuthChallenge>,
281 identities: &Arc<RelayIdentities>,
282 verified: &mut VerifiedChannel<T, S>,
283 our_cert: Option<[u8; 32]>,
284 ) -> Result<ChannelAuthenticationData>
285 where
286 T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
287 S: CoarseTimeProvider + SleepProvider,
288 {
289 let is_responder = auth_challenge_cell.is_none();
292
293 let link_auth = *LINK_AUTH
296 .iter()
297 .filter(|m| auth_challenge_cell.is_none_or(|cell| cell.methods().contains(m)))
298 .max()
299 .ok_or(Error::BadCellAuth)?;
300 let cid = identities.rsa_id_der_digest;
302 let sid = verified.rsa_id_digest;
303 let cid_ed = identities.ed_id_bytes();
304 let sid_ed = verified.ed25519_id.into();
305 let clog = verified.framed_tls.codec_mut().get_clog_digest()?;
307 let slog = verified.framed_tls.codec_mut().get_slog_digest()?;
308
309 let (cid, sid, cid_ed, sid_ed) = if is_responder {
310 (sid, cid, sid_ed, cid_ed)
312 } else {
313 (cid, sid, cid_ed, sid_ed)
315 };
316
317 let (clog, slog) = if is_responder {
318 (slog, clog)
320 } else {
321 (clog, slog)
323 };
324
325 let scert = if is_responder {
326 our_cert.ok_or(internal!("Responder channel without own certificate"))?
327 } else {
328 verified.peer_cert_digest
329 };
330
331 Ok(Self {
332 link_auth,
333 cid,
334 sid,
335 cid_ed,
336 sid_ed,
337 clog,
338 slog,
339 scert,
340 })
341 }
342}
343
344pub(crate) fn build_certs_cell(
348 identities: &Arc<RelayIdentities>,
349 is_responder: bool,
350) -> msg::Certs {
351 let mut certs = msg::Certs::new_empty();
352 certs.push_cert_body(
354 tor_cert::CertType::RSA_ID_X509,
355 identities.cert_id_x509_rsa.clone(),
356 );
357
358 certs.push_cert_body(CertType::RSA_ID_V_IDENTITY, identities.cert_id_rsa.clone());
360
361 certs.push_cert_body(
363 CertType::IDENTITY_V_SIGNING,
364 identities.cert_id_sign_ed.clone(),
365 );
366 if is_responder {
368 certs.push_cert_body(
370 CertType::SIGNING_V_TLS_CERT,
371 identities.cert_sign_tls_ed.clone(),
372 );
373 } else {
374 certs.push_cert_body(
376 CertType::SIGNING_V_LINK_AUTH,
377 identities.cert_sign_link_auth_ed.clone(),
378 );
379 }
380 certs
381}
382
383pub(crate) fn build_netinfo_cell<S>(
387 peer_ip: Option<IpAddr>,
388 my_addrs: Vec<IpAddr>,
389 sleep_prov: &S,
390) -> Result<msg::Netinfo>
391where
392 S: CoarseTimeProvider + SleepProvider,
393{
394 let timestamp = sleep_prov
397 .wallclock()
398 .duration_since(UNIX_EPOCH)
399 .map_err(|e| internal!("Wallclock may have gone backwards: {e}"))?
400 .as_secs()
401 .try_into()
402 .map_err(|e| internal!("Wallclock secs fail to convert to 32bit: {e}"))?;
403 Ok(msg::Netinfo::from_relay(timestamp, peer_ip, my_addrs))
404}