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(Rsne {
140 rsn_capabilities: Some(s_rsn_capabilities),
141 group_mgmt_cipher_suite: s_group_mgmt_cipher_suite,
142 ..
143 }),
144 ProtectionInfo::Rsne(Rsne {
145 rsn_capabilities: Some(a_rsn_capabilities),
146 group_mgmt_cipher_suite: a_group_mgmt_cipher_suite,
147 ..
148 }),
149 ) => {
150 if !s_rsn_capabilities.mgmt_frame_protection_cap()
152 && s_rsn_capabilities.mgmt_frame_protection_req()
153 {
154 return Err(Error::InvalidClientMgmtFrameProtectionCapabilityBit);
155 }
156 if !a_rsn_capabilities.mgmt_frame_protection_cap()
157 && a_rsn_capabilities.mgmt_frame_protection_req()
158 {
159 return Err(Error::InvalidApMgmtFrameProtectionCapabilityBit);
160 }
161
162 if s_rsn_capabilities.mgmt_frame_protection_req()
164 && !a_rsn_capabilities.mgmt_frame_protection_cap()
165 {
166 return Err(Error::MgmtFrameProtectionRequiredByClient);
167 }
168 if !s_rsn_capabilities.mgmt_frame_protection_cap()
169 && a_rsn_capabilities.mgmt_frame_protection_req()
170 {
171 return Err(Error::MgmtFrameProtectionRequiredByAp);
172 }
173
174 if s_rsn_capabilities.mgmt_frame_protection_cap()
175 && a_rsn_capabilities.mgmt_frame_protection_cap()
176 {
177 let s_group_mgmt_cipher_suite =
178 s_group_mgmt_cipher_suite.unwrap_or(DEFAULT_GROUP_MGMT_CIPHER);
179 let a_group_mgmt_cipher_suite =
180 a_group_mgmt_cipher_suite.unwrap_or(DEFAULT_GROUP_MGMT_CIPHER);
181
182 if s_group_mgmt_cipher_suite != a_group_mgmt_cipher_suite {
183 return Err(Error::GroupMgmtCipherMismatch(
184 s_group_mgmt_cipher_suite,
185 a_group_mgmt_cipher_suite,
186 ));
187 }
188
189 return Ok(Some(s_group_mgmt_cipher_suite));
190 }
191 }
192 (_, ProtectionInfo::Rsne(Rsne { rsn_capabilities: Some(a_rsn_capabilities), .. })) => {
193 if a_rsn_capabilities.mgmt_frame_protection_req() {
194 return Err(Error::MgmtFrameProtectionRequiredByAp);
195 }
196 }
197 (ProtectionInfo::Rsne(Rsne { rsn_capabilities: Some(s_rsn_capabilities), .. }), _) => {
198 if s_rsn_capabilities.mgmt_frame_protection_req() {
199 return Err(Error::MgmtFrameProtectionRequiredByClient);
200 }
201 }
202
203 (ProtectionInfo::Rsne(Rsne { rsn_capabilities: None, .. }), _)
206 | (ProtectionInfo::LegacyWpa(_), _) => {}
207 }
208
209 Ok(None)
210}
211
212#[derive(Debug, Clone)]
213pub struct Config {
214 pub role: Role,
215 pub s_addr: MacAddr,
216 pub s_protection: ProtectionInfo,
217 pub a_addr: MacAddr,
218 pub a_protection: ProtectionInfo,
219 pub nonce_rdr: Arc<NonceReader>,
220 pub gtk_provider: Option<Arc<Mutex<GtkProvider>>>,
221 pub igtk_provider: Option<Arc<Mutex<IgtkProvider>>>,
222 pub pmksa_caching_supported: bool,
223
224 _private: (),
227}
228
229impl Config {
230 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
231 pub fn new(
232 role: Role,
233 s_addr: MacAddr,
234 s_protection: ProtectionInfo,
235 a_addr: MacAddr,
236 a_protection: ProtectionInfo,
237 nonce_rdr: Arc<NonceReader>,
238 gtk_provider: Option<Arc<Mutex<GtkProvider>>>,
239 igtk_provider: Option<Arc<Mutex<IgtkProvider>>>,
240 pmksa_caching_supported: bool,
241 ) -> Result<Config, Error> {
242 match (&s_protection, &a_protection) {
244 (ProtectionInfo::Rsne(s_rsne), ProtectionInfo::Rsne(a_rsne)) => {
245 match s_rsne.is_valid_subset_of(a_rsne) {
249 Ok(true) => {}
250 Ok(false) => {
251 return Err(Error::RsneInvalidSubset(s_rsne.clone(), a_rsne.clone()));
252 }
253 Err(e) => return Err(e.into()),
254 };
255 }
256 (_, ProtectionInfo::LegacyWpa(_)) => {}
259 (ProtectionInfo::LegacyWpa(_), _) => {}
260 }
261
262 match NegotiatedProtection::from_protection(&s_protection) {
269 Ok(negotiated_protection) => negotiated_protection,
270 Err(e) => return Err(Error::InvalidSupplicantProtection(format!("{:?}", e))),
271 };
272
273 if role == Role::Authenticator {
277 rsn_ensure!(gtk_provider.is_some(), Error::MissingGtkProvider);
278
279 match get_group_mgmt_cipher(&s_protection, &a_protection)? {
282 Some(group_mgmt_cipher) => match igtk_provider.as_ref() {
283 None => return Err(Error::MissingIgtkProvider),
284 Some(igtk_provider) => {
285 let igtk_provider_cipher = igtk_provider.lock().cipher();
286 rsn_ensure!(
287 group_mgmt_cipher == igtk_provider_cipher,
288 Error::WrongIgtkProviderCipher(group_mgmt_cipher, igtk_provider_cipher),
289 );
290 }
291 },
292 None => {}
293 }
294 }
295
296 Ok(Config {
297 role,
298 s_addr,
299 s_protection,
300 a_addr,
301 a_protection,
302 nonce_rdr,
303 gtk_provider,
304 igtk_provider,
305 pmksa_caching_supported,
306 _private: (),
307 })
308 }
309}
310
311impl PartialEq for Config {
312 fn eq(&self, other: &Config) -> bool {
313 self.role == other.role
314 && self.s_addr == other.s_addr
315 && self.s_protection == other.s_protection
316 && self.a_addr == other.a_addr
317 && self.a_protection == other.a_protection
318 && self.pmksa_caching_supported == other.pmksa_caching_supported
319 }
320}
321
322#[derive(Debug, PartialEq)]
323pub enum Fourway {
324 Authenticator(StateMachine<authenticator::State>),
325 Supplicant(StateMachine<supplicant::State>),
326}
327
328impl Fourway {
329 pub fn new(cfg: Config, pmk: Vec<u8>) -> Result<Fourway, anyhow::Error> {
330 let fourway = match &cfg.role {
331 Role::Supplicant => {
332 let state = supplicant::new(cfg, pmk);
333 Fourway::Supplicant(StateMachine::new(state))
334 }
335 Role::Authenticator => {
336 let state = authenticator::new(cfg, pmk);
337 Fourway::Authenticator(StateMachine::new(state))
338 }
339 };
340 Ok(fourway)
341 }
342
343 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
344 pub fn on_eapol_key_frame<B: SplitByteSlice>(
345 &mut self,
346 update_sink: &mut UpdateSink,
347 frame: Dot11VerifiedKeyFrame<B>,
348 ) -> Result<(), Error> {
349 match self {
350 Fourway::Authenticator(state_machine) => {
351 let frame = FourwayHandshakeFrame::from_verified(frame, Role::Authenticator, None)?;
352 state_machine.replace_state(|state| state.on_eapol_key_frame(update_sink, frame));
353 Ok(())
354 }
355 Fourway::Supplicant(state_machine) => {
356 let anonce = state_machine.as_ref().anonce();
357 let frame = FourwayHandshakeFrame::from_verified(frame, Role::Supplicant, anonce)?;
358 state_machine.replace_state(|state| state.on_eapol_key_frame(update_sink, frame));
359 Ok(())
360 }
361 }
362 }
363
364 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
365 pub fn on_rsna_response_timeout(&self) -> Result<(), Error> {
366 match self {
367 Fourway::Authenticator(state_machine) => state_machine.on_rsna_response_timeout(),
368 Fourway::Supplicant(state_machine) => state_machine.on_rsna_response_timeout(),
369 }
370 }
371
372 pub fn ptk(&self) -> Option<Ptk> {
373 match self {
374 Fourway::Authenticator(state_machine) => state_machine.as_ref().ptk(),
375 Fourway::Supplicant(state_machine) => state_machine.as_ref().ptk(),
376 }
377 }
378
379 pub fn gtk(&self) -> Option<Gtk> {
380 match self {
381 Fourway::Authenticator(state_machine) => state_machine.as_ref().gtk(),
382 Fourway::Supplicant(state_machine) => state_machine.as_ref().gtk(),
383 }
384 }
385
386 pub fn igtk(&self) -> Option<Igtk> {
387 match self {
388 Fourway::Authenticator(state_machine) => state_machine.as_ref().igtk(),
389 Fourway::Supplicant(state_machine) => state_machine.as_ref().igtk(),
390 }
391 }
392
393 #[cfg(test)]
394 pub fn get_config(&self) -> Config {
395 match self {
396 Fourway::Supplicant(state_machine) => match state_machine.as_ref() {
397 supplicant::State::AwaitingMsg1 { cfg, .. }
398 | supplicant::State::AwaitingMsg3 { cfg, .. }
399 | supplicant::State::KeysInstalled { cfg, .. } => cfg.clone(),
400 },
401 Fourway::Authenticator(state_machine) => match state_machine.as_ref() {
402 authenticator::State::Idle { cfg, .. }
403 | authenticator::State::AwaitingMsg2 { cfg, .. }
404 | authenticator::State::AwaitingMsg4 { cfg, .. }
405 | authenticator::State::KeysInstalled { cfg, .. } => cfg.clone(),
406 },
407 }
408 }
409
410 pub fn destroy(self) -> exchange::Config {
411 let cfg = match self {
412 Fourway::Supplicant(state_machine) => state_machine.into_state().destroy(),
413 Fourway::Authenticator(state_machine) => state_machine.into_state().destroy(),
414 };
415 exchange::Config::FourWayHandshake(cfg)
416 }
417}
418
419#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
422fn validate_message_1<B: SplitByteSlice>(frame: &eapol::KeyFrameRx<B>) -> Result<(), Error> {
423 let key_info = frame.key_frame_fields.key_info();
424 rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message1.into()));
426 rsn_ensure!(key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message1.into()));
428 rsn_ensure!(!key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message1.into()));
430 rsn_ensure!(!key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message1.into()));
432 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message1.into()));
434 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message1.into()));
436 rsn_ensure!(
438 !key_info.encrypted_key_data(),
439 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message1.into())
440 );
441 rsn_ensure!(
443 !is_zero(&frame.key_frame_fields.key_nonce[..]),
444 Error::InvalidNonce(MessageNumber::Message1.into())
445 );
446 rsn_ensure!(
449 is_zero(&frame.key_frame_fields.key_iv[..]),
450 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message1.into())
451 );
452 rsn_ensure!(
454 frame.key_frame_fields.key_rsc.get() == 0,
455 Error::InvalidRsc(MessageNumber::Message1.into())
456 );
457
458 Ok(())
466}
467
468#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
469fn validate_message_2<B: SplitByteSlice>(frame: &eapol::KeyFrameRx<B>) -> Result<(), Error> {
470 let key_info = frame.key_frame_fields.key_info();
471 rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message2.into()));
473 rsn_ensure!(!key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message2.into()));
475 rsn_ensure!(key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message2.into()));
477 rsn_ensure!(!key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message2.into()));
479 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message2.into()));
483 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message2.into()));
485 rsn_ensure!(
487 !key_info.encrypted_key_data(),
488 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message2.into())
489 );
490 rsn_ensure!(
492 !is_zero(&frame.key_frame_fields.key_nonce[..]),
493 Error::InvalidNonce(MessageNumber::Message2.into())
494 );
495 rsn_ensure!(
498 is_zero(&frame.key_frame_fields.key_iv[..]),
499 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message2.into())
500 );
501 rsn_ensure!(
503 frame.key_frame_fields.key_rsc.get() == 0,
504 Error::InvalidRsc(MessageNumber::Message2.into())
505 );
506
507 Ok(())
508}
509
510#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
511fn validate_message_3<B: SplitByteSlice>(
512 frame: &eapol::KeyFrameRx<B>,
513 nonce: Option<&[u8]>,
514) -> Result<(), Error> {
515 let key_info = frame.key_frame_fields.key_info();
516 rsn_ensure!(key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message3.into()));
519 rsn_ensure!(key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message3.into()));
521 if frame.key_frame_fields.descriptor_type != eapol::KeyDescriptor::LEGACY_WPA1 {
523 rsn_ensure!(
525 key_info.key_mic(),
526 Error::InvalidKeyMicBitValue(MessageNumber::Message3.into())
527 );
528 rsn_ensure!(
530 key_info.secure(),
531 Error::InvalidSecureBitValue(MessageNumber::Message3.into())
532 );
533 rsn_ensure!(
535 key_info.encrypted_key_data(),
536 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message3.into())
537 );
538 }
539 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message3.into()));
541 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message3.into()));
543 if let Some(nonce) = nonce {
545 rsn_ensure!(
546 !is_zero(&frame.key_frame_fields.key_nonce[..])
547 && &frame.key_frame_fields.key_nonce[..] == nonce,
548 Error::InvalidNonce(MessageNumber::Message3.into())
549 );
550 }
551 rsn_ensure!(
557 frame.eapol_fields.version < eapol::ProtocolVersion::IEEE802DOT1X2010
558 || is_zero(&frame.key_frame_fields.key_iv[..]),
559 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message3.into())
560 );
561 rsn_ensure!(frame.key_data.len() != 0, Error::EmptyKeyData(MessageNumber::Message3.into()));
564
565 Ok(())
566}
567
568#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
569fn validate_message_4<B: SplitByteSlice>(frame: &eapol::KeyFrameRx<B>) -> Result<(), Error> {
570 let key_info = frame.key_frame_fields.key_info();
571 rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message4.into()));
573 rsn_ensure!(!key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message4.into()));
575 rsn_ensure!(key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message4.into()));
577 rsn_ensure!(key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message4.into()));
579 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message4.into()));
583 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message4.into()));
585 rsn_ensure!(
587 !key_info.encrypted_key_data(),
588 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message4.into())
589 );
590 rsn_ensure!(
593 is_zero(&frame.key_frame_fields.key_iv[..]),
594 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message4.into())
595 );
596 rsn_ensure!(
598 frame.key_frame_fields.key_rsc.get() == 0,
599 Error::InvalidRsc(MessageNumber::Message4.into())
600 );
601
602 Ok(())
603}
604
605fn message_number<B: SplitByteSlice>(rx_frame: &eapol::KeyFrameRx<B>) -> MessageNumber {
606 if rx_frame.key_frame_fields.key_info().key_ack() {
615 if rx_frame.key_frame_fields.key_info().install() {
619 MessageNumber::Message3
620 } else {
621 MessageNumber::Message1
622 }
623 } else {
624 if rx_frame.key_frame_fields.key_info().secure() {
628 MessageNumber::Message4
629 } else {
630 MessageNumber::Message2
631 }
632 }
633}
634
635fn is_zero(slice: &[u8]) -> bool {
636 slice.iter().all(|&x| x == 0)
637}
638
639#[cfg(test)]
640mod tests {
641 use super::*;
642 use crate::rsna::{SecAssocUpdate, test_util};
643 use crate::rsne::RsnCapabilities;
644 use wlan_common::ie::rsn::cipher::{CIPHER_BIP_CMAC_128, CIPHER_BIP_CMAC_256};
645 use wlan_common::ie::wpa::fake_wpa_ies::fake_deprecated_wpa1_vendor_ie;
646
647 #[test]
648 fn correct_value_returned_by_authenticator_key_replay_counter() {
649 let key_replay_counter = AuthenticatorKeyReplayCounter(5);
650 assert_eq!(*key_replay_counter, 5);
651 }
652
653 #[test]
654 fn correct_value_returned_by_supplicant_key_replay_counter() {
655 let key_replay_counter = SupplicantKeyReplayCounter(5);
656 assert_eq!(*key_replay_counter, 5);
657 }
658
659 #[test]
660 fn next_replay_counter_is_next_integer() {
661 let s_key_replay_counter = SupplicantKeyReplayCounter(5);
662 let next_key_replay_counter =
663 AuthenticatorKeyReplayCounter::next_after(*s_key_replay_counter);
664 assert_eq!(*next_key_replay_counter, 6);
665 }
666
667 #[test]
669 fn test_supplicant_with_authenticator() {
670 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
671
672 let msg1 = env.initiate(11.into());
674 assert_eq!(msg1.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
675 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
676 assert_eq!(msg2.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
677 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
678 assert_eq!(msg3.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
679 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
680 assert_eq!(msg4.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
681 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
682
683 assert_eq!(s_ptk, a_ptk);
685
686 assert_eq!(s_gtk, a_gtk);
689 assert_eq!(s_gtk.key_id(), 1);
690 assert_eq!(s_gtk.key_rsc(), 3);
691 }
692
693 #[test]
694 fn test_wpa3_handshake_generates_igtk_real_authenticator() {
695 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa3, 1, 754);
696
697 let msg1 = env.initiate(11.into());
699 assert_eq!(msg1.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
700 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
701 assert_eq!(msg2.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
702 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
703 assert_eq!(msg3.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
704 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
705 assert_eq!(msg4.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
706 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
707
708 assert_eq!(s_ptk, a_ptk);
710 assert_eq!(s_gtk, a_gtk);
711 assert_eq!(s_gtk.key_id(), 1);
712 assert_eq!(s_gtk.key_rsc(), 754);
713 assert!(env.supplicant.igtk().is_some());
714 assert_eq!(env.supplicant.igtk(), env.authenticator.igtk());
715 }
716
717 fn run_wpa3_handshake_mock_authenticator(
718 gtk: &[u8],
719 igtk: Option<&[u8]>,
720 ) -> (Ptk, Vec<SecAssocUpdate>) {
721 let anonce = [0xab; 32];
722 let mut supplicant = test_util::make_handshake(
723 test_util::HandshakeKind::Wpa3,
724 super::Role::Supplicant,
725 1,
726 3,
727 );
728 let msg1_buf = test_util::get_wpa3_4whs_msg1(&anonce[..]);
729 let msg1 = msg1_buf.keyframe();
730 let updates = test_util::send_msg_to_fourway(&mut supplicant, msg1, 0.into());
731 let msg2 = test_util::expect_eapol_resp(&updates[..]);
732 let a_ptk =
733 test_util::get_wpa3_ptk(&anonce[..], &msg2.keyframe().key_frame_fields.key_nonce[..]);
734 let msg3_buf = &test_util::get_wpa3_4whs_msg3(&a_ptk, &anonce[..], >k[..], igtk);
735 let msg3 = msg3_buf.keyframe();
736 (a_ptk, test_util::send_msg_to_fourway(&mut supplicant, msg3, 0.into()))
737 }
738
739 #[test]
740 fn test_wpa3_handshake_generates_igtk_mock_authenticator() {
741 let gtk = [0xbb; 32];
742 let igtk = [0xcc; 32];
743 let (ptk, updates) = run_wpa3_handshake_mock_authenticator(>k[..], Some(&igtk[..]));
744
745 test_util::expect_eapol_resp(&updates[..]);
746 let s_ptk = test_util::expect_reported_ptk(&updates[..]);
747 let s_gtk = test_util::expect_reported_gtk(&updates[..]);
748 let s_igtk = test_util::expect_reported_igtk(&updates[..]);
749 assert_eq!(s_ptk, ptk);
750 assert_eq!(&s_gtk.bytes[..], >k[..]);
751 assert_eq!(&s_igtk.igtk[..], &igtk[..]);
752 }
753
754 #[test]
755 fn test_wpa3_handshake_requires_igtk() {
756 let gtk = [0xbb; 32];
757 let (_ptk, updates) = run_wpa3_handshake_mock_authenticator(>k[..], None);
758 assert!(
759 test_util::get_eapol_resp(&updates[..]).is_none(),
760 "WPA3 should not send EAPOL msg4 without IGTK"
761 );
762 }
763
764 #[test]
765 fn test_wpa1_handshake() {
766 let pmk = test_util::get_pmk();
767 let cfg = test_util::make_wpa1_fourway_cfg();
768 let mut supplicant = Fourway::new(cfg, pmk).expect("error while creating 4-Way Handshake");
769
770 let anonce = [0xab; 32];
772 let msg1_buf = test_util::get_wpa1_4whs_msg1(&anonce[..]);
773 let msg1 = msg1_buf.keyframe();
774 let updates = test_util::send_msg_to_fourway(&mut supplicant, msg1, 0.into());
775 let msg2 = test_util::expect_eapol_resp(&updates[..]);
776 let a_ptk =
777 test_util::get_wpa1_ptk(&anonce[..], &msg2.keyframe().key_frame_fields.key_nonce[..]);
778 let msg3_buf = &test_util::get_wpa1_4whs_msg3(&a_ptk, &anonce[..]);
779 let msg3 = msg3_buf.keyframe();
780 let updates = test_util::send_msg_to_fourway(&mut supplicant, msg3, 0.into());
781
782 test_util::expect_eapol_resp(&updates[..]);
784 let s_ptk = test_util::expect_reported_ptk(&updates[..]);
785 assert_eq!(s_ptk, a_ptk);
786 }
787
788 #[test]
789 fn test_supplicant_replay_msg3() {
790 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
791
792 let msg1 = env.initiate(11.into());
794 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
795 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
796 let (_, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
797
798 let mut update_sink = UpdateSink::default();
800
801 env.send_msg3_to_supplicant_capture_updates(msg3.keyframe(), 12.into(), &mut update_sink);
802 let msg4 = test_util::expect_eapol_resp(&update_sink[..]);
803
804 for update in update_sink {
805 if let SecAssocUpdate::Key(_) = update {
806 panic!("reinstalled key");
807 }
808 }
809
810 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
812
813 assert_eq!(s_ptk, a_ptk);
815 assert_eq!(s_gtk, a_gtk);
816 }
817
818 #[test]
819 fn test_supplicant_replay_msg3_different_gtk() {
820 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
821
822 let msg1 = env.initiate(11.into());
824 let anonce = msg1.keyframe().key_frame_fields.key_nonce.clone();
825 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
826 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
827 let (_, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
828
829 let mut other_gtk = s_gtk.bytes.clone();
832 other_gtk[0] ^= 0xFF;
833 let msg3 = test_util::get_wpa2_4whs_msg3(&s_ptk, &anonce[..], &other_gtk[..], |msg3| {
834 msg3.key_frame_fields.key_replay_counter.set(42);
835 });
836 let mut update_sink = UpdateSink::default();
837 env.send_msg3_to_supplicant_capture_updates(msg3.keyframe(), 13.into(), &mut update_sink);
838
839 assert_eq!(update_sink.len(), 0);
841 }
842
843 #[test]
846 fn test_random_iv_msg1_v1() {
847 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
848
849 let msg1 = env.initiate(1.into());
850 let mut buf = vec![];
851 let mut msg1 = msg1.copy_keyframe_mut(&mut buf);
852 msg1.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2001;
853 msg1.key_frame_fields.key_iv = [0xFFu8; 16];
854 env.send_msg1_to_supplicant_expect_err(msg1, 1.into());
855 }
856
857 #[test]
858 fn test_random_iv_msg1_v2() {
859 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
860
861 let msg1 = env.initiate(1.into());
862 let mut buf = vec![];
863 let mut msg1 = msg1.copy_keyframe_mut(&mut buf);
864 msg1.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2004;
865 msg1.key_frame_fields.key_iv = [0xFFu8; 16];
866 env.send_msg1_to_supplicant_expect_err(msg1, 1.into());
867 }
868
869 #[test]
875 fn test_random_iv_msg3_v2001() {
876 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
877
878 let msg1 = env.initiate(11.into());
879 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
880 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
881 let mut buf = vec![];
882 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
883 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2001;
884 msg3.key_frame_fields.key_iv = [0xFFu8; 16];
885 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
886
887 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3, 12.into());
888 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
889
890 assert_eq!(s_ptk, a_ptk);
891 assert_eq!(s_gtk, a_gtk);
892 }
893
894 #[test]
895 fn test_random_iv_msg3_v2004() {
896 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
897
898 let msg1 = env.initiate(11.into());
899 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
900 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
901 let mut buf = vec![];
902 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
903 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2004;
904 msg3.key_frame_fields.key_iv = [0xFFu8; 16];
905 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
906
907 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3, 12.into());
908 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
909
910 assert_eq!(s_ptk, a_ptk);
911 assert_eq!(s_gtk, a_gtk);
912 }
913
914 #[test]
915 fn test_zeroed_iv_msg3_v2004() {
916 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
917
918 let msg1 = env.initiate(11.into());
919 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
920 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
921 let mut buf = vec![];
922 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
923 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2004;
924 msg3.key_frame_fields.key_iv = [0u8; 16];
925 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
926
927 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3, 12.into());
928 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
929
930 assert_eq!(s_ptk, a_ptk);
931 assert_eq!(s_gtk, a_gtk);
932 }
933
934 #[test]
935 fn test_random_iv_msg3_v2010() {
936 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
937
938 let msg1 = env.initiate(11.into());
939 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
940 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
941 let mut buf = vec![];
942 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
943 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2010;
944 msg3.key_frame_fields.key_iv = [0xFFu8; 16];
945 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
946
947 env.send_msg3_to_supplicant_expect_err(msg3, 12.into());
948 }
949
950 fn make_protection_info_with_mfp_parameters(
951 mfp_bits: Option<(bool, bool)>, group_mgmt_cipher_suite: Option<Cipher>,
953 ) -> ProtectionInfo {
954 ProtectionInfo::Rsne(Rsne {
955 rsn_capabilities: match mfp_bits {
956 None => None,
957 Some((mfpc, mfpr)) => Some(
958 RsnCapabilities(0)
959 .with_mgmt_frame_protection_cap(mfpc)
960 .with_mgmt_frame_protection_req(mfpr),
961 ),
962 },
963 group_mgmt_cipher_suite,
964 ..Default::default()
965 })
966 }
967
968 fn check_rsne_get_group_mgmt_cipher(
969 s_mfp_bits: Option<(bool, bool)>, s_cipher: Option<Cipher>,
971 a_mfp_bits: Option<(bool, bool)>, a_cipher: Option<Cipher>,
973 expected_result: Result<Option<Cipher>, Error>,
974 ) {
975 let s_protection_info = make_protection_info_with_mfp_parameters(s_mfp_bits, s_cipher);
976 let a_protection_info = make_protection_info_with_mfp_parameters(a_mfp_bits, a_cipher);
977
978 assert_eq!(get_group_mgmt_cipher(&s_protection_info, &a_protection_info), expected_result);
979 }
980
981 #[test]
982 fn test_get_group_mgmt_cipher() {
983 assert!(
986 CIPHER_BIP_CMAC_256 != DEFAULT_GROUP_MGMT_CIPHER,
987 "default group mgmt cipher is CIPHER_BIP_CMAC_256"
988 );
989
990 for (s_mfpr, a_mfpr) in vec![(false, false), (false, true), (true, false), (true, true)] {
991 check_rsne_get_group_mgmt_cipher(
992 Some((true, s_mfpr)),
993 None,
994 Some((true, a_mfpr)),
995 None,
996 Ok(Some(DEFAULT_GROUP_MGMT_CIPHER)),
997 );
998 }
999
1000 for (s_mfpr, a_mfpr) in vec![(false, false), (false, true), (true, false), (true, true)] {
1001 check_rsne_get_group_mgmt_cipher(
1002 Some((true, s_mfpr)),
1003 Some(CIPHER_BIP_CMAC_256),
1004 Some((true, a_mfpr)),
1005 Some(CIPHER_BIP_CMAC_256),
1006 Ok(Some(CIPHER_BIP_CMAC_256)),
1007 );
1008 }
1009
1010 for (s_mfpc, a_mfpc) in vec![(false, false), (false, true), (true, false)] {
1011 check_rsne_get_group_mgmt_cipher(
1012 Some((s_mfpc, false)),
1013 Some(CIPHER_BIP_CMAC_128),
1014 Some((a_mfpc, false)),
1015 None,
1016 Ok(None),
1017 );
1018 }
1019
1020 for (s_mfpc, a_mfpc) in vec![(false, false), (false, true), (true, false)] {
1021 check_rsne_get_group_mgmt_cipher(
1022 Some((s_mfpc, false)),
1023 None,
1024 Some((a_mfpc, false)),
1025 None,
1026 Ok(None),
1027 );
1028 }
1029
1030 let s_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1031 let a_protection_info = make_protection_info_with_mfp_parameters(None, None);
1032 assert_eq!(get_group_mgmt_cipher(&s_protection_info, &a_protection_info), Ok(None));
1033
1034 let s_protection_info = make_protection_info_with_mfp_parameters(None, None);
1035 let a_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1036 assert_eq!(get_group_mgmt_cipher(&s_protection_info, &a_protection_info), Ok(None));
1037 }
1038
1039 #[test]
1040 fn test_get_group_mgmt_cipher_errors() {
1041 check_rsne_get_group_mgmt_cipher(
1043 Some((false, true)),
1044 None,
1045 Some((false, false)),
1046 None,
1047 Err(Error::InvalidClientMgmtFrameProtectionCapabilityBit),
1048 );
1049 check_rsne_get_group_mgmt_cipher(
1050 Some((false, false)),
1051 None,
1052 Some((false, true)),
1053 None,
1054 Err(Error::InvalidApMgmtFrameProtectionCapabilityBit),
1055 );
1056
1057 check_rsne_get_group_mgmt_cipher(
1059 Some((true, true)),
1060 None,
1061 Some((false, false)),
1062 None,
1063 Err(Error::MgmtFrameProtectionRequiredByClient),
1064 );
1065 check_rsne_get_group_mgmt_cipher(
1066 Some((true, true)),
1067 None,
1068 None,
1069 None,
1070 Err(Error::MgmtFrameProtectionRequiredByClient),
1071 );
1072 let s_protection_info = make_protection_info_with_mfp_parameters(Some((true, true)), None);
1073 let a_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1074 assert_eq!(
1075 get_group_mgmt_cipher(&s_protection_info, &a_protection_info),
1076 Err(Error::MgmtFrameProtectionRequiredByClient)
1077 );
1078
1079 check_rsne_get_group_mgmt_cipher(
1081 Some((false, false)),
1082 None,
1083 Some((true, true)),
1084 None,
1085 Err(Error::MgmtFrameProtectionRequiredByAp),
1086 );
1087 check_rsne_get_group_mgmt_cipher(
1088 None,
1089 None,
1090 Some((true, true)),
1091 None,
1092 Err(Error::MgmtFrameProtectionRequiredByAp),
1093 );
1094 let s_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1095 let a_protection_info = make_protection_info_with_mfp_parameters(Some((true, true)), None);
1096 assert_eq!(
1097 get_group_mgmt_cipher(&s_protection_info, &a_protection_info),
1098 Err(Error::MgmtFrameProtectionRequiredByAp)
1099 );
1100
1101 check_rsne_get_group_mgmt_cipher(
1103 Some((true, true)),
1104 Some(CIPHER_BIP_CMAC_128),
1105 Some((true, true)),
1106 Some(CIPHER_BIP_CMAC_256),
1107 Err(Error::GroupMgmtCipherMismatch(CIPHER_BIP_CMAC_128, CIPHER_BIP_CMAC_256)),
1108 );
1109 check_rsne_get_group_mgmt_cipher(
1110 Some((true, true)),
1111 Some(CIPHER_BIP_CMAC_256),
1112 Some((true, true)),
1113 None,
1114 Err(Error::GroupMgmtCipherMismatch(CIPHER_BIP_CMAC_256, DEFAULT_GROUP_MGMT_CIPHER)),
1115 );
1116 }
1117}