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

            
3
use super::{KeyGenerator, RelayHandshakeError, RelayHandshakeResult};
4
use crate::util::ct;
5
use crate::{Error, Result, SecretBytes};
6
use tor_bytes::{Reader, Writer};
7
use tor_llcrypto::d;
8
use tor_llcrypto::pk::curve25519::*;
9
use tor_llcrypto::pk::rsa::RsaIdentity;
10
use tor_llcrypto::util::rand_compat::RngCompatExt;
11

            
12
use digest::Mac;
13
use rand_core::{CryptoRng, RngCore};
14
use zeroize::Zeroizing;
15

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

            
19
impl super::ClientHandshake for NtorClient {
20
    type KeyType = NtorPublicKey;
21
    type StateType = NtorHandshakeState;
22
    type KeyGen = NtorHkdfKeyGenerator;
23

            
24
28
    fn client1<R: RngCore + CryptoRng>(
25
28
        rng: &mut R,
26
28
        key: &Self::KeyType,
27
28
    ) -> Result<(Self::StateType, Vec<u8>)> {
28
28
        Ok(client_handshake_ntor_v1(rng, key))
29
28
    }
30

            
31
14
    fn client2<T: AsRef<[u8]>>(state: Self::StateType, msg: T) -> Result<Self::KeyGen> {
32
14
        client_handshake2_ntor_v1(msg, &state)
33
14
    }
34
}
35

            
36
/// Server side of the ntor handshake.
37
pub(crate) struct NtorServer;
38

            
39
impl super::ServerHandshake for NtorServer {
40
    type KeyType = NtorSecretKey;
41
    type KeyGen = NtorHkdfKeyGenerator;
42

            
43
12
    fn server<R: RngCore + CryptoRng, T: AsRef<[u8]>>(
44
12
        rng: &mut R,
45
12
        key: &[Self::KeyType],
46
12
        msg: T,
47
12
    ) -> RelayHandshakeResult<(Self::KeyGen, Vec<u8>)> {
48
12
        server_handshake_ntor_v1(rng, msg, key)
49
12
    }
50
}
51

            
52
/// A set of public keys used by a client to initiate an ntor handshake.
53
31
#[derive(Clone, Debug)]
54
pub(crate) struct NtorPublicKey {
55
    /// Public RSA identity fingerprint for the relay; used in authentication
56
    /// calculation.
57
    pub(crate) id: RsaIdentity,
58
    /// Public curve25519 ntor key for the relay.
59
    pub(crate) pk: PublicKey,
60
}
61

            
62
/// A secret key used by a relay to answer an ntor request
63
pub(crate) struct NtorSecretKey {
64
    /// Public key components; must match those held by the client.
65
    pk: NtorPublicKey,
66
    /// Secret curve25519 ntor key for the relay; must correspond to
67
    /// the public key in pk.pk.
68
    sk: StaticSecret,
69
}
70

            
71
use subtle::{Choice, ConstantTimeEq};
72
impl NtorSecretKey {
73
    /// Construct a new NtorSecretKey from its components.
74
    #[allow(unused)]
75
8
    pub(crate) fn new(sk: StaticSecret, pk: PublicKey, id: RsaIdentity) -> Self {
76
8
        NtorSecretKey {
77
8
            pk: NtorPublicKey { id, pk },
78
8
            sk,
79
8
        }
80
8
    }
81
    /// Return true if the curve25519 public key in `self` matches `pk`.
82
    ///
83
    /// Used for looking up keys in an array.
84
13
    fn matches_pk(&self, pk: &PublicKey) -> Choice {
85
13
        self.pk.pk.as_bytes().ct_eq(pk.as_bytes())
86
13
    }
87
}
88

            
89
/// Client state for an ntor handshake.
90
pub(crate) struct NtorHandshakeState {
91
    /// The relay's public key.  We need to remember this since it is
92
    /// used to finish the handshake.
93
    relay_public: NtorPublicKey,
94
    /// The temporary curve25519 secret (x) that we've generated for
95
    /// this handshake.
96
    // We'd like to EphemeralSecret here, but we can't since we need
97
    // to use it twice.
98
    my_sk: StaticSecret,
99
    /// The public key `X` corresponding to my_sk.
100
    my_public: PublicKey,
101
}
102

            
103
/// KeyGenerator for use with ntor circuit handshake.
104
pub(crate) struct NtorHkdfKeyGenerator {
105
    /// Secret key information derived from the handshake, used as input
106
    /// to HKDF
107
    seed: SecretBytes,
108
}
109

            
110
impl NtorHkdfKeyGenerator {
111
    /// Create a new key generator to expand a given seed
112
26
    pub(crate) fn new(seed: SecretBytes) -> Self {
113
26
        NtorHkdfKeyGenerator { seed }
114
26
    }
115
}
116

            
117
impl KeyGenerator for NtorHkdfKeyGenerator {
118
12
    fn expand(self, keylen: usize) -> Result<SecretBytes> {
119
12
        let ntor1_key = &b"ntor-curve25519-sha256-1:key_extract"[..];
120
12
        let ntor1_expand = &b"ntor-curve25519-sha256-1:key_expand"[..];
121
12
        use crate::crypto::ll::kdf::{Kdf, Ntor1Kdf};
122
12
        Ntor1Kdf::new(ntor1_key, ntor1_expand).derive(&self.seed[..], keylen)
123
12
    }
124
}
125

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

            
129
/// Perform a client handshake, generating an onionskin and a state object
130
28
fn client_handshake_ntor_v1<R>(
131
28
    rng: &mut R,
132
28
    relay_public: &NtorPublicKey,
133
28
) -> (NtorHandshakeState, Vec<u8>)
134
28
where
135
28
    R: RngCore + CryptoRng,
