1
//! Circuit extension handshake for Tor.
2
//!
3
//! Tor circuit handshakes all implement a one-way-authenticated key
4
//! exchange, where a client that knows a public "onion key" for a
5
//! relay sends a "client onionskin" to extend to a relay, and receives a
6
//! "relay onionskin" in response.  When the handshake is successful,
7
//! both the client and relay share a set of session keys, and the
8
//! client knows that nobody _else_ shares those keys unless they
9
//! relay's private onion key.
10
//!
11
//! Currently, this module implements only the "ntor" handshake used
12
//! for circuits on today's Tor.
13
pub(crate) mod fast;
14
#[cfg(feature = "hs-common")]
15
pub mod hs_ntor;
16
pub(crate) mod ntor;
17
pub(crate) mod ntor_v3;
18

            
19
use std::borrow::Borrow;
20

            
21
use crate::Result;
22
//use zeroize::Zeroizing;
23
use rand_core::{CryptoRng, RngCore};
24
use tor_bytes::SecretBuf;
25

            
26
/// A ClientHandshake is used to generate a client onionskin and
27
/// handle a relay onionskin.
28
pub(crate) trait ClientHandshake {
29
    /// The type for the onion key.
30
    type KeyType;
31
    /// The type for the state that the client holds while waiting for a reply.
32
    type StateType;
33
    /// A type that is returned and used to generate session keys.x
34
    type KeyGen;
35
    /// Type of extra data sent from client (without forward secrecy).
36
    type ClientAuxData: ?Sized;
37
    /// Type of extra data returned by server (without forward secrecy).
38
    type ServerAuxData;
39
    /// Generate a new client onionskin for a relay with a given onion key,
40
    /// including `client_aux_data` to be sent without forward secrecy.
41
    ///
42
    /// On success, return a state object that will be used to
43
    /// complete the handshake, along with the message to send.
44
    fn client1<R: RngCore + CryptoRng, M: Borrow<Self::ClientAuxData>>(
45
        rng: &mut R,
46
        key: &Self::KeyType,
47
        client_aux_data: &M,
48
    ) -> Result<(Self::StateType, Vec<u8>)>;
49
    /// Handle an onionskin from a relay, and produce aux data returned
50
    /// from the server, and a key generator.
51
    ///
52
    /// The state object must match the one that was used to make the
53
    /// client onionskin that the server is replying to.
54
    fn client2<T: AsRef<[u8]>>(
55
        state: Self::StateType,
56
        msg: T,
57
    ) -> Result<(Self::ServerAuxData, Self::KeyGen)>;
58
}
59

            
60
/// Trait for an object that handles incoming auxiliary data and
61
/// returns the server's auxiliary data to be included in the reply.
62
///
63
/// This is implemented for `FnMut(&H::ClientAuxData) -> Option<H::ServerAuxData>` automatically.
64
pub(crate) trait AuxDataReply<H>
65
where
66
    H: ServerHandshake + ?Sized,
67
{
68
    /// Given a list of extensions received from a client, decide
69
    /// what extensions to send in reply.
70
    ///
71
    /// Return None if the handshake should fail.
72
    fn reply(&mut self, msg: &H::ClientAuxData) -> Option<H::ServerAuxData>;
73
}
74

            
75
impl<F, H> AuxDataReply<H> for F
76
where
77
    H: ServerHandshake + ?Sized,
78
    F: FnMut(&H::ClientAuxData) -> Option<H::ServerAuxData>,
