1use std::borrow::Borrow;
4
5use super::{AuxDataReply, KeyGenerator, RelayHandshakeError, RelayHandshakeResult};
6use crate::util::ct;
7use crate::{Error, Result};
8use tor_bytes::{EncodeResult, Reader, SecretBuf, Writer};
9use tor_error::into_internal;
10use tor_llcrypto::d;
11use tor_llcrypto::pk::curve25519::*;
12use tor_llcrypto::pk::rsa::RsaIdentity;
13use tor_llcrypto::util::ct::ct_lookup;
14
15use digest::Mac;
16use rand_core::{CryptoRng, Rng};
17
18pub(crate) struct NtorClient;
20
21impl super::ClientHandshake for NtorClient {
22 type KeyType = NtorPublicKey;
23 type StateType = NtorHandshakeState;
24 type KeyGen = NtorHkdfKeyGenerator;
25 type ClientAuxData = ();
26 type ServerAuxData = ();
27
28 fn client1<R: Rng + CryptoRng, M: Borrow<()>>(
29 rng: &mut R,
30 key: &Self::KeyType,
31 _client_aux_data: &M,
32 ) -> Result<(Self::StateType, Vec<u8>)> {
33 client_handshake_ntor_v1(rng, key)
34 }
35
36 fn client2<T: AsRef<[u8]>>(state: Self::StateType, msg: T) -> Result<((), Self::KeyGen)> {
37 let keygen = client_handshake2_ntor_v1(msg, &state)?;
38 Ok(((), keygen))
39 }
40}
41
42pub(crate) struct NtorServer;
44
45impl super::ServerHandshake for NtorServer {
46 type KeyType = NtorSecretKey;
47 type KeyGen = NtorHkdfKeyGenerator;
48 type ClientAuxData = ();
49 type ServerAuxData = ();
50
51 fn server<R: Rng + CryptoRng, REPLY: AuxDataReply<Self>, T: AsRef<[u8]>>(
52 rng: &mut R,
53 reply_fn: &mut REPLY,
54 keys: &[Self::KeyType],
55 msg: T,
56 ) -> RelayHandshakeResult<(Self::KeyGen, Vec<u8>)> {
57 let _reply_msg = reply_fn
58 .reply(&())
59 .ok_or(RelayHandshakeError::BadClientHandshake)?;
60
61 server_handshake_ntor_v1(rng, msg, keys)
62 }
63}
64
65#[derive(Clone, Debug)]
67pub(crate) struct NtorPublicKey {
68 pub(crate) id: RsaIdentity,
71 pub(crate) pk: PublicKey,
73}
74
75pub(crate) struct NtorSecretKey {
77 pk: NtorPublicKey,
79 sk: StaticSecret,
82}
83
84use subtle::{Choice, ConstantTimeEq};
85impl NtorSecretKey {
86 #[allow(unused)]
88 pub(crate) fn new(sk: StaticSecret, pk: PublicKey, id: RsaIdentity) -> Self {
89 NtorSecretKey {
90 pk: NtorPublicKey { id, pk },
91 sk,
92 }
93 }
94 fn matches_pk(&self, pk: &PublicKey) -> Choice {
98 self.pk.pk.as_bytes().ct_eq(pk.as_bytes())
99 }
100}
101
102pub(crate) struct NtorHandshakeState {
104 relay_public: NtorPublicKey,
107 my_sk: StaticSecret,
112 my_public: PublicKey,
114}
115
116pub(crate) struct NtorHkdfKeyGenerator {
118 seed: SecretBuf,
121}
122
123impl NtorHkdfKeyGenerator {
124 pub(crate) fn new(seed: SecretBuf) -> Self {
126 NtorHkdfKeyGenerator { seed }
127 }
128}
129
130impl KeyGenerator for NtorHkdfKeyGenerator {
131 fn expand(self, keylen: usize) -> Result<SecretBuf> {
132 let ntor1_key = &b"ntor-curve25519-sha256-1:key_extract"[..];
133 let ntor1_expand = &b"ntor-curve25519-sha256-1:key_expand"[..];
134 use crate::crypto::ll::kdf::{Kdf, Ntor1Kdf};
135 Ntor1Kdf::new(ntor1_key, ntor1_expand).derive(&self.seed[..], keylen)
136 }
137}
138
139type Authcode = digest::CtOutput<hmac::Hmac<d::Sha256>>;
141
142fn client_handshake_ntor_v1<R>(
144 rng: &mut R,
145 relay_public: &NtorPublicKey,
146) -> Result<(NtorHandshakeState, Vec<u8>)>
147where
148 R: Rng + CryptoRng,
149{
150 let my_sk = StaticSecret::random_from_rng(rng);
151 let my_public = PublicKey::from(&my_sk);
152
153 client_handshake_ntor_v1_no_keygen(my_public, my_sk, relay_public)
154}
155
156fn client_handshake_ntor_v1_no_keygen(
158 my_public: PublicKey,
159 my_sk: StaticSecret,
160 relay_public: &NtorPublicKey,
161) -> Result<(NtorHandshakeState, Vec<u8>)> {
162 let mut v: Vec<u8> = Vec::new();
163
164 v.write(&relay_public.id)
165 .and_then(|_| v.write(&relay_public.pk))
166 .and_then(|_| v.write(&my_public))
167 .map_err(|e| Error::from_bytes_enc(e, "Can't encode client handshake."))?;
168
169 assert_eq!(v.len(), 20 + 32 + 32);
170
171 let state = NtorHandshakeState {
172 relay_public: relay_public.clone(),
173 my_public,
174 my_sk,
175 };
176
177 Ok((state, v))
178}
179
180fn client_handshake2_ntor_v1<T>(msg: T, state: &NtorHandshakeState) -> Result<NtorHkdfKeyGenerator>
182where
183 T: AsRef<[u8]>,
184{
185 let mut cur = Reader::from_slice(msg.as_ref());
186 let their_pk: PublicKey = cur
187 .extract()
188 .map_err(|e| Error::from_bytes_err(e, "v3 ntor handshake"))?;
189 let auth: Authcode = cur
190 .extract()
191 .map_err(|e| Error::from_bytes_err(e, "v3 ntor handshake"))?;
192
193 let xy = state.my_sk.diffie_hellman(&their_pk);
194 let xb = state.my_sk.diffie_hellman(&state.relay_public.pk);
195
196 let (keygen, authcode) =
197 ntor_derive(&xy, &xb, &state.relay_public, &state.my_public, &their_pk)
198 .map_err(into_internal!("Error deriving keys"))?;
199
200 let okay = authcode.ct_eq(&auth)
201 & ct::bool_to_choice(xy.was_contributory())
202 & ct::bool_to_choice(xb.was_contributory());
203
204 if okay.into() {
205 Ok(keygen)
206 } else {
207 Err(Error::BadCircHandshakeAuth)
208 }
209}
210
211fn ntor_derive(
216 xy: &SharedSecret,
217 xb: &SharedSecret,
218 server_pk: &NtorPublicKey,
219 x: &PublicKey,
220 y: &PublicKey,
221) -> EncodeResult<(NtorHkdfKeyGenerator, Authcode)> {
222 let ntor1_protoid = &b"ntor-curve25519-sha256-1"[..];
223 let ntor1_mac = &b"ntor-curve25519-sha256-1:mac"[..];
224 let ntor1_verify = &b"ntor-curve25519-sha256-1:verify"[..];
225 let server_string = &b"Server"[..];
226
227 let mut secret_input = SecretBuf::new();
228 secret_input.write(xy)?; secret_input.write(xb)?; secret_input.write(&server_pk.id)?; secret_input.write(&server_pk.pk)?; secret_input.write(x)?; secret_input.write(y)?; secret_input.write(ntor1_protoid)?; use hmac::Hmac;
237 use tor_llcrypto::d::Sha256;
238 let verify = {
239 let mut m =
240 Hmac::<Sha256>::new_from_slice(ntor1_verify).expect("Hmac allows keys of any size");
241 m.update(&secret_input[..]);
242 m.finalize()
243 };
244 let mut auth_input = Vec::new();
245 auth_input.write_and_consume(verify)?; auth_input.write(&server_pk.id)?; auth_input.write(&server_pk.pk)?; auth_input.write(y)?; auth_input.write(x)?; auth_input.write(ntor1_protoid)?; auth_input.write(server_string)?; let auth_mac = {
254 let mut m =
255 Hmac::<Sha256>::new_from_slice(ntor1_mac).expect("Hmac allows keys of any size");
256 m.update(&auth_input[..]);
257 m.finalize()
258 };
259
260 let keygen = NtorHkdfKeyGenerator::new(secret_input);
261 Ok((keygen, auth_mac))
262}
263
264fn server_handshake_ntor_v1<R, T>(
268 rng: &mut R,
269 msg: T,
270 keys: &[NtorSecretKey],
271) -> RelayHandshakeResult<(NtorHkdfKeyGenerator, Vec<u8>)>
272where
273 R: Rng + CryptoRng,
274 T: AsRef<[u8]>,
275{
276 let ephem = EphemeralSecret::random_from_rng(rng);
281 let ephem_pub = PublicKey::from(&ephem);
282
283 server_handshake_ntor_v1_no_keygen(ephem_pub, ephem, msg, keys)
284}
285
286fn server_handshake_ntor_v1_no_keygen<T>(
288 ephem_pub: PublicKey,
289 ephem: EphemeralSecret,
290 msg: T,
291 keys: &[NtorSecretKey],
292) -> RelayHandshakeResult<(NtorHkdfKeyGenerator, Vec<u8>)>
293where
294 T: AsRef<[u8]>,
295{
296 let mut cur = Reader::from_slice(msg.as_ref());
297
298 let my_id: RsaIdentity = cur.extract()?;
299 let my_key: PublicKey = cur.extract()?;
300 let their_pk: PublicKey = cur.extract()?;
301
302 let keypair = ct_lookup(keys, |key| key.matches_pk(&my_key));
303 let keypair = match keypair {
304 Some(k) => k,
305 None => return Err(RelayHandshakeError::MissingKey),
306 };
307
308 if my_id != keypair.pk.id {
309 return Err(RelayHandshakeError::MissingKey);
310 }
311
312 let xy = ephem.diffie_hellman(&their_pk);
313 let xb = keypair.sk.diffie_hellman(&their_pk);
314
315 let okay =
316 ct::bool_to_choice(xy.was_contributory()) & ct::bool_to_choice(xb.was_contributory());
317
318 let (keygen, authcode) = ntor_derive(&xy, &xb, &keypair.pk, &their_pk, &ephem_pub)
319 .map_err(into_internal!("Error deriving keys"))?;
320
321 let mut reply: Vec<u8> = Vec::new();
322 reply
323 .write(&ephem_pub)
324 .and_then(|_| reply.write_and_consume(authcode))
325 .map_err(into_internal!(
326 "Generated relay handshake we couldn't encode"
327 ))?;
328
329 if okay.into() {
330 Ok((keygen, reply))
331 } else {
332 Err(RelayHandshakeError::BadClientHandshake)
333 }
334}
335
336#[cfg(test)]
337mod tests {
338 #![allow(clippy::unwrap_used)]
339 use super::*;
340 use crate::crypto::testing::FakePRNG;
341 use tor_basic_utils::test_rng::testing_rng;
342
343 #[test]
344 fn simple() -> Result<()> {
345 use crate::crypto::handshake::{ClientHandshake, ServerHandshake};
346 let mut rng = testing_rng();
347 let relay_secret = StaticSecret::random_from_rng(&mut rng);
348 let relay_public = PublicKey::from(&relay_secret);
349 let relay_identity = RsaIdentity::from_bytes(&[12; 20]).unwrap();
350 let relay_ntpk = NtorPublicKey {
351 id: relay_identity,
352 pk: relay_public,
353 };
354 let (state, cmsg) = NtorClient::client1(&mut rng, &relay_ntpk, &())?;
355
356 let relay_ntsk = NtorSecretKey {
357 pk: relay_ntpk,
358 sk: relay_secret,
359 };
360 let relay_ntsks = [relay_ntsk];
361
362 let (skeygen, smsg) =
363 NtorServer::server(&mut rng, &mut |_: &()| Some(()), &relay_ntsks, &cmsg).unwrap();
364
365 let (_extensions, ckeygen) = NtorClient::client2(state, smsg)?;
366
367 let skeys = skeygen.expand(55)?;
368 let ckeys = ckeygen.expand(55)?;
369
370 assert_eq!(skeys, ckeys);
371
372 Ok(())
373 }
374
375 fn make_fake_ephem_key(bytes: &[u8]) -> EphemeralSecret {
376 assert_eq!(bytes.len(), 32);
377 let rng = FakePRNG::new(bytes);
378 EphemeralSecret::random_from_rng(rng)
379 }
380
381 #[test]
382 fn testvec() -> Result<()> {
383 use hex_literal::hex;
384
385 let b_sk = hex!("4820544f4c4420594f5520444f474954204b454550532048415050454e494e47");
386 let b_pk = hex!("ccbc8541904d18af08753eae967874749e6149f873de937f57f8fd903a21c471");
387 let x_sk = hex!("706f6461792069207075742e2e2e2e2e2e2e2e4a454c4c59206f6e2074686973");
388 let x_pk = hex!("e65dfdbef8b2635837fe2cebc086a8096eae3213e6830dc407516083d412b078");
389 let y_sk = hex!("70686520737175697272656c2e2e2e2e2e2e2e2e686173206869732067616d65");
390 let y_pk = hex!("390480a14362761d6aec1fea840f6e9e928fb2adb7b25c670be1045e35133a37");
391 let id = hex!("69546f6c64596f7541626f75745374616972732e");
392 let client_handshake = hex!(
393 "69546f6c64596f7541626f75745374616972732eccbc8541904d18af08753eae967874749e6149f873de937f57f8fd903a21c471e65dfdbef8b2635837fe2cebc086a8096eae3213e6830dc407516083d412b078"
394 );
395 let server_handshake = hex!(
396 "390480a14362761d6aec1fea840f6e9e928fb2adb7b25c670be1045e35133a371cbdf68b89923e1f85e8e18ee6e805ea333fe4849c790ffd2670bd80fec95cc8"
397 );
398 let keys = hex!(
399 "0c62dee7f48893370d0ef896758d35729867beef1a5121df80e00f79ed349af39b51cae125719182f19d932a667dae1afbf2e336e6910e7822223e763afad0a13342157969dc6b79"
400 );
401
402 let relay_pk = NtorPublicKey {
403 id: RsaIdentity::from_bytes(&id).unwrap(),
404 pk: b_pk.into(),
405 };
406 let relay_sk = NtorSecretKey {
407 pk: relay_pk.clone(),
408 sk: b_sk.into(),
409 };
410
411 let (state, create_msg) =
412 client_handshake_ntor_v1_no_keygen(x_pk.into(), x_sk.into(), &relay_pk).unwrap();
413 assert_eq!(&create_msg[..], &client_handshake[..]);
414
415 let ephem = make_fake_ephem_key(&y_sk[..]);
416 let ephem_pub = y_pk.into();
417 let (s_keygen, created_msg) =
418 server_handshake_ntor_v1_no_keygen(ephem_pub, ephem, &create_msg[..], &[relay_sk])
419 .unwrap();
420 assert_eq!(&created_msg[..], &server_handshake[..]);
421
422 let c_keygen = client_handshake2_ntor_v1(created_msg, &state)?;
423
424 let c_keys = c_keygen.expand(keys.len())?;
425 let s_keys = s_keygen.expand(keys.len())?;
426 assert_eq!(&c_keys[..], &keys[..]);
427 assert_eq!(&s_keys[..], &keys[..]);
428
429 Ok(())
430 }
431
432 #[test]
433 fn failing_handshakes() {
434 use crate::crypto::handshake::{ClientHandshake, ServerHandshake};
435 let mut rng = testing_rng();
436
437 let relay_secret = StaticSecret::random_from_rng(&mut rng);
439 let relay_public = PublicKey::from(&relay_secret);
440 let wrong_public = PublicKey::from([16_u8; 32]);
441 let relay_identity = RsaIdentity::from_bytes(&[12; 20]).unwrap();
442 let wrong_identity = RsaIdentity::from_bytes(&[13; 20]).unwrap();
443 let relay_ntpk = NtorPublicKey {
444 id: relay_identity,
445 pk: relay_public,
446 };
447 let relay_ntsk = NtorSecretKey {
448 pk: relay_ntpk.clone(),
449 sk: relay_secret,
450 };
451 let relay_ntsks = &[relay_ntsk];
452 let wrong_ntpk1 = NtorPublicKey {
453 id: wrong_identity,
454 pk: relay_public,
455 };
456 let wrong_ntpk2 = NtorPublicKey {
457 id: relay_identity,
458 pk: wrong_public,
459 };
460
461 let (_, handshake1) = NtorClient::client1(&mut rng, &wrong_ntpk1, &()).unwrap();
464 let (_, handshake2) = NtorClient::client1(&mut rng, &wrong_ntpk2, &()).unwrap();
465 let (st3, handshake3) = NtorClient::client1(&mut rng, &relay_ntpk, &()).unwrap();
466
467 let ans1 = NtorServer::server(&mut rng, &mut |_: &()| Some(()), relay_ntsks, &handshake1);
468 let ans2 = NtorServer::server(&mut rng, &mut |_: &()| Some(()), relay_ntsks, &handshake2);
469
470 assert!(ans1.is_err());
471 assert!(ans2.is_err());
472
473 let (_, mut smsg) =
476 NtorServer::server(&mut rng, &mut |_: &()| Some(()), relay_ntsks, &handshake3).unwrap();
477 smsg[60] ^= 7;
478 let ans3 = NtorClient::client2(st3, smsg);
479 assert!(ans3.is_err());
480 }
481}