1mod authenticator;
6mod supplicant;
7
8use crate::key::exchange;
9use crate::key::gtk::{Gtk, GtkProvider};
10use crate::key::igtk::{Igtk, IgtkProvider};
11use crate::key::ptk::Ptk;
12use crate::nonce::NonceReader;
13use crate::rsna::{Dot11VerifiedKeyFrame, NegotiatedProtection, Role, UpdateSink};
14use crate::{rsn_ensure, Error, ProtectionInfo};
15use ieee80211::MacAddr;
16use std::ops::Deref;
17use std::sync::{Arc, Mutex};
18use wlan_common::ie::rsn::cipher::Cipher;
19use wlan_common::ie::rsn::rsne::Rsne;
20use wlan_common::ie::rsn::suite_filter::DEFAULT_GROUP_MGMT_CIPHER;
21use wlan_statemachine::StateMachine;
22use zerocopy::SplitByteSlice;
23
24#[derive(Debug, PartialEq)]
25pub enum MessageNumber {
26 Message1 = 1,
27 Message2 = 2,
28 Message3 = 3,
29 Message4 = 4,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, Copy)]
35pub struct AuthenticatorKeyReplayCounter(u64);
36
37impl Deref for AuthenticatorKeyReplayCounter {
38 type Target = u64;
39
40 fn deref(&self) -> &u64 {
41 &self.0
42 }
43}
44
45impl AuthenticatorKeyReplayCounter {
46 pub fn next_after(key_replay_counter: u64) -> Self {
47 Self(key_replay_counter + 1)
48 }
49}
50
51#[derive(Debug, Clone, Copy)]
54pub struct SupplicantKeyReplayCounter(u64);
55
56impl Deref for SupplicantKeyReplayCounter {
57 type Target = u64;
58
59 fn deref(&self) -> &u64 {
60 &self.0
61 }
62}
63
64impl From<u64> for SupplicantKeyReplayCounter {
65 fn from(a: u64) -> Self {
66 Self(a)
67 }
68}
69
70pub struct FourwayHandshakeFrame<B: SplitByteSlice>(Dot11VerifiedKeyFrame<B>);
73
74impl<B: SplitByteSlice> FourwayHandshakeFrame<B> {
75 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
76 pub fn from_verified(
77 frame: Dot11VerifiedKeyFrame<B>,
78 role: Role,
79 nonce: Option<&[u8]>,
80 ) -> Result<FourwayHandshakeFrame<B>, Error> {
81 let raw_frame = frame.unsafe_get_raw();
83 let msg_no = message_number(raw_frame);
85 match role {
86 Role::Authenticator => match msg_no {
88 MessageNumber::Message2 | MessageNumber::Message4 => {}
89 _ => return Err(Error::UnexpectedHandshakeMessage(msg_no.into()).into()),
90 },
91 Role::Supplicant => match msg_no {
92 MessageNumber::Message1 | MessageNumber::Message3 => {}
93 _ => return Err(Error::UnexpectedHandshakeMessage(msg_no.into()).into()),
94 },
95 };
96
97 match msg_no {
99 MessageNumber::Message1 => validate_message_1(raw_frame),
100 MessageNumber::Message2 => validate_message_2(raw_frame),
101 MessageNumber::Message3 => validate_message_3(raw_frame, nonce),
102 MessageNumber::Message4 => validate_message_4(raw_frame),
103 }?;
104
105 Ok(FourwayHandshakeFrame(frame))
106 }
107
108 pub fn get(self) -> Dot11VerifiedKeyFrame<B> {
109 self.0
110 }
111
112 fn message_number(&self) -> MessageNumber {
114 message_number(self.unsafe_get_raw())
116 }
117}
118
119impl<B: SplitByteSlice> std::ops::Deref for FourwayHandshakeFrame<B> {
120 type Target = Dot11VerifiedKeyFrame<B>;
121
122 fn deref(&self) -> &Dot11VerifiedKeyFrame<B> {
123 &self.0
124 }
125}
126
127#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
128pub fn get_group_mgmt_cipher(
129 s_protection: &ProtectionInfo,
130 a_protection: &ProtectionInfo,
131) -> Result<Option<Cipher>, Error> {
132 match (s_protection, a_protection) {
137 (
138 ProtectionInfo::Rsne(Rsne {
139 rsn_capabilities: Some(s_rsn_capabilities),
140 group_mgmt_cipher_suite: s_group_mgmt_cipher_suite,
141 ..
142 }),
143 ProtectionInfo::Rsne(Rsne {
144 rsn_capabilities: Some(a_rsn_capabilities),
145 group_mgmt_cipher_suite: a_group_mgmt_cipher_suite,
146 ..
147 }),
148 ) => {
149 if !s_rsn_capabilities.mgmt_frame_protection_cap()
151 && s_rsn_capabilities.mgmt_frame_protection_req()
152 {
153 return Err(Error::InvalidClientMgmtFrameProtectionCapabilityBit);
154 }
155 if !a_rsn_capabilities.mgmt_frame_protection_cap()
156 && a_rsn_capabilities.mgmt_frame_protection_req()
157 {
158 return Err(Error::InvalidApMgmtFrameProtectionCapabilityBit);
159 }
160
161 if s_rsn_capabilities.mgmt_frame_protection_req()
163 && !a_rsn_capabilities.mgmt_frame_protection_cap()
164 {
165 return Err(Error::MgmtFrameProtectionRequiredByClient);
166 }
167 if !s_rsn_capabilities.mgmt_frame_protection_cap()
168 && a_rsn_capabilities.mgmt_frame_protection_req()
169 {
170 return Err(Error::MgmtFrameProtectionRequiredByAp);
171 }
172
173 if s_rsn_capabilities.mgmt_frame_protection_cap()
174 && a_rsn_capabilities.mgmt_frame_protection_cap()
175 {
176 let s_group_mgmt_cipher_suite =
177 s_group_mgmt_cipher_suite.unwrap_or(DEFAULT_GROUP_MGMT_CIPHER);
178 let a_group_mgmt_cipher_suite =
179 a_group_mgmt_cipher_suite.unwrap_or(DEFAULT_GROUP_MGMT_CIPHER);
180
181 if s_group_mgmt_cipher_suite != a_group_mgmt_cipher_suite {
182 return Err(Error::GroupMgmtCipherMismatch(
183 s_group_mgmt_cipher_suite,
184 a_group_mgmt_cipher_suite,
185 ));
186 }
187
188 return Ok(Some(s_group_mgmt_cipher_suite));
189 }
190 }
191 (_, ProtectionInfo::Rsne(Rsne { rsn_capabilities: Some(a_rsn_capabilities), .. })) => {
192 if a_rsn_capabilities.mgmt_frame_protection_req() {
193 return Err(Error::MgmtFrameProtectionRequiredByAp);
194 }
195 }
196 (ProtectionInfo::Rsne(Rsne { rsn_capabilities: Some(s_rsn_capabilities), .. }), _) => {
197 if s_rsn_capabilities.mgmt_frame_protection_req() {
198 return Err(Error::MgmtFrameProtectionRequiredByClient);
199 }
200 }
201
202 (ProtectionInfo::Rsne(Rsne { rsn_capabilities: None, .. }), _)
205 | (ProtectionInfo::LegacyWpa(_), _) => {}
206 }
207
208 Ok(None)
209}
210
211#[derive(Debug, Clone)]
212pub struct Config {
213 pub role: Role,
214 pub s_addr: MacAddr,
215 pub s_protection: ProtectionInfo,
216 pub a_addr: MacAddr,
217 pub a_protection: ProtectionInfo,
218 pub nonce_rdr: Arc<NonceReader>,
219 pub gtk_provider: Option<Arc<Mutex<GtkProvider>>>,
220 pub igtk_provider: Option<Arc<Mutex<IgtkProvider>>>,
221
222 _private: (),
225}
226
227impl Config {
228 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
229 pub fn new(
230 role: Role,
231 s_addr: MacAddr,
232 s_protection: ProtectionInfo,
233 a_addr: MacAddr,
234 a_protection: ProtectionInfo,
235 nonce_rdr: Arc<NonceReader>,
236 gtk_provider: Option<Arc<Mutex<GtkProvider>>>,
237 igtk_provider: Option<Arc<Mutex<IgtkProvider>>>,
238 ) -> Result<Config, Error> {
239 match (&s_protection, &a_protection) {
241 (ProtectionInfo::Rsne(s_rsne), ProtectionInfo::Rsne(a_rsne)) => {
242 match s_rsne.is_valid_subset_of(a_rsne) {
246 Ok(true) => {}
247 Ok(false) => {
248 return Err(Error::RsneInvalidSubset(s_rsne.clone(), a_rsne.clone()))
249 }
250 Err(e) => return Err(e.into()),
251 };
252 }
253 (_, ProtectionInfo::LegacyWpa(_)) => {}
256 (ProtectionInfo::LegacyWpa(_), _) => {}
257 }
258
259 match NegotiatedProtection::from_protection(&s_protection) {
266 Ok(negotiated_protection) => negotiated_protection,
267 Err(e) => return Err(Error::InvalidSupplicantProtection(format!("{:?}", e))),
268 };
269
270 if role == Role::Authenticator {
274 rsn_ensure!(gtk_provider.is_some(), Error::MissingGtkProvider);
275
276 match get_group_mgmt_cipher(&s_protection, &a_protection)? {
279 Some(group_mgmt_cipher) => match igtk_provider.as_ref() {
280 None => return Err(Error::MissingIgtkProvider),
281 Some(igtk_provider) => {
282 let igtk_provider_cipher = igtk_provider.lock().unwrap().cipher();
283 rsn_ensure!(
284 group_mgmt_cipher == igtk_provider_cipher,
285 Error::WrongIgtkProviderCipher(group_mgmt_cipher, igtk_provider_cipher),
286 );
287 }
288 },
289 None => {}
290 }
291 }
292
293 Ok(Config {
294 role,
295 s_addr,
296 s_protection,
297 a_addr,
298 a_protection,
299 nonce_rdr,
300 gtk_provider,
301 igtk_provider,
302 _private: (),
303 })
304 }
305}
306
307impl PartialEq for Config {
308 fn eq(&self, other: &Config) -> bool {
309 self.role == other.role
310 && self.s_addr == other.s_addr
311 && self.s_protection == other.s_protection
312 && self.a_addr == other.a_addr
313 && self.a_protection == other.a_protection
314 }
315}
316
317#[derive(Debug, PartialEq)]
318pub enum Fourway {
319 Authenticator(StateMachine<authenticator::State>),
320 Supplicant(StateMachine<supplicant::State>),
321}
322
323impl Fourway {
324 pub fn new(cfg: Config, pmk: Vec<u8>) -> Result<Fourway, anyhow::Error> {
325 let fourway = match &cfg.role {
326 Role::Supplicant => {
327 let state = supplicant::new(cfg, pmk);
328 Fourway::Supplicant(StateMachine::new(state))
329 }
330 Role::Authenticator => {
331 let state = authenticator::new(cfg, pmk);
332 Fourway::Authenticator(StateMachine::new(state))
333 }
334 };
335 Ok(fourway)
336 }
337
338 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
339 pub fn on_eapol_key_frame<B: SplitByteSlice>(
340 &mut self,
341 update_sink: &mut UpdateSink,
342 frame: Dot11VerifiedKeyFrame<B>,
343 ) -> Result<(), Error> {
344 match self {
345 Fourway::Authenticator(state_machine) => {
346 let frame = FourwayHandshakeFrame::from_verified(frame, Role::Authenticator, None)?;
347 state_machine.replace_state(|state| state.on_eapol_key_frame(update_sink, frame));
348 Ok(())
349 }
350 Fourway::Supplicant(state_machine) => {
351 let anonce = state_machine.as_ref().anonce();
352 let frame = FourwayHandshakeFrame::from_verified(frame, Role::Supplicant, anonce)?;
353 state_machine.replace_state(|state| state.on_eapol_key_frame(update_sink, frame));
354 Ok(())
355 }
356 }
357 }
358
359 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
360 pub fn on_rsna_response_timeout(&self) -> Result<(), Error> {
361 match self {
362 Fourway::Authenticator(state_machine) => state_machine.on_rsna_response_timeout(),
363 Fourway::Supplicant(state_machine) => state_machine.on_rsna_response_timeout(),
364 }
365 }
366
367 pub fn ptk(&self) -> Option<Ptk> {
368 match self {
369 Fourway::Authenticator(state_machine) => state_machine.as_ref().ptk(),
370 Fourway::Supplicant(state_machine) => state_machine.as_ref().ptk(),
371 }
372 }
373
374 pub fn gtk(&self) -> Option<Gtk> {
375 match self {
376 Fourway::Authenticator(state_machine) => state_machine.as_ref().gtk(),
377 Fourway::Supplicant(state_machine) => state_machine.as_ref().gtk(),
378 }
379 }
380
381 pub fn igtk(&self) -> Option<Igtk> {
382 match self {
383 Fourway::Authenticator(state_machine) => state_machine.as_ref().igtk(),
384 Fourway::Supplicant(state_machine) => state_machine.as_ref().igtk(),
385 }
386 }
387
388 #[cfg(test)]
389 pub fn get_config(&self) -> Config {
390 match self {
391 Fourway::Supplicant(state_machine) => match state_machine.as_ref() {
392 supplicant::State::AwaitingMsg1 { cfg, .. }
393 | supplicant::State::AwaitingMsg3 { cfg, .. }
394 | supplicant::State::KeysInstalled { cfg, .. } => cfg.clone(),
395 },
396 Fourway::Authenticator(state_machine) => match state_machine.as_ref() {
397 authenticator::State::Idle { cfg, .. }
398 | authenticator::State::AwaitingMsg2 { cfg, .. }
399 | authenticator::State::AwaitingMsg4 { cfg, .. }
400 | authenticator::State::KeysInstalled { cfg, .. } => cfg.clone(),
401 },
402 }
403 }
404
405 pub fn destroy(self) -> exchange::Config {
406 let cfg = match self {
407 Fourway::Supplicant(state_machine) => state_machine.into_state().destroy(),
408 Fourway::Authenticator(state_machine) => state_machine.into_state().destroy(),
409 };
410 exchange::Config::FourWayHandshake(cfg)
411 }
412}
413
414#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
417fn validate_message_1<B: SplitByteSlice>(frame: &eapol::KeyFrameRx<B>) -> Result<(), Error> {
418 let key_info = frame.key_frame_fields.key_info();
419 rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message1.into()));
421 rsn_ensure!(key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message1.into()));
423 rsn_ensure!(!key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message1.into()));
425 rsn_ensure!(!key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message1.into()));
427 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message1.into()));
429 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message1.into()));
431 rsn_ensure!(
433 !key_info.encrypted_key_data(),
434 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message1.into())
435 );
436 rsn_ensure!(
438 !is_zero(&frame.key_frame_fields.key_nonce[..]),
439 Error::InvalidNonce(MessageNumber::Message1.into())
440 );
441 rsn_ensure!(
444 is_zero(&frame.key_frame_fields.key_iv[..]),
445 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message1.into())
446 );
447 rsn_ensure!(
449 frame.key_frame_fields.key_rsc.to_native() == 0,
450 Error::InvalidRsc(MessageNumber::Message1.into())
451 );
452
453 Ok(())
461}
462
463#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
464fn validate_message_2<B: SplitByteSlice>(frame: &eapol::KeyFrameRx<B>) -> Result<(), Error> {
465 let key_info = frame.key_frame_fields.key_info();
466 rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message2.into()));
468 rsn_ensure!(!key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message2.into()));
470 rsn_ensure!(key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message2.into()));
472 rsn_ensure!(!key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message2.into()));
474 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message2.into()));
478 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message2.into()));
480 rsn_ensure!(
482 !key_info.encrypted_key_data(),
483 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message2.into())
484 );
485 rsn_ensure!(
487 !is_zero(&frame.key_frame_fields.key_nonce[..]),
488 Error::InvalidNonce(MessageNumber::Message2.into())
489 );
490 rsn_ensure!(
493 is_zero(&frame.key_frame_fields.key_iv[..]),
494 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message2.into())
495 );
496 rsn_ensure!(
498 frame.key_frame_fields.key_rsc.to_native() == 0,
499 Error::InvalidRsc(MessageNumber::Message2.into())
500 );
501
502 Ok(())
503}
504
505#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
506fn validate_message_3<B: SplitByteSlice>(
507 frame: &eapol::KeyFrameRx<B>,
508 nonce: Option<&[u8]>,
509) -> Result<(), Error> {
510 let key_info = frame.key_frame_fields.key_info();
511 rsn_ensure!(key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message3.into()));
514 rsn_ensure!(key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message3.into()));
516 if frame.key_frame_fields.descriptor_type != eapol::KeyDescriptor::LEGACY_WPA1 {
518 rsn_ensure!(
520 key_info.key_mic(),
521 Error::InvalidKeyMicBitValue(MessageNumber::Message3.into())
522 );
523 rsn_ensure!(
525 key_info.secure(),
526 Error::InvalidSecureBitValue(MessageNumber::Message3.into())
527 );
528 rsn_ensure!(
530 key_info.encrypted_key_data(),
531 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message3.into())
532 );
533 }
534 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message3.into()));
536 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message3.into()));
538 if let Some(nonce) = nonce {
540 rsn_ensure!(
541 !is_zero(&frame.key_frame_fields.key_nonce[..])
542 && &frame.key_frame_fields.key_nonce[..] == nonce,
543 Error::InvalidNonce(MessageNumber::Message3.into())
544 );
545 }
546 rsn_ensure!(
552 frame.eapol_fields.version < eapol::ProtocolVersion::IEEE802DOT1X2010
553 || is_zero(&frame.key_frame_fields.key_iv[..]),
554 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message3.into())
555 );
556 rsn_ensure!(frame.key_data.len() != 0, Error::EmptyKeyData(MessageNumber::Message3.into()));
559
560 Ok(())
561}
562
563#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
564fn validate_message_4<B: SplitByteSlice>(frame: &eapol::KeyFrameRx<B>) -> Result<(), Error> {
565 let key_info = frame.key_frame_fields.key_info();
566 rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message4.into()));
568 rsn_ensure!(!key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message4.into()));
570 rsn_ensure!(key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message4.into()));
572 rsn_ensure!(key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message4.into()));
574 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message4.into()));
578 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message4.into()));
580 rsn_ensure!(
582 !key_info.encrypted_key_data(),
583 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message4.into())
584 );
585 rsn_ensure!(
588 is_zero(&frame.key_frame_fields.key_iv[..]),
589 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message4.into())
590 );
591 rsn_ensure!(
593 frame.key_frame_fields.key_rsc.to_native() == 0,
594 Error::InvalidRsc(MessageNumber::Message4.into())
595 );
596
597 Ok(())
598}
599
600fn message_number<B: SplitByteSlice>(rx_frame: &eapol::KeyFrameRx<B>) -> MessageNumber {
601 if rx_frame.key_frame_fields.key_info().key_ack() {
610 if rx_frame.key_frame_fields.key_info().install() {
614 MessageNumber::Message3
615 } else {
616 MessageNumber::Message1
617 }
618 } else {
619 if rx_frame.key_frame_fields.key_info().secure() {
623 MessageNumber::Message4
624 } else {
625 MessageNumber::Message2
626 }
627 }
628}
629
630fn is_zero(slice: &[u8]) -> bool {
631 slice.iter().all(|&x| x == 0)
632}
633
634#[cfg(test)]
635mod tests {
636 use super::*;
637 use crate::rsna::{test_util, SecAssocUpdate};
638 use crate::rsne::RsnCapabilities;
639 use wlan_common::ie::rsn::cipher::{CIPHER_BIP_CMAC_128, CIPHER_BIP_CMAC_256};
640 use wlan_common::ie::wpa::fake_wpa_ies::fake_deprecated_wpa1_vendor_ie;
641
642 #[test]
643 fn correct_value_returned_by_authenticator_key_replay_counter() {
644 let key_replay_counter = AuthenticatorKeyReplayCounter(5);
645 assert_eq!(*key_replay_counter, 5);
646 }
647
648 #[test]
649 fn correct_value_returned_by_supplicant_key_replay_counter() {
650 let key_replay_counter = SupplicantKeyReplayCounter(5);
651 assert_eq!(*key_replay_counter, 5);
652 }
653
654 #[test]
655 fn next_replay_counter_is_next_integer() {
656 let s_key_replay_counter = SupplicantKeyReplayCounter(5);
657 let next_key_replay_counter =
658 AuthenticatorKeyReplayCounter::next_after(*s_key_replay_counter);
659 assert_eq!(*next_key_replay_counter, 6);
660 }
661
662 #[test]
664 fn test_supplicant_with_authenticator() {
665 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
666
667 let msg1 = env.initiate(11.into());
669 assert_eq!(msg1.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
670 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
671 assert_eq!(msg2.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
672 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
673 assert_eq!(msg3.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
674 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
675 assert_eq!(msg4.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
676 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
677
678 assert_eq!(s_ptk, a_ptk);
680
681 assert_eq!(s_gtk, a_gtk);
684 assert_eq!(s_gtk.key_id(), 1);
685 assert_eq!(s_gtk.key_rsc(), 3);
686 }
687
688 #[test]
689 fn test_wpa3_handshake_generates_igtk_real_authenticator() {
690 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa3, 1, 754);
691
692 let msg1 = env.initiate(11.into());
694 assert_eq!(msg1.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
695 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
696 assert_eq!(msg2.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
697 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
698 assert_eq!(msg3.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
699 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
700 assert_eq!(msg4.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
701 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
702
703 assert_eq!(s_ptk, a_ptk);
705 assert_eq!(s_gtk, a_gtk);
706 assert_eq!(s_gtk.key_id(), 1);
707 assert_eq!(s_gtk.key_rsc(), 754);
708 assert!(env.supplicant.igtk().is_some());
709 assert_eq!(env.supplicant.igtk(), env.authenticator.igtk());
710 }
711
712 fn run_wpa3_handshake_mock_authenticator(
713 gtk: &[u8],
714 igtk: Option<&[u8]>,
715 ) -> (Ptk, Vec<SecAssocUpdate>) {
716 let anonce = [0xab; 32];
717 let mut supplicant = test_util::make_handshake(
718 test_util::HandshakeKind::Wpa3,
719 super::Role::Supplicant,
720 1,
721 3,
722 );
723 let msg1_buf = test_util::get_wpa3_4whs_msg1(&anonce[..]);
724 let msg1 = msg1_buf.keyframe();
725 let updates = test_util::send_msg_to_fourway(&mut supplicant, msg1, 0.into());
726 let msg2 = test_util::expect_eapol_resp(&updates[..]);
727 let a_ptk =
728 test_util::get_wpa3_ptk(&anonce[..], &msg2.keyframe().key_frame_fields.key_nonce[..]);
729 let msg3_buf = &test_util::get_wpa3_4whs_msg3(&a_ptk, &anonce[..], >k[..], igtk);
730 let msg3 = msg3_buf.keyframe();
731 (a_ptk, test_util::send_msg_to_fourway(&mut supplicant, msg3, 0.into()))
732 }
733
734 #[test]
735 fn test_wpa3_handshake_generates_igtk_mock_authenticator() {
736 let gtk = [0xbb; 32];
737 let igtk = [0xcc; 32];
738 let (ptk, updates) = run_wpa3_handshake_mock_authenticator(>k[..], Some(&igtk[..]));
739
740 test_util::expect_eapol_resp(&updates[..]);
741 let s_ptk = test_util::expect_reported_ptk(&updates[..]);
742 let s_gtk = test_util::expect_reported_gtk(&updates[..]);
743 let s_igtk = test_util::expect_reported_igtk(&updates[..]);
744 assert_eq!(s_ptk, ptk);
745 assert_eq!(&s_gtk.bytes[..], >k[..]);
746 assert_eq!(&s_igtk.igtk[..], &igtk[..]);
747 }
748
749 #[test]
750 fn test_wpa3_handshake_requires_igtk() {
751 let gtk = [0xbb; 32];
752 let (_ptk, updates) = run_wpa3_handshake_mock_authenticator(>k[..], None);
753 assert!(
754 test_util::get_eapol_resp(&updates[..]).is_none(),
755 "WPA3 should not send EAPOL msg4 without IGTK"
756 );
757 }
758
759 #[test]
760 fn test_wpa1_handshake() {
761 let pmk = test_util::get_pmk();
762 let cfg = test_util::make_wpa1_fourway_cfg();
763 let mut supplicant = Fourway::new(cfg, pmk).expect("error while creating 4-Way Handshake");
764
765 let anonce = [0xab; 32];
767 let msg1_buf = test_util::get_wpa1_4whs_msg1(&anonce[..]);
768 let msg1 = msg1_buf.keyframe();
769 let updates = test_util::send_msg_to_fourway(&mut supplicant, msg1, 0.into());
770 let msg2 = test_util::expect_eapol_resp(&updates[..]);
771 let a_ptk =
772 test_util::get_wpa1_ptk(&anonce[..], &msg2.keyframe().key_frame_fields.key_nonce[..]);
773 let msg3_buf = &test_util::get_wpa1_4whs_msg3(&a_ptk, &anonce[..]);
774 let msg3 = msg3_buf.keyframe();
775 let updates = test_util::send_msg_to_fourway(&mut supplicant, msg3, 0.into());
776
777 test_util::expect_eapol_resp(&updates[..]);
779 let s_ptk = test_util::expect_reported_ptk(&updates[..]);
780 assert_eq!(s_ptk, a_ptk);
781 }
782
783 #[test]
784 fn test_supplicant_replay_msg3() {
785 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
786
787 let msg1 = env.initiate(11.into());
789 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
790 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
791 let (_, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
792
793 let mut update_sink = UpdateSink::default();
795
796 env.send_msg3_to_supplicant_capture_updates(msg3.keyframe(), 12.into(), &mut update_sink);
797 let msg4 = test_util::expect_eapol_resp(&update_sink[..]);
798
799 for update in update_sink {
800 if let SecAssocUpdate::Key(_) = update {
801 panic!("reinstalled key");
802 }
803 }
804
805 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
807
808 assert_eq!(s_ptk, a_ptk);
810 assert_eq!(s_gtk, a_gtk);
811 }
812
813 #[test]
814 fn test_supplicant_replay_msg3_different_gtk() {
815 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
816
817 let msg1 = env.initiate(11.into());
819 let anonce = msg1.keyframe().key_frame_fields.key_nonce.clone();
820 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
821 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
822 let (_, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
823
824 let mut other_gtk = s_gtk.bytes.clone();
827 other_gtk[0] ^= 0xFF;
828 let msg3 = test_util::get_wpa2_4whs_msg3(&s_ptk, &anonce[..], &other_gtk[..], |msg3| {
829 msg3.key_frame_fields.key_replay_counter.set_from_native(42);
830 });
831 let mut update_sink = UpdateSink::default();
832 env.send_msg3_to_supplicant_capture_updates(msg3.keyframe(), 13.into(), &mut update_sink);
833
834 assert_eq!(update_sink.len(), 0);
836 }
837
838 #[test]
841 fn test_random_iv_msg1_v1() {
842 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
843
844 let msg1 = env.initiate(1.into());
845 let mut buf = vec![];
846 let mut msg1 = msg1.copy_keyframe_mut(&mut buf);
847 msg1.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2001;
848 msg1.key_frame_fields.key_iv = [0xFFu8; 16];
849 env.send_msg1_to_supplicant_expect_err(msg1, 1.into());
850 }
851
852 #[test]
853 fn test_random_iv_msg1_v2() {
854 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
855
856 let msg1 = env.initiate(1.into());
857 let mut buf = vec![];
858 let mut msg1 = msg1.copy_keyframe_mut(&mut buf);
859 msg1.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2004;
860 msg1.key_frame_fields.key_iv = [0xFFu8; 16];
861 env.send_msg1_to_supplicant_expect_err(msg1, 1.into());
862 }
863
864 #[test]
870 fn test_random_iv_msg3_v2001() {
871 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
872
873 let msg1 = env.initiate(11.into());
874 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
875 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
876 let mut buf = vec![];
877 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
878 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2001;
879 msg3.key_frame_fields.key_iv = [0xFFu8; 16];
880 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
881
882 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3, 12.into());
883 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
884
885 assert_eq!(s_ptk, a_ptk);
886 assert_eq!(s_gtk, a_gtk);
887 }
888
889 #[test]
890 fn test_random_iv_msg3_v2004() {
891 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
892
893 let msg1 = env.initiate(11.into());
894 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
895 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
896 let mut buf = vec![];
897 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
898 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2004;
899 msg3.key_frame_fields.key_iv = [0xFFu8; 16];
900 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
901
902 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3, 12.into());
903 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
904
905 assert_eq!(s_ptk, a_ptk);
906 assert_eq!(s_gtk, a_gtk);
907 }
908
909 #[test]
910 fn test_zeroed_iv_msg3_v2004() {
911 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
912
913 let msg1 = env.initiate(11.into());
914 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
915 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
916 let mut buf = vec![];
917 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
918 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2004;
919 msg3.key_frame_fields.key_iv = [0u8; 16];
920 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
921
922 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3, 12.into());
923 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
924
925 assert_eq!(s_ptk, a_ptk);
926 assert_eq!(s_gtk, a_gtk);
927 }
928
929 #[test]
930 fn test_random_iv_msg3_v2010() {
931 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
932
933 let msg1 = env.initiate(11.into());
934 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
935 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
936 let mut buf = vec![];
937 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
938 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2010;
939 msg3.key_frame_fields.key_iv = [0xFFu8; 16];
940 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
941
942 env.send_msg3_to_supplicant_expect_err(msg3, 12.into());
943 }
944
945 fn make_protection_info_with_mfp_parameters(
946 mfp_bits: Option<(bool, bool)>, group_mgmt_cipher_suite: Option<Cipher>,
948 ) -> ProtectionInfo {
949 ProtectionInfo::Rsne(Rsne {
950 rsn_capabilities: match mfp_bits {
951 None => None,
952 Some((mfpc, mfpr)) => Some(
953 RsnCapabilities(0)
954 .with_mgmt_frame_protection_cap(mfpc)
955 .with_mgmt_frame_protection_req(mfpr),
956 ),
957 },
958 group_mgmt_cipher_suite,
959 ..Default::default()
960 })
961 }
962
963 fn check_rsne_get_group_mgmt_cipher(
964 s_mfp_bits: Option<(bool, bool)>, s_cipher: Option<Cipher>,
966 a_mfp_bits: Option<(bool, bool)>, a_cipher: Option<Cipher>,
968 expected_result: Result<Option<Cipher>, Error>,
969 ) {
970 let s_protection_info = make_protection_info_with_mfp_parameters(s_mfp_bits, s_cipher);
971 let a_protection_info = make_protection_info_with_mfp_parameters(a_mfp_bits, a_cipher);
972
973 assert_eq!(get_group_mgmt_cipher(&s_protection_info, &a_protection_info), expected_result);
974 }
975
976 #[test]
977 fn test_get_group_mgmt_cipher() {
978 assert!(
981 CIPHER_BIP_CMAC_256 != DEFAULT_GROUP_MGMT_CIPHER,
982 "default group mgmt cipher is CIPHER_BIP_CMAC_256"
983 );
984
985 for (s_mfpr, a_mfpr) in vec![(false, false), (false, true), (true, false), (true, true)] {
986 check_rsne_get_group_mgmt_cipher(
987 Some((true, s_mfpr)),
988 None,
989 Some((true, a_mfpr)),
990 None,
991 Ok(Some(DEFAULT_GROUP_MGMT_CIPHER)),
992 );
993 }
994
995 for (s_mfpr, a_mfpr) in vec![(false, false), (false, true), (true, false), (true, true)] {
996 check_rsne_get_group_mgmt_cipher(
997 Some((true, s_mfpr)),
998 Some(CIPHER_BIP_CMAC_256),
999 Some((true, a_mfpr)),
1000 Some(CIPHER_BIP_CMAC_256),
1001 Ok(Some(CIPHER_BIP_CMAC_256)),
1002 );
1003 }
1004
1005 for (s_mfpc, a_mfpc) in vec![(false, false), (false, true), (true, false)] {
1006 check_rsne_get_group_mgmt_cipher(
1007 Some((s_mfpc, false)),
1008 Some(CIPHER_BIP_CMAC_128),
1009 Some((a_mfpc, false)),
1010 None,
1011 Ok(None),
1012 );
1013 }
1014
1015 for (s_mfpc, a_mfpc) in vec![(false, false), (false, true), (true, false)] {
1016 check_rsne_get_group_mgmt_cipher(
1017 Some((s_mfpc, false)),
1018 None,
1019 Some((a_mfpc, false)),
1020 None,
1021 Ok(None),
1022 );
1023 }
1024
1025 let s_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1026 let a_protection_info = make_protection_info_with_mfp_parameters(None, None);
1027 assert_eq!(get_group_mgmt_cipher(&s_protection_info, &a_protection_info), Ok(None));
1028
1029 let s_protection_info = make_protection_info_with_mfp_parameters(None, None);
1030 let a_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1031 assert_eq!(get_group_mgmt_cipher(&s_protection_info, &a_protection_info), Ok(None));
1032 }
1033
1034 #[test]
1035 fn test_get_group_mgmt_cipher_errors() {
1036 check_rsne_get_group_mgmt_cipher(
1038 Some((false, true)),
1039 None,
1040 Some((false, false)),
1041 None,
1042 Err(Error::InvalidClientMgmtFrameProtectionCapabilityBit),
1043 );
1044 check_rsne_get_group_mgmt_cipher(
1045 Some((false, false)),
1046 None,
1047 Some((false, true)),
1048 None,
1049 Err(Error::InvalidApMgmtFrameProtectionCapabilityBit),
1050 );
1051
1052 check_rsne_get_group_mgmt_cipher(
1054 Some((true, true)),
1055 None,
1056 Some((false, false)),
1057 None,
1058 Err(Error::MgmtFrameProtectionRequiredByClient),
1059 );
1060 check_rsne_get_group_mgmt_cipher(
1061 Some((true, true)),
1062 None,
1063 None,
1064 None,
1065 Err(Error::MgmtFrameProtectionRequiredByClient),
1066 );
1067 let s_protection_info = make_protection_info_with_mfp_parameters(Some((true, true)), None);
1068 let a_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1069 assert_eq!(
1070 get_group_mgmt_cipher(&s_protection_info, &a_protection_info),
1071 Err(Error::MgmtFrameProtectionRequiredByClient)
1072 );
1073
1074 check_rsne_get_group_mgmt_cipher(
1076 Some((false, false)),
1077 None,
1078 Some((true, true)),
1079 None,
1080 Err(Error::MgmtFrameProtectionRequiredByAp),
1081 );
1082 check_rsne_get_group_mgmt_cipher(
1083 None,
1084 None,
1085 Some((true, true)),
1086 None,
1087 Err(Error::MgmtFrameProtectionRequiredByAp),
1088 );
1089 let s_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1090 let a_protection_info = make_protection_info_with_mfp_parameters(Some((true, true)), None);
1091 assert_eq!(
1092 get_group_mgmt_cipher(&s_protection_info, &a_protection_info),
1093 Err(Error::MgmtFrameProtectionRequiredByAp)
1094 );
1095
1096 check_rsne_get_group_mgmt_cipher(
1098 Some((true, true)),
1099 Some(CIPHER_BIP_CMAC_128),
1100 Some((true, true)),
1101 Some(CIPHER_BIP_CMAC_256),
1102 Err(Error::GroupMgmtCipherMismatch(CIPHER_BIP_CMAC_128, CIPHER_BIP_CMAC_256)),
1103 );
1104 check_rsne_get_group_mgmt_cipher(
1105 Some((true, true)),
1106 Some(CIPHER_BIP_CMAC_256),
1107 Some((true, true)),
1108 None,
1109 Err(Error::GroupMgmtCipherMismatch(CIPHER_BIP_CMAC_256, DEFAULT_GROUP_MGMT_CIPHER)),
1110 );
1111 }
1112}