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::{universal_hash::UniversalHash, Polyval};
25use static_assertions::const_assert;
26use tor_cell::{
27 chancell::{ChanCmd, CELL_DATA_LEN},
28 relaycell::msg::SendmeTag,
29};
30use tor_error::internal;
31use zeroize::Zeroizing;
32
33use super::{CryptInit, RelayCellBody};
34use crate::{circuit::CircuitBinding, util::ct};
35
36const CGO_TAG_LEN: usize = 16;
38const CGO_PAYLOAD_LEN: usize = CELL_DATA_LEN - CGO_TAG_LEN;
40
41const CGO_AD_LEN: usize = 16;
45
46const HLEN_UIV: usize = CGO_TAG_LEN + CGO_AD_LEN;
48
49const BLK_LEN: usize = 16;
52type BlockLen = typenum::U16;
55type Block = [u8; BLK_LEN];
57
58pub(crate) trait BlkCipher:
63 BlockCipher + KeyInit + BlockSizeUser<BlockSize = BlockLen> + Clone
64{
65 const KEY_LEN: usize;
67}
68
69pub(crate) trait BlkCipherEnc: BlkCipher + BlockEncrypt {}
74
75pub(crate) trait BlkCipherDec: BlkCipher + BlockDecrypt {}
80
81impl BlkCipher for Aes128 {
82 const KEY_LEN: usize = 16;
83}
84impl BlkCipherEnc for Aes128 {}
85impl BlkCipherDec for Aes128 {}
86impl BlkCipher for Aes128Enc {
87 const KEY_LEN: usize = 16;
88}
89impl BlkCipherEnc for Aes128Enc {}
90impl BlkCipher for Aes128Dec {
91 const KEY_LEN: usize = 16;
92}
93impl BlkCipherDec for Aes128Dec {}
94
95impl BlkCipher for Aes256 {
96 const KEY_LEN: usize = 32;
97}
98impl BlkCipherEnc for Aes256 {}
99impl BlkCipherDec for Aes256 {}
100impl BlkCipher for Aes256Enc {
101 const KEY_LEN: usize = 32;
102}
103impl BlkCipherEnc for Aes256Enc {}
104impl BlkCipher for Aes256Dec {
105 const KEY_LEN: usize = 32;
106}
107impl BlkCipherDec for Aes256Dec {}
108
109mod et {
111 use super::*;
112
113 pub(super) type EtTweak<'a> = (&'a [u8; CGO_TAG_LEN], u8, &'a [u8; CGO_PAYLOAD_LEN]);
118 pub(super) const TLEN_ET: usize = CGO_TAG_LEN + 1 + CGO_PAYLOAD_LEN;
120
121 #[derive(Clone)]
127 pub(super) struct EtCipher<BC: BlkCipher> {
128 kb: BC,
130 ku: Polyval,
132 }
133 impl<BC: BlkCipher> EtCipher<BC> {
134 fn compute_tweak_hash(&self, tweak: EtTweak<'_>) -> Zeroizing<Block> {
137 let mut ku = self.ku.clone();
140
141 let mut block1 = Zeroizing::new([0_u8; 16]);
142 block1[0] = tweak.1;
143 block1[1..16].copy_from_slice(&tweak.2[0..15]);
144 ku.update(&[(*tweak.0).into(), (*block1).into()]);
145 ku.update_padded(&tweak.2[15..]);
146 Zeroizing::new(ku.finalize().into())
147 }
148 }
149 impl<BC: BlkCipherEnc> EtCipher<BC> {
150 pub(super) fn encrypt(&self, tweak: EtTweak<'_>, block: &mut Block) {
152 let tag: Zeroizing<[u8; 16]> = self.compute_tweak_hash(tweak);
154 xor_into(block, &tag);
155 self.kb.encrypt_block(block.into());
156 xor_into(block, &tag);
157 }
158 }
159 impl<BC: BlkCipherDec> EtCipher<BC> {
160 pub(super) fn decrypt(&self, tweak: EtTweak<'_>, block: &mut Block) {
162 let tag: Zeroizing<[u8; 16]> = self.compute_tweak_hash(tweak);
164 xor_into(block, &tag);
165 self.kb.decrypt_block(block.into());
166 xor_into(block, &tag);
167 }
168 }
169 impl<BC: BlkCipher> CryptInit for EtCipher<BC> {
170 fn seed_len() -> usize {
171 BC::key_size() + polyval::KEY_SIZE
172 }
173 fn initialize(seed: &[u8]) -> crate::Result<Self> {
174 if seed.len() != Self::seed_len() {
177 return Err(internal!("Invalid seed length").into());
178 }
179 let (kb, ku) = seed.split_at(BC::key_size());
180 Ok(Self {
181 kb: BC::new(kb.into()),
182 ku: Polyval::new(ku.into()),
183 })
184 }
185 }
186}
187
188mod prf {
190 use tor_error::internal;
191
192 use super::*;
193
194 type PrfTweak = [u8; 16];
196 const PRF_N0_LEN: usize = CGO_PAYLOAD_LEN;
198 const PRF_N1_OFFSET: usize = 31 * 16;
200 const_assert!(PRF_N1_OFFSET >= PRF_N0_LEN);
201
202 #[derive(Clone)]
207 pub(super) struct Prf<BC: BlkCipherEnc> {
208 k: BC,
210 b: Polyval,
212 }
213 impl<BC: BlkCipherEnc> Prf<BC> {
214 fn cipher(&self, tweak: &PrfTweak, t: bool) -> ctr::Ctr128BE<BC> {
217 use {
218 cipher::{InnerIvInit as _, StreamCipherSeek as _},
219 ctr::CtrCore,
220 };
221 let mut b = self.b.clone(); b.update(&[(*tweak).into()]);
223 let mut iv = b.finalize();
224 *iv.last_mut().expect("no last element?") &= 0xC0; let mut cipher: ctr::Ctr128BE<BC> = cipher::StreamCipherCoreWrapper::from_core(
226 CtrCore::inner_iv_init(self.k.clone(), &iv),
227 );
228 if t {
229 debug_assert_eq!(cipher.current_pos::<u32>(), 0_u32);
230 cipher.seek(PRF_N1_OFFSET);
231 }
232
233 cipher
234 }
235
236 pub(super) fn xor_n0_stream(&self, tweak: &PrfTweak, out: &mut [u8; PRF_N0_LEN]) {
239 let mut stream = self.cipher(tweak, false);
240 stream.apply_keystream(out);
241 }
242
243 pub(super) fn get_n1_stream(&self, tweak: &PrfTweak, n: usize) -> Zeroizing<Vec<u8>> {
246 let mut output = Zeroizing::new(vec![0_u8; n]);
247 self.cipher(tweak, true).apply_keystream(output.as_mut());
248 output
249 }
250 }
251
252 impl<BC: BlkCipherEnc> CryptInit for Prf<BC> {
253 fn seed_len() -> usize {
254 BC::key_size() + polyval::KEY_SIZE
255 }
256 fn initialize(seed: &[u8]) -> crate::Result<Self> {
257 if seed.len() != Self::seed_len() {
258 return Err(internal!("Invalid seed length").into());
259 }
260 let (k, b) = seed.split_at(BC::key_size());
261 Ok(Self {
262 k: BC::new(k.into()),
263 b: Polyval::new(b.into()),
264 })
265 }
266 }
267}
268
269mod uiv {
273 use super::*;
274
275 pub(super) type UivTweak<'a> = (&'a [u8; BLK_LEN], u8);
277
278 #[derive(Clone)]
280 pub(super) struct Uiv<EtBC: BlkCipher, PrfBC: BlkCipherEnc> {
281 j: et::EtCipher<EtBC>,
283 s: prf::Prf<PrfBC>,
285
286 #[cfg(test)]
291 pub(super) keys: Zeroizing<Vec<u8>>,
292 }
293
294 fn split(
297 cell_body: &mut [u8; CELL_DATA_LEN],
298 ) -> (&mut [u8; CGO_TAG_LEN], &mut [u8; CGO_PAYLOAD_LEN]) {
299 let (left, right) = cell_body.split_at_mut(CGO_TAG_LEN);
301 (
302 left.try_into().expect("split_at_mut returned wrong size!"),
303 right.try_into().expect("split_at_mut returned wrong size!"),
304 )
305 }
306
307 impl<EtBC: BlkCipherEnc, PrfBC: BlkCipherEnc> Uiv<EtBC, PrfBC> {
308 pub(super) fn encrypt(&self, tweak: UivTweak<'_>, cell_body: &mut [u8; CELL_DATA_LEN]) {
312 let (left, right) = split(cell_body);
317 self.j.encrypt((tweak.0, tweak.1, right), left);
318 self.s.xor_n0_stream(left, right);
319 }
320 }
321 impl<EtBC: BlkCipherDec, PrfBC: BlkCipherEnc> Uiv<EtBC, PrfBC> {
322 pub(super) fn decrypt(&self, tweak: UivTweak<'_>, cell_body: &mut [u8; CELL_DATA_LEN]) {
326 let (left, right) = split(cell_body);
331 self.s.xor_n0_stream(left, right);
332 self.j.decrypt((tweak.0, tweak.1, right), left);
333 }
334 }
335 impl<EtBC: BlkCipher, PrfBC: BlkCipherEnc> Uiv<EtBC, PrfBC> {
336 pub(super) fn update(&mut self, nonce: &mut [u8; BLK_LEN]) {
341 let n_bytes = Self::seed_len() + BLK_LEN;
349 let seed = self.s.get_n1_stream(nonce, n_bytes);
350 #[cfg(test)]
351 {
352 self.keys = Zeroizing::new(seed[..Self::seed_len()].to_vec());
353 }
354 let (j, s, n) = Self::split_seed(&seed);
355 self.j = et::EtCipher::initialize(j).expect("Invalid slice len");
356 self.s = prf::Prf::initialize(s).expect("invalid slice len");
357 nonce[..].copy_from_slice(n);
358 }
359
360 fn split_seed(seed: &[u8]) -> (&[u8], &[u8], &[u8]) {
362 let len_j = et::EtCipher::<EtBC>::seed_len();
363 let len_s = prf::Prf::<PrfBC>::seed_len();
364 (
365 &seed[0..len_j],
366 &seed[len_j..len_j + len_s],
367 &seed[len_j + len_s..],
368 )
369 }
370 }
371
372 impl<EtBC: BlkCipher, PrfBC: BlkCipherEnc> CryptInit for Uiv<EtBC, PrfBC> {
373 fn seed_len() -> usize {
374 super::et::EtCipher::<EtBC>::seed_len() + super::prf::Prf::<PrfBC>::seed_len()
375 }
376 fn initialize(seed: &[u8]) -> crate::Result<Self> {
377 if seed.len() != Self::seed_len() {
378 return Err(internal!("Invalid seed length").into());
379 }
380 #[cfg(test)]
381 let keys = Zeroizing::new(seed.to_vec());
382 let (j, s, n) = Self::split_seed(seed);
383 debug_assert!(n.is_empty());
384 Ok(Self {
385 j: et::EtCipher::initialize(j)?,
386 s: prf::Prf::initialize(s)?,
387 #[cfg(test)]
388 keys,
389 })
390 }
391 }
392}
393
394fn xor_into<const N: usize>(output: &mut [u8; N], input: &[u8; N]) {
396 for i in 0..N {
397 output[i] ^= input[i];
398 }
399}
400
401#[inline]
406fn first_block(bytes: &[u8]) -> &[u8; BLK_LEN] {
407 bytes[0..BLK_LEN].try_into().expect("Slice too short!")
408}
409
410#[derive(Clone)]
412struct CryptState<EtBC: BlkCipher, PrfBC: BlkCipherEnc> {
413 uiv: uiv::Uiv<EtBC, PrfBC>,
415 nonce: Zeroizing<[u8; BLK_LEN]>,
417 tag: Zeroizing<[u8; BLK_LEN]>,
419}
420
421impl<EtBC: BlkCipher, PrfBC: BlkCipherEnc> CryptInit for CryptState<EtBC, PrfBC> {
422 fn seed_len() -> usize {
423 uiv::Uiv::<EtBC, PrfBC>::seed_len() + BLK_LEN
424 }
425 fn initialize(seed: &[u8]) -> crate::Result<Self> {
427 if seed.len() != Self::seed_len() {
428 return Err(internal!("Invalid seed length").into());
429 }
430 let (j_s, n) = seed.split_at(uiv::Uiv::<EtBC, PrfBC>::seed_len());
431 Ok(Self {
432 uiv: uiv::Uiv::initialize(j_s)?,
433 nonce: Zeroizing::new(n.try_into().expect("invalid splice length")),
434 tag: Zeroizing::new([0; BLK_LEN]),
435 })
436 }
437}
438
439#[derive(Clone, derive_more::From)]
441pub(crate) struct ClientOutbound<EtBC, PrfBC>(CryptState<EtBC, PrfBC>)
442where
443 EtBC: BlkCipherDec,
444 PrfBC: BlkCipherEnc;
445impl<EtBC, PrfBC> super::OutboundClientLayer for ClientOutbound<EtBC, PrfBC>
446where
447 EtBC: BlkCipherDec,
448 PrfBC: BlkCipherEnc,
449{
450 fn originate_for(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) -> SendmeTag {
451 cell.0[0..BLK_LEN].copy_from_slice(&self.0.nonce[..]);
452 self.encrypt_outbound(cmd, cell);
453 self.0.uiv.update(&mut self.0.nonce);
454 SendmeTag::try_from(&cell.0[0..BLK_LEN]).expect("Block length not a valid sendme tag.")
455 }
456 fn encrypt_outbound(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) {
457 let t_new: [u8; BLK_LEN] = *first_block(&*cell.0);
459
460 self.0.uiv.decrypt((&self.0.tag, cmd.into()), &mut cell.0);
463 *self.0.tag = t_new;
464 }
465}
466
467#[derive(Clone, derive_more::From)]
469pub(crate) struct ClientInbound<EtBC, PrfBC>(CryptState<EtBC, PrfBC>)
470where
471 EtBC: BlkCipherDec,
472 PrfBC: BlkCipherEnc;
473impl<EtBC, PrfBC> super::InboundClientLayer for ClientInbound<EtBC, PrfBC>
474where
475 EtBC: BlkCipherDec,
476 PrfBC: BlkCipherEnc,
477{
478 fn decrypt_inbound(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) -> Option<SendmeTag> {
479 let mut t_orig: [u8; BLK_LEN] = *first_block(&*cell.0);
480 self.0.uiv.decrypt((&self.0.tag, cmd.into()), &mut cell.0);
485 *self.0.tag = t_orig;
486 if ct::bytes_eq(&cell.0[..CGO_TAG_LEN], &self.0.nonce[..]) {
487 self.0.uiv.update(&mut t_orig);
488 *self.0.nonce = t_orig;
489 Some((*self.0.tag).into())
491 } else {
492 None
493 }
494 }
495}
496
497#[derive(Clone, derive_more::From)]
499pub(crate) struct RelayOutbound<EtBC, PrfBC>(CryptState<EtBC, PrfBC>)
500where
501 EtBC: BlkCipherEnc,
502 PrfBC: BlkCipherEnc;
503impl<EtBC, PrfBC> super::OutboundRelayLayer for RelayOutbound<EtBC, PrfBC>
504where
505 EtBC: BlkCipherEnc,
506 PrfBC: BlkCipherEnc,
507{
508 fn decrypt_outbound(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) -> Option<SendmeTag> {
509 let tag = SendmeTag::try_from(&cell.0[0..BLK_LEN]).expect("Invalid sendme length");
510 self.0.uiv.encrypt((&self.0.tag, cmd.into()), &mut cell.0);
513 *self.0.tag = *first_block(&*cell.0);
514 if ct::bytes_eq(self.0.tag.as_ref(), &self.0.nonce[..]) {
515 self.0.uiv.update(&mut self.0.nonce);
516 Some(tag)
517 } else {
518 None
519 }
520 }
521}
522
523#[derive(Clone, derive_more::From)]
525pub(crate) struct RelayInbound<EtBC, PrfBC>(CryptState<EtBC, PrfBC>)
526where
527 EtBC: BlkCipherEnc,
528 PrfBC: BlkCipherEnc;
529impl<EtBC, PrfBC> super::InboundRelayLayer for RelayInbound<EtBC, PrfBC>
530where
531 EtBC: BlkCipherEnc,
532 PrfBC: BlkCipherEnc,
533{
534 fn originate(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) -> SendmeTag {
535 cell.0[0..BLK_LEN].copy_from_slice(&self.0.nonce[..]);
536 self.encrypt_inbound(cmd, cell);
537 self.0.nonce.copy_from_slice(&cell.0[0..BLK_LEN]);
538 self.0.uiv.update(&mut self.0.nonce);
539 (*self.0.tag).into()
541 }
542 fn encrypt_inbound(&mut self, cmd: ChanCmd, cell: &mut RelayCellBody) {
543 self.0.uiv.encrypt((&self.0.tag, cmd.into()), &mut cell.0);
546 *self.0.tag = *first_block(&*cell.0);
547 }
548}
549
550#[derive(Clone)]
553pub(crate) struct CryptStatePair<EtBC, PrfBC>
554where
555 EtBC: BlkCipher,
556 PrfBC: BlkCipherEnc,
557{
558 outbound: CryptState<EtBC, PrfBC>,
560 inbound: CryptState<EtBC, PrfBC>,
562 binding: CircuitBinding,
564}
565
566impl<EtBC, PrfBC> CryptInit for CryptStatePair<EtBC, PrfBC>
567where
568 EtBC: BlkCipher,
569 PrfBC: BlkCipherEnc,
570{
571 fn seed_len() -> usize {
572 CryptState::<EtBC, PrfBC>::seed_len() * 2 + crate::crypto::binding::CIRC_BINDING_LEN
573 }
574 fn initialize(seed: &[u8]) -> crate::Result<Self> {
575 assert_eq!(EtBC::KEY_LEN, PrfBC::KEY_LEN);
576 if seed.len() != Self::seed_len() {
582 return Err(internal!("Invalid seed length").into());
583 }
584 let slen = CryptState::<EtBC, PrfBC>::seed_len();
585 let (outb, inb, binding) = (&seed[0..slen], &seed[slen..slen * 2], &seed[slen * 2..]);
586 Ok(Self {
587 outbound: CryptState::initialize(outb)?,
588 inbound: CryptState::initialize(inb)?,
589 binding: binding.try_into().expect("Invalid slice length"),
590 })
591 }
592}
593
594impl<EtBC, PrfBC> super::ClientLayer<ClientOutbound<EtBC, PrfBC>, ClientInbound<EtBC, PrfBC>>
595 for CryptStatePair<EtBC, PrfBC>
596where
597 EtBC: BlkCipherDec,
598 PrfBC: BlkCipherEnc,
599{
600 fn split_client_layer(
601 self,
602 ) -> (
603 ClientOutbound<EtBC, PrfBC>,
604 ClientInbound<EtBC, PrfBC>,
605 CircuitBinding,
606 ) {
607 (self.outbound.into(), self.inbound.into(), self.binding)
608 }
609}
610
611impl<EtBC, PrfBC> super::RelayLayer<RelayOutbound<EtBC, PrfBC>, RelayInbound<EtBC, PrfBC>>
612 for CryptStatePair<EtBC, PrfBC>
613where
614 EtBC: BlkCipherEnc,
615 PrfBC: BlkCipherEnc,
616{
617 fn split_relay_layer(
618 self,
619 ) -> (
620 RelayOutbound<EtBC, PrfBC>,
621 RelayInbound<EtBC, PrfBC>,
622 CircuitBinding,
623 ) {
624 (self.outbound.into(), self.inbound.into(), self.binding)
625 }
626}
627
628#[cfg(feature = "bench")]
630pub mod bench_utils {
631 #![allow(private_bounds)]
633 use super::*;
634
635 use crate::bench_utils::{
636 InboundClientLayerWrapper, OutboundClientLayerWrapper, RelayBody, RelayCryptState,
637 };
638 use crate::crypto::cell::{ClientLayer, InboundRelayLayer, OutboundRelayLayer, RelayLayer};
639 use crate::crypto::handshake::ShakeKeyGenerator as KGen;
640 use crate::Result;
641 use tor_bytes::SecretBuf;
642
643 pub const CGO_THROUGHPUT: u64 = 488;
645
646 pub struct CgoClientCryptState<EtBC: BlkCipherDec, PrfBC: BlkCipherEnc> {
648 fwd: ClientOutbound<EtBC, PrfBC>,
650 back: ClientInbound<EtBC, PrfBC>,
652 }
653
654 impl<EtBC: BlkCipherDec, PrfBC: BlkCipherEnc> CgoClientCryptState<EtBC, PrfBC> {
655 pub fn construct(seed: SecretBuf) -> Result<Self> {
657 let (outbound, inbound, _) =
658 CryptStatePair::construct(KGen::new(seed))?.split_client_layer();
659 Ok(Self {
660 back: inbound,
661 fwd: outbound,
662 })
663 }
664 }
665
666 impl<EtBC, PrfBC> From<CgoClientCryptState<EtBC, PrfBC>> for OutboundClientLayerWrapper
667 where
668 EtBC: BlkCipherDec + Send + 'static,
669 PrfBC: BlkCipherEnc + Send + 'static,
670 {
671 fn from(state: CgoClientCryptState<EtBC, PrfBC>) -> Self {
672 Self(Box::new(state.fwd))
673 }
674 }
675
676 impl<EtBC, PrfBC> From<CgoClientCryptState<EtBC, PrfBC>> for InboundClientLayerWrapper
677 where
678 EtBC: BlkCipherDec + Send + 'static,
679 PrfBC: BlkCipherEnc + Send + 'static,
680 {
681 fn from(state: CgoClientCryptState<EtBC, PrfBC>) -> Self {
682 Self(Box::new(state.back))
683 }
684 }
685
686 pub struct CgoRelayCryptState<EtBC: BlkCipherEnc, PrfBC: BlkCipherEnc> {
688 fwd: RelayOutbound<EtBC, PrfBC>,
690 back: RelayInbound<EtBC, PrfBC>,
692 }
693
694 impl<EtBC: BlkCipherEnc, PrfBC: BlkCipherEnc> CgoRelayCryptState<EtBC, PrfBC> {
695 pub fn construct(seed: SecretBuf) -> Result<Self> {
697 let (outbound, inbound, _) =
698 CryptStatePair::construct(KGen::new(seed))?.split_relay_layer();
699 Ok(Self {
700 back: inbound,
701 fwd: outbound,
702 })
703 }
704 }
705
706 impl<EtBC: BlkCipherEnc, PrfBC: BlkCipherEnc> RelayCryptState for CgoRelayCryptState<EtBC, PrfBC> {
707 fn originate(&mut self, cell: &mut RelayBody) {
708 let cell = &mut cell.0;
709 self.back.originate(ChanCmd::RELAY, cell);
710 }
711
712 fn encrypt(&mut self, cell: &mut RelayBody) {
713 let cell = &mut cell.0;
714 self.back.encrypt_inbound(ChanCmd::RELAY, cell);
715 }
716
717 fn decrypt(&mut self, cell: &mut RelayBody) {
718 let cell = &mut cell.0;
719 self.fwd.decrypt_outbound(ChanCmd::RELAY, cell);
720 }
721 }
722}
723
724#[cfg(test)]
725mod test {
726 #![allow(clippy::bool_assert_comparison)]
728 #![allow(clippy::clone_on_copy)]
729 #![allow(clippy::dbg_macro)]
730 #![allow(clippy::mixed_attributes_style)]
731 #![allow(clippy::print_stderr)]
732 #![allow(clippy::print_stdout)]
733 #![allow(clippy::single_char_pattern)]
734 #![allow(clippy::unwrap_used)]
735 #![allow(clippy::unchecked_duration_subtraction)]
736 #![allow(clippy::useless_vec)]
737 #![allow(clippy::needless_pass_by_value)]
738 use crate::crypto::cell::{
741 InboundRelayLayer, OutboundClientCrypt, OutboundClientLayer, OutboundRelayLayer,
742 };
743
744 use super::*;
745 use hex_literal::hex;
746 use rand::Rng as _;
747 use tor_basic_utils::test_rng::testing_rng;
748
749 #[test]
750 fn testvec_xor() {
751 let mut b: [u8; 20] = *b"turning and turning ";
752 let s = b"in the widening gyre";
753 xor_into(&mut b, s);
754 assert_eq!(b[..], hex!("1d1b521a010b4757080a014e1d1b154e0e171545"));
755 }
756
757 #[test]
758 fn testvec_polyval() {
759 use polyval::universal_hash::{KeyInit, UniversalHash};
760 use polyval::Polyval;
761
762 let h = hex!("25629347589242761d31f826ba4b757b");
764 let x_1 = hex!("4f4f95668c83dfb6401762bb2d01a262");
765 let x_2 = hex!("d1a24ddd2721d006bbe45f20d3c9f362");
766
767 let mut hash = Polyval::new(&h.into());
768 hash.update(&[x_1.into(), x_2.into()]);
769 let result: [u8; 16] = hash.finalize().into();
770 assert_eq!(result, hex!("f7a3b47b846119fae5b7866cf5e5b77e"));
771 }
772
773 #[allow(non_upper_case_globals)]
775 const False: bool = false;
776 #[allow(non_upper_case_globals)]
777 const True: bool = true;
778 include!("../../../testdata/cgo_et.rs");
779 include!("../../../testdata/cgo_prf.rs");
780 include!("../../../testdata/cgo_uiv.rs");
781 include!("../../../testdata/cgo_relay.rs");
782 include!("../../../testdata/cgo_client.rs");
783
784 fn unhex<const N: usize>(s: &str) -> [u8; N] {
786 hex::decode(s).unwrap().try_into().unwrap()
787 }
788
789 #[test]
790 fn testvec_et() {
791 for (encrypt, keys, tweak, input, expect_output) in ET_TEST_VECTORS {
792 let keys: [u8; 32] = unhex(keys);
793 let tweak: [u8; et::TLEN_ET] = unhex(tweak);
794 let mut block: [u8; 16] = unhex(input);
795 let expect_output: [u8; 16] = unhex(expect_output);
796 let et: et::EtCipher<Aes128> = et::EtCipher::initialize(&keys).unwrap();
797 let tweak = (
798 tweak[0..16].try_into().unwrap(),
799 tweak[16],
800 &tweak[17..].try_into().unwrap(),
801 );
802 if *encrypt {
803 et.encrypt(tweak, &mut block);
804 } else {
805 et.decrypt(tweak, &mut block);
806 }
807 assert_eq!(block, expect_output);
808 }
809 }
810
811 #[test]
812 fn testvec_prf() {
813 for (keys, offset, tweak, expect_output) in PRF_TEST_VECTORS {
814 let keys: [u8; 32] = unhex(keys);
815 assert!([0, 1].contains(offset));
816 let tweak: [u8; 16] = unhex(tweak);
817 let expect_output = hex::decode(expect_output).unwrap();
818 let prf: prf::Prf<Aes128> = prf::Prf::initialize(&keys).unwrap();
819 if *offset == 0 {
820 assert_eq!(expect_output.len(), CGO_PAYLOAD_LEN);
821 let mut data = [0_u8; CGO_PAYLOAD_LEN];
822 prf.xor_n0_stream(&tweak, &mut data);
823 assert_eq!(expect_output[..], data[..]);
824 } else {
825 let data = prf.get_n1_stream(&tweak, expect_output.len());
826 assert_eq!(expect_output[..], data[..]);
827 }
828 }
829 }
830
831 #[test]
832 fn testvec_uiv() {
833 for (encrypt, keys, tweak, left, right, (expect_left, expect_right)) in UIV_TEST_VECTORS {
834 let keys: [u8; 64] = unhex(keys);
835 let tweak: [u8; 17] = unhex(tweak);
836 let mut cell: [u8; 509] = unhex(&format!("{left}{right}"));
837 let expected: [u8; 509] = unhex(&format!("{expect_left}{expect_right}"));
838
839 let uiv: uiv::Uiv<Aes128, Aes128> = uiv::Uiv::initialize(&keys).unwrap();
840 let htweak = (tweak[0..16].try_into().unwrap(), tweak[16]);
841 if *encrypt {
842 uiv.encrypt(htweak, &mut cell);
843 } else {
844 uiv.decrypt(htweak, &mut cell);
845 }
846 assert_eq!(cell, expected);
847 }
848 }
849
850 #[test]
851 fn testvec_uiv_update() {
852 let mut rng = testing_rng();
853
854 for (keys, nonce, (expect_keys, expect_nonce)) in UIV_UPDATE_TEST_VECTORS {
855 let keys: [u8; 64] = unhex(keys);
856 let mut nonce: [u8; 16] = unhex(nonce);
857 let mut uiv: uiv::Uiv<Aes128, Aes128> = uiv::Uiv::initialize(&keys).unwrap();
858 let expect_keys: [u8; 64] = unhex(expect_keys);
859 let expect_nonce: [u8; 16] = unhex(expect_nonce);
860 uiv.update(&mut nonce);
861 assert_eq!(&nonce, &expect_nonce);
862 assert_eq!(&uiv.keys[..], &expect_keys[..]);
863
864 let uiv2: uiv::Uiv<Aes128, Aes128> = uiv::Uiv::initialize(&uiv.keys[..]).unwrap();
867
868 let tweak: [u8; 16] = rng.random();
869 let cmd = rng.random();
870 let mut msg1: [u8; CELL_DATA_LEN] = rng.random();
871 let mut msg2 = msg1.clone();
872
873 uiv.encrypt((&tweak, cmd), &mut msg1);
874 uiv2.encrypt((&tweak, cmd), &mut msg2);
875 }
876 }
877
878 #[test]
879 fn testvec_cgo_relay() {
880 for (inbound, (k, n, tprime), ad, t, c, output) in CGO_RELAY_TEST_VECTORS {
881 let k_n: [u8; 80] = unhex(&format!("{k}{n}"));
882 let tprime: [u8; 16] = unhex(tprime);
883 let ad: [u8; 1] = unhex(ad);
884 let msg: [u8; CELL_DATA_LEN] = unhex(&format!("{t}{c}"));
885 let mut msg = RelayCellBody(Box::new(msg));
886
887 let mut state = CryptState::<Aes128, Aes128>::initialize(&k_n).unwrap();
888 *state.tag = tprime;
889 let state = if *inbound {
890 let mut s = RelayInbound::from(state);
891 s.encrypt_inbound(ad[0].into(), &mut msg);
892 s.0
893 } else {
894 let mut s = RelayOutbound::from(state);
895 s.decrypt_outbound(ad[0].into(), &mut msg);
896 s.0
897 };
898
899 let ((ex_k, ex_n, ex_tprime), (ex_t, ex_c)) = output;
901 let ex_msg: [u8; CELL_DATA_LEN] = unhex(&format!("{ex_t}{ex_c}"));
902 let ex_k: [u8; 64] = unhex(ex_k);
903 let ex_n: [u8; 16] = unhex(ex_n);
904 let ex_tprime: [u8; 16] = unhex(ex_tprime);
905 assert_eq!(&ex_msg[..], &msg.0[..]);
906 assert_eq!(&state.uiv.keys[..], &ex_k[..]);
907 assert_eq!(&state.nonce[..], &ex_n[..]);
908 assert_eq!(&state.tag[..], &ex_tprime[..]);
909 }
910 }
911
912 #[test]
913 fn testvec_cgo_relay_originate() {
914 for ((k, n, tprime), ad, m, output) in CGO_RELAY_ORIGINATE_TEST_VECTORS {
915 let k_n: [u8; 80] = unhex(&format!("{k}{n}"));
916 let tprime: [u8; 16] = unhex(tprime);
917 let ad: [u8; 1] = unhex(ad);
918 let msg_body: [u8; CGO_PAYLOAD_LEN] = unhex(m);
919 let mut msg = [0_u8; CELL_DATA_LEN];
920 msg[16..].copy_from_slice(&msg_body[..]);
921 let mut msg = RelayCellBody(Box::new(msg));
922
923 let mut state = CryptState::<Aes128, Aes128>::initialize(&k_n).unwrap();
924 *state.tag = tprime;
925 let mut state = RelayInbound::from(state);
926 state.originate(ad[0].into(), &mut msg);
927 let state = state.0;
928
929 let ((ex_k, ex_n, ex_tprime), (ex_t, ex_c)) = output;
930 let ex_msg: [u8; CELL_DATA_LEN] = unhex(&format!("{ex_t}{ex_c}"));
931 let ex_k: [u8; 64] = unhex(ex_k);
932 let ex_n: [u8; 16] = unhex(ex_n);
933 let ex_tprime: [u8; 16] = unhex(ex_tprime);
934 assert_eq!(&ex_msg[..], &msg.0[..]);
935 assert_eq!(&state.uiv.keys[..], &ex_k[..]);
936 assert_eq!(&state.nonce[..], &ex_n[..]);
937 assert_eq!(&state.tag[..], &ex_tprime[..]);
938 }
939 }
940
941 #[test]
942 fn testvec_cgo_client_originate() {
943 for (ss, hop, ad, m, output) in CGO_CLIENT_ORIGINATE_TEST_VECTORS {
944 assert!(*hop > 0); let mut client = OutboundClientCrypt::new();
946 let mut individual_layers = Vec::new();
947 for (k, n, tprime) in ss {
948 let k_n: [u8; 80] = unhex(&format!("{k}{n}"));
949 let tprime: [u8; 16] = unhex(tprime);
950 let mut state = CryptState::<Aes128, Aes128>::initialize(&k_n).unwrap();
951 *state.tag = tprime;
952 client.add_layer(Box::new(ClientOutbound::from(state.clone())));
953 individual_layers.push(ClientOutbound::from(state));
954 }
955
956 let ad: [u8; 1] = unhex(ad);
957 let msg_body: [u8; CGO_PAYLOAD_LEN] = unhex(m);
958 let mut msg = [0_u8; CELL_DATA_LEN];
959 msg[16..].copy_from_slice(&msg_body[..]);
960 let mut msg = RelayCellBody(Box::new(msg));
961 let mut msg2 = msg.clone();
962
963 client
965 .encrypt(ad[0].into(), &mut msg, (*hop - 1).into())
966 .unwrap();
967 {
971 let hop_idx = usize::from(*hop) - 1;
972 individual_layers[hop_idx].originate_for(ad[0].into(), &mut msg2);
973 for idx in (0..hop_idx).rev() {
974 individual_layers[idx].encrypt_outbound(ad[0].into(), &mut msg2);
975 }
976 }
977 assert_eq!(&msg.0[..], &msg2.0[..]);
978
979 let (ex_ss, (ex_t, ex_c)) = output;
980 let ex_msg: [u8; CELL_DATA_LEN] = unhex(&format!("{ex_t}{ex_c}"));
981 assert_eq!(&ex_msg[..], &msg.0[..]);
982
983 for (layer, (ex_k, ex_n, ex_tprime)) in individual_layers.iter().zip(ex_ss.iter()) {
984 let state = &layer.0;
985 let ex_k: [u8; 64] = unhex(ex_k);
986 let ex_n: [u8; 16] = unhex(ex_n);
987 let ex_tprime: [u8; 16] = unhex(ex_tprime);
988
989 assert_eq!(&state.uiv.keys[..], &ex_k[..]);
990 assert_eq!(&state.nonce[..], &ex_n[..]);
991 assert_eq!(&state.tag[..], &ex_tprime);
992 }
993 }
994 }
995}