136
28
{
137
28
    let my_sk = StaticSecret::new(rng.rng_compat());
138
28
    let my_public = PublicKey::from(&my_sk);
139
28

            
140
28
    client_handshake_ntor_v1_no_keygen(my_public, my_sk, relay_public)
141
28
}
142

            
143
/// Helper: client handshake _without_ generating  new keys.
144
29
fn client_handshake_ntor_v1_no_keygen(
145
29
    my_public: PublicKey,
146
29
    my_sk: StaticSecret,
147
29
    relay_public: &NtorPublicKey,
148
29
) -> (NtorHandshakeState, Vec<u8>) {
149
29
    let mut v: Vec<u8> = Vec::new();
150
29

            
151
29
    v.write(&relay_public.id);
152
29
    v.write(&relay_public.pk);
153
29
    v.write(&my_public);
154
29

            
155
29
    assert_eq!(v.len(), 20 + 32 + 32);
156

            
157
29
    let state = NtorHandshakeState {
158
29
        relay_public: relay_public.clone(),
159
29
        my_public,
160
29
        my_sk,
161
29
    };
162
29

            
163
29
    (state, v)
164
29
}
165

            
166
/// Complete a client handshake, returning a key generator on success.
167
15
fn client_handshake2_ntor_v1<T>(msg: T, state: &NtorHandshakeState) -> Result<NtorHkdfKeyGenerator>
168
15
where
169
15
    T: AsRef<[u8]>,
