1
//! Implements the ntor handshake, as used in modern Tor.
2

            
3
use std::borrow::Borrow;
4
use std::marker::PhantomData;
5

            
6
use super::{AuxDataReply, KeyGenerator, RelayHandshakeError, RelayHandshakeResult};
7
use crate::util::ct;
8
use crate::{Error, Result};
9
use subtle::{Choice, ConstantTimeEq};
10
use tor_bytes::{EncodeResult, Reader, SecretBuf, Writer};
11
use tor_error::into_internal;
12
use tor_llcrypto::d;
13
use tor_llcrypto::pk::curve25519::*;
14
use tor_llcrypto::pk::rsa::RsaIdentity;
15
use tor_llcrypto::util::ct::ct_lookup;
16

            
17
use digest::Mac;
18
use rand_core::{CryptoRng, Rng};
19

            
20
/// Client side of the Ntor handshake.
21
pub(crate) struct NtorClient;
22

            
23
impl super::ClientHandshake for NtorClient {
24
    type KeyType = NtorPublicKey;
25
    type StateType = NtorHandshakeState;
26
    type KeyGen = NtorHkdfKeyGenerator;
27
    type ClientAuxData = ();
28
    type ServerAuxData = ();
29

            
30
46
    fn client1<R: Rng + CryptoRng, M: Borrow<()>>(
31
46
        rng: &mut R,
32
46
        key: &Self::KeyType,
33
46
        _client_aux_data: &M,
34
46
    ) -> Result<(Self::StateType, Vec<u8>)> {
35
46
        client_handshake_ntor_v1(rng, key)
36
46
    }
37

            
38
23
    fn client2<T: AsRef<[u8]>>(state: Self::StateType, msg: T) -> Result<((), Self::KeyGen)> {
39
23
        let keygen = client_handshake2_ntor_v1(msg, &state)?;
40
16
        Ok(((), keygen))
41
23
    }
42
}
43

            
44
/// Server side of the ntor handshake.
45
pub(crate) struct NtorServer<K: NtorServerKeys> {
46
    /// The `ServerHandshake` trait requires the `KeyType` to be a property of the implementer,
47
    /// so this generic needs to go here. ¯\_(ツ)_/¯
48
    _phantom: PhantomData<K>,
49
}
50

            
51
impl<K: NtorServerKeys> super::ServerHandshake for NtorServer<K> {
52
    type KeyType = K;
53
    type KeyGen = NtorHkdfKeyGenerator;
54
    type ClientAuxData = ();
55
    type ServerAuxData = ();
56

            
57
21
    fn server<R: Rng + CryptoRng, REPLY: AuxDataReply<Self>, T: AsRef<[u8]>>(
58
21
        rng: &mut R,
59
21
        reply_fn: &mut REPLY,
60
21
        keys: &[Self::KeyType],
61
21
        msg: T,
62
21
    ) -> RelayHandshakeResult<(Self::KeyGen, Vec<u8>)> {
63
21
        let _reply_msg = reply_fn
64
21
            .reply(&())
65
21
            .ok_or(RelayHandshakeError::BadClientHandshake)?;
66

            
67
21
        server_handshake_ntor_v1(rng, msg, keys)
68
21
    }
69
}
70

            
71
/// An object holding the keys necessary for a server-side ntor handshake.
72
pub(crate) trait NtorServerKeys {
73
    /// The server's identity.
74
    fn ident(&self) -> &RsaIdentity;
75

            
76
    /// The server's public key.
77
    fn public_key(&self) -> &PublicKey;
78

            
79
    /// The server's secret key.
80
    fn secret_key(&self) -> &StaticSecret;
81

            
82
    /// Return true if the curve25519 public key in `self` matches `pk`.
83
    ///
84
    /// Used for looking up keys in an array.
85
    ///
86
    /// This should not be implemented manually.
87
22
    fn matches_pk(&self, pk: &PublicKey) -> Choice {
88
22
        self.public_key().as_bytes().ct_eq(pk.as_bytes())
89
22
    }
90
}
91

            
92
/// A set of public keys used by a client to initiate an ntor handshake.
93
#[derive(Clone, Debug)]
94
pub(crate) struct NtorPublicKey {
95
    /// Public RSA identity fingerprint for the relay; used in authentication
96
    /// calculation.
97
    pub(crate) id: RsaIdentity,
98
    /// Public curve25519 ntor key for the relay.
99
    pub(crate) pk: PublicKey,
100
}
101

            
102
/// Client state for an ntor handshake.
103
pub(crate) struct NtorHandshakeState {
104
    /// The relay's public key.  We need to remember this since it is
105
    /// used to finish the handshake.
106
    relay_public: NtorPublicKey,
107
    /// The temporary curve25519 secret (x) that we've generated for
108
    /// this handshake.
109
    // We'd like to EphemeralSecret here, but we can't since we need
110
    // to use it twice.
111
    my_sk: StaticSecret,
112
    /// The public key `X` corresponding to my_sk.
113
    my_public: PublicKey,
114
}
115

            
116
/// KeyGenerator for use with ntor circuit handshake.
117
pub(crate) struct NtorHkdfKeyGenerator {
118
    /// Secret key information derived from the handshake, used as input
119
    /// to HKDF
120
    seed: SecretBuf,
121
}
122

            
123
impl NtorHkdfKeyGenerator {
124
    /// Create a new key generator to expand a given seed
125
42
    pub(crate) fn new(seed: SecretBuf) -> Self {
126
42
        NtorHkdfKeyGenerator { seed }
127
42
    }
128
}
129

            
130
impl KeyGenerator for NtorHkdfKeyGenerator {
131
22
    fn expand(self, keylen: usize) -> Result<SecretBuf> {
132
22
        let ntor1_key = &b"ntor-curve25519-sha256-1:key_extract"[..];
133
22
        let ntor1_expand = &b"ntor-curve25519-sha256-1:key_expand"[..];
134
        use crate::crypto::ll::kdf::{Kdf, Ntor1Kdf};
135
22
        Ntor1Kdf::new(ntor1_key, ntor1_expand).derive(&self.seed[..], keylen)
136
22
    }
137
}
138

            
139
/// Alias for an HMAC output, used to validate correctness of a handshake.
140
type Authcode = digest::CtOutput<hmac::Hmac<d::Sha256>>;
141

            
142
/// Perform a client handshake, generating an onionskin and a state object
143
46
fn client_handshake_ntor_v1<R>(
144
46
    rng: &mut R,
145
46
    relay_public: &NtorPublicKey,
146
46
) -> Result<(NtorHandshakeState, Vec<u8>)>
147
46
where
148
46
    R: Rng + CryptoRng,
