tor_llcrypto/
cipher.rs

1//! Ciphers used to implement the Tor protocols.
2//!
3//! Fortunately, Tor has managed not to proliferate ciphers.  It only
4//! uses AES, and (so far) only uses AES in counter mode.
5
6/// Re-exports implementations of counter-mode AES.
7///
8/// These ciphers implement the `cipher::StreamCipher` trait, so use
9/// the [`cipher`](https://docs.rs/cipher) crate to access them.
10#[cfg_attr(docsrs, doc(cfg(all())))]
11#[cfg(not(feature = "with-openssl"))]
12pub mod aes {
13    // These implement StreamCipher.
14    /// AES128 in counter mode as used by Tor.
15    pub type Aes128Ctr = ctr::Ctr128BE<aes::Aes128>;
16
17    /// AES256 in counter mode as used by Tor.  
18    pub type Aes256Ctr = ctr::Ctr128BE<aes::Aes256>;
19}
20
21/// Compatibility layer between OpenSSL and `cipher::StreamCipher`.
22///
23/// These ciphers implement the `cipher::StreamCipher` trait, so use
24/// the [`cipher`](https://docs.rs/cipher) crate to access them.
25#[cfg_attr(docsrs, doc(cfg(all())))]
26#[cfg(feature = "with-openssl")]
27pub mod aes {
28    use cipher::generic_array::GenericArray;
29    use cipher::inout::InOutBuf;
30    use cipher::{InnerIvInit, IvSizeUser, StreamCipher, StreamCipherError};
31    use digest::crypto_common::{InnerUser, KeyInit, KeySizeUser};
32    use openssl::symm::{Cipher, Crypter, Mode};
33    use zeroize::{Zeroize, ZeroizeOnDrop};
34
35    /// AES 128 in counter mode as used by Tor.
36    pub struct Aes128Ctr(Crypter);
37
38    /// AES 128 key
39    #[derive(Zeroize, ZeroizeOnDrop)]
40    pub struct Aes128Key([u8; 16]);
41
42    impl KeySizeUser for Aes128Key {
43        type KeySize = typenum::consts::U16;
44    }
45
46    impl KeyInit for Aes128Key {
47        fn new(key: &GenericArray<u8, Self::KeySize>) -> Self {
48            Aes128Key((*key).into())
49        }
50    }
51
52    impl InnerUser for Aes128Ctr {
53        type Inner = Aes128Key;
54    }
55
56    impl IvSizeUser for Aes128Ctr {
57        type IvSize = typenum::consts::U16;
58    }
59
60    impl StreamCipher for Aes128Ctr {
61        fn try_apply_keystream_inout(
62            &mut self,
63            mut buf: InOutBuf<'_, '_, u8>,
64        ) -> Result<(), StreamCipherError> {
65            // TODO(nickm): It would be lovely if we could get rid of this copy somehow.
66            let in_buf = buf.get_in().to_vec();
67            self.0
68                .update(&in_buf, buf.get_out())
69                .map_err(|_| StreamCipherError)?;
70            Ok(())
71        }
72    }
73
74    impl InnerIvInit for Aes128Ctr {
75        fn inner_iv_init(inner: Self::Inner, iv: &GenericArray<u8, Self::IvSize>) -> Self {
76            let crypter = Crypter::new(Cipher::aes_128_ctr(), Mode::Encrypt, &inner.0, Some(iv))
77                .expect("openssl error while initializing Aes128Ctr");
78            Aes128Ctr(crypter)
79        }
80    }
81
82    /// AES 256 in counter mode as used by Tor.
83    pub struct Aes256Ctr(Crypter);
84
85    /// AES 256 key
86    #[derive(Zeroize, ZeroizeOnDrop)]
87    pub struct Aes256Key([u8; 32]);
88
89    impl KeySizeUser for Aes256Key {
90        type KeySize = typenum::consts::U32;
91    }
92
93    impl KeyInit for Aes256Key {
94        fn new(key: &GenericArray<u8, Self::KeySize>) -> Self {
95            Aes256Key((*key).into())
96        }
97    }
98
99    impl InnerUser for Aes256Ctr {
100        type Inner = Aes256Key;
101    }
102
103    impl IvSizeUser for Aes256Ctr {
104        type IvSize = typenum::consts::U16;
105    }
106
107    impl StreamCipher for Aes256Ctr {
108        fn try_apply_keystream_inout(
109            &mut self,
110            mut buf: InOutBuf<'_, '_, u8>,
111        ) -> Result<(), StreamCipherError> {
112            // TODO(nickm): It would be lovely if we could get rid of this copy.
113            let in_buf = buf.get_in().to_vec();
114            self.0
115                .update(&in_buf, buf.get_out())
116                .map_err(|_| StreamCipherError)?;
117            Ok(())
118        }
119    }
120
121    impl InnerIvInit for Aes256Ctr {
122        fn inner_iv_init(inner: Self::Inner, iv: &GenericArray<u8, Self::IvSize>) -> Self {
123            let crypter = Crypter::new(Cipher::aes_256_ctr(), Mode::Encrypt, &inner.0, Some(iv))
124                .expect("openssl error while initializing Aes256Ctr");
125            Aes256Ctr(crypter)
126        }
127    }
128}