wlan_rsn/key/exchange/handshake/fourway/
mod.rs

1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5mod 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/// Represents the current value of an Authenticator's Key Replay Counter
34/// as defined in IEEE 802.11-2016 12.7.2 EAPOL-Key frames.
35#[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/// Represents the current value of a Supplicant's Key Replay Counter
53/// as defined in IEEE 802.11-2016 12.7.2 EAPOL-Key frames.
54#[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
71/// Struct which carries EAPOL key frames which comply with IEEE Std 802.11-2016, 12.7.2 and
72/// IEEE Std 802.11-2016, 12.7.6.
73pub 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        // Safe: the raw frame is never exposed outside of this function.
83        let raw_frame = frame.unsafe_get_raw();
84        // Drop messages which were not expected by the configured role.
85        let msg_no = message_number(raw_frame);
86        match role {
87            // Authenticator should only receive message 2 and 4.
88            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        // Explicit validation based on the frame's message number.
99        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    /// Returns the 4-Way Handshake's message number.
114    fn message_number(&self) -> MessageNumber {
115        // Safe: At this point the frame was validated to be a valid 4-Way Handshake frame.
116        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    // IEEE 802.1-2016 12.6.3 - Management frame protection is
134    // negotiated when an AP and non-AP STA set the Management
135    // Frame Protection Capable field to 1 in their respective
136    // RSNEs in the (re)association procedure, ...
137    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            // Check for invalid bits
151            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            // Check for incompatible capabilities and requirements
163            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        // If management frame protection will not be used or is not required, then we can
204        // safely ignore the supplicant ProtectionInfo
205        (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 field to ensure Config can only be created by one of Config's
224    // associated functions.
225    _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        // Check that the supplicant protection is a subset of the authenticator protection.
241        match (&s_protection, &a_protection) {
242            (ProtectionInfo::Rsne(s_rsne), ProtectionInfo::Rsne(a_rsne)) => {
243                // TODO(https://fxbug.dev/42104575): Replace with ? syntax when
244                // NegotiatedProtection::from_protection no longer returns
245                // anyhow::Error.
246                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            // TODO(https://fxbug.dev/42149656): Check if the ProtectionInfo::LegacyWpa is a
255            // subset or superset of the other ProtectionInfo
256            (_, ProtectionInfo::LegacyWpa(_)) => {}
257            (ProtectionInfo::LegacyWpa(_), _) => {}
258        }
259
260        // TODO(https://fxbug.dev/42104575): Replace with ? syntax when
261        // NegotiatedProtection::from_protection no longer returns
262        // anyhow::Error.
263        // TODO(https://fxbug.dev/42149659): NegotiatedProtection should take into
264        // account a_protection since the use of management frame
265        // protection cannot be determined from s_protection alone.
266        match NegotiatedProtection::from_protection(&s_protection) {
267            Ok(negotiated_protection) => negotiated_protection,
268            Err(e) => return Err(Error::InvalidSupplicantProtection(format!("{:?}", e))),
269        };
270
271        // Check that both an GtkProvider and IgtkProvider are provided if this configuration
272        // is for an authenticator. An IgtkProvider is only required if management frame
273        // protection is activated by this Config.
274        if role == Role::Authenticator {
275            rsn_ensure!(gtk_provider.is_some(), Error::MissingGtkProvider);
276
277            // TODO(https://fxbug.dev/42149659): NegotiatedProtection should have a group_mgmt_cipher
278            // associated function instead.
279            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// Verbose and explicit verification of Message 1 to 4 against IEEE Std 802.11-2016, 12.7.6.2.
416
417#[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    // IEEE Std 802.11-2016, 12.7.2 b.4)
421    rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message1.into()));
422    // IEEE Std 802.11-2016, 12.7.2 b.5)
423    rsn_ensure!(key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message1.into()));
424    // IEEE Std 802.11-2016, 12.7.2 b.6)
425    rsn_ensure!(!key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message1.into()));
426    // IEEE Std 802.11-2016, 12.7.2 b.7)
427    rsn_ensure!(!key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message1.into()));
428    // IEEE Std 802.11-2016, 12.7.2 b.8)
429    rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message1.into()));
430    // IEEE Std 802.11-2016, 12.7.2 b.9)
431    rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message1.into()));
432    // IEEE Std 802.11-2016, 12.7.2 b.10)
433    rsn_ensure!(
434        !key_info.encrypted_key_data(),
435        Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message1.into())
436    );
437    // IEEE Std 802.11-2016, 12.7.2 e)
438    rsn_ensure!(
439        !is_zero(&frame.key_frame_fields.key_nonce[..]),
440        Error::InvalidNonce(MessageNumber::Message1.into())
441    );
442    // IEEE Std 802.11-2016, 12.7.2 f)
443    // IEEE Std 802.11-2016, 12.7.6.2
444    rsn_ensure!(
445        is_zero(&frame.key_frame_fields.key_iv[..]),
446        Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message1.into())
447    );
448    // IEEE Std 802.11-2016, 12.7.2 g)
449    rsn_ensure!(
450        frame.key_frame_fields.key_rsc.get() == 0,
451        Error::InvalidRsc(MessageNumber::Message1.into())
452    );
453
454    // The first message of the Handshake is also required to carry a zeroed MIC.
455    // Some routers however send messages without zeroing out the MIC beforehand.
456    // To ensure compatibility with such routers, the MIC of the first message is
457    // allowed to be set.
458    // This assumption faces no security risk because the message's MIC is only
459    // validated in the Handshake and not in the Supplicant or Authenticator
460    // implementation.
461    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    // IEEE Std 802.11-2016, 12.7.2 b.4)
468    rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message2.into()));
469    // IEEE Std 802.11-2016, 12.7.2 b.5)
470    rsn_ensure!(!key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message2.into()));
471    // IEEE Std 802.11-2016, 12.7.2 b.6)
472    rsn_ensure!(key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message2.into()));
473    // IEEE Std 802.11-2016, 12.7.2 b.7)
474    rsn_ensure!(!key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message2.into()));
475    // IEEE Std 802.11-2016, 12.7.2 b.8)
476    // Error bit only set by Supplicant in MIC failures in SMK derivation.
477    // SMK derivation not yet supported.
478    rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message2.into()));
479    // IEEE Std 802.11-2016, 12.7.2 b.9)
480    rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message2.into()));
481    // IEEE Std 802.11-2016, 12.7.2 b.10)
482    rsn_ensure!(
483        !key_info.encrypted_key_data(),
484        Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message2.into())
485    );
486    // IEEE Std 802.11-2016, 12.7.2 e)
487    rsn_ensure!(
488        !is_zero(&frame.key_frame_fields.key_nonce[..]),
489        Error::InvalidNonce(MessageNumber::Message2.into())
490    );
491    // IEEE Std 802.11-2016, 12.7.2 f)
492    // IEEE Std 802.11-2016, 12.7.6.3
493    rsn_ensure!(
494        is_zero(&frame.key_frame_fields.key_iv[..]),
495        Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message2.into())
496    );
497    // IEEE Std 802.11-2016, 12.7.2 g)
498    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    // IEEE Std 802.11-2016, 12.7.2 b.4)
513    // Install = 0 is only used in key mapping with TKIP and WEP, neither is supported by Fuchsia.
514    rsn_ensure!(key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message3.into()));
515    // IEEE Std 802.11-2016, 12.7.2 b.5)
516    rsn_ensure!(key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message3.into()));
517    // These bit values are not used by WPA1.
518    if frame.key_frame_fields.descriptor_type != eapol::KeyDescriptor::LEGACY_WPA1 {
519        // IEEE Std 802.11-2016, 12.7.2 b.6)
520        rsn_ensure!(
521            key_info.key_mic(),
522            Error::InvalidKeyMicBitValue(MessageNumber::Message3.into())
523        );
524        // IEEE Std 802.11-2016, 12.7.2 b.7)
525        rsn_ensure!(
526            key_info.secure(),
527            Error::InvalidSecureBitValue(MessageNumber::Message3.into())
528        );
529        // IEEE Std 802.11-2016, 12.7.2 b.10)
530        rsn_ensure!(
531            key_info.encrypted_key_data(),
532            Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message3.into())
533        );
534    }
535    // IEEE Std 802.11-2016, 12.7.2 b.8)
536    rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message3.into()));
537    // IEEE Std 802.11-2016, 12.7.2 b.9)
538    rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message3.into()));
539    // IEEE Std 802.11-2016, 12.7.2 e)
540    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    // IEEE Std 802.11-2016, 12.7.2 f)
548    // IEEE Std 802.11-2016, 12.7.6.4
549    // IEEE 802.11-2016 requires a zeroed IV for 802.1X-2004+ and allows random ones for older
550    // protocols. Some APs such as TP-Link violate this requirement and send non-zeroed IVs while
551    // using 802.1X-2004. For compatibility, random IVs are allowed for 802.1X-2004.
552    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    // IEEE Std 802.11-2016, 12.7.2 i) & j)
558    // Key Data must not be empty.
559    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    // IEEE Std 802.11-2016, 12.7.2 b.4)
568    rsn_ensure!(!key_info.install(), Error::InvalidInstallBitValue(MessageNumber::Message4.into()));
569    // IEEE Std 802.11-2016, 12.7.2 b.5)
570    rsn_ensure!(!key_info.key_ack(), Error::InvalidKeyAckBitValue(MessageNumber::Message4.into()));
571    // IEEE Std 802.11-2016, 12.7.2 b.6)
572    rsn_ensure!(key_info.key_mic(), Error::InvalidKeyMicBitValue(MessageNumber::Message4.into()));
573    // IEEE Std 802.11-2016, 12.7.2 b.7)
574    rsn_ensure!(key_info.secure(), Error::InvalidSecureBitValue(MessageNumber::Message4.into()));
575    // IEEE Std 802.11-2016, 12.7.2 b.8)
576    // Error bit only set by Supplicant in MIC failures in SMK derivation.
577    // SMK derivation not yet supported.
578    rsn_ensure!(!key_info.error(), Error::InvalidErrorBitValue(MessageNumber::Message4.into()));
579    // IEEE Std 802.11-2016, 12.7.2 b.9)
580    rsn_ensure!(!key_info.request(), Error::InvalidRequestBitValue(MessageNumber::Message4.into()));
581    // IEEE Std 802.11-2016, 12.7.2 b.10)
582    rsn_ensure!(
583        !key_info.encrypted_key_data(),
584        Error::InvalidEncryptedKeyDataBitValue(MessageNumber::Message4.into())
585    );
586    // IEEE Std 802.11-2016, 12.7.2 f)
587    // IEEE Std 802.11-2016, 12.7.6.5
588    rsn_ensure!(
589        is_zero(&frame.key_frame_fields.key_iv[..]),
590        Error::InvalidIv(frame.eapol_fields.version, MessageNumber::Message4.into())
591    );
592    // IEEE Std 802.11-2016, 12.7.2 g)
593    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    // IEEE does not specify how to determine a frame's message number in the 4-Way Handshake
603    // sequence. However, it's important to know a frame's message number to do further
604    // validations. To derive the message number the key info field is used.
605    // 4-Way Handshake specific EAPOL Key frame requirements:
606    // IEEE Std 802.11-2016, 12.7.6.1
607
608    // IEEE Std 802.11-2016, 12.7.6.2 & 12.7.6.4
609    // Authenticator requires acknowledgement of all its sent frames.
610    if rx_frame.key_frame_fields.key_info().key_ack() {
611        // Authenticator only sends 1st and 3rd message of the handshake.
612        // IEEE Std 802.11-2016, 12.7.2 b.4)
613        // The third requires key installation while the first one doesn't.
614        if rx_frame.key_frame_fields.key_info().install() {
615            MessageNumber::Message3
616        } else {
617            MessageNumber::Message1
618        }
619    } else {
620        // Supplicant only sends 2nd and 4th message of the handshake.
621        // IEEE Std 802.11-2016, 12.7.2 b.7)
622        // The fourth message is secured while the second one is not.
623        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    // Create an Authenticator and Supplicant and performs the entire 4-Way Handshake.
664    #[test]
665    fn test_supplicant_with_authenticator() {
666        let mut env = test_util::FourwayTestEnv::new(test_util::HandshakeKind::Wpa2, 1, 3);
667
668        // Use arbitrarily chosen key_replay_counter.
669        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        // Verify Supplicant and Authenticator derived the same PTK.
680        assert_eq!(s_ptk, a_ptk);
681
682        // Verify Supplicant and Authenticator derived the same GTK and the Key Identifier and
683        // RSC are correct.
684        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        // Use arbitrarily chosen key_replay_counter.
694        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        // Finally verify that Supplicant and Authenticator derived the same keys.
705        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[..], &gtk[..], 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(&gtk[..], 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[..], &gtk[..]);
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(&gtk[..], 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        // We don't have a WPA1 authenticator so we use fake messages.
767        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        // Verify that we completed the exchange and computed the same PTK as our fake AP would.
779        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        // Use arbitrarily chosen key_replay_counter.
789        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        // Replay third message pretending Authenticator did not receive Supplicant's response.
795        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 Authenticator process 4th message.
807        let (a_ptk, a_gtk) = env.send_msg4_to_authenticator(msg4.keyframe(), 13.into());
808
809        // Finally verify that Supplicant and Authenticator derived the same keys.
810        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        // Use arbitrarily chosen key_replay_counter.
819        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        // Replay third message pretending Authenticator did not receive Supplicant's response.
826        // Modify GTK to simulate GTK rotation while 4-Way Handshake was in progress.
827        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        // Ensure Supplicant rejected and dropped 3rd message without replying.
836        assert_eq!(update_sink.len(), 0);
837    }
838
839    // First messages of 4-Way Handshake must carry a zeroed IV in all protocol versions.
840
841    #[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    // EAPOL Key frames can carry a random IV in the third message of the 4-Way Handshake if
866    // protocol version 1, 802.1X-2001, is used. All other protocol versions require a zeroed IV
867    // for the third message of the handshake. Some vendors violate this requirement. For
868    // compatibility, Fuchsia relaxes this requirement and allows random IVs with 802.1X-2004.
869
870    #[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)>, // Option<(mfpc, mfpr)>
948        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)>, // Option<(mfpc, mfpr)>
966        s_cipher: Option<Cipher>,
967        a_mfp_bits: Option<(bool, bool)>, // Option<(mfpc, mfpr)>
968        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        // Check that CIPHER_BIP_CMAC_256 is not DEFAULT_GROUP_MGMT_CIPHER so we can check cases when a
980        // non-default cipher is specified.
981        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        // Error::Invalid*MgmtFrameProtectionCapabilityBit
1038        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        // Error::MgmtFrameProtectionRequiredByClient
1054        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        // Error::MgmtFrameProtectionRequiredByAp
1076        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        // Error::GroupMgmtCipherMismatch
1098        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}