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