149
{
150
46
    let my_sk = StaticSecret::random_from_rng(rng);
151
46
    let my_public = PublicKey::from(&my_sk);
152

            
153
46
    client_handshake_ntor_v1_no_keygen(my_public, my_sk, relay_public)
154
46
}
155

            
156
/// Helper: client handshake _without_ generating  new keys.
157
47
fn client_handshake_ntor_v1_no_keygen(
158
47
    my_public: PublicKey,
159
47
    my_sk: StaticSecret,
160
47
    relay_public: &NtorPublicKey,
161
47
) -> Result<(NtorHandshakeState, Vec<u8>)> {
162
47
    let mut v: Vec<u8> = Vec::new();
163

            
164
47
    v.write(&relay_public.id)
165
47
        .and_then(|_| v.write(&relay_public.pk))
166
47
        .and_then(|_| v.write(&my_public))
167
47
        .map_err(|e| Error::from_bytes_enc(e, "Can't encode client handshake."))?;
168

            
169
47
    assert_eq!(v.len(), 20 + 32 + 32);
170

            
171
47
    let state = NtorHandshakeState {
172
47
        relay_public: relay_public.clone(),
173
47
        my_public,
174
47
        my_sk,
175
47
    };
176

            
177
47
    Ok((state, v))
178
47
}
179

            
180
/// Complete a client handshake, returning a key generator on success.
181
24
fn client_handshake2_ntor_v1<T>(msg: T, state: &NtorHandshakeState) -> Result<NtorHkdfKeyGenerator>
182
24
where
183
24
    T: AsRef<[u8]>,
