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