79
{
80
70
    fn reply(&mut self, msg: &H::ClientAuxData) -> Option<H::ServerAuxData> {
81
70
        self(msg)
82
70
    }
83
}
84

            
85
/// A ServerHandshake is used to handle a client onionskin and generate a
86
/// server onionskin.
87
pub(crate) trait ServerHandshake {
88
    /// The type for the onion key.  This is a private key type.
89
    type KeyType;
90
    /// The returned key generator type.
91
    type KeyGen;
92
    /// Type of extra data sent from client (without forward secrecy).
93
    type ClientAuxData: ?Sized;
94
    /// Type of extra data returned by server (without forward secrecy).
95
    type ServerAuxData;
96

            
97
    /// Perform the server handshake.  Take as input a strong PRNG in `rng`, a
98
    /// function for processing requested extensions, a slice of all our private
99
    /// onion keys, and the client's message.
100
    ///
101
    /// On success, return a key generator and a server handshake message
102
    /// to send in reply.
103
    #[allow(dead_code)] // TODO #1383 ????
104
    fn server<R: RngCore + CryptoRng, REPLY: AuxDataReply<Self>, T: AsRef<[u8]>>(
105
        rng: &mut R,
106
        reply_fn: &mut REPLY,
107
        key: &[Self::KeyType],
108
        msg: T,
109
    ) -> RelayHandshakeResult<(Self::KeyGen, Vec<u8>)>;
110
}
111

            
112
/// A KeyGenerator is returned by a handshake, and used to generate
113
/// session keys for the protocol.
114
///
115
/// Typically, it wraps a KDF function, and some seed key material.
116
///
117
/// It can only be used once.
118
#[allow(unreachable_pub)] // This is only exported depending on enabled features.
119
pub trait KeyGenerator {
120
    /// Consume the key
121
    fn expand(self, keylen: usize) -> Result<SecretBuf>;
122
}
123

            
124
/// Generates keys based on the KDF-TOR function.
125
///
126
/// This is deprecated and shouldn't be used for new keys.
127
pub(crate) struct TapKeyGenerator {
128
    /// Seed for the TAP KDF.
129
    seed: SecretBuf,
130
}
131

            
132
impl TapKeyGenerator {
133
    /// Create a key generator based on a provided seed
134
30
    pub(crate) fn new(seed: SecretBuf) -> Self {
135
30
        TapKeyGenerator { seed }
136
30
    }
137
}
138

            
139
impl KeyGenerator for TapKeyGenerator {
140
20
    fn expand(self, keylen: usize) -> Result<SecretBuf> {
141
        use crate::crypto::ll::kdf::{Kdf, LegacyKdf};
142
20
        LegacyKdf::new(1).derive(&self.seed[..], keylen)
143
20
    }
144
}
145

            
146
/// Generates keys based on SHAKE-256.
147
pub(crate) struct ShakeKeyGenerator {
148
    /// Seed for the key generator
149
    seed: SecretBuf,
150
}
151

            
152
impl ShakeKeyGenerator {
153
    /// Create a key generator based on a provided seed
154
    #[allow(dead_code)] // We'll construct these for v3 onion services
155
12
    pub(crate) fn new(seed: SecretBuf) -> Self {
156
12
        ShakeKeyGenerator { seed }
157
12
    }
158
}
159

            
160
impl KeyGenerator for ShakeKeyGenerator {
161
12
    fn expand(self, keylen: usize) -> Result<SecretBuf> {
162
        use crate::crypto::ll::kdf::{Kdf, ShakeKdf};
163
12
        ShakeKdf::new().derive(&self.seed[..], keylen)
164
12
    }
165
}
166

            
167
/// An error produced by a Relay's attempt to handle a client's onion handshake.
168
#[derive(Clone, Debug, thiserror::Error)]
169
pub(crate) enum RelayHandshakeError {
170
    /// An error in parsing  a handshake message.
171
    #[error("Problem decoding onion handshake")]
172
    Fmt(#[from] tor_bytes::Error),
173
    /// The client asked for a key we didn't have.
174
    #[error("Client asked for a key or ID that we don't have")]
175
    MissingKey,
176
    /// The client did something wrong with their handshake or cryptography.
177
    #[error("Bad handshake from client")]
178
    BadClientHandshake,
179
    /// An internal error.
180
    #[error("Internal error")]
181
    Internal(#[from] tor_error::Bug),
182
}
183

            
184
/// Type alias for results from a relay's attempt to handle a client's onion
185
/// handshake.
186
pub(crate) type RelayHandshakeResult<T> = std::result::Result<T, RelayHandshakeError>;