170
15
{
171
15
    let mut cur = Reader::from_slice(msg.as_ref());
172
15
    let their_pk: PublicKey = cur.extract()?;
173
15
    let auth: Authcode = cur.extract()?;
174

            
175
15
    let xy = state.my_sk.diffie_hellman(&their_pk);
176
15
    let xb = state.my_sk.diffie_hellman(&state.relay_public.pk);
177
15

            
178
15
    let (keygen, authcode) =
179
15
        ntor_derive(&xy, &xb, &state.relay_public, &state.my_public, &their_pk);
180
15

            
181
15
    let okay = authcode.ct_eq(&auth)
182
15
        & ct::bool_to_choice(xy.was_contributory())
183
15
        & ct::bool_to_choice(xb.was_contributory());
184
15

            
185
15
    if okay.into() {
186
10
        Ok(keygen)
187
    } else {
188
5
        Err(Error::BadCircHandshake)
189
    }
190
15
}
191

            
192
/// helper: compute a key generator and an authentication code from a set
193
/// of ntor parameters.
194
///
195
/// These parameter names are as described in tor-spec.txt
196
26
fn ntor_derive(
197
26
    xy: &SharedSecret,
198
26
    xb: &SharedSecret,
199
26
    server_pk: &NtorPublicKey,
200
26
    x: &PublicKey,
201
26
    y: &PublicKey,
202
26
) -> (NtorHkdfKeyGenerator, Authcode) {
203
26
    let ntor1_protoid = &b"ntor-curve25519-sha256-1"[..];
204
26
    let ntor1_mac = &b"ntor-curve25519-sha256-1:mac"[..];
205
26
    let ntor1_verify = &b"ntor-curve25519-sha256-1:verify"[..];
206
26
    let server_string = &b"Server"[..];
207
26

            
208
26
    let mut secret_input = Zeroizing::new(Vec::new());
209
26
    secret_input.write(xy); // EXP(X,y)
210
26
    secret_input.write(xb); // EXP(X,b)
211
26
    secret_input.write(&server_pk.id); // ID
212
26
    secret_input.write(&server_pk.pk); // B
213
26
    secret_input.write(x); // X
214
26
    secret_input.write(y); // Y
215
26
    secret_input.write(ntor1_protoid); // PROTOID
216
26

            
217
26
    use hmac::Hmac;
218
26
    use tor_llcrypto::d::Sha256;
219
26
    let verify = {
220
26
        let mut m =
221
26
            Hmac::<Sha256>::new_from_slice(ntor1_verify).expect("Hmac allows keys of any size");
222
26
        m.update(&secret_input[..]);
223
26
        m.finalize()
224
26
    };
225
26
    let mut auth_input: SecretBytes = Zeroizing::new(Vec::new());
226
26
    auth_input.write_and_consume(verify); // verify
227
26
    auth_input.write(&server_pk.id); // ID
228
26
    auth_input.write(&server_pk.pk); // B
229
26
    auth_input.write(y); // Y
230
26
    auth_input.write(x); // X
231
26
    auth_input.write(ntor1_protoid); // PROTOID
232
26
    auth_input.write(server_string); // "Server"
233
26

            
234
26
    let auth_mac = {
235
26
        let mut m =
236
26
            Hmac::<Sha256>::new_from_slice(ntor1_mac).expect("Hmac allows keys of any size");
237
26
        m.update(&auth_input[..]);
238
26
        m.finalize()
239
26
    };
240
26

            
241
26
    let keygen = NtorHkdfKeyGenerator::new(secret_input);
242
26
    (keygen, auth_mac)
243
26
}
244

            
245
/// Perform a server-side ntor handshake.
246
///
247
/// On success returns a key generator and a server onionskin.
248
12
fn server_handshake_ntor_v1<R, T>(
249
12
    rng: &mut R,
250
12
    msg: T,
251
12
    keys: &[NtorSecretKey],
252
12
) -> RelayHandshakeResult<(NtorHkdfKeyGenerator, Vec<u8>)>
253
12
where
254
12
    R: RngCore + CryptoRng,
255
12
    T: AsRef<[u8]>,
256
12
{
257
12
    // TODO(nickm): we generate this key whether or not we are
258
12
    // actually going to find our nodeid or keyid. Perhaps we should
259
12
    // delay that till later?  It shouldn't matter for most cases,
260
12
    // though.
261
12
    let ephem = EphemeralSecret::new(rng.rng_compat());
262
12
    let ephem_pub = PublicKey::from(&ephem);
263
12

            
264
12
    server_handshake_ntor_v1_no_keygen(ephem_pub, ephem, msg, keys)
265
12
}
266

            
267
/// Helper: perform a server handshake without generating any new keys.
268
13
fn server_handshake_ntor_v1_no_keygen<T>(
269
13
    ephem_pub: PublicKey,
270
13
    ephem: EphemeralSecret,
271
13
    msg: T,
272
13
    keys: &[NtorSecretKey],
273
13
) -> RelayHandshakeResult<(NtorHkdfKeyGenerator, Vec<u8>)>
274
13
where
275
13
    T: AsRef<[u8]>,
