1use anyhow::{Error, bail};
6use mundane::hash::Sha256;
7use num::FromPrimitive;
8use wlan_common::ie::rsn::akm::{self, Akm};
9
10use crate::boringssl::{Bignum, EcGroupId, EcPoint};
11use crate::ecc;
12use crate::fcg::FiniteCyclicGroup;
13use crate::hmac_utils::{HmacUtils, HmacUtilsImpl};
14
15type FcgConstructor<E> =
18 Box<dyn Fn() -> Result<Box<dyn FiniteCyclicGroup<Element = E>>, Error> + Send + 'static>;
19
20#[derive(Debug)]
21pub enum OweUpdate {
22 TxPublicKey { group_id: u16, key: Vec<u8> },
23 Success { key: Vec<u8> },
24}
25
26pub type OweUpdateSink = Vec<OweUpdate>;
27
28pub trait ClientOweHandshake: Send {
36 fn initiate_owe(&mut self, sink: &mut OweUpdateSink) -> Result<(), Error>;
39
40 fn handle_public_key(
43 &mut self,
44 sink: &mut OweUpdateSink,
45 group: u16,
46 peer_public_key: Vec<u8>,
47 ) -> Result<(), Error>;
48}
49
50pub trait ApOweHandshake: Send {
52 fn handle_public_key(
56 &mut self,
57 sink: &mut OweUpdateSink,
58 group: u16,
59 peer_public_key: Vec<u8>,
60 ) -> Result<(), Error>;
61}
62
63pub enum OweHandshakeEntity {
64 Client,
65 Ap,
66}
67
68pub fn new_client_owe_handshake(
70 group_id: u16,
71 akm: Akm,
72) -> Result<Box<dyn ClientOweHandshake>, Error> {
73 new_owe_handshake(group_id, akm, OweHandshakeEntity::Client)
74 .map(|h| Box::new(h) as Box<dyn ClientOweHandshake>)
75}
76
77pub fn new_ap_owe_handshake(group_id: u16, akm: Akm) -> Result<Box<dyn ApOweHandshake>, Error> {
79 new_owe_handshake(group_id, akm, OweHandshakeEntity::Ap)
80 .map(|h| Box::new(h) as Box<dyn ApOweHandshake>)
81}
82
83fn new_owe_handshake(
84 group_id: u16,
85 akm: Akm,
86 entity: OweHandshakeEntity,
87) -> Result<OweHandshakeImpl<EcPoint>, Error> {
88 match akm.suite_type {
89 akm::OWE => (),
90 _ => bail!("Cannot construct OWE handshake with AKM {:?}", akm),
91 };
92 let (hmac, group_constructor) = match EcGroupId::from_u16(group_id) {
93 Some(EcGroupId::P256) => {
94 let hmac = Box::new(HmacUtilsImpl::<Sha256>::new());
97 let group_constructor = Box::new(|| {
98 ecc::Group::new(EcGroupId::P256).map(|group| {
99 Box::new(group)
100 as Box<
101 dyn FiniteCyclicGroup<
102 Element = <ecc::Group as FiniteCyclicGroup>::Element,
103 >,
104 >
105 })
106 });
107 (hmac, group_constructor)
108 }
109 _ => bail!("Unsupported OWE group id: {}", group_id),
110 };
111
112 let params = OweParameters { hmac, group_id, entity };
113 Ok(OweHandshakeImpl::new(group_constructor, params))
114}
115
116#[derive(Debug, Clone)]
117struct AsymmetricKeyPair {
118 private_key: Vec<u8>,
119 public_key: Vec<u8>,
120}
121
122struct OweHandshakeImpl<E> {
123 fcg: FcgConstructor<E>,
124 key_pair: Option<AsymmetricKeyPair>,
125 params: OweParameters,
126}
127
128struct OweParameters {
129 pub hmac: Box<dyn HmacUtils + Send>,
130 pub group_id: u16,
131 entity: OweHandshakeEntity,
132}
133
134impl<E> OweHandshakeImpl<E> {
135 pub fn new(fcg_constructor: FcgConstructor<E>, params: OweParameters) -> Self {
136 Self { fcg: fcg_constructor, key_pair: None, params }
137 }
138
139 fn generate_keys(&mut self, sink: &mut OweUpdateSink) -> Result<(), Error> {
140 self.internal_generate_keys(sink, |order| Bignum::rand_range_ex(2, &order))
143 }
144
145 fn internal_generate_keys(
146 &mut self,
147 sink: &mut OweUpdateSink,
148 generate_private_key: impl FnOnce(Bignum) -> Result<Bignum, Error>,
149 ) -> Result<(), Error> {
150 let fcg = (self.fcg)()?;
151 let order = fcg.order()?;
152 let private_key = generate_private_key(order)?;
153 let generator: E = fcg.generator()?;
156 let public_key_element = fcg.scalar_op(&private_key, &generator)?;
157 let public_key = fcg.element_to_octets_compact(&public_key_element)?;
160 self.key_pair = Some(AsymmetricKeyPair {
161 private_key: private_key.to_be_vec(0),
162 public_key: public_key.clone(),
163 });
164 sink.push(OweUpdate::TxPublicKey { group_id: self.params.group_id, key: public_key });
165 Ok(())
166 }
167
168 fn internal_handle_public_key(
173 &mut self,
174 sink: &mut OweUpdateSink,
175 group: u16,
176 peer_public_key: Vec<u8>,
177 ) -> Result<(), Error> {
178 if group != EcGroupId::P256.id() {
179 bail!("Received unsupported OWE group {}", group);
180 }
181 if let OweHandshakeEntity::Ap = self.params.entity {
182 if self.key_pair.is_none() {
183 self.generate_keys(sink)?;
184 }
185 }
186 let (private_key, self_public_key) = match &self.key_pair {
187 Some(key_pair) => {
188 (Bignum::new_from_slice(&key_pair.private_key)?, key_pair.public_key.clone())
189 }
190 _ => bail!("Received public key from peer but private key has not been generated"),
191 };
192 let fcg = (self.fcg)()?;
193 let peer_public_key_element = match fcg.element_from_octets_compact(&peer_public_key)? {
196 Some(element) => element,
197 None => bail!("Failed to convert peer public key octets to FCG element"),
198 };
199 let element_s = fcg.scalar_op(&private_key, &peer_public_key_element)?;
202 let s = match fcg.map_to_secret_value(&element_s)? {
204 Some(s) => s,
205 None => bail!("Failed to map shared secret element to scalar"),
206 };
207 let (client_public_key, ap_public_key) = match self.params.entity {
209 OweHandshakeEntity::Client => (&self_public_key, &peer_public_key),
210 OweHandshakeEntity::Ap => (&peer_public_key, &self_public_key),
211 };
212 let salt =
213 concat_public_keys_and_group(client_public_key, ap_public_key, self.params.group_id);
214 let prk = self.params.hmac.hkdf_extract(&salt, &s);
215 let pmk =
217 self.params.hmac.hkdf_expand(&prk, "OWE Key Generation", self.params.hmac.bits() / 8);
218 sink.push(OweUpdate::Success { key: pmk });
219 Ok(())
220 }
221}
222
223impl<E> ClientOweHandshake for OweHandshakeImpl<E> {
224 fn initiate_owe(&mut self, sink: &mut OweUpdateSink) -> Result<(), Error> {
225 self.generate_keys(sink)
226 }
227
228 fn handle_public_key(
229 &mut self,
230 sink: &mut OweUpdateSink,
231 group: u16,
232 ap_public_key: Vec<u8>,
233 ) -> Result<(), Error> {
234 self.internal_handle_public_key(sink, group, ap_public_key)
235 }
236}
237
238impl<E> ApOweHandshake for OweHandshakeImpl<E> {
239 fn handle_public_key(
240 &mut self,
241 sink: &mut OweUpdateSink,
242 group: u16,
243 client_public_key: Vec<u8>,
244 ) -> Result<(), Error> {
245 self.generate_keys(sink)?;
246 self.internal_handle_public_key(sink, group, client_public_key)
247 }
248}
249
250fn concat_public_keys_and_group(
251 client_public_key: &[u8],
252 ap_public_key: &[u8],
253 group_id: u16,
254) -> Vec<u8> {
255 let mut result: Vec<u8> = Vec::with_capacity(client_public_key.len() + ap_public_key.len() + 2);
256 result.extend_from_slice(&client_public_key);
257 result.extend_from_slice(&ap_public_key);
258 result.extend_from_slice(&group_id.to_le_bytes());
259 result
260}
261
262#[cfg(test)]
263mod tests {
264 use super::*;
265 use assert_matches::assert_matches;
266 use wlan_common::ie::rsn::akm::AKM_OWE;
267
268 struct TestHandshake {
269 client: Box<dyn ClientOweHandshake>,
270 ap: Box<dyn ApOweHandshake>,
271 }
272
273 struct TxPublicKey {
274 group_id: u16,
275 key: Vec<u8>,
276 }
277
278 impl TestHandshake {
279 fn new(group_id: u16) -> Self {
280 let client = new_client_owe_handshake(group_id, AKM_OWE).unwrap();
281 let ap = new_ap_owe_handshake(group_id, AKM_OWE).unwrap();
282 Self { client, ap }
283 }
284
285 fn client_initiate_owe(&mut self) -> TxPublicKey {
286 let mut sink = OweUpdateSink::new();
287 self.client.initiate_owe(&mut sink).unwrap();
288 assert_eq!(sink.len(), 1);
289 expect_tx_public_key(&mut sink)
290 }
291
292 fn ap_handle_public_key(
293 &mut self,
294 client_public_key: TxPublicKey,
295 ) -> (TxPublicKey, Vec<u8>) {
296 let mut sink = OweUpdateSink::new();
297 self.ap
298 .handle_public_key(&mut sink, client_public_key.group_id, client_public_key.key)
299 .unwrap();
300 assert_eq!(sink.len(), 2);
301 let ap_public_key = expect_tx_public_key(&mut sink);
302 let pmk = assert_matches!(sink.remove(0), OweUpdate::Success { key } => key);
303 (ap_public_key, pmk)
304 }
305
306 fn client_handle_public_key(&mut self, ap_public_key: TxPublicKey) -> Vec<u8> {
307 let mut sink = OweUpdateSink::new();
308 self.client
309 .handle_public_key(&mut sink, ap_public_key.group_id, ap_public_key.key)
310 .unwrap();
311 assert_eq!(sink.len(), 1);
312 assert_matches!(sink.remove(0), OweUpdate::Success { key } => key)
313 }
314 }
315
316 fn expect_tx_public_key(sink: &mut OweUpdateSink) -> TxPublicKey {
317 let (group_id, key) = assert_matches!(sink.remove(0), OweUpdate::TxPublicKey { group_id, key } => (group_id, key));
318 TxPublicKey { group_id, key }
319 }
320
321 #[test]
322 fn test_owe_handshake() {
323 for i in 0..10 {
324 let mut handshake = TestHandshake::new(EcGroupId::P256.id());
325 let client_public_key = handshake.client_initiate_owe();
326 let (ap_public_key, ap_pmk) = handshake.ap_handle_public_key(client_public_key);
327 let client_pmk = handshake.client_handle_public_key(ap_public_key);
328 if client_pmk != ap_pmk {
329 panic!(
330 "Iteration {}: PMKs do not match:\n client: {:x?}\n ap: {:x?}",
331 i, client_pmk, ap_pmk
332 );
333 }
334 }
335 }
336
337 #[test]
338 fn test_new_handshake_unsupported_group() {
339 for group_id in [20, 21] {
340 let result = new_owe_handshake(group_id, AKM_OWE, OweHandshakeEntity::Client);
341 assert!(result.is_err());
342 }
343 }
344
345 #[test]
346 fn test_handshake_handle_public_key_unsupported_group() {
347 let mut handshake = TestHandshake::new(EcGroupId::P256.id());
348 let client_public_key = handshake.client_initiate_owe();
349 for group in [20, 21] {
350 let result = handshake.ap.handle_public_key(
351 &mut Vec::new(),
352 group,
353 client_public_key.key.clone(),
354 );
355 assert!(result.is_err());
356 }
357 }
358
359 const SELF_PRIVATE_KEY: &str =
363 "5d6edb96f46993e0fb7621f93e5d3450813eb8c63ece17ecbf45376c574debb2";
364 const EXPECTED_SELF_PUBLIC_KEY: &str =
365 "4abf7c206407893a1c8b27a7b9b2c1dc6e3d7038fed9ad7ae2250d03dc18e080";
366 const PEER_PUBLIC_KEY: &str =
367 "40ac0ba500964f5872fb969e673d0c83869dd8976c688cec46fe4ba4b140e7ef";
368 const EXPECTED_PMK: &str = "afac9db29ab652d7f76054c9c51204a3bb59339e302523d9c114b269a46f5734";
369
370 #[test]
371 fn test_handshake_test_vector() {
372 let mut handshake =
373 new_owe_handshake(EcGroupId::P256.id(), AKM_OWE, OweHandshakeEntity::Client).unwrap();
374 let mut sink = OweUpdateSink::new();
375 handshake
376 .internal_generate_keys(&mut sink, |_| {
377 let private_key = hex::decode(SELF_PRIVATE_KEY).unwrap();
378 Ok(Bignum::new_from_slice(&private_key).unwrap())
379 })
380 .unwrap();
381 let tx_public_key = expect_tx_public_key(&mut sink);
382 let expected_self_public_key = hex::decode(EXPECTED_SELF_PUBLIC_KEY).unwrap();
383 assert_eq!(tx_public_key.key, expected_self_public_key);
384
385 let peer_public_key = hex::decode(PEER_PUBLIC_KEY).unwrap();
386 handshake
387 .internal_handle_public_key(&mut sink, EcGroupId::P256.id(), peer_public_key)
388 .unwrap();
389 let pmk = assert_matches!(sink.remove(0), OweUpdate::Success { key } => key);
390 let expected_pmk = hex::decode(EXPECTED_PMK).unwrap();
391 assert_eq!(pmk, expected_pmk);
392 }
393}