1use aes::{Aes128, Aes256};
2use ctr::cipher::{KeyIvInit, StreamCipher};
3use curve25519_dalek::edwards::CompressedEdwardsY;
4use curve25519_dalek::scalar::Scalar;
5use hmac::{Hmac, Mac};
6use rand::RngCore;
7use sha1::Sha1;
8use sha2::Sha256;
9use sha3::digest::{ExtendableOutput, Update, XofReader};
10use sha3::{Digest as ShaDigest, Sha3_256, Shake256};
11use x25519_dalek::{PublicKey, StaticSecret};
12
13use crate::error::{ensure, Error, Result};
14use crate::tor::{K_CELL_BODY_LEN, K_RELAY_HEADER_LEN, K_RELAY_PAYLOAD_LEN};
15use crate::util::{put_u64, read_u16, Bytes};
16
17pub fn random_bytes(n: usize) -> Bytes {
18 let mut b = vec![0; n];
19 rand::rngs::OsRng.fill_bytes(&mut b);
20 b
21}
22
23pub fn ct_equal(a: &[u8], b: &[u8]) -> bool {
24 if a.len() != b.len() {
25 return false;
26 }
27 let mut diff = 0u8;
28 for (&x, &y) in a.iter().zip(b) {
29 diff |= x ^ y;
30 }
31 diff == 0
32}
33
34pub fn sha1(in_bytes: &[u8]) -> Bytes {
35 let mut h = Sha1::new();
36 sha1::Digest::update(&mut h, in_bytes);
37 h.finalize().to_vec()
38}
39
40pub fn sha256(in_bytes: &[u8]) -> Bytes {
41 let mut h = Sha256::new();
42 sha2::Digest::update(&mut h, in_bytes);
43 h.finalize().to_vec()
44}
45
46pub fn sha3_256(in_bytes: &[u8]) -> Bytes {
47 let mut h = Sha3_256::new();
48 ShaDigest::update(&mut h, in_bytes);
49 h.finalize().to_vec()
50}
51
52pub fn hmac_sha256(key: &[u8], msg: &[u8]) -> Result<Bytes> {
53 let mut mac = Hmac::<Sha256>::new_from_slice(key).map_err(|_| Error::new("hmac failed"))?;
54 Mac::update(&mut mac, msg);
55 Ok(mac.finalize().into_bytes().to_vec())
56}
57
58pub fn shake256(in_bytes: &[u8], out_len: usize) -> Bytes {
59 let mut h = Shake256::default();
60 h.update(in_bytes);
61 let mut reader = h.finalize_xof();
62 let mut out = vec![0; out_len];
63 reader.read(&mut out);
64 out
65}
66
67pub fn tor_mac(key: &[u8], msg: &[u8]) -> Bytes {
68 let mut input = Bytes::new();
69 put_u64(&mut input, key.len() as u64);
70 input.extend_from_slice(key);
71 input.extend_from_slice(msg);
72 sha3_256(&input)
73}
74
75type Aes128Ctr = ctr::Ctr128BE<Aes128>;
76type Aes256Ctr = ctr::Ctr128BE<Aes256>;
77
78enum AesCtr {
79 Aes128(Box<Aes128Ctr>),
80 Aes256(Box<Aes256Ctr>),
81}
82
83impl AesCtr {
84 fn new(key: &[u8], iv: &[u8]) -> Result<Self> {
85 ensure(iv.len() == 16, "bad aes ctr iv")?;
86 match key.len() {
87 16 => Ok(Self::Aes128(Box::new(
88 Aes128Ctr::new_from_slices(key, iv).map_err(|_| Error::new("aes setkey failed"))?,
89 ))),
90 32 => Ok(Self::Aes256(Box::new(
91 Aes256Ctr::new_from_slices(key, iv).map_err(|_| Error::new("aes setkey failed"))?,
92 ))),
93 _ => Err(Error::new("aes setkey failed")),
94 }
95 }
96
97 fn apply(&mut self, input: &[u8]) -> Bytes {
98 let mut out = input.to_vec();
99 match self {
100 Self::Aes128(c) => c.apply_keystream(&mut out),
101 Self::Aes256(c) => c.apply_keystream(&mut out),
102 }
103 out
104 }
105}
106
107pub fn aes_ctr_crypt(key: &[u8], input: &[u8], iv: Option<&[u8]>) -> Result<Bytes> {
108 let zero = [0u8; 16];
109 let mut c = AesCtr::new(key, iv.unwrap_or(&zero))?;
110 Ok(c.apply(input))
111}
112
113pub struct AesCtrStream {
114 ctr: AesCtr,
115}
116
117impl AesCtrStream {
118 pub fn new(key: &[u8]) -> Self {
119 let iv = [0u8; 16];
120 Self {
121 ctr: AesCtr::new(key, &iv).expect("valid relay AES key length"),
122 }
123 }
124
125 pub fn apply(&mut self, input: &[u8]) -> Result<Bytes> {
126 Ok(self.ctr.apply(input))
127 }
128}
129
130#[derive(Clone)]
131pub enum DigestState {
132 Sha1(Sha1),
133 Sha3(Box<Sha3_256>),
134}
135
136impl DigestState {
137 pub fn sha1_with_seed(seed: &[u8]) -> Self {
138 let mut h = Sha1::new();
139 sha1::Digest::update(&mut h, seed);
140 Self::Sha1(h)
141 }
142
143 pub fn sha3_with_seed(seed: &[u8]) -> Self {
144 let mut h = Sha3_256::new();
145 ShaDigest::update(&mut h, seed);
146 Self::Sha3(Box::new(h))
147 }
148
149 fn update(&mut self, bytes: &[u8]) {
150 match self {
151 Self::Sha1(h) => sha1::Digest::update(h, bytes),
152 Self::Sha3(h) => ShaDigest::update(h.as_mut(), bytes),
153 }
154 }
155
156 fn current(&self) -> Bytes {
157 match self {
158 Self::Sha1(h) => h.clone().finalize().to_vec(),
159 Self::Sha3(h) => h.as_ref().clone().finalize().to_vec(),
160 }
161 }
162}
163
164#[derive(Clone, Copy, Debug, Eq, PartialEq)]
165pub enum DigestKind {
166 Sha1,
167 Sha3,
168}
169
170pub struct RelayCrypto {
171 f: AesCtrStream,
172 b: AesCtrStream,
173 sf: DigestState,
174 sb: DigestState,
175}
176
177impl RelayCrypto {
178 pub fn new(df: &[u8], db: &[u8], kf: &[u8], kb: &[u8], kind: DigestKind) -> Self {
179 let sf = match kind {
180 DigestKind::Sha1 => DigestState::sha1_with_seed(df),
181 DigestKind::Sha3 => DigestState::sha3_with_seed(df),
182 };
183 let sb = match kind {
184 DigestKind::Sha1 => DigestState::sha1_with_seed(db),
185 DigestKind::Sha3 => DigestState::sha3_with_seed(db),
186 };
187 Self {
188 f: AesCtrStream::new(kf),
189 b: AesCtrStream::new(kb),
190 sf,
191 sb,
192 }
193 }
194
195 pub fn encrypt_relay(&mut self, relay_cmd: u8, stream_id: u16, data: &[u8]) -> Result<Bytes> {
196 ensure(data.len() <= K_RELAY_PAYLOAD_LEN, "relay payload too large")?;
197 let mut body = vec![0; K_CELL_BODY_LEN];
198 body[0] = relay_cmd;
199 body[3] = (stream_id >> 8) as u8;
200 body[4] = stream_id as u8;
201 body[9] = (data.len() >> 8) as u8;
202 body[10] = data.len() as u8;
203 body[K_RELAY_HEADER_LEN..K_RELAY_HEADER_LEN + data.len()].copy_from_slice(data);
204 self.sf.update(&body);
205 let d = self.sf.current();
206 body[5..9].copy_from_slice(&d[..4]);
207 self.encrypt_body_only(&body)
208 }
209
210 pub fn decrypt_recognized(&mut self, encrypted: &[u8]) -> Result<Option<Bytes>> {
211 let body = self.decrypt_body_only(encrypted)?;
212 if self.recognize_decrypted(&body) {
213 Ok(Some(body))
214 } else {
215 Ok(None)
216 }
217 }
218
219 pub fn recognize_decrypted(&mut self, body: &[u8]) -> bool {
220 if body.len() != K_CELL_BODY_LEN || body[1] != 0 || body[2] != 0 {
221 return false;
222 }
223 let mut tmp = body.to_vec();
224 tmp[5..9].fill(0);
225 let checkpoint = self.sb.clone();
226 self.sb.update(&tmp);
227 let d = self.sb.current();
228 if d[..4] == body[5..9] {
229 true
230 } else {
231 self.sb = checkpoint;
232 false
233 }
234 }
235
236 pub fn encrypt_body_only(&mut self, body: &[u8]) -> Result<Bytes> {
237 self.f.apply(body)
238 }
239
240 pub fn decrypt_body_only(&mut self, body: &[u8]) -> Result<Bytes> {
241 self.b.apply(body)
242 }
243}
244
245pub fn kdf_tor(k0: &[u8], len: usize) -> Bytes {
246 let mut out = Bytes::new();
247 let mut i = 0u8;
248 while out.len() < len {
249 let mut input = k0.to_vec();
250 input.push(i);
251 out.extend_from_slice(&sha1(&input));
252 i = i.wrapping_add(1);
253 }
254 out.truncate(len);
255 out
256}
257
258pub fn hkdf_sha256_expand(key_seed: &[u8], info: &[u8], len: usize) -> Result<Bytes> {
259 let mut out = Bytes::new();
260 let mut prev = Bytes::new();
261 let mut i = 1u8;
262 while out.len() < len {
263 let mut msg = prev;
264 msg.extend_from_slice(info);
265 msg.push(i);
266 prev = hmac_sha256(key_seed, &msg)?;
267 out.extend_from_slice(&prev);
268 i = i.wrapping_add(1);
269 }
270 out.truncate(len);
271 Ok(out)
272}
273
274pub fn x25519_public_from_private(privkey: &[u8]) -> Result<Bytes> {
275 ensure(privkey.len() == 32, "bad x25519 private key")?;
276 let mut raw = [0u8; 32];
277 raw.copy_from_slice(privkey);
278 let secret = StaticSecret::from(raw);
279 let public = PublicKey::from(&secret);
280 Ok(public.as_bytes().to_vec())
281}
282
283pub fn x25519_shared(privkey: &[u8], pubkey: &[u8]) -> Result<Bytes> {
284 ensure(
285 privkey.len() == 32 && pubkey.len() == 32,
286 "bad x25519 inputs",
287 )?;
288 let mut priv_raw = [0u8; 32];
289 let mut pub_raw = [0u8; 32];
290 priv_raw.copy_from_slice(privkey);
291 pub_raw.copy_from_slice(pubkey);
292 let secret = StaticSecret::from(priv_raw);
293 let public = PublicKey::from(pub_raw);
294 Ok(secret.diffie_hellman(&public).as_bytes().to_vec())
295}
296
297pub fn ed25519_point_is_valid(pubkey: &[u8]) -> bool {
298 if pubkey.len() != 32 {
299 return false;
300 }
301 let mut raw = [0u8; 32];
302 raw.copy_from_slice(pubkey);
303 CompressedEdwardsY(raw).decompress().is_some()
304}
305
306pub fn ed25519_scalarmult_noclamp(scalar_bytes: &[u8], pubkey: &[u8]) -> Result<Bytes> {
307 ensure(
308 scalar_bytes.len() == 32 && pubkey.len() == 32,
309 "bad ed25519 inputs",
310 )?;
311 let mut s = [0u8; 32];
312 let mut p = [0u8; 32];
313 s.copy_from_slice(scalar_bytes);
314 p.copy_from_slice(pubkey);
315 let point = CompressedEdwardsY(p)
316 .decompress()
317 .ok_or_else(|| Error::new("ed25519 key blinding failed"))?;
318 let scalar = Scalar::from_bytes_mod_order(s);
319 Ok((scalar * point).compress().to_bytes().to_vec())
320}
321
322pub fn relay_body_len(body: &[u8]) -> Result<usize> {
323 read_u16(body, 9).map(|v| v as usize)
324}