276
13
{
277
13
    let mut cur = Reader::from_slice(msg.as_ref());
278

            
279
13
    let my_id: RsaIdentity = cur.extract()?;
280
13
    let my_key: PublicKey = cur.extract()?;
281
13
    let their_pk: PublicKey = cur.extract()?;
282

            
283
13
    let keypair = ct::lookup(keys, |key| key.matches_pk(&my_key));
284
13
    let keypair = match keypair {
285
12
        Some(k) => k,
286
1
        None => return Err(RelayHandshakeError::MissingKey),
287
    };
288

            
289
12
    if my_id != keypair.pk.id {
290
1
        return Err(RelayHandshakeError::MissingKey);
291
11
    }
292
11

            
293
11
    let xy = ephem.diffie_hellman(&their_pk);
294
11
    let xb = keypair.sk.diffie_hellman(&their_pk);
295
11

            
296
11
    let okay =
297
11
        ct::bool_to_choice(xy.was_contributory()) & ct::bool_to_choice(xb.was_contributory());
298
11

            
299
11
    let (keygen, authcode) = ntor_derive(&xy, &xb, &keypair.pk, &their_pk, &ephem_pub);
300
11

            
301
11
    let mut reply: Vec<u8> = Vec::new();
302
11
    reply.write(&ephem_pub);
303
11
    reply.write_and_consume(authcode);
304
11

            
305
11
    if okay.into() {
306
11
        Ok((keygen, reply))
307
    } else {
308
        Err(RelayHandshakeError::BadHandshake)
309
    }
310
13
}
311

            
312
#[cfg(test)]
313
mod tests {
314
    #![allow(clippy::unwrap_used)]
315
    use super::*;
316
    use crate::crypto::testing::FakePRNG;
317

            
318
    #[test]
319
    fn simple() -> Result<()> {
320
        use crate::crypto::handshake::{ClientHandshake, ServerHandshake};
321
        let mut rng = rand::thread_rng().rng_compat();
322
        let relay_secret = StaticSecret::new(&mut rng);
323
        let relay_public = PublicKey::from(&relay_secret);
324
        let relay_identity = RsaIdentity::from_bytes(&[12; 20]).unwrap();
325
        let relay_ntpk = NtorPublicKey {
326
            id: relay_identity,
327
            pk: relay_public,
328
        };
329
        let (state, cmsg) = NtorClient::client1(&mut rng, &relay_ntpk)?;
330

            
331
        let relay_ntsk = NtorSecretKey {
332
            pk: relay_ntpk,
333
            sk: relay_secret,
334
        };
335
        let relay_ntsks = [relay_ntsk];
336

            
337
        let (skeygen, smsg) = NtorServer::server(&mut rng, &relay_ntsks, &cmsg).unwrap();
338

            
339
        let ckeygen = NtorClient::client2(state, smsg)?;
340

            
341
        let skeys = skeygen.expand(55)?;
342
        let ckeys = ckeygen.expand(55)?;
343

            
344
        assert_eq!(skeys, ckeys);
345

            
346
        Ok(())
347
    }
348

            
349
    fn make_fake_ephem_key(bytes: &[u8]) -> EphemeralSecret {
350
        assert_eq!(bytes.len(), 32);
351
        let mut rng = FakePRNG::new(bytes).rng_compat();
352
        EphemeralSecret::new(&mut rng)
353
    }
354

            
355
    #[test]
356
    fn testvec() -> Result<()> {
357
        use hex_literal::hex;
358

            
359
        let b_sk = hex!("4820544f4c4420594f5520444f474954204b454550532048415050454e494e47");
360
        let b_pk = hex!("ccbc8541904d18af08753eae967874749e6149f873de937f57f8fd903a21c471");
361
        let x_sk = hex!("706f6461792069207075742e2e2e2e2e2e2e2e4a454c4c59206f6e2074686973");
362
        let x_pk = hex!("e65dfdbef8b2635837fe2cebc086a8096eae3213e6830dc407516083d412b078");
363
        let y_sk = hex!("70686520737175697272656c2e2e2e2e2e2e2e2e686173206869732067616d65");
364
        let y_pk = hex!("390480a14362761d6aec1fea840f6e9e928fb2adb7b25c670be1045e35133a37");
365
        let id = hex!("69546f6c64596f7541626f75745374616972732e");
366
        let client_handshake = hex!("69546f6c64596f7541626f75745374616972732eccbc8541904d18af08753eae967874749e6149f873de937f57f8fd903a21c471e65dfdbef8b2635837fe2cebc086a8096eae3213e6830dc407516083d412b078");
367
        let server_handshake = hex!("390480a14362761d6aec1fea840f6e9e928fb2adb7b25c670be1045e35133a371cbdf68b89923e1f85e8e18ee6e805ea333fe4849c790ffd2670bd80fec95cc8");
368
        let keys = hex!("0c62dee7f48893370d0ef896758d35729867beef1a5121df80e00f79ed349af39b51cae125719182f19d932a667dae1afbf2e336e6910e7822223e763afad0a13342157969dc6b79");
369

            
370
        let relay_pk = NtorPublicKey {
371
            id: RsaIdentity::from_bytes(&id).unwrap(),
372
            pk: b_pk.into(),
373
        };
374
        let relay_sk = NtorSecretKey {
375
            pk: relay_pk.clone(),
376
            sk: b_sk.into(),
377
        };
378

            
379
        let (state, create_msg) =
380
            client_handshake_ntor_v1_no_keygen(x_pk.into(), x_sk.into(), &relay_pk);
381
        assert_eq!(&create_msg[..], &client_handshake[..]);
382

            
383
        let ephem = make_fake_ephem_key(&y_sk[..]);
384
        let ephem_pub = y_pk.into();
385
        let (s_keygen, created_msg) =
386
            server_handshake_ntor_v1_no_keygen(ephem_pub, ephem, &create_msg[..], &[relay_sk])
387
                .unwrap();
388
        assert_eq!(&created_msg[..], &server_handshake[..]);
389

            
390
        let c_keygen = client_handshake2_ntor_v1(created_msg, &state)?;
391

            
392
        let c_keys = c_keygen.expand(keys.len())?;
393
        let s_keys = s_keygen.expand(keys.len())?;
394
        assert_eq!(&c_keys[..], &keys[..]);
395
        assert_eq!(&s_keys[..], &keys[..]);
396

            
397
        Ok(())
398
    }
399

            
400
    #[test]
401
    fn failing_handshakes() {
402
        use crate::crypto::handshake::{ClientHandshake, ServerHandshake};
403
        let mut rng = rand::thread_rng().rng_compat();
404

            
405
        // Set up keys.
406
        let relay_secret = StaticSecret::new(&mut rng);
407
        let relay_public = PublicKey::from(&relay_secret);
408
        let wrong_public = PublicKey::from([16_u8; 32]);
409
        let relay_identity = RsaIdentity::from_bytes(&[12; 20]).unwrap();
410
        let wrong_identity = RsaIdentity::from_bytes(&[13; 20]).unwrap();
411
        let relay_ntpk = NtorPublicKey {
412
            id: relay_identity,
413
            pk: relay_public,
414
        };
415
        let relay_ntsk = NtorSecretKey {
416
            pk: relay_ntpk.clone(),
417
            sk: relay_secret,
418
        };
419
        let relay_ntsks = &[relay_ntsk];
420
        let wrong_ntpk1 = NtorPublicKey {
421
            id: wrong_identity,
422
            pk: relay_public,
423
        };
424
        let wrong_ntpk2 = NtorPublicKey {
425
            id: relay_identity,
426
            pk: wrong_public,
427
        };
428

            
429
        // If the client uses the wrong keys, the relay should reject the
430
        // handshake.
431
        let (_, handshake1) = NtorClient::client1(&mut rng, &wrong_ntpk1).unwrap();
432
        let (_, handshake2) = NtorClient::client1(&mut rng, &wrong_ntpk2).unwrap();
433
        let (st3, handshake3) = NtorClient::client1(&mut rng, &relay_ntpk).unwrap();
434

            
435
        let ans1 = NtorServer::server(&mut rng, relay_ntsks, &handshake1);
436
        let ans2 = NtorServer::server(&mut rng, relay_ntsks, &handshake2);
437

            
438
        assert!(ans1.is_err());
439
        assert!(ans2.is_err());
440

            
441
        // If the relay's message is tampered with, the client will
442
        // reject the handshake.
443
        let (_, mut smsg) = NtorServer::server(&mut rng, relay_ntsks, &handshake3).unwrap();
444
        smsg[60] ^= 7;
445
        let ans3 = NtorClient::client2(st3, smsg);
446
        assert!(ans3.is_err());
447
    }
448
}