184
{
185
24
    let mut cur = Reader::from_slice(msg.as_ref());
186
24
    let their_pk: PublicKey = cur
187
24
        .extract()
188
24
        .map_err(|e| Error::from_bytes_err(e, "v3 ntor handshake"))?;
189
24
    let auth: Authcode = cur
190
24
        .extract()
191
24
        .map_err(|e| Error::from_bytes_err(e, "v3 ntor handshake"))?;
192

            
193
24
    let xy = state.my_sk.diffie_hellman(&their_pk);
194
24
    let xb = state.my_sk.diffie_hellman(&state.relay_public.pk);
195

            
196
24
    let (keygen, authcode) =
197
24
        ntor_derive(&xy, &xb, &state.relay_public, &state.my_public, &their_pk)
198
24
            .map_err(into_internal!("Error deriving keys"))?;
199

            
200
24
    let okay = authcode.ct_eq(&auth)
201
24
        & ct::bool_to_choice(xy.was_contributory())
202
24
        & ct::bool_to_choice(xb.was_contributory());
203

            
204
24
    if okay.into() {
205
17
        Ok(keygen)
206
    } else {
207
7
        Err(Error::BadCircHandshakeAuth)
208
    }
209
24
}
210

            
211
/// helper: compute a key generator and an authentication code from a set
212
/// of ntor parameters.
213
///
214
/// These parameter names are as described in tor-spec.txt
215
42
fn ntor_derive(
216
42
    xy: &SharedSecret,
217
42
    xb: &SharedSecret,
218
42
    server_pk: &NtorPublicKey,
219
42
    x: &PublicKey,
220
42
    y: &PublicKey,
221
42
) -> EncodeResult<(NtorHkdfKeyGenerator, Authcode)> {
222
42
    let ntor1_protoid = &b"ntor-curve25519-sha256-1"[..];
223
42
    let ntor1_mac = &b"ntor-curve25519-sha256-1:mac"[..];
224
42
    let ntor1_verify = &b"ntor-curve25519-sha256-1:verify"[..];
225
42
    let server_string = &b"Server"[..];
226

            
227
42
    let mut secret_input = SecretBuf::new();
228
42
    secret_input.write(xy)?; // EXP(X,y)
229
42
    secret_input.write(xb)?; // EXP(X,b)
230
42
    secret_input.write(&server_pk.id)?; // ID
231
42
    secret_input.write(&server_pk.pk)?; // B
232
42
    secret_input.write(x)?; // X
233
42
    secret_input.write(y)?; // Y
234
42
    secret_input.write(ntor1_protoid)?; // PROTOID
235

            
236
    use hmac::Hmac;
237
    use tor_llcrypto::d::Sha256;
238
42
    let verify = {
239
42
        let mut m =
240
42
            Hmac::<Sha256>::new_from_slice(ntor1_verify).expect("Hmac allows keys of any size");
241
42
        m.update(&secret_input[..]);
242
42
        m.finalize()
243
    };
244
42
    let mut auth_input = Vec::new();
245
42
    auth_input.write_and_consume(verify)?; // verify
246
42
    auth_input.write(&server_pk.id)?; // ID
247
42
    auth_input.write(&server_pk.pk)?; // B
248
42
    auth_input.write(y)?; // Y
249
42
    auth_input.write(x)?; // X
250
42
    auth_input.write(ntor1_protoid)?; // PROTOID
251
42
    auth_input.write(server_string)?; // "Server"
252

            
253
42
    let auth_mac = {
254
42
        let mut m =
255
42
            Hmac::<Sha256>::new_from_slice(ntor1_mac).expect("Hmac allows keys of any size");
256
42
        m.update(&auth_input[..]);
257
42
        m.finalize()
258
    };
259

            
260
42
    let keygen = NtorHkdfKeyGenerator::new(secret_input);
261
42
    Ok((keygen, auth_mac))
262
42
}
263

            
264
/// Perform a server-side ntor handshake.
265
///
266
/// On success returns a key generator and a server onionskin.
267
21
fn server_handshake_ntor_v1<R, T, K: NtorServerKeys>(
268
21
    rng: &mut R,
269
21
    msg: T,
270
21
    keys: &[K],
271
21
) -> RelayHandshakeResult<(NtorHkdfKeyGenerator, Vec<u8>)>
272
21
where
273
21
    R: Rng + CryptoRng,
