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, Rng};
24
use tor_bytes::SecretBuf;
25
use tor_error::{ErrorKind, HasKind};
26

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

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

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

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

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

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

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

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

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

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

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

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

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

            
187
impl HasKind for RelayHandshakeError {
188
    fn kind(&self) -> ErrorKind {
189
        match self {
190
            Self::Fmt(_) => ErrorKind::RemoteProtocolViolation,
191
            Self::MissingKey => ErrorKind::RemoteProtocolViolation,
192
            Self::BadClientHandshake => ErrorKind::RemoteProtocolViolation,
193
            Self::Internal(_) => ErrorKind::Internal,
194
        }
195
    }
196
}
197

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