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
223 _private: (),
226}
227
228impl Config {
229 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
230 pub fn new(
231 role: Role,
232 s_addr: MacAddr,
233 s_protection: ProtectionInfo,
234 a_addr: MacAddr,
235 a_protection: ProtectionInfo,
236 nonce_rdr: Arc<NonceReader>,
237 gtk_provider: Option<Arc<Mutex<GtkProvider>>>,
238 igtk_provider: Option<Arc<Mutex<IgtkProvider>>>,
239 ) -> Result<Config, Error> {
240 match (&s_protection, &a_protection) {
242 (ProtectionInfo::Rsne(s_rsne), ProtectionInfo::Rsne(a_rsne)) => {
243 match s_rsne.is_valid_subset_of(a_rsne) {
247 Ok(true) => {}
248 Ok(false) => {
249 return Err(Error::RsneInvalidSubset(s_rsne.clone(), a_rsne.clone()));
250 }
251 Err(e) => return Err(e.into()),
252 };
253 }
254 (_, ProtectionInfo::LegacyWpa(_)) => {}
257 (ProtectionInfo::LegacyWpa(_), _) => {}
258 }
259
260 match NegotiatedProtection::from_protection(&s_protection) {
267 Ok(negotiated_protection) => negotiated_protection,
268 Err(e) => return Err(Error::InvalidSupplicantProtection(format!("{:?}", e))),
269 };
270
271 if role == Role::Authenticator {
275 rsn_ensure!(gtk_provider.is_some(), Error::MissingGtkProvider);
276
277 match get_group_mgmt_cipher(&s_protection, &a_protection)? {
280 Some(group_mgmt_cipher) => match igtk_provider.as_ref() {
281 None => return Err(Error::MissingIgtkProvider),
282 Some(igtk_provider) => {
283 let igtk_provider_cipher = igtk_provider.lock().cipher();
284 rsn_ensure!(
285 group_mgmt_cipher == igtk_provider_cipher,
286 Error::WrongIgtkProviderCipher(group_mgmt_cipher, igtk_provider_cipher),
287 );
288 }
289 },
290 None => {}
291 }
292 }
293
294 Ok(Config {
295 role,
296 s_addr,
297 s_protection,
298 a_addr,
299 a_protection,
300 nonce_rdr,
301 gtk_provider,
302 igtk_provider,
303 _private: (),
304 })
305 }
306}
307
308impl PartialEq for Config {
309 fn eq(&self, other: &Config) -> bool {
310 self.role == other.role
311 && self.s_addr == other.s_addr
312 && self.s_protection == other.s_protection
313 && self.a_addr == other.a_addr
314 && self.a_protection == other.a_protection
315 }
316}
317
318#[derive(Debug, PartialEq)]
319pub enum Fourway {
320 Authenticator(StateMachine<authenticator::State>),
321 Supplicant(StateMachine<supplicant::State>),
322}
323
324impl Fourway {
325 pub fn new(cfg: Config, pmk: Vec<u8>) -> Result<Fourway, anyhow::Error> {
326 let fourway = match &cfg.role {
327 Role::Supplicant => {
328 let state = supplicant::new(cfg, pmk);
329 Fourway::Supplicant(StateMachine::new(state))
330 }
331 Role::Authenticator => {
332 let state = authenticator::new(cfg, pmk);
333 Fourway::Authenticator(StateMachine::new(state))
334 }
335 };
336 Ok(fourway)
337 }
338
339 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
340 pub fn on_eapol_key_frame<B: SplitByteSlice>(
341 &mut self,
342 update_sink: &mut UpdateSink,
343 frame: Dot11VerifiedKeyFrame<B>,
344 ) -> Result<(), Error> {
345 match self {
346 Fourway::Authenticator(state_machine) => {
347 let frame = FourwayHandshakeFrame::from_verified(frame, Role::Authenticator, None)?;
348 state_machine.replace_state(|state| state.on_eapol_key_frame(update_sink, frame));
349 Ok(())
350 }
351 Fourway::Supplicant(state_machine) => {
352 let anonce = state_machine.as_ref().anonce();
353 let frame = FourwayHandshakeFrame::from_verified(frame, Role::Supplicant, anonce)?;
354 state_machine.replace_state(|state| state.on_eapol_key_frame(update_sink, frame));
355 Ok(())
356 }
357 }
358 }
359
360 #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
361 pub fn on_rsna_response_timeout(&self) -> Result<(), Error> {
362 match self {
363 Fourway::Authenticator(state_machine) => state_machine.on_rsna_response_timeout(),
364 Fourway::Supplicant(state_machine) => state_machine.on_rsna_response_timeout(),
365 }
366 }
367
368 pub fn ptk(&self) -> Option<Ptk> {
369 match self {
370 Fourway::Authenticator(state_machine) => state_machine.as_ref().ptk(),
371 Fourway::Supplicant(state_machine) => state_machine.as_ref().ptk(),
372 }
373 }
374
375 pub fn gtk(&self) -> Option<Gtk> {
376 match self {
377 Fourway::Authenticator(state_machine) => state_machine.as_ref().gtk(),
378 Fourway::Supplicant(state_machine) => state_machine.as_ref().gtk(),
379 }
380 }
381
382 pub fn igtk(&self) -> Option<Igtk> {
383 match self {
384 Fourway::Authenticator(state_machine) => state_machine.as_ref().igtk(),
385 Fourway::Supplicant(state_machine) => state_machine.as_ref().igtk(),
386 }
387 }
388
389 #[cfg(test)]
390 pub fn get_config(&self) -> Config {
391 match self {
392 Fourway::Supplicant(state_machine) => match state_machine.as_ref() {
393 supplicant::State::AwaitingMsg1 { cfg, .. }
394 | supplicant::State::AwaitingMsg3 { cfg, .. }
395 | supplicant::State::KeysInstalled { cfg, .. } => cfg.clone(),
396 },
397 Fourway::Authenticator(state_machine) => match state_machine.as_ref() {
398 authenticator::State::Idle { cfg, .. }
399 | authenticator::State::AwaitingMsg2 { cfg, .. }
400 | authenticator::State::AwaitingMsg4 { cfg, .. }
401 | authenticator::State::KeysInstalled { cfg, .. } => cfg.clone(),
402 },
403 }
404 }
405
406 pub fn destroy(self) -> exchange::Config {
407 let cfg = match self {
408 Fourway::Supplicant(state_machine) => state_machine.into_state().destroy(),
409 Fourway::Authenticator(state_machine) => state_machine.into_state().destroy(),
410 };
411 exchange::Config::FourWayHandshake(cfg)
412 }
413}
414
415#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
418fn validate_message_1<B: SplitByteSlice>(frame: &eapol::KeyFrameRx<B>) -> Result<(), Error> {
419 let key_info = frame.key_frame_fields.key_info();
420 rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message1.into()));
422 rsn_ensure!(key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message1.into()));
424 rsn_ensure!(!key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message1.into()));
426 rsn_ensure!(!key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message1.into()));
428 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message1.into()));
430 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message1.into()));
432 rsn_ensure!(
434 !key_info.encrypted_key_data(),
435 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message1.into())
436 );
437 rsn_ensure!(
439 !is_zero(&frame.key_frame_fields.key_nonce[..]),
440 Error::InvalidNonce(MessageNumber::Message1.into())
441 );
442 rsn_ensure!(
445 is_zero(&frame.key_frame_fields.key_iv[..]),
446 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message1.into())
447 );
448 rsn_ensure!(
450 frame.key_frame_fields.key_rsc.get() == 0,
451 Error::InvalidRsc(MessageNumber::Message1.into())
452 );
453
454 Ok(())
462}
463
464#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
465fn validate_message_2<B: SplitByteSlice>(frame: &eapol::KeyFrameRx<B>) -> Result<(), Error> {
466 let key_info = frame.key_frame_fields.key_info();
467 rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message2.into()));
469 rsn_ensure!(!key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message2.into()));
471 rsn_ensure!(key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message2.into()));
473 rsn_ensure!(!key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message2.into()));
475 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message2.into()));
479 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message2.into()));
481 rsn_ensure!(
483 !key_info.encrypted_key_data(),
484 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message2.into())
485 );
486 rsn_ensure!(
488 !is_zero(&frame.key_frame_fields.key_nonce[..]),
489 Error::InvalidNonce(MessageNumber::Message2.into())
490 );
491 rsn_ensure!(
494 is_zero(&frame.key_frame_fields.key_iv[..]),
495 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message2.into())
496 );
497 rsn_ensure!(
499 frame.key_frame_fields.key_rsc.get() == 0,
500 Error::InvalidRsc(MessageNumber::Message2.into())
501 );
502
503 Ok(())
504}
505
506#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
507fn validate_message_3<B: SplitByteSlice>(
508 frame: &eapol::KeyFrameRx<B>,
509 nonce: Option<&[u8]>,
510) -> Result<(), Error> {
511 let key_info = frame.key_frame_fields.key_info();
512 rsn_ensure!(key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message3.into()));
515 rsn_ensure!(key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message3.into()));
517 if frame.key_frame_fields.descriptor_type != eapol::KeyDescriptor::LEGACY_WPA1 {
519 rsn_ensure!(
521 key_info.key_mic(),
522 Error::InvalidKeyMicBitValue(MessageNumber::Message3.into())
523 );
524 rsn_ensure!(
526 key_info.secure(),
527 Error::InvalidSecureBitValue(MessageNumber::Message3.into())
528 );
529 rsn_ensure!(
531 key_info.encrypted_key_data(),
532 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message3.into())
533 );
534 }
535 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message3.into()));
537 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message3.into()));
539 if let Some(nonce) = nonce {
541 rsn_ensure!(
542 !is_zero(&frame.key_frame_fields.key_nonce[..])
543 && &frame.key_frame_fields.key_nonce[..] == nonce,
544 Error::InvalidNonce(MessageNumber::Message3.into())
545 );
546 }
547 rsn_ensure!(
553 frame.eapol_fields.version < eapol::ProtocolVersion::IEEE802DOT1X2010
554 || is_zero(&frame.key_frame_fields.key_iv[..]),
555 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message3.into())
556 );
557 rsn_ensure!(frame.key_data.len() != 0, Error::EmptyKeyData(MessageNumber::Message3.into()));
560
561 Ok(())
562}
563
564#[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
565fn validate_message_4<B: SplitByteSlice>(frame: &eapol::KeyFrameRx<B>) -> Result<(), Error> {
566 let key_info = frame.key_frame_fields.key_info();
567 rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message4.into()));
569 rsn_ensure!(!key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message4.into()));
571 rsn_ensure!(key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message4.into()));
573 rsn_ensure!(key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message4.into()));
575 rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message4.into()));
579 rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message4.into()));
581 rsn_ensure!(
583 !key_info.encrypted_key_data(),
584 Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message4.into())
585 );
586 rsn_ensure!(
589 is_zero(&frame.key_frame_fields.key_iv[..]),
590 Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message4.into())
591 );
592 rsn_ensure!(
594 frame.key_frame_fields.key_rsc.get() == 0,
595 Error::InvalidRsc(MessageNumber::Message4.into())
596 );
597
598 Ok(())
599}
600
601fn message_number<B: SplitByteSlice>(rx_frame: &eapol::KeyFrameRx<B>) -> MessageNumber {
602 if rx_frame.key_frame_fields.key_info().key_ack() {
611 if rx_frame.key_frame_fields.key_info().install() {
615 MessageNumber::Message3
616 } else {
617 MessageNumber::Message1
618 }
619 } else {
620 if rx_frame.key_frame_fields.key_info().secure() {
624 MessageNumber::Message4
625 } else {
626 MessageNumber::Message2
627 }
628 }
629}
630
631fn is_zero(slice: &[u8]) -> bool {
632 slice.iter().all(|&x| x == 0)
633}
634
635#[cfg(test)]
636mod tests {
637 use super::*;
638 use crate::rsna::{SecAssocUpdate, test_util};
639 use crate::rsne::RsnCapabilities;
640 use wlan_common::ie::rsn::cipher::{CIPHER_BIP_CMAC_128, CIPHER_BIP_CMAC_256};
641 use wlan_common::ie::wpa::fake_wpa_ies::fake_deprecated_wpa1_vendor_ie;
642
643 #[test]
644 fn correct_value_returned_by_authenticator_key_replay_counter() {
645 let key_replay_counter = AuthenticatorKeyReplayCounter(5);
646 assert_eq!(*key_replay_counter, 5);
647 }
648
649 #[test]
650 fn correct_value_returned_by_supplicant_key_replay_counter() {
651 let key_replay_counter = SupplicantKeyReplayCounter(5);
652 assert_eq!(*key_replay_counter, 5);
653 }
654
655 #[test]
656 fn next_replay_counter_is_next_integer() {
657 let s_key_replay_counter = SupplicantKeyReplayCounter(5);
658 let next_key_replay_counter =
659 AuthenticatorKeyReplayCounter::next_after(*s_key_replay_counter);
660 assert_eq!(*next_key_replay_counter, 6);
661 }
662
663 #[test]
665 fn test_supplicant_with_authenticator() {
666 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
667
668 let msg1 = env.initiate(11.into());
670 assert_eq!(msg1.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
671 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
672 assert_eq!(msg2.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
673 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
674 assert_eq!(msg3.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
675 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
676 assert_eq!(msg4.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
677 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
678
679 assert_eq!(s_ptk, a_ptk);
681
682 assert_eq!(s_gtk, a_gtk);
685 assert_eq!(s_gtk.key_id(), 1);
686 assert_eq!(s_gtk.key_rsc(), 3);
687 }
688
689 #[test]
690 fn test_wpa3_handshake_generates_igtk_real_authenticator() {
691 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa3, 1, 754);
692
693 let msg1 = env.initiate(11.into());
695 assert_eq!(msg1.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
696 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
697 assert_eq!(msg2.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
698 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
699 assert_eq!(msg3.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
700 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
701 assert_eq!(msg4.keyframe().eapol_fields.version, eapol::ProtocolVersion::IEEE802DOT1X2004);
702 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
703
704 assert_eq!(s_ptk, a_ptk);
706 assert_eq!(s_gtk, a_gtk);
707 assert_eq!(s_gtk.key_id(), 1);
708 assert_eq!(s_gtk.key_rsc(), 754);
709 assert!(env.supplicant.igtk().is_some());
710 assert_eq!(env.supplicant.igtk(), env.authenticator.igtk());
711 }
712
713 fn run_wpa3_handshake_mock_authenticator(
714 gtk: &[u8],
715 igtk: Option<&[u8]>,
716 ) -> (Ptk, Vec<SecAssocUpdate>) {
717 let anonce = [0xab; 32];
718 let mut supplicant = test_util::make_handshake(
719 test_util::HandshakeKind::Wpa3,
720 super::Role::Supplicant,
721 1,
722 3,
723 );
724 let msg1_buf = test_util::get_wpa3_4whs_msg1(&anonce[..]);
725 let msg1 = msg1_buf.keyframe();
726 let updates = test_util::send_msg_to_fourway(&mut supplicant, msg1, 0.into());
727 let msg2 = test_util::expect_eapol_resp(&updates[..]);
728 let a_ptk =
729 test_util::get_wpa3_ptk(&anonce[..], &msg2.keyframe().key_frame_fields.key_nonce[..]);
730 let msg3_buf = &test_util::get_wpa3_4whs_msg3(&a_ptk, &anonce[..], >k[..], igtk);
731 let msg3 = msg3_buf.keyframe();
732 (a_ptk, test_util::send_msg_to_fourway(&mut supplicant, msg3, 0.into()))
733 }
734
735 #[test]
736 fn test_wpa3_handshake_generates_igtk_mock_authenticator() {
737 let gtk = [0xbb; 32];
738 let igtk = [0xcc; 32];
739 let (ptk, updates) = run_wpa3_handshake_mock_authenticator(>k[..], Some(&igtk[..]));
740
741 test_util::expect_eapol_resp(&updates[..]);
742 let s_ptk = test_util::expect_reported_ptk(&updates[..]);
743 let s_gtk = test_util::expect_reported_gtk(&updates[..]);
744 let s_igtk = test_util::expect_reported_igtk(&updates[..]);
745 assert_eq!(s_ptk, ptk);
746 assert_eq!(&s_gtk.bytes[..], >k[..]);
747 assert_eq!(&s_igtk.igtk[..], &igtk[..]);
748 }
749
750 #[test]
751 fn test_wpa3_handshake_requires_igtk() {
752 let gtk = [0xbb; 32];
753 let (_ptk, updates) = run_wpa3_handshake_mock_authenticator(>k[..], None);
754 assert!(
755 test_util::get_eapol_resp(&updates[..]).is_none(),
756 "WPA3 should not send EAPOL msg4 without IGTK"
757 );
758 }
759
760 #[test]
761 fn test_wpa1_handshake() {
762 let pmk = test_util::get_pmk();
763 let cfg = test_util::make_wpa1_fourway_cfg();
764 let mut supplicant = Fourway::new(cfg, pmk).expect("error while creating 4-Way Handshake");
765
766 let anonce = [0xab; 32];
768 let msg1_buf = test_util::get_wpa1_4whs_msg1(&anonce[..]);
769 let msg1 = msg1_buf.keyframe();
770 let updates = test_util::send_msg_to_fourway(&mut supplicant, msg1, 0.into());
771 let msg2 = test_util::expect_eapol_resp(&updates[..]);
772 let a_ptk =
773 test_util::get_wpa1_ptk(&anonce[..], &msg2.keyframe().key_frame_fields.key_nonce[..]);
774 let msg3_buf = &test_util::get_wpa1_4whs_msg3(&a_ptk, &anonce[..]);
775 let msg3 = msg3_buf.keyframe();
776 let updates = test_util::send_msg_to_fourway(&mut supplicant, msg3, 0.into());
777
778 test_util::expect_eapol_resp(&updates[..]);
780 let s_ptk = test_util::expect_reported_ptk(&updates[..]);
781 assert_eq!(s_ptk, a_ptk);
782 }
783
784 #[test]
785 fn test_supplicant_replay_msg3() {
786 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
787
788 let msg1 = env.initiate(11.into());
790 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
791 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
792 let (_, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
793
794 let mut update_sink = UpdateSink::default();
796
797 env.send_msg3_to_supplicant_capture_updates(msg3.keyframe(), 12.into(), &mut update_sink);
798 let msg4 = test_util::expect_eapol_resp(&update_sink[..]);
799
800 for update in update_sink {
801 if let SecAssocUpdate::Key(_) = update {
802 panic!("reinstalled key");
803 }
804 }
805
806 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
808
809 assert_eq!(s_ptk, a_ptk);
811 assert_eq!(s_gtk, a_gtk);
812 }
813
814 #[test]
815 fn test_supplicant_replay_msg3_different_gtk() {
816 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
817
818 let msg1 = env.initiate(11.into());
820 let anonce = msg1.keyframe().key_frame_fields.key_nonce.clone();
821 let (msg2, _) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
822 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
823 let (_, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3.keyframe(), 12.into());
824
825 let mut other_gtk = s_gtk.bytes.clone();
828 other_gtk[0] ^= 0xFF;
829 let msg3 = test_util::get_wpa2_4whs_msg3(&s_ptk, &anonce[..], &other_gtk[..], |msg3| {
830 msg3.key_frame_fields.key_replay_counter.set(42);
831 });
832 let mut update_sink = UpdateSink::default();
833 env.send_msg3_to_supplicant_capture_updates(msg3.keyframe(), 13.into(), &mut update_sink);
834
835 assert_eq!(update_sink.len(), 0);
837 }
838
839 #[test]
842 fn test_random_iv_msg1_v1() {
843 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
844
845 let msg1 = env.initiate(1.into());
846 let mut buf = vec![];
847 let mut msg1 = msg1.copy_keyframe_mut(&mut buf);
848 msg1.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2001;
849 msg1.key_frame_fields.key_iv = [0xFFu8; 16];
850 env.send_msg1_to_supplicant_expect_err(msg1, 1.into());
851 }
852
853 #[test]
854 fn test_random_iv_msg1_v2() {
855 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
856
857 let msg1 = env.initiate(1.into());
858 let mut buf = vec![];
859 let mut msg1 = msg1.copy_keyframe_mut(&mut buf);
860 msg1.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2004;
861 msg1.key_frame_fields.key_iv = [0xFFu8; 16];
862 env.send_msg1_to_supplicant_expect_err(msg1, 1.into());
863 }
864
865 #[test]
871 fn test_random_iv_msg3_v2001() {
872 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
873
874 let msg1 = env.initiate(11.into());
875 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
876 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
877 let mut buf = vec![];
878 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
879 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2001;
880 msg3.key_frame_fields.key_iv = [0xFFu8; 16];
881 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
882
883 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3, 12.into());
884 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
885
886 assert_eq!(s_ptk, a_ptk);
887 assert_eq!(s_gtk, a_gtk);
888 }
889
890 #[test]
891 fn test_random_iv_msg3_v2004() {
892 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
893
894 let msg1 = env.initiate(11.into());
895 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
896 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
897 let mut buf = vec![];
898 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
899 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2004;
900 msg3.key_frame_fields.key_iv = [0xFFu8; 16];
901 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
902
903 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3, 12.into());
904 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
905
906 assert_eq!(s_ptk, a_ptk);
907 assert_eq!(s_gtk, a_gtk);
908 }
909
910 #[test]
911 fn test_zeroed_iv_msg3_v2004() {
912 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
913
914 let msg1 = env.initiate(11.into());
915 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
916 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
917 let mut buf = vec![];
918 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
919 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2004;
920 msg3.key_frame_fields.key_iv = [0u8; 16];
921 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
922
923 let (msg4, s_ptk, s_gtk) = env.send_msg3_to_supplicant(msg3, 12.into());
924 let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
925
926 assert_eq!(s_ptk, a_ptk);
927 assert_eq!(s_gtk, a_gtk);
928 }
929
930 #[test]
931 fn test_random_iv_msg3_v2010() {
932 let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
933
934 let msg1 = env.initiate(11.into());
935 let (msg2, ptk) = env.send_msg1_to_supplicant(msg1.keyframe(), 11.into());
936 let msg3 = env.send_msg2_to_authenticator(msg2.keyframe(), 12.into());
937 let mut buf = vec![];
938 let mut msg3 = msg3.copy_keyframe_mut(&mut buf);
939 msg3.eapol_fields.version = eapol::ProtocolVersion::IEEE802DOT1X2010;
940 msg3.key_frame_fields.key_iv = [0xFFu8; 16];
941 env.finalize_key_frame(&mut msg3, Some(ptk.kck()));
942
943 env.send_msg3_to_supplicant_expect_err(msg3, 12.into());
944 }
945
946 fn make_protection_info_with_mfp_parameters(
947 mfp_bits: Option<(bool, bool)>, group_mgmt_cipher_suite: Option<Cipher>,
949 ) -> ProtectionInfo {
950 ProtectionInfo::Rsne(Rsne {
951 rsn_capabilities: match mfp_bits {
952 None => None,
953 Some((mfpc, mfpr)) => Some(
954 RsnCapabilities(0)
955 .with_mgmt_frame_protection_cap(mfpc)
956 .with_mgmt_frame_protection_req(mfpr),
957 ),
958 },
959 group_mgmt_cipher_suite,
960 ..Default::default()
961 })
962 }
963
964 fn check_rsne_get_group_mgmt_cipher(
965 s_mfp_bits: Option<(bool, bool)>, s_cipher: Option<Cipher>,
967 a_mfp_bits: Option<(bool, bool)>, a_cipher: Option<Cipher>,
969 expected_result: Result<Option<Cipher>, Error>,
970 ) {
971 let s_protection_info = make_protection_info_with_mfp_parameters(s_mfp_bits, s_cipher);
972 let a_protection_info = make_protection_info_with_mfp_parameters(a_mfp_bits, a_cipher);
973
974 assert_eq!(get_group_mgmt_cipher(&s_protection_info, &a_protection_info), expected_result);
975 }
976
977 #[test]
978 fn test_get_group_mgmt_cipher() {
979 assert!(
982 CIPHER_BIP_CMAC_256 != DEFAULT_GROUP_MGMT_CIPHER,
983 "default group mgmt cipher is CIPHER_BIP_CMAC_256"
984 );
985
986 for (s_mfpr, a_mfpr) in vec![(false, false), (false, true), (true, false), (true, true)] {
987 check_rsne_get_group_mgmt_cipher(
988 Some((true, s_mfpr)),
989 None,
990 Some((true, a_mfpr)),
991 None,
992 Ok(Some(DEFAULT_GROUP_MGMT_CIPHER)),
993 );
994 }
995
996 for (s_mfpr, a_mfpr) in vec![(false, false), (false, true), (true, false), (true, true)] {
997 check_rsne_get_group_mgmt_cipher(
998 Some((true, s_mfpr)),
999 Some(CIPHER_BIP_CMAC_256),
1000 Some((true, a_mfpr)),
1001 Some(CIPHER_BIP_CMAC_256),
1002 Ok(Some(CIPHER_BIP_CMAC_256)),
1003 );
1004 }
1005
1006 for (s_mfpc, a_mfpc) in vec![(false, false), (false, true), (true, false)] {
1007 check_rsne_get_group_mgmt_cipher(
1008 Some((s_mfpc, false)),
1009 Some(CIPHER_BIP_CMAC_128),
1010 Some((a_mfpc, false)),
1011 None,
1012 Ok(None),
1013 );
1014 }
1015
1016 for (s_mfpc, a_mfpc) in vec![(false, false), (false, true), (true, false)] {
1017 check_rsne_get_group_mgmt_cipher(
1018 Some((s_mfpc, false)),
1019 None,
1020 Some((a_mfpc, false)),
1021 None,
1022 Ok(None),
1023 );
1024 }
1025
1026 let s_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1027 let a_protection_info = make_protection_info_with_mfp_parameters(None, None);
1028 assert_eq!(get_group_mgmt_cipher(&s_protection_info, &a_protection_info), Ok(None));
1029
1030 let s_protection_info = make_protection_info_with_mfp_parameters(None, None);
1031 let a_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1032 assert_eq!(get_group_mgmt_cipher(&s_protection_info, &a_protection_info), Ok(None));
1033 }
1034
1035 #[test]
1036 fn test_get_group_mgmt_cipher_errors() {
1037 check_rsne_get_group_mgmt_cipher(
1039 Some((false, true)),
1040 None,
1041 Some((false, false)),
1042 None,
1043 Err(Error::InvalidClientMgmtFrameProtectionCapabilityBit),
1044 );
1045 check_rsne_get_group_mgmt_cipher(
1046 Some((false, false)),
1047 None,
1048 Some((false, true)),
1049 None,
1050 Err(Error::InvalidApMgmtFrameProtectionCapabilityBit),
1051 );
1052
1053 check_rsne_get_group_mgmt_cipher(
1055 Some((true, true)),
1056 None,
1057 Some((false, false)),
1058 None,
1059 Err(Error::MgmtFrameProtectionRequiredByClient),
1060 );
1061 check_rsne_get_group_mgmt_cipher(
1062 Some((true, true)),
1063 None,
1064 None,
1065 None,
1066 Err(Error::MgmtFrameProtectionRequiredByClient),
1067 );
1068 let s_protection_info = make_protection_info_with_mfp_parameters(Some((true, true)), None);
1069 let a_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1070 assert_eq!(
1071 get_group_mgmt_cipher(&s_protection_info, &a_protection_info),
1072 Err(Error::MgmtFrameProtectionRequiredByClient)
1073 );
1074
1075 check_rsne_get_group_mgmt_cipher(
1077 Some((false, false)),
1078 None,
1079 Some((true, true)),
1080 None,
1081 Err(Error::MgmtFrameProtectionRequiredByAp),
1082 );
1083 check_rsne_get_group_mgmt_cipher(
1084 None,
1085 None,
1086 Some((true, true)),
1087 None,
1088 Err(Error::MgmtFrameProtectionRequiredByAp),
1089 );
1090 let s_protection_info = ProtectionInfo::LegacyWpa(fake_deprecated_wpa1_vendor_ie());
1091 let a_protection_info = make_protection_info_with_mfp_parameters(Some((true, true)), None);
1092 assert_eq!(
1093 get_group_mgmt_cipher(&s_protection_info, &a_protection_info),
1094 Err(Error::MgmtFrameProtectionRequiredByAp)
1095 );
1096
1097 check_rsne_get_group_mgmt_cipher(
1099 Some((true, true)),
1100 Some(CIPHER_BIP_CMAC_128),
1101 Some((true, true)),
1102 Some(CIPHER_BIP_CMAC_256),
1103 Err(Error::GroupMgmtCipherMismatch(CIPHER_BIP_CMAC_128, CIPHER_BIP_CMAC_256)),
1104 );
1105 check_rsne_get_group_mgmt_cipher(
1106 Some((true, true)),
1107 Some(CIPHER_BIP_CMAC_256),
1108 Some((true, true)),
1109 None,
1110 Err(Error::GroupMgmtCipherMismatch(CIPHER_BIP_CMAC_256, DEFAULT_GROUP_MGMT_CIPHER)),
1111 );
1112 }
1113}