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

            
3
use std::borrow::Borrow;
4

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

            
15
use digest::Mac;
16
use rand_core::{CryptoRng, RngCore};
17

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

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

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

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

            
42
/// Server side of the ntor handshake.
43
#[allow(dead_code)] // TODO #1467
44
pub(crate) struct NtorServer;
45

            
46
impl super::ServerHandshake for NtorServer {
47
    type KeyType = NtorSecretKey;
48
    type KeyGen = NtorHkdfKeyGenerator;
49
    type ClientAuxData = ();
50
    type ServerAuxData = ();
51

            
52
32
    fn server<R: RngCore + CryptoRng, REPLY: AuxDataReply<Self>, T: AsRef<[u8]>>(
53
32
        rng: &mut R,
54
32
        reply_fn: &mut REPLY,
55
32
        key: &[Self::KeyType],
56
32
        msg: T,
57
32
    ) -> RelayHandshakeResult<(Self::KeyGen, Vec<u8>)> {
58
32
        let _reply_msg = reply_fn
59
32
            .reply(&())
60
32
            .ok_or(RelayHandshakeError::BadClientHandshake)?;
61

            
62
32
        server_handshake_ntor_v1(rng, msg, key)
63
32
    }
64
}
65

            
66
/// A set of public keys used by a client to initiate an ntor handshake.
67
#[derive(Clone, Debug)]
68
pub(crate) struct NtorPublicKey {
69
    /// Public RSA identity fingerprint for the relay; used in authentication
70
    /// calculation.
71
    pub(crate) id: RsaIdentity,
72
    /// Public curve25519 ntor key for the relay.
73
    pub(crate) pk: PublicKey,
74
}
75

            
76
/// A secret key used by a relay to answer an ntor request
77
#[allow(dead_code)] // TODO #1467
78
pub(crate) struct NtorSecretKey {
79
    /// Public key components; must match those held by the client.
80
    pk: NtorPublicKey,
81
    /// Secret curve25519 ntor key for the relay; must correspond to
82
    /// the public key in pk.pk.
83
    sk: StaticSecret,
84
}
85

            
86
use subtle::{Choice, ConstantTimeEq};
87
impl NtorSecretKey {
88
    /// Construct a new NtorSecretKey from its components.
89
    #[allow(unused)]
90
24
    pub(crate) fn new(sk: StaticSecret, pk: PublicKey, id: RsaIdentity) -> Self {
91
24
        NtorSecretKey {
92
24
            pk: NtorPublicKey { id, pk },
93
24
            sk,
94
24
        }
95
24
    }
96
    /// Return true if the curve25519 public key in `self` matches `pk`.
97
    ///
98
    /// Used for looking up keys in an array.
99
    #[allow(dead_code)] // TODO #1467
100
34
    fn matches_pk(&self, pk: &PublicKey) -> Choice {
101
34
        self.pk.pk.as_bytes().ct_eq(pk.as_bytes())
102
34
    }
103
}
104

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

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

            
126
impl NtorHkdfKeyGenerator {
127
    /// Create a new key generator to expand a given seed
128
72
    pub(crate) fn new(seed: SecretBuf) -> Self {
129
72
        NtorHkdfKeyGenerator { seed }
130
72
    }
131
}
132

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

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

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

            
156
80
    client_handshake_ntor_v1_no_keygen(my_public, my_sk, relay_public)
157
80
}
158

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

            
167
82
    v.write(&relay_public.id)
168
123
        .and_then(|_| v.write(&relay_public.pk))
169
123
        .and_then(|_| v.write(&my_public))
170
82
        .map_err(|e| Error::from_bytes_enc(e, "Can't encode client handshake."))?;
171

            
172
82
    assert_eq!(v.len(), 20 + 32 + 32);
173

            
174
82
    let state = NtorHandshakeState {
175
82
        relay_public: relay_public.clone(),
176
82
        my_public,
177
82
        my_sk,
178
82
    };
179

            
180
82
    Ok((state, v))
181
82
}
182

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

            
196
42
    let xy = state.my_sk.diffie_hellman(&their_pk);
197
42
    let xb = state.my_sk.diffie_hellman(&state.relay_public.pk);
198

            
199
42
    let (keygen, authcode) =
200
42
        ntor_derive(&xy, &xb, &state.relay_public, &state.my_public, &their_pk)
201
42
            .map_err(into_internal!("Error deriving keys"))?;
202

            
203
42
    let okay = authcode.ct_eq(&auth)
204
42
        & ct::bool_to_choice(xy.was_contributory())
205
42
        & ct::bool_to_choice(xb.was_contributory());
206

            
207
42
    if okay.into() {
208
28
        Ok(keygen)
209
    } else {
210
14
        Err(Error::BadCircHandshakeAuth)
211
    }
212
42
}
213

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

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

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

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

            
263
72
    let keygen = NtorHkdfKeyGenerator::new(secret_input);
264
72
    Ok((keygen, auth_mac))
265
72
}
266

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

            
287
32
    server_handshake_ntor_v1_no_keygen(ephem_pub, ephem, msg, keys)
288
32
}
289

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

            
302
34
    let my_id: RsaIdentity = cur.extract()?;
303
34
    let my_key: PublicKey = cur.extract()?;
304
34
    let their_pk: PublicKey = cur.extract()?;
305

            
306
34
    let keypair = ct_lookup(keys, |key| key.matches_pk(&my_key));
307
34
    let keypair = match keypair {
308
32
        Some(k) => k,
309
2
        None => return Err(RelayHandshakeError::MissingKey),
310
    };