274
21
    T: AsRef<[u8]>,
275
{
276
    // TODO(nickm): we generate this key whether or not we are
277
    // actually going to find our nodeid or keyid. Perhaps we should
278
    // delay that till later?  It shouldn't matter for most cases,
279
    // though.
280
21
    let ephem = EphemeralSecret::random_from_rng(rng);
281
21
    let ephem_pub = PublicKey::from(&ephem);
282

            
283
21
    server_handshake_ntor_v1_no_keygen(ephem_pub, ephem, msg, keys)
284
21
}
285

            
286
/// Helper: perform a server handshake without generating any new keys.
287
22
fn server_handshake_ntor_v1_no_keygen<T, K: NtorServerKeys>(
288
22
    ephem_pub: PublicKey,
289
22
    ephem: EphemeralSecret,
290
22
    msg: T,
291
22
    keys: &[K],
292
22
) -> RelayHandshakeResult<(NtorHkdfKeyGenerator, Vec<u8>)>
293
22
where
294
22
    T: AsRef<[u8]>,
295
{
296
22
    let mut cur = Reader::from_slice(msg.as_ref());
297

            
298
22
    let my_id: RsaIdentity = cur.extract()?;
299
22
    let my_key: PublicKey = cur.extract()?;
300
22
    let their_pk: PublicKey = cur.extract()?;
301

            
302
22
    let keypair = ct_lookup(keys, |key| key.matches_pk(&my_key));
303
22
    let keypair = match keypair {
304
21
        Some(k) => k,
305
1
        None => return Err(RelayHandshakeError::MissingKey),
306
    };
307

            
308
21
    if &my_id != keypair.ident() {
309
3
        return Err(RelayHandshakeError::MissingKey);
310
18
    }
311

            
312
18
    let xy = ephem.diffie_hellman(&their_pk);
313
18
    let xb = keypair.secret_key().diffie_hellman(&their_pk);
314

            
315
18
    let okay =
316
18
        ct::bool_to_choice(xy.was_contributory()) & ct::bool_to_choice(xb.was_contributory());
317

            
318
    // TODO: Update `ntor_derive()` so that we don't need to copy these bytes.
319
18
    let relay_pk = NtorPublicKey {
320
18
        id: *keypair.ident(),
321
18
        pk: *keypair.public_key(),
322
18
    };
323
18
    let (keygen, authcode) = ntor_derive(&xy, &xb, &relay_pk, &their_pk, &ephem_pub)
324
18
        .map_err(into_internal!("Error deriving keys"))?;
325

            
326
18
    let mut reply: Vec<u8> = Vec::new();
327
18
    reply
328
18
        .write(&ephem_pub)
329
18
        .and_then(|_| reply.write_and_consume(authcode))
330
18
        .map_err(into_internal!(
331
            "Generated relay handshake we couldn't encode"
332
        ))?;
333

            
334
18
    if okay.into() {
335
18
        Ok((keygen, reply))
336
    } else {
337
        Err(RelayHandshakeError::BadClientHandshake)
338
    }
339
22
}
340

            
341
#[cfg(test)]
342
pub(crate) mod tests {
343
    #![allow(clippy::unwrap_used)]
344
    use super::*;
345
    use crate::crypto::testing::FakePRNG;
346
    use tor_basic_utils::test_rng::testing_rng;
347

            
348
    /// A secret key used by a relay to answer an ntor request
349
    pub(crate) struct NtorSecretKey {
350
        /// Public key components; must match those held by the client.
351
        pk: NtorPublicKey,
352
        /// Secret curve25519 ntor key for the relay; must correspond to
353
        /// the public key in pk.pk.
354
        sk: StaticSecret,
355
    }
356

            
357
    impl NtorSecretKey {
358
        /// Construct a new NtorSecretKey from its components.
359
        pub(crate) fn new(sk: StaticSecret, pk: PublicKey, id: RsaIdentity) -> Self {
360
            NtorSecretKey {
361
                pk: NtorPublicKey { id, pk },
362
                sk,
363
            }
364
        }
365
    }
366

            
367
    impl NtorServerKeys for NtorSecretKey {
368
        fn ident(&self) -> &RsaIdentity {
369
            &self.pk.id
370
        }
371

            
372
        fn public_key(&self) -> &PublicKey {
373
            &self.pk.pk
374
        }
375

            
376
        fn secret_key(&self) -> &StaticSecret {
377
            &self.sk
378
        }
379
    }
380

            
381
    #[test]
382
    fn simple() -> Result<()> {
383
        use crate::crypto::handshake::{ClientHandshake, ServerHandshake};
384
        let mut rng = testing_rng();
385
        let relay_secret = StaticSecret::random_from_rng(&mut rng);
386
        let relay_public = PublicKey::from(&relay_secret);
387
        let relay_identity = RsaIdentity::from_bytes(&[12; 20]).unwrap();
388
        let relay_ntpk = NtorPublicKey {
389
            id: relay_identity,
390
            pk: relay_public,
391
        };
392
        let (state, cmsg) = NtorClient::client1(&mut rng, &relay_ntpk, &())?;
393

            
394
        let relay_ntsk = NtorSecretKey {
395
            pk: relay_ntpk,
396
            sk: relay_secret,
397
        };
398
        let relay_ntsks = [relay_ntsk];
399

            
400
        let (skeygen, smsg) =
401
            NtorServer::server(&mut rng, &mut |_: &()| Some(()), &relay_ntsks, &cmsg).unwrap();
402

            
403
        let (_extensions, ckeygen) = NtorClient::client2(state, smsg)?;
404

            
405
        let skeys = skeygen.expand(55)?;
406
        let ckeys = ckeygen.expand(55)?;
407

            
408
        assert_eq!(skeys, ckeys);
409

            
410
        Ok(())
411
    }
412

            
413
    fn make_fake_ephem_key(bytes: &[u8]) -> EphemeralSecret {
414
        assert_eq!(bytes.len(), 32);
415
        let rng = FakePRNG::new(bytes);
416
        EphemeralSecret::random_from_rng(rng)
417
    }
418

            
419
    #[test]
420
    fn testvec() -> Result<()> {
421
        use hex_literal::hex;
422

            
423
        let b_sk = hex!("4820544f4c4420594f5520444f474954204b454550532048415050454e494e47");
424
        let b_pk = hex!("ccbc8541904d18af08753eae967874749e6149f873de937f57f8fd903a21c471");
425
        let x_sk = hex!("706f6461792069207075742e2e2e2e2e2e2e2e4a454c4c59206f6e2074686973");
426
        let x_pk = hex!("e65dfdbef8b2635837fe2cebc086a8096eae3213e6830dc407516083d412b078");
427
        let y_sk = hex!("70686520737175697272656c2e2e2e2e2e2e2e2e686173206869732067616d65");
428
        let y_pk = hex!("390480a14362761d6aec1fea840f6e9e928fb2adb7b25c670be1045e35133a37");
429
        let id = hex!("69546f6c64596f7541626f75745374616972732e");
430
        let client_handshake = hex!(
431
            "69546f6c64596f7541626f75745374616972732eccbc8541904d18af08753eae967874749e6149f873de937f57f8fd903a21c471e65dfdbef8b2635837fe2cebc086a8096eae3213e6830dc407516083d412b078"
432
        );
433
        let server_handshake = hex!(
434
            "390480a14362761d6aec1fea840f6e9e928fb2adb7b25c670be1045e35133a371cbdf68b89923e1f85e8e18ee6e805ea333fe4849c790ffd2670bd80fec95cc8"
435
        );
436
        let keys = hex!(
437
            "0c62dee7f48893370d0ef896758d35729867beef1a5121df80e00f79ed349af39b51cae125719182f19d932a667dae1afbf2e336e6910e7822223e763afad0a13342157969dc6b79"
438
        );
439

            
440
        let relay_pk = NtorPublicKey {
441
            id: RsaIdentity::from_bytes(&id).unwrap(),
442
            pk: b_pk.into(),
443
        };
444
        let relay_sk = NtorSecretKey {
445
            pk: relay_pk.clone(),
446
            sk: b_sk.into(),
447
        };
448

            
449
        let (state, create_msg) =
450
            client_handshake_ntor_v1_no_keygen(x_pk.into(), x_sk.into(), &relay_pk).unwrap();
451
        assert_eq!(&create_msg[..], &client_handshake[..]);
452

            
453
        let ephem = make_fake_ephem_key(&y_sk[..]);
454
        let ephem_pub = y_pk.into();
455
        let (s_keygen, created_msg) =
456
            server_handshake_ntor_v1_no_keygen(ephem_pub, ephem, &create_msg[..], &[relay_sk])
457
                .unwrap();
458
        assert_eq!(&created_msg[..], &server_handshake[..]);
459

            
460
        let c_keygen = client_handshake2_ntor_v1(created_msg, &state)?;
461

            
462
        let c_keys = c_keygen.expand(keys.len())?;
463
        let s_keys = s_keygen.expand(keys.len())?;
464
        assert_eq!(&c_keys[..], &keys[..]);
465
        assert_eq!(&s_keys[..], &keys[..]);
466

            
467
        Ok(())
468
    }
469

            
470
    #[test]
471
    fn failing_handshakes() {
472
        use crate::crypto::handshake::{ClientHandshake, ServerHandshake};
473
        let mut rng = testing_rng();
474

            
475
        // Set up keys.
476
        let relay_secret = StaticSecret::random_from_rng(&mut rng);
477
        let relay_public = PublicKey::from(&relay_secret);
478
        let wrong_public = PublicKey::from([16_u8; 32]);
479
        let relay_identity = RsaIdentity::from_bytes(&[12; 20]).unwrap();
480
        let wrong_identity = RsaIdentity::from_bytes(&[13; 20]).unwrap();
481
        let relay_ntpk = NtorPublicKey {
482
            id: relay_identity,
483
            pk: relay_public,
484
        };
485
        let relay_ntsk = NtorSecretKey {
486
            pk: relay_ntpk.clone(),
487
            sk: relay_secret,
488
        };
489
        let relay_ntsks = &[relay_ntsk];
490
        let wrong_ntpk1 = NtorPublicKey {
491
            id: wrong_identity,
492
            pk: relay_public,
493
        };
494
        let wrong_ntpk2 = NtorPublicKey {
495
            id: relay_identity,
496
            pk: wrong_public,
497
        };
498

            
499
        // If the client uses the wrong keys, the relay should reject the
500
        // handshake.
501
        let (_, handshake1) = NtorClient::client1(&mut rng, &wrong_ntpk1, &()).unwrap();
502
        let (_, handshake2) = NtorClient::client1(&mut rng, &wrong_ntpk2, &()).unwrap();
503
        let (st3, handshake3) = NtorClient::client1(&mut rng, &relay_ntpk, &()).unwrap();
504

            
505
        let ans1 = NtorServer::server(&mut rng, &mut |_: &()| Some(()), relay_ntsks, &handshake1);
506
        let ans2 = NtorServer::server(&mut rng, &mut |_: &()| Some(()), relay_ntsks, &handshake2);
507

            
508
        assert!(ans1.is_err());
509
        assert!(ans2.is_err());
510

            
511
        // If the relay's message is tampered with, the client will
512
        // reject the handshake.
513
        let (_, mut smsg) =
514
            NtorServer::server(&mut rng, &mut |_: &()| Some(()), relay_ntsks, &handshake3).unwrap();
515
        smsg[60] ^= 7;
516
        let ans3 = NtorClient::client2(st3, smsg);
517
        assert!(ans3.is_err());
518
    }
519
}