1use crate::{Error, Result};
34use derive_deftly::Deftly;
35use tor_cell::chancell::BoxedCellBody;
36use tor_error::internal;
37use tor_memquota::derive_deftly_template_HasMemoryCost;
38
39use digest::generic_array::GenericArray;
40
41use super::binding::CircuitBinding;
42
43#[derive(Clone, derive_more::From, derive_more::Into)]
45pub(crate) struct RelayCellBody(BoxedCellBody);
46
47impl AsRef<[u8]> for RelayCellBody {
48 fn as_ref(&self) -> &[u8] {
49 &self.0[..]
50 }
51}
52impl AsMut<[u8]> for RelayCellBody {
53 fn as_mut(&mut self) -> &mut [u8] {
54 &mut self.0[..]
55 }
56}
57
58pub(crate) trait CryptInit: Sized {
61 fn seed_len() -> usize;
63 fn initialize(seed: &[u8]) -> Result<Self>;
65 fn construct<K: super::handshake::KeyGenerator>(keygen: K) -> Result<Self> {
67 let seed = keygen.expand(Self::seed_len())?;
68 Self::initialize(&seed[..])
69 }
70}
71
72pub(crate) trait ClientLayer<F, B>
77where
78 F: OutboundClientLayer,
79 B: InboundClientLayer,
80{
81 fn split(self) -> (F, B, CircuitBinding);
84}
85
86#[allow(dead_code)] pub(crate) trait RelayCrypt {
89 fn originate(&mut self, cell: &mut RelayCellBody);
91 fn encrypt_inbound(&mut self, cell: &mut RelayCellBody);
93 fn decrypt_outbound(&mut self, cell: &mut RelayCellBody) -> bool;
97}
98
99pub(crate) trait OutboundClientLayer {
102 fn originate_for(&mut self, cell: &mut RelayCellBody) -> &[u8];
107 fn encrypt_outbound(&mut self, cell: &mut RelayCellBody);
109}
110
111pub(crate) trait InboundClientLayer {
114 fn decrypt_inbound(&mut self, cell: &mut RelayCellBody) -> Option<&[u8]>;
118}
119
120#[derive(Copy, Clone, Eq, PartialEq, Debug, Deftly)]
124#[derive_deftly(HasMemoryCost)]
125pub struct HopNum(u8);
126
127impl HopNum {
128 pub fn display(&self) -> HopNumDisplay {
136 HopNumDisplay(*self)
137 }
138}
139
140#[derive(Copy, Clone, Eq, PartialEq, Debug)]
146pub struct HopNumDisplay(HopNum);
147
148impl std::fmt::Display for HopNumDisplay {
149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
150 let hop_num: u8 = self.0.into();
151
152 write!(f, "#{}", hop_num + 1)
153 }
154}
155
156impl From<HopNum> for u8 {
157 fn from(hop: HopNum) -> u8 {
158 hop.0
159 }
160}
161
162impl From<u8> for HopNum {
163 fn from(v: u8) -> HopNum {
164 HopNum(v)
165 }
166}
167
168impl From<HopNum> for usize {
169 fn from(hop: HopNum) -> usize {
170 hop.0 as usize
171 }
172}
173
174pub(crate) struct OutboundClientCrypt {
177 layers: Vec<Box<dyn OutboundClientLayer + Send>>,
180}
181
182pub(crate) struct InboundClientCrypt {
185 layers: Vec<Box<dyn InboundClientLayer + Send>>,
188}
189
190pub(crate) const SENDME_TAG_LEN: usize = 20;
193
194impl OutboundClientCrypt {
195 pub(crate) fn new() -> Self {
197 OutboundClientCrypt { layers: Vec::new() }
198 }
199 pub(crate) fn encrypt(
207 &mut self,
208 cell: &mut RelayCellBody,
209 hop: HopNum,
210 ) -> Result<&[u8; SENDME_TAG_LEN]> {
211 let hop: usize = hop.into();
212 if hop >= self.layers.len() {
213 return Err(Error::NoSuchHop);
214 }
215
216 let mut layers = self.layers.iter_mut().take(hop + 1).rev();
217 let first_layer = layers.next().ok_or(Error::NoSuchHop)?;
218 let tag = first_layer.originate_for(cell);
219 for layer in layers {
220 layer.encrypt_outbound(cell);
221 }
222 Ok(tag.try_into().expect("wrong SENDME digest size"))
223 }
224
225 pub(crate) fn add_layer(&mut self, layer: Box<dyn OutboundClientLayer + Send>) {
227 assert!(self.layers.len() < u8::MAX as usize);
228 self.layers.push(layer);
229 }
230
231 pub(crate) fn n_layers(&self) -> usize {
233 self.layers.len()
234 }
235}
236
237impl InboundClientCrypt {
238 pub(crate) fn new() -> Self {
240 InboundClientCrypt { layers: Vec::new() }
241 }
242 pub(crate) fn decrypt(&mut self, cell: &mut RelayCellBody) -> Result<(HopNum, &[u8])> {
247 for (hopnum, layer) in self.layers.iter_mut().enumerate() {
248 if let Some(tag) = layer.decrypt_inbound(cell) {
249 let hopnum = HopNum(u8::try_from(hopnum).expect("Somehow > 255 hops"));
250 return Ok((hopnum, tag));
251 }
252 }
253 Err(Error::BadCellAuth)
254 }
255 pub(crate) fn add_layer(&mut self, layer: Box<dyn InboundClientLayer + Send>) {
257 assert!(self.layers.len() < u8::MAX as usize);
258 self.layers.push(layer);
259 }
260
261 #[allow(dead_code)]
265 pub(crate) fn n_layers(&self) -> usize {
266 self.layers.len()
267 }
268}
269
270pub(crate) type Tor1RelayCrypto<RCF> =
272 tor1::CryptStatePair<tor_llcrypto::cipher::aes::Aes128Ctr, tor_llcrypto::d::Sha1, RCF>;
273
274#[cfg(feature = "hs-common")]
278pub(crate) type Tor1Hsv3RelayCrypto<RCF> =
279 tor1::CryptStatePair<tor_llcrypto::cipher::aes::Aes256Ctr, tor_llcrypto::d::Sha3_256, RCF>;
280
281pub(crate) mod tor1 {
291 use std::marker::PhantomData;
292
293 use crate::crypto::binding::CIRC_BINDING_LEN;
294
295 use super::*;
296 use cipher::{KeyIvInit, StreamCipher};
297 use digest::Digest;
298 use tor_cell::relaycell::{RelayCellFields, RelayCellFormatTrait};
299 use typenum::Unsigned;
300
301 pub(crate) struct CryptState<SC: StreamCipher, D: Digest + Clone, RCF: RelayCellFormatTrait> {
315 cipher: SC,
319 digest: D,
323 last_digest_val: GenericArray<u8, D::OutputSize>,
325 relay_cell_format: PhantomData<RCF>,
327 }
328
329 pub(crate) struct CryptStatePair<SC: StreamCipher, D: Digest + Clone, RCF: RelayCellFormatTrait> {
333 fwd: CryptState<SC, D, RCF>,
335 back: CryptState<SC, D, RCF>,
337 binding: CircuitBinding,
339 }
340
341 impl<SC: StreamCipher + KeyIvInit, D: Digest + Clone, RCF: RelayCellFormatTrait> CryptInit
342 for CryptStatePair<SC, D, RCF>
343 {
344 fn seed_len() -> usize {
345 SC::KeySize::to_usize() * 2 + D::OutputSize::to_usize() * 2 + CIRC_BINDING_LEN
346 }
347 fn initialize(mut seed: &[u8]) -> Result<Self> {
348 if seed.len() != Self::seed_len() {
351 return Err(Error::from(internal!(
352 "seed length {} was invalid",
353 seed.len()
354 )));
355 }
356
357 let mut take_seed = |n: usize| -> &[u8] {
359 let res = &seed[..n];
360 seed = &seed[n..];
361 res
362 };
363
364 let dlen = D::OutputSize::to_usize();
365 let keylen = SC::KeySize::to_usize();
366
367 let df = take_seed(dlen);
368 let db = take_seed(dlen);
369 let kf = take_seed(keylen);
370 let kb = take_seed(keylen);
371 let binding_key = take_seed(CIRC_BINDING_LEN);
372
373 let fwd = CryptState {
374 cipher: SC::new(kf.into(), &Default::default()),
375 digest: D::new().chain_update(df),
376 last_digest_val: GenericArray::default(),
377 relay_cell_format: PhantomData,
378 };
379 let back = CryptState {
380 cipher: SC::new(kb.into(), &Default::default()),
381 digest: D::new().chain_update(db),
382 last_digest_val: GenericArray::default(),
383 relay_cell_format: PhantomData,
384 };
385 let binding = CircuitBinding::try_from(binding_key)?;
386
387 Ok(CryptStatePair { fwd, back, binding })
388 }
389 }
390
391 impl<SC, D, RCF> ClientLayer<CryptState<SC, D, RCF>, CryptState<SC, D, RCF>>
392 for CryptStatePair<SC, D, RCF>
393 where
394 SC: StreamCipher,
395 D: Digest + Clone,
396 RCF: RelayCellFormatTrait,
397 {
398 fn split(
399 self,
400 ) -> (
401 CryptState<SC, D, RCF>,
402 CryptState<SC, D, RCF>,
403 CircuitBinding,
404 ) {
405 (self.fwd, self.back, self.binding)
406 }
407 }
408
409 impl<SC: StreamCipher, D: Digest + Clone, RCF: RelayCellFormatTrait> RelayCrypt
410 for CryptStatePair<SC, D, RCF>
411 {
412 fn originate(&mut self, cell: &mut RelayCellBody) {
413 let mut d_ignored = GenericArray::default();
414 cell.set_digest::<_, RCF>(&mut self.back.digest, &mut d_ignored);
415 }
416 fn encrypt_inbound(&mut self, cell: &mut RelayCellBody) {
417 self.back.cipher.apply_keystream(cell.as_mut());
419 }
420 fn decrypt_outbound(&mut self, cell: &mut RelayCellBody) -> bool {
421 self.fwd.cipher.apply_keystream(cell.as_mut());
423 let mut d_ignored = GenericArray::default();
424 cell.is_recognized::<_, RCF>(&mut self.fwd.digest, &mut d_ignored)
425 }
426 }
427
428 impl<SC: StreamCipher, D: Digest + Clone, RCF: RelayCellFormatTrait> OutboundClientLayer
429 for CryptState<SC, D, RCF>
430 {
431 fn originate_for(&mut self, cell: &mut RelayCellBody) -> &[u8] {
432 cell.set_digest::<_, RCF>(&mut self.digest, &mut self.last_digest_val);
433 self.encrypt_outbound(cell);
434 &self.last_digest_val[..SENDME_TAG_LEN]
437 }
438 fn encrypt_outbound(&mut self, cell: &mut RelayCellBody) {
439 self.cipher.apply_keystream(&mut cell.0[..]);
442 }
443 }
444
445 impl<SC: StreamCipher, D: Digest + Clone, RCF: RelayCellFormatTrait> InboundClientLayer
446 for CryptState<SC, D, RCF>
447 {
448 fn decrypt_inbound(&mut self, cell: &mut RelayCellBody) -> Option<&[u8]> {
449 self.cipher.apply_keystream(&mut cell.0[..]);
452 if cell.is_recognized::<_, RCF>(&mut self.digest, &mut self.last_digest_val) {
453 Some(&self.last_digest_val[..SENDME_TAG_LEN])
454 } else {
455 None
456 }
457 }
458 }
459
460 impl RelayCellBody {
471 fn recognized<RCF: RelayCellFormatTrait>(&self) -> &[u8] {
473 &self.0[RCF::FIELDS::RECOGNIZED_RANGE]
474 }
475 fn recognized_mut<RCF: RelayCellFormatTrait>(&mut self) -> &mut [u8] {
477 &mut self.0[RCF::FIELDS::RECOGNIZED_RANGE]
478 }
479 fn digest<RCF: RelayCellFormatTrait>(&self) -> &[u8] {
481 &self.0[RCF::FIELDS::DIGEST_RANGE]
482 }
483 fn digest_mut<RCF: RelayCellFormatTrait>(&mut self) -> &mut [u8] {
485 &mut self.0[RCF::FIELDS::DIGEST_RANGE]
486 }
487 fn set_digest<D: Digest + Clone, RCF: RelayCellFormatTrait>(
489 &mut self,
490 d: &mut D,
491 used_digest: &mut GenericArray<u8, D::OutputSize>,
492 ) {
493 self.recognized_mut::<RCF>().fill(0); self.digest_mut::<RCF>().fill(0); d.update(&self.0[..]);
497 *used_digest = d.clone().finalize();
499 let used_digest_prefix = &used_digest[0..RCF::FIELDS::DIGEST_RANGE.len()];
500 self.digest_mut::<RCF>().copy_from_slice(used_digest_prefix);
501 }
502 fn is_recognized<D: Digest + Clone, RCF: RelayCellFormatTrait>(
511 &self,
512 d: &mut D,
513 rcvd: &mut GenericArray<u8, D::OutputSize>,
514 ) -> bool {
515 use crate::util::ct;
516
517 if !ct::is_zero(self.recognized::<RCF>()) {
519 return false;
520 }
521
522 let mut dtmp = d.clone();
525 dtmp.update(&self.0[..RCF::FIELDS::DIGEST_RANGE.start]);
527 dtmp.update(RCF::FIELDS::EMPTY_DIGEST);
529 dtmp.update(&self.0[RCF::FIELDS::DIGEST_RANGE.end..]);
531 let dtmp_clone = dtmp.clone();
534 let result = dtmp.finalize();
535
536 if ct::bytes_eq(
537 self.digest::<RCF>(),
538 &result[0..RCF::FIELDS::DIGEST_RANGE.len()],
539 ) {
540 *d = dtmp_clone;
542 *rcvd = result;
543 return true;
544 }
545
546 false
547 }
548 }
549
550 #[cfg(feature = "bench")]
552 pub(crate) mod bench_utils {
553 use super::*;
554
555 #[repr(transparent)]
557 pub struct RelayBody(pub(in crate::crypto) RelayCellBody);
558
559 impl From<[u8; 509]> for RelayBody {
560 fn from(body: [u8; 509]) -> Self {
561 let body = Box::new(body);
562 Self(body.into())
563 }
564 }
565
566 impl RelayBody {
567 pub fn set_digest<D: Digest + Clone, RCF: RelayCellFormatTrait>(
569 &mut self,
570 d: &mut D,
571 used_digest: &mut GenericArray<u8, D::OutputSize>,
572 ) {
573 self.0.set_digest::<D, RCF>(d, used_digest);
574 }
575
576 pub fn is_recognized<D: Digest + Clone, RCF: RelayCellFormatTrait>(
578 &self,
579 d: &mut D,
580 rcvd: &mut GenericArray<u8, D::OutputSize>,
581 ) -> bool {
582 self.0.is_recognized::<D, RCF>(d, rcvd)
583 }
584 }
585 }
586}
587
588#[cfg(test)]
589mod test {
590 #![allow(clippy::bool_assert_comparison)]
592 #![allow(clippy::clone_on_copy)]
593 #![allow(clippy::dbg_macro)]
594 #![allow(clippy::mixed_attributes_style)]
595 #![allow(clippy::print_stderr)]
596 #![allow(clippy::print_stdout)]
597 #![allow(clippy::single_char_pattern)]
598 #![allow(clippy::unwrap_used)]
599 #![allow(clippy::unchecked_duration_subtraction)]
600 #![allow(clippy::useless_vec)]
601 #![allow(clippy::needless_pass_by_value)]
602 use super::*;
604 use rand::RngCore;
605 use tor_basic_utils::test_rng::testing_rng;
606 use tor_bytes::SecretBuf;
607 use tor_cell::relaycell::RelayCellFormatV0;
608
609 fn add_layers(
610 cc_out: &mut OutboundClientCrypt,
611 cc_in: &mut InboundClientCrypt,
612 pair: Tor1RelayCrypto<RelayCellFormatV0>,
614 ) {
615 let (outbound, inbound, _) = pair.split();
616 cc_out.add_layer(Box::new(outbound));
617 cc_in.add_layer(Box::new(inbound));
618 }
619
620 #[test]
621 fn roundtrip() {
622 use crate::crypto::handshake::ShakeKeyGenerator as KGen;
624 fn s(seed: &[u8]) -> SecretBuf {
625 seed.to_vec().into()
626 }
627
628 let seed1 = s(b"hidden we are free");
629 let seed2 = s(b"free to speak, to free ourselves");
630 let seed3 = s(b"free to hide no more");
631
632 let mut cc_out = OutboundClientCrypt::new();
633 let mut cc_in = InboundClientCrypt::new();
634 let pair = Tor1RelayCrypto::construct(KGen::new(seed1.clone())).unwrap();
635 add_layers(&mut cc_out, &mut cc_in, pair);
636 let pair = Tor1RelayCrypto::construct(KGen::new(seed2.clone())).unwrap();
637 add_layers(&mut cc_out, &mut cc_in, pair);
638 let pair = Tor1RelayCrypto::construct(KGen::new(seed3.clone())).unwrap();
639 add_layers(&mut cc_out, &mut cc_in, pair);
640
641 assert_eq!(cc_in.n_layers(), 3);
642 assert_eq!(cc_out.n_layers(), 3);
643
644 let mut r1 = Tor1RelayCrypto::<RelayCellFormatV0>::construct(KGen::new(seed1)).unwrap();
645 let mut r2 = Tor1RelayCrypto::<RelayCellFormatV0>::construct(KGen::new(seed2)).unwrap();
646 let mut r3 = Tor1RelayCrypto::<RelayCellFormatV0>::construct(KGen::new(seed3)).unwrap();
647
648 let mut rng = testing_rng();
649 for _ in 1..300 {
650 let mut cell = Box::new([0_u8; 509]);
652 let mut cell_orig = [0_u8; 509];
653 rng.fill_bytes(&mut cell_orig);
654 cell.copy_from_slice(&cell_orig);
655 let mut cell = cell.into();
656 let _tag = cc_out.encrypt(&mut cell, 2.into()).unwrap();
657 assert_ne!(&cell.as_ref()[9..], &cell_orig.as_ref()[9..]);
658 assert!(!r1.decrypt_outbound(&mut cell));
659 assert!(!r2.decrypt_outbound(&mut cell));
660 assert!(r3.decrypt_outbound(&mut cell));
661
662 assert_eq!(&cell.as_ref()[9..], &cell_orig.as_ref()[9..]);
663
664 let mut cell = Box::new([0_u8; 509]);
666 let mut cell_orig = [0_u8; 509];
667 rng.fill_bytes(&mut cell_orig);
668 cell.copy_from_slice(&cell_orig);
669 let mut cell = cell.into();
670
671 r3.originate(&mut cell);
672 r3.encrypt_inbound(&mut cell);
673 r2.encrypt_inbound(&mut cell);
674 r1.encrypt_inbound(&mut cell);
675 let (layer, _tag) = cc_in.decrypt(&mut cell).unwrap();
676 assert_eq!(layer, 2.into());
677 assert_eq!(&cell.as_ref()[9..], &cell_orig.as_ref()[9..]);
678
679 }
681
682 {
684 let mut cell = Box::new([0_u8; 509]).into();
685 let err = cc_out.encrypt(&mut cell, 10.into());
686 assert!(matches!(err, Err(Error::NoSuchHop)));
687 }
688
689 {
691 let mut cell = Box::new([0_u8; 509]).into();
692 let err = cc_in.decrypt(&mut cell);
693 assert!(matches!(err, Err(Error::BadCellAuth)));
694 }
695 }
696
697 #[test]
700 fn testvec() {
701 use digest::XofReader;
702 use digest::{ExtendableOutput, Update};
703
704 const K1: &[u8; 92] =
706 b" 'My public key is in this signed x509 object', said Tom assertively. (N-PREG-VIRYL)";
707 const K2: &[u8; 92] =
708 b"'Let's chart the pedal phlanges in the tomb', said Tom cryptographically. (PELCG-GBR-TENCU)";
709 const K3: &[u8; 92] =
710 b" 'Segmentation fault bugs don't _just happen_', said Tom seethingly. (P-GUVAT-YL)";
711
712 const SEED: &[u8;108] = b"'You mean to tell me that there's a version of Sha-3 with no limit on the output length?', said Tom shakily.";
713
714 let data: &[(usize, &str)] = &include!("../../testdata/cell_crypt.rs");
716
717 let mut cc_out = OutboundClientCrypt::new();
718 let mut cc_in = InboundClientCrypt::new();
719 let pair = Tor1RelayCrypto::<RelayCellFormatV0>::initialize(&K1[..]).unwrap();
720 add_layers(&mut cc_out, &mut cc_in, pair);
721 let pair = Tor1RelayCrypto::<RelayCellFormatV0>::initialize(&K2[..]).unwrap();
722 add_layers(&mut cc_out, &mut cc_in, pair);
723 let pair = Tor1RelayCrypto::<RelayCellFormatV0>::initialize(&K3[..]).unwrap();
724 add_layers(&mut cc_out, &mut cc_in, pair);
725
726 let mut xof = tor_llcrypto::d::Shake256::default();
727 xof.update(&SEED[..]);
728 let mut stream = xof.finalize_xof();
729
730 let mut j = 0;
731 for cellno in 0..51 {
732 let mut body = Box::new([0_u8; 509]);
733 body[0] = 2; body[4] = 1; body[9] = 1; body[10] = 242;
737 stream.read(&mut body[11..]);
738
739 let mut cell = body.into();
740 let _ = cc_out.encrypt(&mut cell, 2.into());
741
742 if cellno == data[j].0 {
743 let expected = hex::decode(data[j].1).unwrap();
744 assert_eq!(cell.as_ref(), &expected[..]);
745 j += 1;
746 }
747 }
748 }
749
750 #[test]
751 fn hop_num_display() {
752 for i in 0..10 {
753 let hop_num = HopNum::from(i);
754 let expect = format!("#{}", i + 1);
755
756 assert_eq!(expect, hop_num.display().to_string());
757 }
758 }
759}