1#![allow(dead_code)] use aes::{Aes128, Aes128Dec, Aes128Enc, Aes256, Aes256Dec, Aes256Enc};
22use cipher::{BlockCipher, BlockDecrypt, BlockEncrypt, BlockSizeUser, StreamCipher as _};
23use digest::KeyInit;
24use polyval::{Polyval, universal_hash::UniversalHash};
25use tor_cell::{
26 chancell::{CELL_DATA_LEN, ChanCmd},
27 relaycell::msg::SendmeTag,
28};
29use tor_error::internal;
30use zeroize::Zeroizing;
31
32use super::{CryptInit, RelayCellBody};
33use crate::{client::circuit::CircuitBinding, util::ct};
34
35const CGO_TAG_LEN: usize = 16;
37const CGO_PAYLOAD_LEN: usize = CELL_DATA_LEN - CGO_TAG_LEN;
39
40const CGO_AD_LEN: usize = 16;
44
45const HLEN_UIV: usize = CGO_TAG_LEN + CGO_AD_LEN;
47
48const BLK_LEN: usize = 16;
51type BlockLen = typenum::U16;
54type Block = [u8; BLK_LEN];
56
57#[cfg_attr(feature = "bench", visibility::make(pub))]
62pub(crate) trait BlkCipher:
63 BlockCipher + KeyInit + BlockSizeUser<BlockSize = BlockLen> + Clone
64{
65 const KEY_LEN: usize;
67}
68
69#[cfg_attr(feature = "bench", visibility::make(pub))]
74pub(crate) trait BlkCipherEnc: BlkCipher + BlockEncrypt {}
75
76#[cfg_attr(feature = "bench", visibility::make(pub))]
81pub(crate) trait BlkCipherDec: BlkCipher + BlockDecrypt {}
82
83impl BlkCipher for Aes128 {
84 const KEY_LEN: usize = 16;
85}
86impl BlkCipherEnc for Aes128 {}
87impl BlkCipherDec for Aes128 {}
88impl BlkCipher for Aes128Enc {
89 const KEY_LEN: usize = 16;
90}
91impl BlkCipherEnc for Aes128Enc {}
92impl BlkCipher for Aes128Dec {
93 const KEY_LEN: usize = 16;
94}
95impl BlkCipherDec for Aes128Dec {}
96
97impl BlkCipher for Aes256 {
98 const KEY_LEN: usize = 32;
99}
100impl BlkCipherEnc for Aes256 {}
101impl BlkCipherDec for Aes256 {}
102impl BlkCipher for Aes256Enc {
103 const KEY_LEN: usize = 32;
104}
105impl BlkCipherEnc for Aes256Enc {}
106impl BlkCipher for Aes256Dec {
107 const KEY_LEN: usize = 32;
108}
109impl BlkCipherDec for Aes256Dec {}
110
111mod et {
113 use super::*;
114
115 pub(super) type EtTweak<'a> = (&'a [u8; CGO_TAG_LEN], u8, &'a [u8; CGO_PAYLOAD_LEN]);
120 pub(super) const TLEN_ET: usize = CGO_TAG_LEN + 1 + CGO_PAYLOAD_LEN;
122
123 #[derive(Clone)]
129 pub(super) struct EtCipher<BC: BlkCipher> {
130 kb: BC,
132 ku: Polyval,
134 }
135 impl<BC: BlkCipher> EtCipher<BC> {
136 fn compute_tweak_hash(&self, tweak: EtTweak<'_>) -> Zeroizing<Block> {
139 let mut ku = self.ku.clone();
142
143 let mut block1 = Zeroizing::new([0_u8; 16]);
144 block1[0] = tweak.1;
145 block1[1..16].copy_from_slice(&tweak.2[0..15]);
146 ku.update(&[(*tweak.0).into(), (*block1).into()]);
147 ku.update_padded(&tweak.2[15..]);
148 Zeroizing::new(ku.finalize().into())
149 }
150 }
151 impl<BC: BlkCipherEnc> EtCipher<BC> {
152 pub(super) fn encrypt(&self, tweak: EtTweak<'_>, block: &mut Block) {
154 let tag: Zeroizing<[u8; 16]> = self.compute_tweak_hash(tweak);
156 xor_into(block, &tag);
157 self.kb.encrypt_block(block.into());
158 xor_into(block, &tag);
159 }
160 }
161 impl<BC: BlkCipherDec> EtCipher<BC> {
162 pub(super) fn decrypt(&self, tweak: EtTweak<'_>, block: &mut Block) {
164 let tag: Zeroizing<[u8; 16]> = self.compute_tweak_hash(tweak);
166 xor_into(block, &tag);
167 self.kb.decrypt_block(block.into());
168 xor_into(block, &tag);
169 }
170 }
171 impl<BC: BlkCipher> CryptInit for EtCipher<BC> {
172 fn seed_len() -> usize {
173 BC::key_size() + polyval::KEY_SIZE
174 }
175 fn initialize(seed: &[u8]) -> crate::Result<Self> {
176 if seed.len() != Self::seed_len() {
179 return Err(internal!("Invalid seed length").into());
180 }
181 let (kb, ku) = seed.split_at(BC::key_size());
182 let ku: &[u8; 16] = ku
183 .try_into()
184 .expect("Incorrect key size, even though it was validated!?");
185 Ok(Self {
186 kb: BC::new(kb.into()),
187 ku: Polyval::new(ku.into()),
188 })
189 }
190 }
191}
192
193mod prf {
195 use tor_error::internal;
196
197 use super::*;
198
199 type PrfTweak = [u8; 16];
201 const PRF_N0_LEN: usize = CGO_PAYLOAD_LEN;
203 const PRF_N1_OFFSET: usize = 31 * 16;
205 const _: () = assert!(PRF_N1_OFFSET >= PRF_N0_LEN);
206
207 #[derive(Clone)]
212 pub(super) struct Prf<BC: BlkCipherEnc> {
213 k: BC,
215 b: Polyval,
217 }
218 impl<BC: BlkCipherEnc> Prf<BC> {
219 fn cipher(&self, tweak: &PrfTweak, t: bool) -> ctr::Ctr128BE<BC> {
222 use {
223 cipher::{InnerIvInit as _, StreamCipherSeek as _},
224 ctr::CtrCore,
225 };
226 let mut b = self.b.clone(); b.update(&[(*tweak).into()]);
228 let mut iv = b.finalize();
229 *iv.last_mut().expect("no last element?") &= 0xC0; let iv: [u8; 16] = iv.into(); let mut cipher: ctr::Ctr128BE<BC> = cipher::StreamCipherCoreWrapper::from_core(
232 CtrCore::inner_iv_init(self.k.clone(), (&iv).into()),
233 );
234 if t {
235 debug_assert_eq!(cipher.current_pos::<u32>(), 0_u32);
236 cipher.seek(PRF_N1_OFFSET);
237 }
238
239 cipher
240 }
241
242 pub(super) fn xor_n0_stream(&self, tweak: &PrfTweak, out: &mut [u8; PRF_N0_LEN]) {
245 let mut stream = self.cipher(tweak, false);
246 stream.apply_keystream(out);
247 }
248
249 pub(super) fn get_n1_stream(&self, tweak: &PrfTweak, n: usize) -> Zeroizing<Vec<u8>> {
252 let mut output = Zeroizing::new(vec![0_u8; n]);
253 self.cipher(tweak, true).apply_keystream(output.as_mut());
254 output
255 }
256 }
257
258 impl<BC: BlkCipherEnc> CryptInit for Prf<BC> {
259 fn seed_len() -> usize {
260 BC::key_size() + polyval::KEY_SIZE
261 }
262 fn initialize(seed: &[u8]) -> crate::Result<Self> {
263 if seed.len() != Self::seed_len() {
264 return Err(internal!("Invalid seed length").into());
265 }
266 let (k, b) = seed.split_at(BC::key_size());
267 let b: &[u8; 16] = b
268 .try_into()
269 .expect("Incorrect key size, even though it was validated!?");
270 Ok(Self {
271 k: BC::new(k.into()),
272 b: Polyval::new(b.into()),
273 })
274 }
275 }
276}
277
278mod uiv {
282 use super::*;
283
284 pub(super) type UivTweak<'a> = (&'a [u8; BLK_LEN], u8);
286
287 #[derive(Clone)]
289 pub(super) struct Uiv<EtBC: BlkCipher, PrfBC: BlkCipherEnc> {
290 j: et::EtCipher<EtBC>,
292 s: prf::Prf<PrfBC>,
294
295 #[cfg(test)]
300 pub(super) keys: Zeroizing<Vec<u8>>,
301 }
302
303 fn split(
306 cell_body: &mut [u8; CELL_DATA_LEN],
307 ) -> (&mut [u8; CGO_TAG_LEN], &mut [u8; CGO_PAYLOAD_LEN]) {
308 let (left, right) = cell_body.split_at_mut(CGO_TAG_LEN);
310 (
311 left.try_into().expect("split_at_mut returned wrong size!"),
312 right.try_into().expect("split_at_mut returned wrong size!"),
313 )
314 }
315
316 impl<EtBC: BlkCipherEnc, PrfBC: BlkCipherEnc> Uiv<EtBC, PrfBC> {
317 pub(super) fn encrypt(&self, tweak: UivTweak<'_>, cell_body: &mut [u8; CELL_DATA_LEN]) {
321 let (left, right) = split(cell_body);
326 self.j.encrypt((tweak.0, tweak.1, right), left);
327 self.s.xor_n0_stream(left, right);
328 }
329 }
330 impl<EtBC: BlkCipherDec, PrfBC: BlkCipherEnc> Uiv<EtBC, PrfBC> {
331 pub(super) fn decrypt(&self, tweak: UivTweak<'_>, cell_body: &mut [u8; CELL_DATA_LEN]) {
335 let (left, right) = split(cell_body);
340 self.s.xor_n0_stream(left, right);
341 self.j.decrypt((tweak.0, tweak.1, right), left);
342 }
343 }
344 impl<EtBC: BlkCipher, PrfBC: BlkCipherEnc> Uiv<EtBC, PrfBC> {
345 pub(super) fn update(&mut self, nonce: &mut [u8; BLK_LEN]) {
350 let n_bytes = Self::seed_len() + BLK_LEN;
358 let seed = self.s.get_n1_stream(nonce, n_bytes);
359 #[cfg(test)]
360 {
361 self.keys = Zeroizing::new(seed[..Self::seed_len()].to_vec());
362 }
363 let (j, s, n) = Self::split_seed(&seed);
364 self.j = et::EtCipher::initialize(j).expect("Invalid slice len");
365 self.s = prf::Prf::initialize(s).expect("invalid slice len");
366 nonce[..].copy_from_slice(n);
367 }
368
369 fn split_seed(seed: &[u8]) -> (&[u8], &[u8], &[u8]) {
371 let len_j = et::EtCipher::<EtBC>::seed_len();
372 let len_s = prf::Prf::<PrfBC>::seed_len();
373 (
374 &seed[0..len_j],
375 &seed[len_j..len_j + len_s],
376 &seed[len_j + len_s..],
377 )
378 }
379 }
380
381 impl<EtBC: BlkCipher, PrfBC: BlkCipherEnc> CryptInit for Uiv<EtBC, PrfBC> {
382 fn seed_len() -> usize {
383 super::et::EtCipher::<EtBC>::seed_len() + super::prf::Prf::<PrfBC>::seed_len()
384 }
385 fn initialize(seed: &[u8]) -> crate::Result<Self> {
386 if seed.len() != Self::seed_len() {
387 return Err(internal!("Invalid seed length").into());
388 }
389 #[cfg(test)]
390 let keys = Zeroizing::new(seed.to_vec());
391 let (j, s, n) = Self::split_seed(seed);
392 debug_assert!(n.is_empty());
393 Ok(Self {
394 j: et::EtCipher::initialize(j)?,
395 s: prf::Prf::initialize(s)?,
396 #[cfg(test)]
397 keys,
398 })
399 }
400 }
401}
402
403fn xor_into<const N: usize>(output: &mut [u8; N], input: &[u8; N]) {
405 for i in 0..N {
406 output[i] ^= input[i];
407 }
408}
409
410#[inline]
415fn first_block(bytes: &[u8]) -> &[u8; BLK_LEN] {
416 bytes[0..BLK_LEN].try_into().expect("Slice too short!")
417}
418
419#[derive(Clone)]
421struct CryptState<EtBC: BlkCipher, PrfBC: BlkCipherEnc> {
422 uiv: uiv::Uiv<EtBC, PrfBC>,
424 nonce: Zeroizing<[u8; BLK_LEN]>,
426 tag: Zeroizing<[u8; BLK_LEN]>,
428}
429
430impl<EtBC: BlkCipher, PrfBC: BlkCipherEnc> CryptInit for CryptState<EtBC, PrfBC> {
431 fn seed_len() -> usize {
432 uiv::Uiv::<EtBC, PrfBC>::seed_len() + BLK_LEN
433 }
434 fn initialize(seed: &[u8]) -> crate::Result<Self> {
436 if seed.len() != Self::seed_len() {
437 return Err(internal!("Invalid seed length").into());
438 }
439 let (j_s, n) = seed.split_at(uiv::Uiv::<EtBC, PrfBC>::seed_len());
440 Ok(Self {
441 uiv: uiv::Uiv::initialize(j_s)?,
442 nonce: Zeroizing::new(n.try_into().expect("invalid splice length")),
443 tag: Zeroizing::new([0; BLK_LEN]),
444 })
445 }
446}
447
448#[cfg_attr(feature = "bench", visibility::make(pub))]
450#[derive(Clone, derive_more::From)]
451pub(crate) struct ClientOutbound<EtBC, PrfBC>(CryptState<EtBC, PrfBC>)
452where
453 EtBC: BlkCipherDec,
454 PrfBC: BlkCipherEnc;
455impl<EtBC, PrfBC> super::OutboundClientLayer for ClientOutbound<EtBC, PrfBC>
456where
457 EtBC: BlkCipherDec,
458 PrfBC: BlkCipherEnc,
459{
460 fn originate_for(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) -> SendmeTag {
461 cell.0[0..BLK_LEN].copy_from_slice(&self.0.nonce[..]);
462 self.encrypt_outbound(cmd, cell);
463 self.0.uiv.update(&mut self.0.nonce);
464 SendmeTag::try_from(&cell.0[0..BLK_LEN]).expect("Block length not a valid sendme tag.")
465 }
466 fn encrypt_outbound(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) {
467 let t_new: [u8; BLK_LEN] = *first_block(&*cell.0);
469
470 self.0.uiv.decrypt((&self.0.tag, cmd.into()), &mut cell.0);
473 *self.0.tag = t_new;
474 }
475}
476
477#[cfg_attr(feature = "bench", visibility::make(pub))]
479#[derive(Clone, derive_more::From)]
480pub(crate) struct ClientInbound<EtBC, PrfBC>(CryptState<EtBC, PrfBC>)
481where
482 EtBC: BlkCipherDec,
483 PrfBC: BlkCipherEnc;
484impl<EtBC, PrfBC> super::InboundClientLayer for ClientInbound<EtBC, PrfBC>
485where
486 EtBC: BlkCipherDec,
487 PrfBC: BlkCipherEnc,
488{
489 fn decrypt_inbound(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) -> Option<SendmeTag> {
490 let mut t_orig: [u8; BLK_LEN] = *first_block(&*cell.0);
491 self.0.uiv.decrypt((&self.0.tag, cmd.into()), &mut cell.0);
496 *self.0.tag = t_orig;
497 if ct::bytes_eq(&cell.0[..CGO_TAG_LEN], &self.0.nonce[..]) {
498 self.0.uiv.update(&mut t_orig);
499 *self.0.nonce = t_orig;
500 Some((*self.0.tag).into())
502 } else {
503 None
504 }
505 }
506}
507
508#[cfg_attr(feature = "bench", visibility::make(pub))]
510#[derive(Clone, derive_more::From)]
511pub(crate) struct RelayOutbound<EtBC, PrfBC>(CryptState<EtBC, PrfBC>)
512where
513 EtBC: BlkCipherEnc,
514 PrfBC: BlkCipherEnc;
515impl<EtBC, PrfBC> super::OutboundRelayLayer for RelayOutbound<EtBC, PrfBC>
516where
517 EtBC: BlkCipherEnc,
518 PrfBC: BlkCipherEnc,
519{
520 fn decrypt_outbound(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) -> Option<SendmeTag> {
521 let tag = SendmeTag::try_from(&cell.0[0..BLK_LEN]).expect("Invalid sendme length");
522 self.0.uiv.encrypt((&self.0.tag, cmd.into()), &mut cell.0);
525 *self.0.tag = *first_block(&*cell.0);
526 if ct::bytes_eq(self.0.tag.as_ref(), &self.0.nonce[..]) {
527 self.0.uiv.update(&mut self.0.nonce);
528 Some(tag)
529 } else {
530 None
531 }
532 }
533}
534
535#[cfg_attr(feature = "bench", visibility::make(pub))]
537#[derive(Clone, derive_more::From)]
538pub(crate) struct RelayInbound<EtBC, PrfBC>(CryptState<EtBC, PrfBC>)
539where
540 EtBC: BlkCipherEnc,
541 PrfBC: BlkCipherEnc;
542impl<EtBC, PrfBC> super::InboundRelayLayer for RelayInbound<EtBC, PrfBC>
543where
544 EtBC: BlkCipherEnc,
545 PrfBC: BlkCipherEnc,
546{
547 fn originate(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) -> SendmeTag {
548 cell.0[0..BLK_LEN].copy_from_slice(&self.0.nonce[..]);
549 self.encrypt_inbound(cmd, cell);
550 self.0.nonce.copy_from_slice(&cell.0[0..BLK_LEN]);
551 self.0.uiv.update(&mut self.0.nonce);
552 (*self.0.tag).into()
554 }
555 fn encrypt_inbound(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) {
556 self.0.uiv.encrypt((&self.0.tag, cmd.into()), &mut cell.0);
559 *self.0.tag = *first_block(&*cell.0);
560 }
561}
562
563#[cfg_attr(feature = "bench", visibility::make(pub))]
566#[derive(Clone)]
567pub(crate) struct CryptStatePair<EtBC, PrfBC>
568where
569 EtBC: BlkCipher,
570 PrfBC: BlkCipherEnc,
571{
572 outbound: CryptState<EtBC, PrfBC>,
574 inbound: CryptState<EtBC, PrfBC>,
576 binding: CircuitBinding,
578}
579
580impl<EtBC, PrfBC> CryptInit for CryptStatePair<EtBC, PrfBC>
581where
582 EtBC: BlkCipher,
583 PrfBC: BlkCipherEnc,
584{
585 fn seed_len() -> usize {
586 CryptState::<EtBC, PrfBC>::seed_len() * 2 + crate::crypto::binding::CIRC_BINDING_LEN
587 }
588 fn initialize(seed: &[u8]) -> crate::Result<Self> {
589 const {
590 assert!(EtBC::KEY_LEN == PrfBC::KEY_LEN);
592 }
593 if seed.len() != Self::seed_len() {
594 return Err(internal!("Invalid seed length").into());
595 }
596 let slen = CryptState::<EtBC, PrfBC>::seed_len();
597 let (outb, inb, binding) = (&seed[0..slen], &seed[slen..slen * 2], &seed[slen * 2..]);
598 Ok(Self {
599 outbound: CryptState::initialize(outb)?,
600 inbound: CryptState::initialize(inb)?,
601 binding: binding.try_into().expect("Invalid slice length"),
602 })
603 }
604}
605
606impl<EtBC, PrfBC> super::ClientLayer<ClientOutbound<EtBC, PrfBC>, ClientInbound<EtBC, PrfBC>>
607 for CryptStatePair<EtBC, PrfBC>
608where
609 EtBC: BlkCipherDec,
610 PrfBC: BlkCipherEnc,
611{
612 fn split_client_layer(
613 self,
614 ) -> (
615 ClientOutbound<EtBC, PrfBC>,
616 ClientInbound<EtBC, PrfBC>,
617 CircuitBinding,
618 ) {
619 (self.outbound.into(), self.inbound.into(), self.binding)
620 }
621}
622
623impl<EtBC, PrfBC> super::RelayLayer<RelayOutbound<EtBC, PrfBC>, RelayInbound<EtBC, PrfBC>>
624 for CryptStatePair<EtBC, PrfBC>
625where
626 EtBC: BlkCipherEnc,
627 PrfBC: BlkCipherEnc,
628{
629 fn split_relay_layer(
630 self,
631 ) -> (
632 RelayOutbound<EtBC, PrfBC>,
633 RelayInbound<EtBC, PrfBC>,
634 CircuitBinding,
635 ) {
636 (self.outbound.into(), self.inbound.into(), self.binding)
637 }
638}
639
640#[cfg(feature = "bench")]
642pub mod bench_utils {
643 pub use super::ClientInbound;
644 pub use super::ClientOutbound;
645 pub use super::CryptStatePair;
646 pub use super::RelayInbound;
647 pub use super::RelayOutbound;
648
649 pub const CGO_THROUGHPUT: u64 = 488;
651}
652
653#[cfg(test)]
654mod test {
655 #![allow(clippy::bool_assert_comparison)]
657 #![allow(clippy::clone_on_copy)]
658 #![allow(clippy::dbg_macro)]
659 #![allow(clippy::mixed_attributes_style)]
660 #![allow(clippy::print_stderr)]
661 #![allow(clippy::print_stdout)]
662 #![allow(clippy::single_char_pattern)]
663 #![allow(clippy::unwrap_used)]
664 #![allow(clippy::unchecked_time_subtraction)]
665 #![allow(clippy::useless_vec)]
666 #![allow(clippy::needless_pass_by_value)]
667 use crate::crypto::cell::{
670 InboundRelayLayer, OutboundClientCrypt, OutboundClientLayer, OutboundRelayLayer,
671 };
672
673 use super::*;
674 use hex_literal::hex;
675 use rand::Rng as _;
676 use tor_basic_utils::test_rng::testing_rng;
677
678 #[test]
679 fn testvec_xor() {
680 let mut b: [u8; 20] = *b"turning and turning ";
681 let s = b"in the widening gyre";
682 xor_into(&mut b, s);
683 assert_eq!(b[..], hex!("1d1b521a010b4757080a014e1d1b154e0e171545"));
684 }
685
686 #[test]
687 fn testvec_polyval() {
688 use polyval::Polyval;
689 use polyval::universal_hash::UniversalHash;
690
691 let h = hex!("25629347589242761d31f826ba4b757b");
693 let x_1 = hex!("4f4f95668c83dfb6401762bb2d01a262");
694 let x_2 = hex!("d1a24ddd2721d006bbe45f20d3c9f362");
695
696 let mut hash = Polyval::new(&h.into());
697 hash.update(&[x_1.into(), x_2.into()]);
698 let result: [u8; 16] = hash.finalize().into();
699 assert_eq!(result, hex!("f7a3b47b846119fae5b7866cf5e5b77e"));
700 }
701
702 #[allow(non_upper_case_globals)]
704 const False: bool = false;
705 #[allow(non_upper_case_globals)]
706 const True: bool = true;
707 include!("../../../testdata/cgo_et.rs");
708 include!("../../../testdata/cgo_prf.rs");
709 include!("../../../testdata/cgo_uiv.rs");
710 include!("../../../testdata/cgo_relay.rs");
711 include!("../../../testdata/cgo_client.rs");
712
713 fn unhex<const N: usize>(s: &str) -> [u8; N] {
715 hex::decode(s).unwrap().try_into().unwrap()
716 }
717
718 #[test]
719 fn testvec_et() {
720 for (encrypt, keys, tweak, input, expect_output) in ET_TEST_VECTORS {
721 let keys: [u8; 32] = unhex(keys);
722 let tweak: [u8; et::TLEN_ET] = unhex(tweak);
723 let mut block: [u8; 16] = unhex(input);
724 let expect_output: [u8; 16] = unhex(expect_output);
725 let et: et::EtCipher<Aes128> = et::EtCipher::initialize(&keys).unwrap();
726 let tweak = (
727 tweak[0..16].try_into().unwrap(),
728 tweak[16],
729 &tweak[17..].try_into().unwrap(),
730 );
731 if *encrypt {
732 et.encrypt(tweak, &mut block);
733 } else {
734 et.decrypt(tweak, &mut block);
735 }
736 assert_eq!(block, expect_output);
737 }
738 }
739
740 #[test]
741 fn testvec_prf() {
742 for (keys, offset, tweak, expect_output) in PRF_TEST_VECTORS {
743 let keys: [u8; 32] = unhex(keys);
744 assert!([0, 1].contains(offset));
745 let tweak: [u8; 16] = unhex(tweak);
746 let expect_output = hex::decode(expect_output).unwrap();
747 let prf: prf::Prf<Aes128> = prf::Prf::initialize(&keys).unwrap();
748 if *offset == 0 {
749 assert_eq!(expect_output.len(), CGO_PAYLOAD_LEN);
750 let mut data = [0_u8; CGO_PAYLOAD_LEN];
751 prf.xor_n0_stream(&tweak, &mut data);
752 assert_eq!(expect_output[..], data[..]);
753 } else {
754 let data = prf.get_n1_stream(&tweak, expect_output.len());
755 assert_eq!(expect_output[..], data[..]);
756 }
757 }
758 }
759
760 #[test]
761 fn testvec_uiv() {
762 for (encrypt, keys, tweak, left, right, (expect_left, expect_right)) in UIV_TEST_VECTORS {
763 let keys: [u8; 64] = unhex(keys);
764 let tweak: [u8; 17] = unhex(tweak);
765 let mut cell: [u8; 509] = unhex(&format!("{left}{right}"));
766 let expected: [u8; 509] = unhex(&format!("{expect_left}{expect_right}"));
767
768 let uiv: uiv::Uiv<Aes128, Aes128> = uiv::Uiv::initialize(&keys).unwrap();
769 let htweak = (tweak[0..16].try_into().unwrap(), tweak[16]);
770 if *encrypt {
771 uiv.encrypt(htweak, &mut cell);
772 } else {
773 uiv.decrypt(htweak, &mut cell);
774 }
775 assert_eq!(cell, expected);
776 }
777 }
778
779 #[test]
780 fn testvec_uiv_update() {
781 let mut rng = testing_rng();
782
783 for (keys, nonce, (expect_keys, expect_nonce)) in UIV_UPDATE_TEST_VECTORS {
784 let keys: [u8; 64] = unhex(keys);
785 let mut nonce: [u8; 16] = unhex(nonce);
786 let mut uiv: uiv::Uiv<Aes128, Aes128> = uiv::Uiv::initialize(&keys).unwrap();
787 let expect_keys: [u8; 64] = unhex(expect_keys);
788 let expect_nonce: [u8; 16] = unhex(expect_nonce);
789 uiv.update(&mut nonce);
790 assert_eq!(&nonce, &expect_nonce);
791 assert_eq!(&uiv.keys[..], &expect_keys[..]);
792
793 let uiv2: uiv::Uiv<Aes128, Aes128> = uiv::Uiv::initialize(&uiv.keys[..]).unwrap();
796
797 let tweak: [u8; 16] = rng.random();
798 let cmd = rng.random();
799 let mut msg1: [u8; CELL_DATA_LEN] = rng.random();
800 let mut msg2 = msg1.clone();
801
802 uiv.encrypt((&tweak, cmd), &mut msg1);
803 uiv2.encrypt((&tweak, cmd), &mut msg2);
804 }
805 }
806
807 #[test]
808 fn testvec_cgo_relay() {
809 for (inbound, (k, n, tprime), ad, t, c, output) in CGO_RELAY_TEST_VECTORS {
810 let k_n: [u8; 80] = unhex(&format!("{k}{n}"));
811 let tprime: [u8; 16] = unhex(tprime);
812 let ad: [u8; 1] = unhex(ad);
813 let msg: [u8; CELL_DATA_LEN] = unhex(&format!("{t}{c}"));
814 let mut msg = RelayCellBody(Box::new(msg));
815
816 let mut state = CryptState::<Aes128, Aes128>::initialize(&k_n).unwrap();
817 *state.tag = tprime;
818 let state = if *inbound {
819 let mut s = RelayInbound::from(state);
820 s.encrypt_inbound(ad[0].into(), &mut msg);
821 s.0
822 } else {
823 let mut s = RelayOutbound::from(state);
824 s.decrypt_outbound(ad[0].into(), &mut msg);
825 s.0
826 };
827
828 let ((ex_k, ex_n, ex_tprime), (ex_t, ex_c)) = output;
830 let ex_msg: [u8; CELL_DATA_LEN] = unhex(&format!("{ex_t}{ex_c}"));
831 let ex_k: [u8; 64] = unhex(ex_k);
832 let ex_n: [u8; 16] = unhex(ex_n);
833 let ex_tprime: [u8; 16] = unhex(ex_tprime);
834 assert_eq!(&ex_msg[..], &msg.0[..]);
835 assert_eq!(&state.uiv.keys[..], &ex_k[..]);
836 assert_eq!(&state.nonce[..], &ex_n[..]);
837 assert_eq!(&state.tag[..], &ex_tprime[..]);
838 }
839 }
840
841 #[test]
842 fn testvec_cgo_relay_originate() {
843 for ((k, n, tprime), ad, m, output) in CGO_RELAY_ORIGINATE_TEST_VECTORS {
844 let k_n: [u8; 80] = unhex(&format!("{k}{n}"));
845 let tprime: [u8; 16] = unhex(tprime);
846 let ad: [u8; 1] = unhex(ad);
847 let msg_body: [u8; CGO_PAYLOAD_LEN] = unhex(m);
848 let mut msg = [0_u8; CELL_DATA_LEN];
849 msg[16..].copy_from_slice(&msg_body[..]);
850 let mut msg = RelayCellBody(Box::new(msg));
851
852 let mut state = CryptState::<Aes128, Aes128>::initialize(&k_n).unwrap();
853 *state.tag = tprime;
854 let mut state = RelayInbound::from(state);
855 state.originate(ad[0].into(), &mut msg);
856 let state = state.0;
857
858 let ((ex_k, ex_n, ex_tprime), (ex_t, ex_c)) = output;
859 let ex_msg: [u8; CELL_DATA_LEN] = unhex(&format!("{ex_t}{ex_c}"));
860 let ex_k: [u8; 64] = unhex(ex_k);
861 let ex_n: [u8; 16] = unhex(ex_n);
862 let ex_tprime: [u8; 16] = unhex(ex_tprime);
863 assert_eq!(&ex_msg[..], &msg.0[..]);
864 assert_eq!(&state.uiv.keys[..], &ex_k[..]);
865 assert_eq!(&state.nonce[..], &ex_n[..]);
866 assert_eq!(&state.tag[..], &ex_tprime[..]);
867 }
868 }
869
870 #[test]
871 fn testvec_cgo_client_originate() {
872 for (ss, hop, ad, m, output) in CGO_CLIENT_ORIGINATE_TEST_VECTORS {
873 assert!(*hop > 0); let mut client = OutboundClientCrypt::new();
875 let mut individual_layers = Vec::new();
876 for (k, n, tprime) in ss {
877 let k_n: [u8; 80] = unhex(&format!("{k}{n}"));
878 let tprime: [u8; 16] = unhex(tprime);
879 let mut state = CryptState::<Aes128, Aes128>::initialize(&k_n).unwrap();
880 *state.tag = tprime;
881 client.add_layer(Box::new(ClientOutbound::from(state.clone())));
882 individual_layers.push(ClientOutbound::from(state));
883 }
884
885 let ad: [u8; 1] = unhex(ad);
886 let msg_body: [u8; CGO_PAYLOAD_LEN] = unhex(m);
887 let mut msg = [0_u8; CELL_DATA_LEN];
888 msg[16..].copy_from_slice(&msg_body[..]);
889 let mut msg = RelayCellBody(Box::new(msg));
890 let mut msg2 = msg.clone();
891
892 client
894 .encrypt(ad[0].into(), &mut msg, (*hop - 1).into())
895 .unwrap();
896 {
900 let hop_idx = usize::from(*hop) - 1;
901 individual_layers[hop_idx].originate_for(ad[0].into(), &mut msg2);
902 for idx in (0..hop_idx).rev() {
903 individual_layers[idx].encrypt_outbound(ad[0].into(), &mut msg2);
904 }
905 }
906 assert_eq!(&msg.0[..], &msg2.0[..]);
907
908 let (ex_ss, (ex_t, ex_c)) = output;
909 let ex_msg: [u8; CELL_DATA_LEN] = unhex(&format!("{ex_t}{ex_c}"));
910 assert_eq!(&ex_msg[..], &msg.0[..]);
911
912 for (layer, (ex_k, ex_n, ex_tprime)) in individual_layers.iter().zip(ex_ss.iter()) {
913 let state = &layer.0;
914 let ex_k: [u8; 64] = unhex(ex_k);
915 let ex_n: [u8; 16] = unhex(ex_n);
916 let ex_tprime: [u8; 16] = unhex(ex_tprime);
917
918 assert_eq!(&state.uiv.keys[..], &ex_k[..]);
919 assert_eq!(&state.nonce[..], &ex_n[..]);
920 assert_eq!(&state.tag[..], &ex_tprime);
921 }
922 }
923 }
924}