tor_proto/crypto/handshake/
fast.rs1use std::borrow::Borrow;
5
6use super::{RelayHandshakeError, RelayHandshakeResult};
7use crate::crypto::ll::kdf::{Kdf, LegacyKdf};
8use crate::util::ct::bytes_eq;
9use crate::{Error, Result};
10
11use rand::{CryptoRng, Rng};
12use tor_bytes::SecretBuf;
13use tor_error::into_internal;
14
15pub(crate) const FAST_C_HANDSHAKE_LEN: usize = 20;
17pub(crate) const FAST_S_HANDSHAKE_LEN: usize = 20 * 2;
19
20pub(crate) struct CreateFastClientState([u8; FAST_C_HANDSHAKE_LEN]);
22
23pub(crate) struct CreateFastClient;
27
28const SECRET_INPUT_LEN: usize = 40;
30
31impl super::ClientHandshake for CreateFastClient {
32 type KeyType = ();
33 type StateType = CreateFastClientState;
34 type KeyGen = super::TapKeyGenerator;
35 type ClientAuxData = ();
36 type ServerAuxData = ();
37
38 fn client1<R: Rng + CryptoRng, M: Borrow<()>>(
39 rng: &mut R,
40 _key: &Self::KeyType,
41 _client_aux_data: &M,
42 ) -> Result<(Self::StateType, Vec<u8>)> {
43 let mut state = [0_u8; FAST_C_HANDSHAKE_LEN];
44 rng.fill_bytes(&mut state);
45 Ok((CreateFastClientState(state), state.into()))
46 }
47
48 fn client2<T: AsRef<[u8]>>(state: Self::StateType, msg: T) -> Result<((), Self::KeyGen)> {
49 let msg = msg.as_ref();
50 if msg.len() != FAST_S_HANDSHAKE_LEN {
51 return Err(Error::BadCircHandshakeAuth);
52 }
53 let mut inp = SecretBuf::with_capacity(SECRET_INPUT_LEN);
58 inp.extend_from_slice(&state.0[..]);
59 inp.extend_from_slice(&msg[0..20]);
60
61 let kh_expect = LegacyKdf::new(0).derive(&inp[..], 20)?;
62
63 if !bytes_eq(&kh_expect, &msg[20..40]) {
64 return Err(Error::BadCircHandshakeAuth);
65 }
66
67 Ok(((), super::TapKeyGenerator::new(inp)))
68 }
69}
70
71#[allow(dead_code)] pub(crate) struct CreateFastServer;
76
77impl super::ServerHandshake for CreateFastServer {
78 type KeyType = ();
79 type KeyGen = super::TapKeyGenerator;
80 type ClientAuxData = ();
81 type ServerAuxData = ();
82
83 fn server<R: Rng + CryptoRng, REPLY: super::AuxDataReply<Self>, T: AsRef<[u8]>>(
84 rng: &mut R,
85 reply_fn: &mut REPLY,
86 _key: &[Self::KeyType],
87 msg: T,
88 ) -> RelayHandshakeResult<(Self::KeyGen, Vec<u8>)> {
89 let _reply_extensions: () = reply_fn
90 .reply(&())
91 .ok_or(RelayHandshakeError::BadClientHandshake)?;
92
93 let msg = msg.as_ref();
94 if msg.len() != FAST_C_HANDSHAKE_LEN {
95 return Err(RelayHandshakeError::BadClientHandshake);
96 }
97 let mut reply = vec![0_u8; FAST_S_HANDSHAKE_LEN];
98 rng.fill_bytes(&mut reply[0..20]);
99
100 let mut inp = SecretBuf::with_capacity(SECRET_INPUT_LEN);
101 inp.extend_from_slice(msg);
102 inp.extend_from_slice(&reply[0..20]);
103 let kh = LegacyKdf::new(0)
104 .derive(&inp[..], 20)
105 .map_err(into_internal!("Can't expand key"))?;
106 reply[20..].copy_from_slice(&kh);
107
108 Ok((super::TapKeyGenerator::new(inp), reply))
109 }
110}
111
112#[cfg(test)]
113mod test {
114 #![allow(clippy::bool_assert_comparison)]
116 #![allow(clippy::clone_on_copy)]
117 #![allow(clippy::dbg_macro)]
118 #![allow(clippy::mixed_attributes_style)]
119 #![allow(clippy::print_stderr)]
120 #![allow(clippy::print_stdout)]
121 #![allow(clippy::single_char_pattern)]
122 #![allow(clippy::unwrap_used)]
123 #![allow(clippy::unchecked_time_subtraction)]
124 #![allow(clippy::useless_vec)]
125 #![allow(clippy::needless_pass_by_value)]
126 #![allow(clippy::string_slice)] use super::*;
129 use crate::crypto::handshake::{ClientHandshake, KeyGenerator, ServerHandshake};
130 use hex_literal::hex;
131 use tor_basic_utils::test_rng::testing_rng;
132
133 #[test]
134 fn roundtrip() {
135 let mut rng = testing_rng();
136
137 let (state, cmsg) = CreateFastClient::client1(&mut rng, &(), &()).unwrap();
138 let (s_kg, smsg) =
139 CreateFastServer::server(&mut rng, &mut |_: &()| Some(()), &[()], cmsg).unwrap();
140 let (_msg, c_kg) = CreateFastClient::client2(state, smsg).unwrap();
141
142 let s_key = s_kg.expand(200).unwrap();
143 let c_key = c_kg.expand(200).unwrap();
144
145 assert_eq!(s_key, c_key);
146 }
147
148 #[test]
149 fn failure() {
150 let mut rng = testing_rng();
151
152 let cmsg = [6_u8; 19];
154 let ans = CreateFastServer::server(&mut rng, &mut |_: &()| Some(()), &[()], cmsg);
155 assert!(ans.is_err());
156
157 let (state, cmsg) = CreateFastClient::client1(&mut rng, &(), &()).unwrap();
159 let (_, mut smsg) =
160 CreateFastServer::server(&mut rng, &mut |_: &()| Some(()), &[()], cmsg).unwrap();
161 smsg[35] ^= 16;
162 let ans = CreateFastClient::client2(state, smsg);
163 assert!(ans.is_err());
164 }
165
166 fn test_one_handshake(cmsg: [u8; 20], smsg: [u8; 40], keys: [u8; 100]) {
167 use crate::crypto::testing::FakePRNG;
168
169 let mut rng = FakePRNG::new(&cmsg);
170 let (state, cmsg) = CreateFastClient::client1(&mut rng, &(), &()).unwrap();
171
172 let mut rng = FakePRNG::new(&smsg);
173 let (s_kg, smsg) =
174 CreateFastServer::server(&mut rng, &mut |_: &()| Some(()), &[()], cmsg).unwrap();
175 let (_msg, c_kg) = CreateFastClient::client2(state, smsg).unwrap();
176
177 let s_key = s_kg.expand(100).unwrap();
178 let c_key = c_kg.expand(100).unwrap();
179
180 assert_eq!(s_key, c_key);
181 assert_eq!(&s_key[..], &keys[..]);
182 }
183
184 #[test]
185 fn testvec() {
186 test_one_handshake(
188 hex!("080E247DF7C252FCD2DC10F459703480C223E3A6"),
189 hex!(
190 "BA95C0D092335428BF80093BBED0B7A26C49E1E8696FBF9C8D6BE26504219C000D26AFE370FCEF04"
191 ),
192 hex!(
193 "AFA89B4FC8CF882335A582C52478B5FCB1E08DAF707E2C2D23B8C27D30BD461F3DF98A3AF82221CB658AD0AA8680B99067E4F7DBC546970EA9A56B26433C71DA867BDD09C14A1308BC327D6A448D71D2382B3AB6AF0BB4E19649A8DFF607DB9C57A04AC3"
194 ),
195 );
196
197 test_one_handshake(
198 hex!("5F786C724C2F5978474A04FA63772057AD896A03"),
199 hex!(
200 "6210B037001405742FE78B6F5B34E6DB3C9F2F7E24239498613E0ED872E110A00774A3FCB37A7507"
201 ),
202 hex!(
203 "D41B65D83FB4B34A322B658BE4D706EDCD8B62813757E719118C394E1F22E1C8EA8959BAB30E856A914C3054946F547397094DE031F5BCA384C65C8880BF7AAB9CE7BEE33971F9DE8C22A23366F46BF8B5E5112321E216B0E02C62EEA3ABB72A0E062592"
204 ),
205 );
206 }
207}