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
use tor_cell::chancell::msg::DestroyReason;
26
use tor_error::{ErrorKind, HasKind};
27

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

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

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

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

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

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

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

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

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

            
148
/// Generates keys based on SHAKE-256.
149
#[cfg_attr(feature = "bench", visibility::make(pub))]
150
pub(crate) struct ShakeKeyGenerator {
151
    /// Seed for the key generator
152
    seed: SecretBuf,
153
}
154

            
155
impl ShakeKeyGenerator {
156
    /// Create a key generator based on a provided seed
157
    #[allow(dead_code)] // We'll construct these for v3 onion services
158
12
    #[cfg_attr(feature = "bench", visibility::make(pub))]
159
12
    pub(crate) fn new(seed: SecretBuf) -> Self {
160
12
        ShakeKeyGenerator { seed }
161
12
    }
162
}
163

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

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

            
188
impl RelayHandshakeError {
189
    /// The reason to use in a DESTROY message for this failure.
190
    pub(crate) fn destroy_reason(&self) -> DestroyReason {
191
        match self {
192
            Self::Fmt(_) => DestroyReason::PROTOCOL,
193
            // TODO(relay): Is this right?
194
            Self::MissingKey => DestroyReason::OR_IDENTITY,
195
            Self::BadClientHandshake => DestroyReason::PROTOCOL,
196
            Self::Internal(_) => DestroyReason::INTERNAL,
197
        }
198
    }
199
}
200

            
201
impl HasKind for RelayHandshakeError {
202
    fn kind(&self) -> ErrorKind {
203
        match self {
204
            Self::Fmt(_) => ErrorKind::RemoteProtocolViolation,
205
            Self::MissingKey => ErrorKind::RemoteProtocolViolation,
206
            Self::BadClientHandshake => ErrorKind::RemoteProtocolViolation,
207
            Self::Internal(_) => ErrorKind::Internal,
208
        }
209
    }
210
}
211

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