311

            
312
32
    if my_id != keypair.pk.id {
313
2
        return Err(RelayHandshakeError::MissingKey);
314
30
    }
315

            
316
30
    let xy = ephem.diffie_hellman(&their_pk);
317
30
    let xb = keypair.sk.diffie_hellman(&their_pk);
318

            
319
30
    let okay =
320
30
        ct::bool_to_choice(xy.was_contributory()) & ct::bool_to_choice(xb.was_contributory());
321

            
322
30
    let (keygen, authcode) = ntor_derive(&xy, &xb, &keypair.pk, &their_pk, &ephem_pub)
323
30
        .map_err(into_internal!("Error deriving keys"))?;
324

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

            
333
30
    if okay.into() {
334
30
        Ok((keygen, reply))
335
    } else {
336
        Err(RelayHandshakeError::BadClientHandshake)
337
    }
338
34
}
339

            
340
#[cfg(test)]
341
mod 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!(
397
            "69546f6c64596f7541626f75745374616972732eccbc8541904d18af08753eae967874749e6149f873de937f57f8fd903a21c471e65dfdbef8b2635837fe2cebc086a8096eae3213e6830dc407516083d412b078"
398
        );
399
        let server_handshake = hex!(
400
            "390480a14362761d6aec1fea840f6e9e928fb2adb7b25c670be1045e35133a371cbdf68b89923e1f85e8e18ee6e805ea333fe4849c790ffd2670bd80fec95cc8"
401
        );
402
        let keys = hex!(
403
            "0c62dee7f48893370d0ef896758d35729867beef1a5121df80e00f79ed349af39b51cae125719182f19d932a667dae1afbf2e336e6910e7822223e763afad0a13342157969dc6b79"
404
        );
405

            
406
        let relay_pk = NtorPublicKey {
407
            id: RsaIdentity::from_bytes(&id).unwrap(),
408
            pk: b_pk.into(),
409
        };
410
        let relay_sk = NtorSecretKey {
411
            pk: relay_pk.clone(),
412
            sk: b_sk.into(),
413
        };
414

            
415
        let (state, create_msg) =
416
            client_handshake_ntor_v1_no_keygen(x_pk.into(), x_sk.into(), &relay_pk).unwrap();
417
        assert_eq!(&create_msg[..], &client_handshake[..]);
418

            
419
        let ephem = make_fake_ephem_key(&y_sk[..]);
420
        let ephem_pub = y_pk.into();
421
        let (s_keygen, created_msg) =
422
            server_handshake_ntor_v1_no_keygen(ephem_pub, ephem, &create_msg[..], &[relay_sk])
423
                .unwrap();
424
        assert_eq!(&created_msg[..], &server_handshake[..]);
425

            
426
        let c_keygen = client_handshake2_ntor_v1(created_msg, &state)?;
427

            
428
        let c_keys = c_keygen.expand(keys.len())?;
429
        let s_keys = s_keygen.expand(keys.len())?;
430
        assert_eq!(&c_keys[..], &keys[..]);
431
        assert_eq!(&s_keys[..], &keys[..]);
432

            
433
        Ok(())
434
    }
435

            
436
    #[test]
437
    fn failing_handshakes() {
438
        use crate::crypto::handshake::{ClientHandshake, ServerHandshake};
439
        let mut rng = testing_rng();
440

            
441
        // Set up keys.
442
        let relay_secret = StaticSecret::random_from_rng(&mut rng);
443
        let relay_public = PublicKey::from(&relay_secret);
444
        let wrong_public = PublicKey::from([16_u8; 32]);
445
        let relay_identity = RsaIdentity::from_bytes(&[12; 20]).unwrap();
446
        let wrong_identity = RsaIdentity::from_bytes(&[13; 20]).unwrap();
447
        let relay_ntpk = NtorPublicKey {
448
            id: relay_identity,
449
            pk: relay_public,
450
        };
451
        let relay_ntsk = NtorSecretKey {
452
            pk: relay_ntpk.clone(),
453
            sk: relay_secret,
454
        };
455
        let relay_ntsks = &[relay_ntsk];
456
        let wrong_ntpk1 = NtorPublicKey {
457
            id: wrong_identity,
458
            pk: relay_public,
459
        };
460
        let wrong_ntpk2 = NtorPublicKey {
461
            id: relay_identity,
462
            pk: wrong_public,
463
        };
464

            
465
        // If the client uses the wrong keys, the relay should reject the
466
        // handshake.
467
        let (_, handshake1) = NtorClient::client1(&mut rng, &wrong_ntpk1, &()).unwrap();
468
        let (_, handshake2) = NtorClient::client1(&mut rng, &wrong_ntpk2, &()).unwrap();
469
        let (st3, handshake3) = NtorClient::client1(&mut rng, &relay_ntpk, &()).unwrap();
470

            
471
        let ans1 = NtorServer::server(&mut rng, &mut |_: &()| Some(()), relay_ntsks, &handshake1);
472
        let ans2 = NtorServer::server(&mut rng, &mut |_: &()| Some(()), relay_ntsks, &handshake2);
473

            
474
        assert!(ans1.is_err());
475
        assert!(ans2.is_err());
476

            
477
        // If the relay's message is tampered with, the client will
478
        // reject the handshake.
479
        let (_, mut smsg) =
480
            NtorServer::server(&mut rng, &mut |_: &()| Some(()), relay_ntsks, &handshake3).unwrap();
481
        smsg[60] ^= 7;
482
        let ans3 = NtorClient::client2(st3, smsg);
483
        assert!(ans3.is_err());
484
    }
485
}