wlan_common/ie/rsn/
rsne.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
5use super::akm::{self, AKM_OWE, AKM_PSK, AKM_SAE};
6use super::cipher::{self, CIPHER_CCMP_128, CIPHER_GCMP_256};
7use super::suite_filter::DEFAULT_GROUP_MGMT_CIPHER;
8use super::{pmkid, suite_selector};
9
10use crate::append::{Append, BufferTooSmall};
11use crate::organization::Oui;
12use bytes::Bytes;
13use fidl_fuchsia_wlan_common as fidl_common;
14use nom::branch::alt;
15use nom::bytes::streaming::take;
16use nom::combinator::{eof, map, map_res};
17use nom::multi::length_count;
18use nom::number::streaming::{le_u8, le_u16};
19use nom::sequence::terminated;
20use nom::{IResult, Parser};
21use wlan_bitfield::bitfield;
22
23use thiserror::Error;
24
25macro_rules! if_remaining (
26  // alt returns the first parser that succeeds
27  ($f:expr) => (alt((map(eof, |_| None), map($f, Some))));
28);
29
30// IEEE 802.11-2016, 9.4.2.25.1
31pub const ID: u8 = 48;
32pub const VERSION: u16 = 1;
33
34#[derive(Debug, Error, Eq, PartialEq)]
35pub enum Error {
36    #[error("no group data cipher suite")]
37    NoGroupDataCipherSuite,
38    #[error("no pairwise cipher suite")]
39    NoPairwiseCipherSuite,
40    #[error("too many pairwise cipher suites")]
41    TooManyPairwiseCipherSuites,
42    #[error("no akm suite")]
43    NoAkmSuite,
44    #[error("too many akm suites")]
45    TooManyAkmSuites,
46    #[error("AKM suite does not have mic_bytes")]
47    NoAkmMicBytes,
48    #[error("invalid supplicant management frame protection")]
49    InvalidSupplicantMgmtFrameProtection,
50    #[error("invalid authenticator management frame protection")]
51    InvalidAuthenticatorMgmtFrameProtection,
52    #[error("cannot derive WPA2 RSNE")]
53    CannotDeriveWpa2Rsne,
54    #[error("cannot derive WPA3 RSNE")]
55    CannotDeriveWpa3Rsne,
56    #[error("cannot derive OWE RSNE")]
57    CannotDeriveOweRsne,
58}
59
60#[macro_export]
61macro_rules! rsne_ensure {
62    ($cond:expr, $err:expr $(,)?) => {
63        if !$cond {
64            return std::result::Result::Err($err);
65        }
66    };
67}
68
69// IEEE 802.11-2016, 9.4.2.25.1
70#[derive(Debug, PartialOrd, PartialEq, Clone)]
71pub struct Rsne {
72    pub version: u16,
73    pub group_data_cipher_suite: Option<cipher::Cipher>,
74    pub pairwise_cipher_suites: Vec<cipher::Cipher>,
75    pub akm_suites: Vec<akm::Akm>,
76    pub rsn_capabilities: Option<RsnCapabilities>,
77    pub pmkids: Vec<pmkid::Pmkid>,
78    pub group_mgmt_cipher_suite: Option<cipher::Cipher>,
79}
80
81impl Default for Rsne {
82    fn default() -> Self {
83        Rsne {
84            version: VERSION,
85            group_data_cipher_suite: None,
86            pairwise_cipher_suites: vec![],
87            akm_suites: vec![],
88            rsn_capabilities: None,
89            pmkids: vec![],
90            group_mgmt_cipher_suite: None,
91        }
92    }
93}
94
95#[bitfield(
96    0         preauth,
97    1         no_pairwise,
98    2..=3     ptksa_replay_counter,
99    4..=5     gtksa_replay_counter,
100    6         mgmt_frame_protection_req,
101    7         mgmt_frame_protection_cap,
102    8         joint_multiband,
103    9         peerkey_enabled,
104    10        ssp_amsdu_cap,
105    11        ssp_amsdu_req,
106    12        pbac,
107    13        extended_key_id,
108    14..=15   _, // reserved
109)]
110#[derive(PartialOrd, PartialEq, Clone)]
111pub struct RsnCapabilities(pub u16);
112
113impl RsnCapabilities {
114    pub fn is_wpa2_compatible(&self) -> bool {
115        !self.contains_unsupported_capability()
116    }
117
118    pub fn is_wpa3_compatible(&self, wpa2_compatibility_mode: bool) -> bool {
119        self.mgmt_frame_protection_cap()
120            && (self.mgmt_frame_protection_req() || wpa2_compatibility_mode)
121            && !self.contains_unsupported_capability()
122    }
123
124    pub fn is_owe_compatible(&self) -> bool {
125        self.mgmt_frame_protection_cap()
126            && self.mgmt_frame_protection_req()
127            && !self.contains_unsupported_capability()
128    }
129
130    pub fn is_compatible_with_features(
131        &self,
132        security_support: &fidl_common::SecuritySupport,
133    ) -> bool {
134        !self.mgmt_frame_protection_req()
135            || security_support.mfp.as_ref().map_or(false, |mfp| mfp.supported.unwrap_or(false))
136    }
137
138    /// Returns true if RsnCapabilities contains a capability
139    /// which wlanstack cannot currently agree to handle.
140    fn contains_unsupported_capability(&self) -> bool {
141        self.joint_multiband()
142            || self.peerkey_enabled()
143            || self.ssp_amsdu_req()
144            || self.pbac()
145            || self.extended_key_id()
146    }
147}
148
149/// Used to identify the last field we will write into our RSNE buffer.
150#[derive(PartialEq)]
151enum FinalField {
152    Version,
153    GroupData,
154    Pairwise,
155    Akm,
156    Caps,
157    Pmkid,
158    GroupMgmt,
159}
160
161impl Rsne {
162    pub fn wpa2_rsne() -> Self {
163        Rsne {
164            group_data_cipher_suite: Some(CIPHER_CCMP_128),
165            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
166            akm_suites: vec![AKM_PSK],
167            ..Default::default()
168        }
169    }
170
171    pub fn wpa2_rsne_with_caps(rsn_capabilities: RsnCapabilities) -> Self {
172        Self::wpa2_rsne().with_caps(rsn_capabilities)
173    }
174
175    pub fn wpa2_wpa3_rsne() -> Self {
176        Rsne {
177            group_data_cipher_suite: Some(CIPHER_CCMP_128),
178            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
179            akm_suites: vec![AKM_SAE, AKM_PSK],
180            rsn_capabilities: Some(RsnCapabilities(0).with_mgmt_frame_protection_cap(true)),
181            // Always explicitly include a group management cipher suite. There
182            // is no reason to rely on the default group management cipher
183            // suite selection defined in IEEE 802.11-2016 9.4.2.25.2 if we are making
184            // the Rsne ourselves.
185            group_mgmt_cipher_suite: Some(DEFAULT_GROUP_MGMT_CIPHER),
186            ..Default::default()
187        }
188    }
189
190    pub fn wpa2_wpa3_rsne_with_extra_caps(rsn_capabilities: RsnCapabilities) -> Self {
191        let rsne = Self::wpa2_wpa3_rsne();
192        let wpa2_wpa3_minimum_rsn_capabilities = rsne.rsn_capabilities.as_ref().unwrap().clone();
193        rsne.with_caps(RsnCapabilities(
194            wpa2_wpa3_minimum_rsn_capabilities.raw() | rsn_capabilities.raw(),
195        ))
196    }
197
198    pub fn wpa3_rsne() -> Self {
199        Rsne {
200            group_data_cipher_suite: Some(CIPHER_CCMP_128),
201            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
202            akm_suites: vec![AKM_SAE],
203            rsn_capabilities: Some(
204                RsnCapabilities(0)
205                    .with_mgmt_frame_protection_cap(true)
206                    .with_mgmt_frame_protection_req(true),
207            ),
208            // Always explicitly include a group management cipher suite. There
209            // is no reason to rely on the default group management cipher
210            // suite selection defined in IEEE 802.11-2016 9.4.2.25.2 if we are making
211            // the Rsne ourselves.
212            group_mgmt_cipher_suite: Some(DEFAULT_GROUP_MGMT_CIPHER),
213            ..Default::default()
214        }
215    }
216
217    pub fn wpa3_rsne_with_extra_caps(rsn_capabilities: RsnCapabilities) -> Self {
218        let rsne = Self::wpa3_rsne();
219        let wpa3_minimum_rsn_capabilities = rsne.rsn_capabilities.as_ref().unwrap().clone();
220        rsne.with_caps(RsnCapabilities(
221            wpa3_minimum_rsn_capabilities.raw() | rsn_capabilities.raw(),
222        ))
223    }
224
225    /// Common OWE configuration that works with most implementations.
226    ///
227    /// There are multiple possible OWE RSNE variants, but this one is likely to be the one most
228    /// used. For example, only CCMP-128 group and pairwise cipher is used here, but according to
229    /// WPA3 and Wi-Fi Enhanced Open Deployment and Implementation Guide, on extremely-high
230    /// throughput (EHT) deployments, the AP would also have GCMP-256 cipher
231    pub fn common_owe_rsne() -> Self {
232        Rsne {
233            group_data_cipher_suite: Some(CIPHER_CCMP_128),
234            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
235            akm_suites: vec![AKM_OWE],
236            rsn_capabilities: Some(
237                RsnCapabilities(0)
238                    .with_mgmt_frame_protection_cap(true)
239                    .with_mgmt_frame_protection_req(true),
240            ),
241            group_mgmt_cipher_suite: Some(DEFAULT_GROUP_MGMT_CIPHER),
242            ..Default::default()
243        }
244    }
245
246    /// Constructs Supplicant's RSNE with:
247    /// Group Data Cipher: same as A-RSNE (CCMP-128 or TKIP)
248    /// Pairwise Cipher: best from A-RSNE (prefer CCMP-128 over TKIP)
249    /// AKM: PSK
250    pub fn derive_wpa2_s_rsne(
251        &self,
252        security_support: &fidl_common::SecuritySupport,
253    ) -> Result<Self, Error> {
254        if !self.is_wpa2_rsn_compatible(&security_support) {
255            return Err(Error::CannotDeriveWpa2Rsne);
256        }
257
258        // Enable management frame protection if supported.
259        let rsn_capabilities = match self.rsn_capabilities.clone() {
260            Some(cap) => {
261                if cap.mgmt_frame_protection_cap()
262                    && security_support
263                        .mfp
264                        .as_ref()
265                        .map_or(false, |mfp| mfp.supported.unwrap_or(false))
266                {
267                    Some(cap.with_mgmt_frame_protection_req(true))
268                } else {
269                    Some(cap)
270                }
271            }
272            None => None,
273        };
274
275        // CCMP-128 is better than TKIP
276        let pairwise_cipher_suites =
277            vec![match self.pairwise_cipher_suites.iter().max_by_key(|cipher_suite| {
278                match **cipher_suite {
279                    CIPHER_CCMP_128 => 1,
280                    _ => 0,
281                }
282            }) {
283                Some(cipher_suite) => cipher_suite.clone(),
284                None => return Err(Error::NoPairwiseCipherSuite),
285            }];
286
287        Ok(Rsne {
288            group_data_cipher_suite: self.group_data_cipher_suite.clone(),
289            pairwise_cipher_suites,
290            akm_suites: vec![AKM_PSK],
291            rsn_capabilities,
292            ..Default::default()
293        })
294    }
295
296    /// Constructs Supplicant's RSNE with:
297    /// Group Data Cipher: CCMP-128
298    /// Pairwise Cipher: CCMP-128
299    /// AKM: SAE
300    pub fn derive_wpa3_s_rsne(
301        &self,
302        security_support: &fidl_common::SecuritySupport,
303    ) -> Result<Rsne, Error> {
304        if !self.is_wpa3_rsn_compatible(&security_support) {
305            return Err(Error::CannotDeriveWpa3Rsne);
306        }
307
308        let rsn_capabilities = match self.rsn_capabilities.clone() {
309            Some(cap) => Some(cap.with_mgmt_frame_protection_req(true)),
310            None => None,
311        };
312
313        Ok(Rsne {
314            group_data_cipher_suite: self.group_data_cipher_suite.clone(),
315            pairwise_cipher_suites: vec![cipher::Cipher {
316                oui: suite_selector::OUI,
317                suite_type: cipher::CCMP_128,
318            }],
319            akm_suites: vec![akm::Akm { oui: suite_selector::OUI, suite_type: akm::SAE }],
320            rsn_capabilities,
321            ..Default::default()
322        })
323    }
324
325    /// Constructs Supplicant's RSNE with:
326    /// Group Data Cipher: same as A-RSNE (CCMP-128 or GCMP-256)
327    /// Pairwise Cipher: same as A-RSNE (prefer GCMP-256 > CCMP-128 > the rest)
328    /// AKM: OWE
329    pub fn derive_owe_s_rsne(
330        &self,
331        security_support: &fidl_common::SecuritySupport,
332    ) -> Result<Rsne, Error> {
333        if !self.is_owe_rsn_compatible(&security_support) {
334            return Err(Error::CannotDeriveOweRsne);
335        }
336
337        // GCMP-256 > CCMP-128 > the rest (which are uncommon configurations)
338        let pairwise_cipher_suites =
339            vec![match self.pairwise_cipher_suites.iter().max_by_key(|cipher_suite| {
340                match **cipher_suite {
341                    CIPHER_GCMP_256 => 2,
342                    CIPHER_CCMP_128 => 1,
343                    _ => 0,
344                }
345            }) {
346                Some(cipher_suite) => cipher_suite.clone(),
347                None => return Err(Error::NoPairwiseCipherSuite),
348            }];
349
350        Ok(Rsne {
351            group_data_cipher_suite: self.group_data_cipher_suite.clone(),
352            pairwise_cipher_suites,
353            akm_suites: vec![akm::Akm { oui: suite_selector::OUI, suite_type: akm::OWE }],
354            rsn_capabilities: self.rsn_capabilities.clone(),
355            ..Default::default()
356        })
357    }
358
359    /// Validates this RSNE contains only one of each cipher type and only one AKM with
360    /// a defined number of MIC bytes.
361    pub fn ensure_valid_s_rsne(&self) -> Result<(), Error> {
362        let s_rsne = self;
363        s_rsne.group_data_cipher_suite.as_ref().ok_or(Error::NoGroupDataCipherSuite)?;
364
365        rsne_ensure!(s_rsne.pairwise_cipher_suites.len() >= 1, Error::NoPairwiseCipherSuite);
366        rsne_ensure!(s_rsne.pairwise_cipher_suites.len() <= 1, Error::TooManyPairwiseCipherSuites);
367
368        rsne_ensure!(s_rsne.akm_suites.len() >= 1, Error::NoAkmSuite);
369        rsne_ensure!(s_rsne.akm_suites.len() <= 1, Error::TooManyAkmSuites);
370
371        let akm = &s_rsne.akm_suites[0];
372        rsne_ensure!(akm.mic_bytes().is_some(), Error::NoAkmMicBytes);
373
374        Ok(())
375    }
376
377    /// Verify that Supplicant RSNE is a subset of Authenticator RSNE
378    pub fn is_valid_subset_of(&self, a_rsne: &Rsne) -> Result<bool, Error> {
379        let s_rsne = self;
380        s_rsne.ensure_valid_s_rsne()?;
381
382        let s_caps = s_rsne.rsn_capabilities.as_ref().unwrap_or(&RsnCapabilities(0));
383        let s_mgmt_req = s_caps.mgmt_frame_protection_req();
384        let s_mgmt_cap = s_caps.mgmt_frame_protection_cap();
385        let a_caps = a_rsne.rsn_capabilities.as_ref().unwrap_or(&RsnCapabilities(0));
386        let a_mgmt_req = a_caps.mgmt_frame_protection_req();
387        let a_mgmt_cap = a_caps.mgmt_frame_protection_cap();
388
389        // IEEE Std 802.11-2016, 12.6.3, Table 12-2
390        match (a_mgmt_cap, a_mgmt_req, s_mgmt_cap, s_mgmt_req) {
391            (true, _, false, true) => return Err(Error::InvalidSupplicantMgmtFrameProtection),
392            (false, true, true, _) => return Err(Error::InvalidAuthenticatorMgmtFrameProtection),
393            (true, true, false, false) => return Ok(false),
394            (false, false, true, true) => return Ok(false),
395            // the remaining cases fall into either of these buckets:
396            // 1 - spec mentions that "The AP may associate with the STA"
397            // 2 - it's not covered in the spec, which means presumably we can ignore it. For example,
398            //     if AP/client is not management frame protection capable, then it probably doesn't
399            //     matter whether the opposite party advertises an invalid setting
400            _ => (),
401        }
402
403        Ok(a_rsne
404            .group_data_cipher_suite
405            .iter()
406            // .unwrap() will succeed because .ensure_valid_s_rsne() was run at the beginning of this function.
407            .any(|c| c == s_rsne.group_data_cipher_suite.as_ref().unwrap())
408            && a_rsne.pairwise_cipher_suites.iter().any(|c| *c == s_rsne.pairwise_cipher_suites[0])
409            && a_rsne.akm_suites.iter().any(|c| *c == s_rsne.akm_suites[0]))
410    }
411
412    /// IEEE Std. 802.11-2016 9.4.2.25.1
413    ///    "All fields after the Version field are optional. If any
414    ///     nonzero-length field is absent, then none of the subsequent
415    ///     fields is included."
416    /// Determine the last field we will write to produce the smallest RSNE
417    /// that matches this specification.
418    fn final_field(&self) -> FinalField {
419        if self.group_data_cipher_suite.is_none() {
420            FinalField::Version
421        } else if self.rsn_capabilities.is_none() {
422            if self.akm_suites.is_empty() {
423                if self.pairwise_cipher_suites.is_empty() {
424                    FinalField::GroupData
425                } else {
426                    FinalField::Pairwise
427                }
428            } else {
429                FinalField::Akm
430            }
431        } else {
432            if self.group_mgmt_cipher_suite.is_none() {
433                if self.pmkids.is_empty() { FinalField::Caps } else { FinalField::Pmkid }
434            } else {
435                FinalField::GroupMgmt
436            }
437        }
438    }
439
440    /// IEEE Std. 802.11-2016 9.4.2.25.1 specifies lengths for all fields.
441    pub fn len(&self) -> usize {
442        let final_field = self.final_field();
443        let mut length: usize = 4; // Element Id (1) + Length (1) + Version (2)
444        if final_field == FinalField::Version {
445            return length;
446        }
447        length += 4; // Group data cipher (4)
448        if final_field == FinalField::GroupData {
449            return length;
450        }
451        // Pairwise cipher count (2) + pairwise ciphers (4 * count)
452        length += 2 + 4 * self.pairwise_cipher_suites.len();
453        if final_field == FinalField::Pairwise {
454            return length;
455        }
456        // AKM count (2) + AKMs (4 * count)
457        length += 2 + 4 * self.akm_suites.len();
458        if final_field == FinalField::Akm {
459            return length;
460        }
461        length += 2; // RSN capabilities (2)
462        if final_field == FinalField::Caps {
463            return length;
464        }
465        // PMKID count (2) + PMKIDs (16 * count)
466        length += 2 + 16 * self.pmkids.len();
467        if final_field == FinalField::Pmkid {
468            return length;
469        }
470        length + 4 // Group management cipher (4)
471    }
472
473    pub fn into_bytes(self) -> Vec<u8> {
474        let mut buf = Vec::with_capacity(self.len());
475        self.write_into(&mut buf).expect("error writing RSNE into buffer");
476        buf
477    }
478
479    pub fn write_into<A: Append>(&self, buf: &mut A) -> Result<(), BufferTooSmall> {
480        if !buf.can_append(self.len()) {
481            return Err(BufferTooSmall);
482        }
483        let final_field = self.final_field();
484
485        buf.append_byte(ID)?;
486        buf.append_byte((self.len() - 2) as u8)?;
487        buf.append_value(&self.version)?;
488        if final_field == FinalField::Version {
489            return Ok(());
490        }
491
492        match self.group_data_cipher_suite.as_ref() {
493            None => return Ok(()),
494            Some(cipher) => {
495                buf.append_bytes(&cipher.oui[..])?;
496                buf.append_byte(cipher.suite_type)?;
497            }
498        };
499        if final_field == FinalField::GroupData {
500            return Ok(());
501        }
502
503        buf.append_value(&(self.pairwise_cipher_suites.len() as u16))?;
504        for cipher in &self.pairwise_cipher_suites {
505            buf.append_bytes(&cipher.oui[..])?;
506            buf.append_byte(cipher.suite_type)?;
507        }
508        if final_field == FinalField::Pairwise {
509            return Ok(());
510        }
511
512        buf.append_value(&(self.akm_suites.len() as u16))?;
513        for akm in &self.akm_suites {
514            buf.append_bytes(&akm.oui[..])?;
515            buf.append_byte(akm.suite_type)?;
516        }
517        if final_field == FinalField::Akm {
518            return Ok(());
519        }
520
521        match self.rsn_capabilities.as_ref() {
522            None => return Ok(()),
523            Some(caps) => buf.append_value(&caps.0)?,
524        };
525        if final_field == FinalField::Caps {
526            return Ok(());
527        }
528
529        buf.append_value(&(self.pmkids.len() as u16))?;
530        for pmkid in &self.pmkids {
531            buf.append_bytes(&pmkid[..])?;
532        }
533        if final_field == FinalField::Pmkid {
534            return Ok(());
535        }
536
537        if let Some(cipher) = self.group_mgmt_cipher_suite.as_ref() {
538            buf.append_bytes(&cipher.oui[..])?;
539            buf.append_byte(cipher.suite_type)?;
540        }
541        Ok(())
542    }
543
544    /// Supported Ciphers and AKMs:
545    /// Group Data Ciphers: CCMP-128, TKIP
546    /// Pairwise Cipher: CCMP-128, TKIP
547    /// AKM: PSK, SAE
548    pub fn is_wpa2_rsn_compatible(&self, security_support: &fidl_common::SecuritySupport) -> bool {
549        let group_data_supported = self.group_data_cipher_suite.as_ref().is_some_and(|c| {
550            // IEEE allows TKIP usage only for compatibility reasons.
551            c.has_known_usage() && [cipher::CCMP_128, cipher::TKIP].contains(&c.suite_type)
552        });
553
554        let pairwise_supported = self.pairwise_cipher_suites.iter().any(|c| {
555            c.has_known_usage() && [cipher::CCMP_128, cipher::TKIP].contains(&c.suite_type)
556        });
557        let akm_supported =
558            self.akm_suites.iter().any(|a| a.has_known_algorithm() && a.suite_type == akm::PSK);
559        let caps_supported =
560            self.rsn_capabilities.as_ref().map_or(true, RsnCapabilities::is_wpa2_compatible);
561        let features_supported = self
562            .rsn_capabilities
563            .as_ref()
564            .unwrap_or(&RsnCapabilities(0))
565            .is_compatible_with_features(security_support);
566
567        group_data_supported
568            && pairwise_supported
569            && akm_supported
570            && caps_supported
571            && features_supported
572    }
573
574    /// Check if this is a supported WPA3-Personal or WPA3-Personal transition AP per the WFA WPA3 specification.
575    /// Supported Ciphers and AKMs:
576    /// Group Data Ciphers: CCMP-128, TKIP
577    /// Pairwise Cipher: CCMP-128
578    /// AKM: SAE (also PSK in transition mode)
579    /// The MFPR bit is required, except for transition mode.
580    pub fn is_wpa3_rsn_compatible(&self, security_support: &fidl_common::SecuritySupport) -> bool {
581        let group_data_supported = self.group_data_cipher_suite.as_ref().is_some_and(|c| {
582            c.has_known_usage() && [cipher::CCMP_128, cipher::TKIP].contains(&c.suite_type)
583        });
584        let pairwise_supported = self
585            .pairwise_cipher_suites
586            .iter()
587            .any(|c| c.has_known_usage() && c.suite_type == cipher::CCMP_128);
588        let sae_supported =
589            self.akm_suites.iter().any(|a| a.has_known_algorithm() && a.suite_type == akm::SAE);
590        let wpa2_compatibility_mode =
591            self.akm_suites.iter().any(|a| a.has_known_algorithm() && a.suite_type == akm::PSK);
592        let caps_supported = self
593            .rsn_capabilities
594            .as_ref()
595            .is_some_and(|caps| caps.is_wpa3_compatible(wpa2_compatibility_mode));
596        let mut features_supported = self
597            .rsn_capabilities
598            .as_ref()
599            .unwrap_or(&RsnCapabilities(0))
600            .is_compatible_with_features(security_support);
601        // WFA WPA3 specification v3.0: 2.3 rule 7: Verify that we actually support MFP, regardless of whether
602        // the features bits indicate we need that support. SAE without MFP is not a valid configuration.
603        features_supported &=
604            security_support.mfp.as_ref().and_then(|mfp| mfp.supported).unwrap_or(false);
605        group_data_supported
606            && pairwise_supported
607            && sae_supported
608            && caps_supported
609            && features_supported
610    }
611
612    pub fn is_owe_rsn_compatible(&self, security_support: &fidl_common::SecuritySupport) -> bool {
613        let group_data_supported = self.group_data_cipher_suite.as_ref().is_some_and(|cipher| {
614            cipher.has_known_usage()
615                && [cipher::CCMP_128, cipher::GCMP_256].contains(&cipher.suite_type)
616        });
617        let pairwise_supported = self.pairwise_cipher_suites.iter().any(|cipher| {
618            cipher.has_known_usage()
619                && [cipher::CCMP_128, cipher::GCMP_256, cipher::CCMP_256, cipher::GCMP_128]
620                    .contains(&cipher.suite_type)
621        });
622        let akm_supported = self.akm_suites.contains(&AKM_OWE);
623        let caps_supported =
624            self.rsn_capabilities.as_ref().is_some_and(RsnCapabilities::is_owe_compatible);
625        let mut features_supported = self
626            .rsn_capabilities
627            .as_ref()
628            .unwrap_or(&RsnCapabilities(0))
629            .is_compatible_with_features(security_support);
630        // MFP is mandatory for OWE.
631        features_supported &=
632            security_support.mfp.as_ref().and_then(|mfp| mfp.supported).unwrap_or(false);
633        group_data_supported
634            && pairwise_supported
635            && akm_supported
636            && caps_supported
637            && features_supported
638    }
639
640    fn with_caps(mut self, rsn_capabilities: RsnCapabilities) -> Self {
641        self.rsn_capabilities = Some(rsn_capabilities);
642        self
643    }
644}
645
646fn read_suite_selector<T>(input: &[u8]) -> IResult<&[u8], T>
647where
648    T: suite_selector::Factory<Suite = T>,
649{
650    let (i1, bytes) = take(4usize).parse(input)?;
651    let oui = Oui::new([bytes[0], bytes[1], bytes[2]]);
652    return Ok((i1, T::new(oui, bytes[3])));
653}
654
655fn read_pmkid(input: &[u8]) -> IResult<&[u8], pmkid::Pmkid> {
656    let f = |bytes| {
657        let pmkid_data = Bytes::copy_from_slice(bytes);
658        return pmkid::new(pmkid_data);
659    };
660
661    map_res(nom::bytes::streaming::take(16usize), f).parse(input)
662}
663
664fn akm(input: &[u8]) -> IResult<&[u8], akm::Akm> {
665    read_suite_selector::<akm::Akm>(input)
666}
667
668fn cipher(input: &[u8]) -> IResult<&[u8], cipher::Cipher> {
669    read_suite_selector::<cipher::Cipher>(input)
670}
671
672/// convert bytes of an RSNE information element into an RSNE representation. This method
673/// does not depend on the information element length field (second byte) and thus does not
674/// validate that it's correct
675pub fn from_bytes(input: &[u8]) -> IResult<&[u8], Rsne> {
676    map(
677        terminated(
678            (
679                le_u8,
680                le_u8,
681                le_u16,
682                if_remaining!(cipher),
683                if_remaining!(length_count(le_u16, cipher)),
684                if_remaining!(length_count(le_u16, akm)),
685                if_remaining!(map(le_u16, RsnCapabilities)),
686                if_remaining!(length_count(le_u16, read_pmkid)),
687                if_remaining!(cipher),
688            ),
689            eof,
690        ),
691        |(
692            _element_id,
693            _length,
694            version,
695            group_cipher,
696            pairwise_list,
697            akm_list,
698            rsn_capabilities,
699            pmkid_list,
700            group_mgmt_cipher_suite,
701        )| Rsne {
702            version: version,
703            group_data_cipher_suite: group_cipher,
704            pairwise_cipher_suites: pairwise_list.unwrap_or_default(),
705            akm_suites: akm_list.unwrap_or_default(),
706            rsn_capabilities: rsn_capabilities,
707            pmkids: pmkid_list.unwrap_or_default(),
708            group_mgmt_cipher_suite: group_mgmt_cipher_suite,
709        },
710    )
711    .parse(input)
712}
713
714#[cfg(test)]
715mod tests {
716    use super::akm::{AKM_EAP, AKM_FT_PSK};
717    use super::cipher::{CIPHER_BIP_CMAC_256, CIPHER_GCMP_256, CIPHER_TKIP};
718    use super::*;
719    use crate::append::TrackedAppend;
720    use crate::test_utils::FixedSizedTestBuffer;
721    use crate::test_utils::fake_features::fake_security_support_empty;
722    use test_case::test_case;
723
724    #[cfg(feature = "benchmark")]
725    mod bench {
726        use self::test::Bencher;
727        use super::*;
728        #[cfg()]
729        #[bench]
730        fn bench_parse_with_nom(b: &mut Bencher) {
731            let frame: Vec<u8> = vec![
732                0x30, 0x2A, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
733                0x01, 0x00, 0x00, 0x0f, 0xac, 0x02, 0xa8, 0x04, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04,
734                0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x00, 0x0f,
735                0xac, 0x04,
736            ];
737            b.iter(|| from_bytes(&frame));
738        }
739    }
740
741    #[test]
742    fn test_write_into() {
743        let frame: Vec<u8> = vec![
744            0x30, 0x2A, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
745            0x01, 0x00, 0x00, 0x0f, 0xac, 0x02, 0xa8, 0x04, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04,
746            0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x00, 0x0f,
747            0xac, 0x04,
748        ];
749        let result = from_bytes(&frame);
750        assert!(result.is_ok());
751        let rsne = result.unwrap().1;
752        let mut buf = Vec::with_capacity(128);
753        rsne.write_into(&mut buf).expect("failed writing RSNE");
754        let rsne_len = buf.len();
755        let left_over = buf.split_off(rsne_len);
756        assert_eq!(&buf[..], &frame[..]);
757        assert!(left_over.iter().all(|b| *b == 0));
758    }
759
760    #[test]
761    fn test_short_buffer() {
762        let frame: Vec<u8> = vec![
763            0x30, 0x2A, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
764            0x01, 0x00, 0x00, 0x0f, 0xac, 0x02, 0xa8, 0x04, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04,
765            0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x00, 0x0f,
766            0xac, 0x04,
767        ];
768        let mut buf = FixedSizedTestBuffer::new(32);
769        let result = from_bytes(&frame);
770        assert!(result.is_ok());
771        let rsne = result.unwrap().1;
772        rsne.write_into(&mut buf).expect_err("expected writing RSNE to fail");
773        assert_eq!(buf.bytes_appended(), 0);
774    }
775
776    #[test]
777    fn test_rsn_fields_representation() {
778        let frame: Vec<u8> = vec![
779            0x30, // element id
780            0x2A, // length
781            0x01, 0x00, // version
782            0x00, 0x0f, 0xac, 0x04, // group data cipher suite
783            0x01, 0x00, // pairwise cipher suite count
784            0x00, 0x0f, 0xac, 0x04, // pairwise cipher suite list
785            0x01, 0x00, // akm suite count
786            0x00, 0x0f, 0xac, 0x02, // akm suite list
787            0xa8, 0x04, // rsn capabilities
788            0x01, 0x00, // pmk id count
789            // pmk id list
790            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
791            0x10, 0x11, 0x00, 0x0f, 0xac, 0x04, // group management cipher suite
792        ];
793        let result = from_bytes(&frame);
794        assert!(result.is_ok());
795        let rsne = result.unwrap().1;
796
797        assert_eq!(rsne.version, VERSION);
798        assert_eq!(rsne.len(), 0x2a + 2);
799
800        assert!(rsne.group_data_cipher_suite.is_some());
801        assert_eq!(rsne.group_data_cipher_suite, Some(CIPHER_CCMP_128));
802        assert_eq!(rsne.pairwise_cipher_suites.len(), 1);
803        assert_eq!(rsne.pairwise_cipher_suites[0].oui, Oui::DOT11);
804        assert_eq!(rsne.pairwise_cipher_suites[0].suite_type, cipher::CCMP_128);
805        assert_eq!(rsne.akm_suites.len(), 1);
806        assert_eq!(rsne.akm_suites[0].suite_type, akm::PSK);
807
808        let rsn_capabilities = rsne.rsn_capabilities.expect("should have RSN capabilities");
809        assert_eq!(rsn_capabilities.preauth(), false);
810        assert_eq!(rsn_capabilities.no_pairwise(), false);
811        assert_eq!(rsn_capabilities.ptksa_replay_counter(), 2);
812        assert_eq!(rsn_capabilities.gtksa_replay_counter(), 2);
813        assert!(!rsn_capabilities.mgmt_frame_protection_req());
814        assert!(rsn_capabilities.mgmt_frame_protection_cap());
815        assert!(!rsn_capabilities.joint_multiband());
816        assert!(!rsn_capabilities.peerkey_enabled());
817        assert!(rsn_capabilities.ssp_amsdu_cap());
818        assert!(!rsn_capabilities.ssp_amsdu_req());
819        assert!(!rsn_capabilities.pbac());
820        assert!(!rsn_capabilities.extended_key_id());
821
822        assert_eq!(rsn_capabilities.0, 0xa8 + (0x04 << 8));
823
824        let pmkids: &[u8] = &[
825            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
826            0x10, 0x11,
827        ];
828        assert_eq!(rsne.pmkids.len(), 1);
829        assert_eq!(rsne.pmkids[0], Bytes::from(pmkids));
830
831        assert_eq!(rsne.group_mgmt_cipher_suite, Some(CIPHER_CCMP_128));
832    }
833
834    #[test]
835    fn test_rsn_capabilities_setters() {
836        let mut rsn_caps = RsnCapabilities(0u16);
837        rsn_caps.set_ptksa_replay_counter(2);
838        rsn_caps.set_gtksa_replay_counter(2);
839        rsn_caps.set_mgmt_frame_protection_cap(true);
840        rsn_caps.set_ssp_amsdu_cap(true);
841
842        assert_eq!(rsn_caps.0, 0xa8 + (0x04 << 8));
843    }
844
845    #[test]
846    fn test_invalid_wpa2_caps() {
847        assert!(RsnCapabilities(0).is_wpa2_compatible());
848
849        let caps = RsnCapabilities(0).with_joint_multiband(true);
850        assert!(!caps.is_wpa2_compatible());
851
852        let caps = RsnCapabilities(0).with_peerkey_enabled(true);
853        assert!(!caps.is_wpa2_compatible());
854
855        let caps = RsnCapabilities(0).with_ssp_amsdu_req(true);
856        assert!(!caps.is_wpa2_compatible());
857
858        let caps = RsnCapabilities(0).with_pbac(true);
859        assert!(!caps.is_wpa2_compatible());
860
861        let caps = RsnCapabilities(0).with_extended_key_id(true);
862        assert!(!caps.is_wpa2_compatible());
863    }
864
865    use std::sync::LazyLock;
866    static MFP_SUPPORT_ONLY: LazyLock<fidl_common::SecuritySupport> =
867        LazyLock::new(|| fidl_common::SecuritySupport {
868            mfp: Some(fidl_common::MfpFeature { supported: Some(true), ..Default::default() }),
869            sae: Some(fidl_common::SaeFeature {
870                driver_handler_supported: Some(false),
871                sme_handler_supported: Some(false),
872                hash_to_element_supported: Some(false),
873                ..Default::default()
874            }),
875            owe: Some(fidl_common::OweFeature { supported: Some(false), ..Default::default() }),
876            ..Default::default()
877        });
878
879    #[test_case(MFP_SUPPORT_ONLY.clone(), true)]
880    #[test_case(fake_security_support_empty(), false)]
881    #[fuchsia::test]
882    fn test_wpa2_enables_pmf_if_supported(
883        security_support: fidl_common::SecuritySupport,
884        expect_mfp: bool,
885    ) {
886        let a_rsne =
887            Rsne::wpa2_rsne_with_caps(RsnCapabilities(0).with_mgmt_frame_protection_cap(true));
888        assert!(a_rsne.is_wpa2_rsn_compatible(&security_support));
889
890        let s_rsne = a_rsne
891            .derive_wpa2_s_rsne(&security_support)
892            .expect("Should be able to derive s_rsne with PMF");
893        assert!(s_rsne.is_wpa2_rsn_compatible(&security_support));
894        assert_eq!(
895            expect_mfp,
896            s_rsne
897                .rsn_capabilities
898                .expect("PMF RSNE should have RSN capabilities")
899                .mgmt_frame_protection_req()
900        );
901    }
902
903    #[test]
904    fn test_invalid_wpa3_caps() {
905        assert!(!RsnCapabilities(0).is_wpa3_compatible(false));
906
907        let wpa3_caps = RsnCapabilities(0)
908            .with_mgmt_frame_protection_cap(true)
909            .with_mgmt_frame_protection_req(true);
910        assert!(wpa3_caps.is_wpa3_compatible(false));
911
912        let caps = wpa3_caps.clone().with_joint_multiband(true);
913        assert!(!caps.is_wpa3_compatible(false));
914
915        let caps = wpa3_caps.clone().with_peerkey_enabled(true);
916        assert!(!caps.is_wpa3_compatible(false));
917
918        let caps = wpa3_caps.clone().with_ssp_amsdu_req(true);
919        assert!(!caps.is_wpa3_compatible(false));
920
921        let caps = wpa3_caps.clone().with_pbac(true);
922        assert!(!caps.is_wpa3_compatible(false));
923
924        let caps = wpa3_caps.clone().with_extended_key_id(true);
925        assert!(!caps.is_wpa3_compatible(false));
926
927        let wpa2_wpa3_caps = RsnCapabilities(0).with_mgmt_frame_protection_cap(true);
928        assert!(wpa2_wpa3_caps.is_wpa3_compatible(true));
929
930        let caps = wpa2_wpa3_caps.clone().with_extended_key_id(true);
931        assert!(!caps.is_wpa3_compatible(true));
932    }
933
934    #[test]
935    fn test_with_caps() {
936        assert!(Rsne::wpa2_rsne().rsn_capabilities.is_none());
937        let rsne_with_caps =
938            Rsne::wpa2_rsne_with_caps(RsnCapabilities(0).with_peerkey_enabled(true));
939        assert!(rsne_with_caps.rsn_capabilities.as_ref().unwrap().peerkey_enabled());
940
941        assert!(!Rsne::wpa2_wpa3_rsne().rsn_capabilities.unwrap().peerkey_enabled());
942        let rsne_with_caps =
943            Rsne::wpa2_wpa3_rsne_with_extra_caps(RsnCapabilities(0).with_peerkey_enabled(true));
944        assert!(rsne_with_caps.rsn_capabilities.as_ref().unwrap().peerkey_enabled());
945        assert!(rsne_with_caps.rsn_capabilities.as_ref().unwrap().mgmt_frame_protection_cap());
946
947        assert!(!Rsne::wpa3_rsne().rsn_capabilities.unwrap().peerkey_enabled());
948        let rsne_with_caps =
949            Rsne::wpa3_rsne_with_extra_caps(RsnCapabilities(0).with_peerkey_enabled(true));
950        assert!(rsne_with_caps.rsn_capabilities.as_ref().unwrap().peerkey_enabled());
951        assert!(
952            rsne_with_caps.rsn_capabilities.as_ref().unwrap().mgmt_frame_protection_cap()
953                && rsne_with_caps.rsn_capabilities.as_ref().unwrap().mgmt_frame_protection_req()
954        );
955    }
956
957    #[test]
958    fn test_incompatible_group_data_cipher() {
959        let rsne = Rsne {
960            group_data_cipher_suite: Some(CIPHER_GCMP_256),
961            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
962            akm_suites: vec![AKM_PSK],
963            ..Default::default()
964        };
965        assert_eq!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), false);
966    }
967
968    #[test]
969    fn test_no_group_data_cipher() {
970        let rsne = Rsne {
971            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
972            akm_suites: vec![AKM_PSK],
973            ..Default::default()
974        };
975        assert_eq!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), false);
976
977        let rsne = Rsne {
978            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
979            akm_suites: vec![AKM_SAE],
980            ..Default::default()
981        };
982        let mut security_support = fake_security_support_empty();
983        security_support.mfp.as_mut().unwrap().supported = Some(true);
984        assert_eq!(rsne.is_wpa3_rsn_compatible(&security_support), false);
985
986        let rsne = Rsne {
987            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
988            akm_suites: vec![AKM_OWE],
989            ..Default::default()
990        };
991        assert_eq!(rsne.is_owe_rsn_compatible(&security_support), false);
992    }
993
994    #[test]
995    fn test_rsne_unsupported_group_data_cipher() {
996        let s_rsne = Rsne::wpa2_rsne();
997        let mut a_rsne = Rsne::wpa2_rsne();
998        a_rsne.group_data_cipher_suite = Some(CIPHER_GCMP_256);
999        assert!(!s_rsne.is_valid_subset_of(&a_rsne).expect("expect Ok result"));
1000    }
1001
1002    #[test]
1003    fn test_ccmp_128_group_data_cipher_ccmp_128_pairwise_cipher() {
1004        let a_rsne = Rsne {
1005            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1006            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
1007            akm_suites: vec![AKM_PSK],
1008            ..Default::default()
1009        };
1010        assert_eq!(a_rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), true);
1011
1012        let s_rsne = a_rsne
1013            .derive_wpa2_s_rsne(&fake_security_support_empty())
1014            .expect("could not derive WPA2 Supplicant RSNE");
1015        let expected_rsne_bytes = vec![
1016            0x30, // element id, 48 expressed as hexadecimal value
1017            0x12, // length in octets, 18 expressed as hexadecimal value
1018            0x01, 0x00, // Version 1
1019            0x00, 0x0F, 0xac, 0x04, // CCMP-128 as group data cipher suite
1020            0x01, 0x00, // pairwise cipher suite count
1021            0x00, 0x0F, 0xAC, 0x04, // CCMP-128 as pairwise cipher suite
1022            0x01, 0x00, // authentication count
1023            0x00, 0x0F, 0xAC, 0x02, // PSK authentication
1024        ];
1025        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1026    }
1027
1028    #[test]
1029    fn test_tkip_group_data_cipher_ccmp_128_pairwise_cipher() {
1030        let a_rsne = Rsne {
1031            group_data_cipher_suite: Some(CIPHER_TKIP),
1032            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
1033            akm_suites: vec![AKM_PSK],
1034            ..Default::default()
1035        };
1036        assert_eq!(a_rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), true);
1037
1038        let s_rsne = a_rsne
1039            .derive_wpa2_s_rsne(&fake_security_support_empty())
1040            .expect("could not derive WPA2 Supplicant RSNE");
1041        let expected_rsne_bytes = vec![
1042            0x30, // element id, 48 expressed as hexadecimal value
1043            0x12, // length in octets, 18 expressed as hexadecimal value
1044            0x01, 0x00, // Version 1
1045            0x00, 0x0F, 0xac, 0x02, // TKIP as group data cipher suite
1046            0x01, 0x00, // pairwise cipher suite count
1047            0x00, 0x0F, 0xAC, 0x04, // CCMP-128 as pairwise cipher suite
1048            0x01, 0x00, // authentication count
1049            0x00, 0x0F, 0xAC, 0x02, // PSK authentication
1050        ];
1051        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1052    }
1053
1054    #[test]
1055    fn test_tkip_group_data_cipher_tkip_pairwise_cipher() {
1056        let a_rsne = Rsne {
1057            group_data_cipher_suite: Some(CIPHER_TKIP),
1058            pairwise_cipher_suites: vec![CIPHER_TKIP],
1059            akm_suites: vec![AKM_PSK],
1060            ..Default::default()
1061        };
1062        assert_eq!(a_rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), true);
1063
1064        let s_rsne = a_rsne
1065            .derive_wpa2_s_rsne(&fake_security_support_empty())
1066            .expect("could not derive WPA2 Supplicant RSNE");
1067        let expected_rsne_bytes = vec![
1068            0x30, // element id, 48 expressed as hexadecimal value
1069            0x12, // length in octets, 18 expressed as hexadecimal value
1070            0x01, 0x00, // Version 1
1071            0x00, 0x0F, 0xac, 0x02, // TKIP as group data cipher suite
1072            0x01, 0x00, // pairwise cipher suite count
1073            0x00, 0x0F, 0xAC, 0x02, // TKIP as pairwise cipher suite
1074            0x01, 0x00, // authentication count
1075            0x00, 0x0F, 0xAC, 0x02, // PSK authentication
1076        ];
1077        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1078    }
1079
1080    #[test]
1081    fn test_tkip_group_data_cipher_prefer_ccmp_128_pairwise_cipher() {
1082        let a_rsne = Rsne {
1083            group_data_cipher_suite: Some(CIPHER_TKIP),
1084            pairwise_cipher_suites: vec![CIPHER_CCMP_128, CIPHER_TKIP],
1085            akm_suites: vec![AKM_PSK],
1086            ..Default::default()
1087        };
1088        assert_eq!(a_rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), true);
1089
1090        let s_rsne = a_rsne
1091            .derive_wpa2_s_rsne(&fake_security_support_empty())
1092            .expect("could not derive WPA2 Supplicant RSNE");
1093        let expected_rsne_bytes = vec![
1094            0x30, // element id, 48 expressed as hexadecimal value
1095            0x12, // length in octets, 18 expressed as hexadecimal value
1096            0x01, 0x00, // Version 1
1097            0x00, 0x0F, 0xac, 0x02, // TKIP as group data cipher suite
1098            0x01, 0x00, // pairwise cipher suite count
1099            0x00, 0x0F, 0xAC, 0x04, // CCMP-128 as pairwise cipher suite
1100            0x01, 0x00, // authentication count
1101            0x00, 0x0F, 0xAC, 0x02, // PSK authentication
1102        ];
1103        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1104    }
1105
1106    #[test]
1107    fn test_ccmp_128_group_data_cipher_prefer_ccmp_128_pairwise_cipher() {
1108        let a_rsne = Rsne {
1109            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1110            pairwise_cipher_suites: vec![CIPHER_CCMP_128, CIPHER_TKIP],
1111            akm_suites: vec![AKM_PSK],
1112            ..Default::default()
1113        };
1114        assert_eq!(a_rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), true);
1115
1116        let s_rsne = a_rsne
1117            .derive_wpa2_s_rsne(&fake_security_support_empty())
1118            .expect("could not derive WPA2 Supplicant RSNE");
1119        let expected_rsne_bytes = vec![
1120            0x30, // element id, 48 expressed as hexadecimal value
1121            0x12, // length in octets, 18 expressed as hexadecimal value
1122            0x01, 0x00, // Version 1
1123            0x00, 0x0F, 0xac, 0x04, // CCMP-128 as group data cipher suite
1124            0x01, 0x00, // pairwise cipher suite count
1125            0x00, 0x0F, 0xAC, 0x04, // CCMP-128 as pairwise cipher suite
1126            0x01, 0x00, // authentication count
1127            0x00, 0x0F, 0xAC, 0x02, // PSK authentication
1128        ];
1129        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1130    }
1131
1132    #[test]
1133    fn test_compatible_pairwise_cipher() {
1134        let rsne = Rsne {
1135            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1136            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
1137            akm_suites: vec![AKM_PSK],
1138            ..Default::default()
1139        };
1140        assert!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()));
1141
1142        let rsne = Rsne {
1143            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1144            pairwise_cipher_suites: vec![CIPHER_TKIP],
1145            akm_suites: vec![AKM_PSK],
1146            ..Default::default()
1147        };
1148        assert!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()));
1149    }
1150
1151    #[test]
1152    fn test_incompatible_pairwise_cipher() {
1153        let rsne = Rsne {
1154            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1155            pairwise_cipher_suites: vec![CIPHER_BIP_CMAC_256],
1156            akm_suites: vec![AKM_PSK],
1157            ..Default::default()
1158        };
1159        assert_eq!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), false);
1160    }
1161
1162    #[test]
1163    fn test_no_pairwise_cipher() {
1164        let rsne = Rsne {
1165            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1166            akm_suites: vec![AKM_PSK],
1167            ..Default::default()
1168        };
1169        assert_eq!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), false);
1170
1171        let rsne = Rsne {
1172            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1173            akm_suites: vec![AKM_SAE],
1174            ..Default::default()
1175        };
1176        assert_eq!(rsne.is_wpa3_rsn_compatible(&MFP_SUPPORT_ONLY), false);
1177
1178        let rsne = Rsne {
1179            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1180            akm_suites: vec![AKM_OWE],
1181            ..Default::default()
1182        };
1183        assert_eq!(rsne.is_owe_rsn_compatible(&MFP_SUPPORT_ONLY), false);
1184    }
1185
1186    #[test]
1187    fn test_rsne_unsupported_pairwise_cipher() {
1188        let s_rsne = Rsne::wpa2_rsne();
1189        let mut a_rsne = Rsne::wpa2_rsne();
1190        a_rsne.pairwise_cipher_suites = vec![CIPHER_BIP_CMAC_256];
1191        assert!(!s_rsne.is_valid_subset_of(&a_rsne).expect("expect Ok result"));
1192    }
1193
1194    #[test]
1195    fn test_incompatible_akm() {
1196        let rsne = Rsne {
1197            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1198            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
1199            akm_suites: vec![AKM_EAP],
1200            ..Default::default()
1201        };
1202        assert_eq!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), false);
1203        assert_eq!(rsne.is_wpa3_rsn_compatible(&MFP_SUPPORT_ONLY), false);
1204        assert_eq!(rsne.is_owe_rsn_compatible(&MFP_SUPPORT_ONLY), false);
1205
1206        let rsne = Rsne {
1207            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1208            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
1209            akm_suites: vec![AKM_PSK],
1210            ..Default::default()
1211        };
1212        assert_eq!(rsne.is_wpa3_rsn_compatible(&MFP_SUPPORT_ONLY), false);
1213        assert_eq!(rsne.is_owe_rsn_compatible(&MFP_SUPPORT_ONLY), false);
1214
1215        let rsne = Rsne {
1216            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1217            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
1218            akm_suites: vec![AKM_SAE],
1219            ..Default::default()
1220        };
1221        assert_eq!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), false);
1222    }
1223
1224    #[test]
1225    fn test_no_akm() {
1226        let rsne = Rsne {
1227            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1228            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
1229            ..Default::default()
1230        };
1231        assert_eq!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), false);
1232        assert_eq!(rsne.is_wpa3_rsn_compatible(&MFP_SUPPORT_ONLY), false);
1233        assert_eq!(rsne.is_owe_rsn_compatible(&MFP_SUPPORT_ONLY), false);
1234    }
1235
1236    #[test]
1237    fn test_rsne_unsupported_akm() {
1238        let s_rsne = Rsne::wpa2_rsne();
1239        let mut a_rsne = Rsne::wpa2_rsne();
1240        a_rsne.akm_suites = vec![AKM_EAP];
1241        assert!(!s_rsne.is_valid_subset_of(&a_rsne).expect("expect Ok result"));
1242    }
1243
1244    #[test]
1245    fn test_ensure_valid_s_rsne() {
1246        let s_rsne = Rsne::wpa2_rsne();
1247        let result = s_rsne.ensure_valid_s_rsne();
1248        assert!(result.is_ok());
1249
1250        let mut s_rsne = Rsne::wpa2_rsne();
1251        s_rsne.group_data_cipher_suite = None;
1252        let result = s_rsne.ensure_valid_s_rsne();
1253        assert!(result.is_err());
1254        assert_eq!(result.unwrap_err(), Error::NoGroupDataCipherSuite);
1255
1256        let mut s_rsne = Rsne::wpa2_rsne();
1257        s_rsne.pairwise_cipher_suites = vec![];
1258        let result = s_rsne.ensure_valid_s_rsne();
1259        assert!(result.is_err());
1260        assert_eq!(result.unwrap_err(), Error::NoPairwiseCipherSuite);
1261
1262        let mut s_rsne = Rsne::wpa2_rsne();
1263        s_rsne.pairwise_cipher_suites.push(CIPHER_GCMP_256);
1264        let result = s_rsne.ensure_valid_s_rsne();
1265        assert!(result.is_err());
1266        assert_eq!(result.unwrap_err(), Error::TooManyPairwiseCipherSuites);
1267
1268        let mut s_rsne = Rsne::wpa2_rsne();
1269        s_rsne.akm_suites = vec![];
1270        let result = s_rsne.ensure_valid_s_rsne();
1271        assert!(result.is_err());
1272        assert_eq!(result.unwrap_err(), Error::NoAkmSuite);
1273
1274        let mut s_rsne = Rsne::wpa2_rsne();
1275        s_rsne.akm_suites.push(AKM_EAP);
1276        let result = s_rsne.ensure_valid_s_rsne();
1277        assert!(result.is_err());
1278        assert_eq!(result.unwrap_err(), Error::TooManyAkmSuites);
1279
1280        let mut s_rsne = Rsne::wpa2_rsne();
1281        s_rsne.akm_suites = vec![akm::Akm::new_dot11(200)];
1282        let result = s_rsne.ensure_valid_s_rsne();
1283        assert!(result.is_err());
1284        assert_eq!(result.unwrap_err(), Error::NoAkmMicBytes);
1285    }
1286
1287    #[test]
1288    fn test_compatible_wpa2_rsne() {
1289        let rsne = Rsne::wpa2_rsne();
1290        assert!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()));
1291    }
1292
1293    #[test]
1294    fn test_compatible_wpa2_wpa3_rsne() {
1295        let rsne = Rsne::wpa2_wpa3_rsne();
1296        assert!(rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()));
1297        assert!(rsne.is_wpa3_rsn_compatible(&MFP_SUPPORT_ONLY));
1298    }
1299
1300    #[test]
1301    fn test_compatible_wpa3_rsne() {
1302        let rsne = Rsne::wpa3_rsne();
1303        assert!(rsne.is_wpa3_rsn_compatible(&MFP_SUPPORT_ONLY));
1304    }
1305
1306    #[test]
1307    fn test_incompatible_wpa3_rsne_no_mfp() {
1308        let rsne = Rsne::wpa3_rsne();
1309        assert!(!rsne.is_wpa3_rsn_compatible(&fake_security_support_empty()));
1310    }
1311
1312    #[test]
1313    fn test_compatible_owe_rsne() {
1314        let rsne = Rsne::common_owe_rsne();
1315        assert!(rsne.is_owe_rsn_compatible(&MFP_SUPPORT_ONLY));
1316    }
1317
1318    #[test]
1319    fn test_incompatible_owe_rsne_no_mfp() {
1320        let rsne = Rsne::common_owe_rsne();
1321        assert!(!rsne.is_owe_rsn_compatible(&fake_security_support_empty()));
1322    }
1323
1324    #[test]
1325    fn test_ccmp128_group_data_pairwise_cipher_psk() {
1326        let a_rsne = Rsne {
1327            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1328            pairwise_cipher_suites: vec![CIPHER_CCMP_128],
1329            akm_suites: vec![AKM_PSK],
1330            ..Default::default()
1331        };
1332        assert_eq!(a_rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), true);
1333
1334        let s_rsne = a_rsne
1335            .derive_wpa2_s_rsne(&fake_security_support_empty())
1336            .expect("could not derive WPA2 Supplicant RSNE");
1337        let expected_rsne_bytes =
1338            vec![48, 18, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 2];
1339        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1340    }
1341
1342    #[test]
1343    fn test_valid_rsne() {
1344        let s_rsne = Rsne::wpa2_rsne();
1345        let a_rsne = Rsne::wpa2_rsne();
1346        assert!(s_rsne.is_valid_subset_of(&a_rsne).expect("expect Ok result"));
1347    }
1348
1349    #[test]
1350    fn test_ccmp_tkip_mode() {
1351        let a_rsne = Rsne {
1352            group_data_cipher_suite: Some(CIPHER_CCMP_128),
1353            pairwise_cipher_suites: vec![CIPHER_CCMP_128, CIPHER_TKIP],
1354            akm_suites: vec![AKM_PSK, AKM_FT_PSK],
1355            ..Default::default()
1356        };
1357        assert_eq!(a_rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), true);
1358
1359        let s_rsne = a_rsne
1360            .derive_wpa2_s_rsne(&fake_security_support_empty())
1361            .expect("could not derive WPA2 Supplicant RSNE");
1362        let expected_rsne_bytes =
1363            vec![48, 18, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 2];
1364        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1365    }
1366
1367    #[test]
1368    fn test_ccmp128_group_data_pairwise_cipher_sae() {
1369        let a_rsne = Rsne::wpa3_rsne();
1370        assert_eq!(a_rsne.is_wpa3_rsn_compatible(&MFP_SUPPORT_ONLY), true);
1371
1372        let s_rsne = a_rsne
1373            .derive_wpa3_s_rsne(&MFP_SUPPORT_ONLY)
1374            .expect("could not derive WPA2 Supplicant RSNE");
1375        let expected_rsne_bytes =
1376            vec![48, 20, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 8, 192, 0];
1377        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1378    }
1379
1380    #[test]
1381    fn test_wpa3_transition_mode() {
1382        let a_rsne = Rsne::wpa2_wpa3_rsne();
1383        assert_eq!(a_rsne.is_wpa2_rsn_compatible(&fake_security_support_empty()), true);
1384        assert_eq!(a_rsne.is_wpa3_rsn_compatible(&fake_security_support_empty()), false);
1385        assert_eq!(a_rsne.is_wpa3_rsn_compatible(&MFP_SUPPORT_ONLY), true);
1386
1387        let s_rsne = a_rsne
1388            .derive_wpa2_s_rsne(&MFP_SUPPORT_ONLY)
1389            .expect("could not derive WPA2 Supplicant RSNE");
1390        let expected_rsne_bytes =
1391            vec![48, 20, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 2, 192, 0];
1392        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1393
1394        let s_rsne = a_rsne
1395            .derive_wpa3_s_rsne(&MFP_SUPPORT_ONLY)
1396            .expect("could not derive WPA3 Supplicant RSNE");
1397        let expected_rsne_bytes =
1398            vec![48, 20, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 8, 192, 0];
1399        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1400    }
1401
1402    #[test_case(
1403        Rsne::common_owe_rsne(),
1404        vec![48, 20, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 18, 192, 0];
1405        "common OWE RSNE"
1406    )]
1407    #[test_case(
1408        Rsne {
1409            group_data_cipher_suite: Some(CIPHER_GCMP_256),
1410            ..Rsne::common_owe_rsne()
1411        },
1412        vec![48, 20, 1, 0, 0, 15, 172, 9, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 18, 192, 0];
1413        "group data cipher GCMP-256"
1414    )]
1415    #[test_case(
1416        Rsne {
1417            pairwise_cipher_suites: vec![CIPHER_CCMP_128, CIPHER_GCMP_256],
1418            ..Rsne::common_owe_rsne()
1419        },
1420        vec![48, 20, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 9, 1, 0, 0, 15, 172, 18, 192, 0];
1421        "pairwise cipher GCMP-256"
1422    )]
1423    #[test_case(
1424        Rsne {
1425            pairwise_cipher_suites: vec![cipher::Cipher::new_dot11(cipher::CCMP_256)],
1426            ..Rsne::common_owe_rsne()
1427        },
1428        vec![48, 20, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 10, 1, 0, 0, 15, 172, 18, 192, 0];
1429        "pairwise cipher CCMP-256"
1430    )]
1431    #[test_case(
1432        Rsne {
1433            pairwise_cipher_suites: vec![cipher::Cipher::new_dot11(cipher::GCMP_128)],
1434            ..Rsne::common_owe_rsne()
1435        },
1436        vec![48, 20, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 8, 1, 0, 0, 15, 172, 18, 192, 0];
1437        "pairwise cipher GCMP-128"
1438    )]
1439    #[fuchsia::test]
1440    fn test_derive_owe_s_rsne(a_rsne: Rsne, expected_rsne_bytes: Vec<u8>) {
1441        let s_rsne = a_rsne
1442            .derive_owe_s_rsne(&MFP_SUPPORT_ONLY)
1443            .expect("could not derive OWE Supplicant RSNE");
1444        assert_eq!(s_rsne.into_bytes(), expected_rsne_bytes);
1445    }
1446
1447    #[test]
1448    fn test_derive_owe_s_rsne_wrong_group_data_cipher() {
1449        let mut a_rsne = Rsne::common_owe_rsne();
1450        a_rsne.group_data_cipher_suite = Some(CIPHER_TKIP);
1451        a_rsne.derive_owe_s_rsne(&MFP_SUPPORT_ONLY).expect_err("expect failure");
1452    }
1453
1454    #[test]
1455    fn test_derive_owe_s_rsne_wrong_pairwise_data_cipher() {
1456        let mut a_rsne = Rsne::common_owe_rsne();
1457        a_rsne.pairwise_cipher_suites = vec![CIPHER_TKIP];
1458        a_rsne.derive_owe_s_rsne(&MFP_SUPPORT_ONLY).expect_err("expect failure");
1459    }
1460
1461    #[test]
1462    fn test_derive_owe_s_rsne_wrong_akm() {
1463        let mut a_rsne = Rsne::common_owe_rsne();
1464        a_rsne.akm_suites = vec![AKM_SAE];
1465        a_rsne.derive_owe_s_rsne(&MFP_SUPPORT_ONLY).expect_err("expect failure");
1466    }
1467
1468    #[test]
1469    fn test_wpa2_psk_rsne_bytes() {
1470        // Compliant with IEEE Std 802.11-2016, 9.4.2.25.
1471        let expected: Vec<u8> = vec![
1472            0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
1473            0x01, 0x00, 0x00, 0x0f, 0xac, 0x02, 0x00, 0x00,
1474        ];
1475        let rsne = Rsne::wpa2_rsne_with_caps(RsnCapabilities(0));
1476        let mut actual = Vec::with_capacity(rsne.len());
1477        rsne.write_into(&mut actual).expect("error writing RSNE");
1478
1479        assert_eq!(&expected[..], &actual[..]);
1480    }
1481
1482    #[test]
1483    fn test_supplicant_missing_required_mpfc() {
1484        let s_rsne = Rsne::wpa2_rsne();
1485        let a_rsne = Rsne::wpa2_rsne_with_caps(
1486            RsnCapabilities(0)
1487                .with_mgmt_frame_protection_req(true)
1488                .with_mgmt_frame_protection_cap(true),
1489        );
1490        assert!(!s_rsne.is_valid_subset_of(&a_rsne).expect("expect Ok result"));
1491    }
1492
1493    #[test]
1494    fn test_authenticator_missing_required_mpfc() {
1495        let s_rsne = Rsne::wpa2_rsne_with_caps(
1496            RsnCapabilities(0)
1497                .with_mgmt_frame_protection_req(true)
1498                .with_mgmt_frame_protection_cap(true),
1499        );
1500        let a_rsne = Rsne::wpa2_rsne();
1501        assert!(!s_rsne.is_valid_subset_of(&a_rsne).expect("expect Ok result"));
1502    }
1503
1504    #[test]
1505    fn test_supplicant_has_invalid_mgmt_frame_protection_fields() {
1506        let s_rsne = Rsne::wpa2_rsne_with_caps(
1507            RsnCapabilities(0)
1508                .with_mgmt_frame_protection_req(true)
1509                .with_mgmt_frame_protection_cap(false),
1510        );
1511        // AP only cares about client's invalid setting if AP is mgmt frame protection capable
1512        let a_rsne =
1513            Rsne::wpa2_rsne_with_caps(RsnCapabilities(0).with_mgmt_frame_protection_cap(true));
1514
1515        let result = s_rsne.is_valid_subset_of(&a_rsne);
1516        assert!(result.is_err());
1517        assert_eq!(result.unwrap_err(), Error::InvalidSupplicantMgmtFrameProtection);
1518    }
1519
1520    #[test]
1521    fn test_authenticator_has_invalid_mgmt_frame_protection_fields() {
1522        // client only cares about AP's invalid setting if client is mgmt frame protection capable
1523        let s_rsne =
1524            Rsne::wpa2_rsne_with_caps(RsnCapabilities(0).with_mgmt_frame_protection_cap(true));
1525        let a_rsne = Rsne::wpa2_rsne_with_caps(
1526            RsnCapabilities(0)
1527                .with_mgmt_frame_protection_req(true)
1528                .with_mgmt_frame_protection_cap(false),
1529        );
1530
1531        let result = s_rsne.is_valid_subset_of(&a_rsne);
1532        assert!(result.is_err());
1533        assert_eq!(result.unwrap_err(), Error::InvalidAuthenticatorMgmtFrameProtection);
1534    }
1535
1536    #[test]
1537    fn test_write_until_version() {
1538        let expected_frame: Vec<u8> = vec![
1539            0x30, // element id
1540            0x02, // length
1541            0x01, 0x00, // version
1542        ];
1543        let buf = Rsne { version: VERSION, ..Default::default() }.into_bytes();
1544        assert_eq!(&buf[..], &expected_frame[..]);
1545    }
1546
1547    #[test]
1548    fn test_write_until_group_data() {
1549        let expected_frame: Vec<u8> = vec![
1550            0x30, // element id
1551            0x06, // length
1552            0x01, 0x00, // version
1553            0x00, 0x0f, 0xac, 0x04, // group data cipher suite
1554        ];
1555        let buf = Rsne {
1556            version: VERSION,
1557            group_data_cipher_suite: Some(cipher::Cipher::new_dot11(cipher::CCMP_128)),
1558            ..Default::default()
1559        }
1560        .into_bytes();
1561        assert_eq!(&buf[..], &expected_frame[..]);
1562    }
1563
1564    #[test]
1565    fn test_write_until_pairwise() {
1566        let expected_frame: Vec<u8> = vec![
1567            0x30, // element id
1568            12,   // length
1569            0x01, 0x00, // version
1570            0x00, 0x0f, 0xac, 0x04, // group data cipher suite
1571            0x01, 0x00, // pairwise suite count
1572            0x00, 0x0f, 0xac, 0x04, // pairwise cipher suite
1573        ];
1574        let buf = Rsne {
1575            version: VERSION,
1576            group_data_cipher_suite: Some(cipher::Cipher::new_dot11(cipher::CCMP_128)),
1577            pairwise_cipher_suites: vec![cipher::Cipher::new_dot11(cipher::CCMP_128)],
1578            ..Default::default()
1579        }
1580        .into_bytes();
1581        assert_eq!(&buf[..], &expected_frame[..]);
1582    }
1583
1584    #[test]
1585    fn test_write_until_akm() {
1586        let expected_frame: Vec<u8> = vec![
1587            0x30, // element id
1588            14,   // length
1589            0x01, 0x00, // version
1590            0x00, 0x0f, 0xac, 0x04, // group data cipher suite
1591            0x00, 0x00, // pairwise suite count
1592            0x01, 0x00, // pairwise suite count
1593            0x00, 0x0f, 0xac, 0x02, // pairwise cipher suite
1594        ];
1595        let buf = Rsne {
1596            version: VERSION,
1597            group_data_cipher_suite: Some(cipher::Cipher::new_dot11(cipher::CCMP_128)),
1598            akm_suites: vec![akm::Akm::new_dot11(akm::PSK)],
1599            ..Default::default()
1600        }
1601        .into_bytes();
1602        assert_eq!(&buf[..], &expected_frame[..]);
1603    }
1604
1605    #[test]
1606    fn test_write_until_rsn_capabilities() {
1607        let expected_frame: Vec<u8> = vec![
1608            0x30, // element id
1609            12,   // length
1610            0x01, 0x00, // version
1611            0x00, 0x0f, 0xac, 0x04, // group data cipher suite
1612            0x00, 0x00, // pairwise suite count
1613            0x00, 0x00, // akm suite count
1614            0xcd, 0xab, // rsn capabilities
1615        ];
1616        let buf = Rsne {
1617            version: VERSION,
1618            group_data_cipher_suite: Some(cipher::Cipher::new_dot11(cipher::CCMP_128)),
1619            rsn_capabilities: Some(RsnCapabilities(0xabcd)),
1620            ..Default::default()
1621        }
1622        .into_bytes();
1623        assert_eq!(&buf[..], &expected_frame[..]);
1624    }
1625
1626    static PMKID_VAL: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
1627
1628    #[test]
1629    fn test_write_until_pmkids() {
1630        let expected_frame: Vec<u8> = vec![
1631            0x30, // element id
1632            30,   // length
1633            0x01, 0x00, // version
1634            0x00, 0x0f, 0xac, 0x04, // group data cipher suite
1635            0x00, 0x00, // pairwise suite count
1636            0x00, 0x00, // akm suite count
1637            0xcd, 0xab, // rsn capabilities
1638            0x01, 0x00, // pmkid count
1639            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, // pmkid
1640        ];
1641        let buf = Rsne {
1642            version: VERSION,
1643            group_data_cipher_suite: Some(cipher::Cipher::new_dot11(cipher::CCMP_128)),
1644            rsn_capabilities: Some(RsnCapabilities(0xabcd)),
1645            pmkids: vec![Bytes::from_static(&PMKID_VAL[..])],
1646            ..Default::default()
1647        }
1648        .into_bytes();
1649        assert_eq!(&buf[..], &expected_frame[..]);
1650    }
1651
1652    #[test]
1653    fn test_write_until_group_mgmt() {
1654        let expected_frame: Vec<u8> = vec![
1655            0x30, // element id
1656            18,   // length
1657            0x01, 0x00, // version
1658            0x00, 0x0f, 0xac, 0x04, // group data cipher suite
1659            0x00, 0x00, // pairwise suite count
1660            0x00, 0x00, // akm suite count
1661            0xcd, 0xab, // rsn capabilities
1662            0x00, 0x00, // pmkids count
1663            0x00, 0x0f, 0xac, 0x06, // group management cipher suite
1664        ];
1665        let buf = Rsne {
1666            version: VERSION,
1667            group_data_cipher_suite: Some(cipher::Cipher::new_dot11(cipher::CCMP_128)),
1668            rsn_capabilities: Some(RsnCapabilities(0xabcd)),
1669            group_mgmt_cipher_suite: Some(cipher::Cipher::new_dot11(cipher::BIP_CMAC_128)),
1670            ..Default::default()
1671        }
1672        .into_bytes();
1673        assert_eq!(&buf[..], &expected_frame[..]);
1674    }
1675
1676    #[test]
1677    fn test_end_write_on_missing_caps() {
1678        let expected_frame: Vec<u8> = vec![
1679            0x30, // element id
1680            0x06, // length
1681            0x01, 0x00, // version
1682            0x00, 0x0f, 0xac,
1683            0x04, // group data cipher suite
1684                  // We don't write group management suite because caps are missing.
1685        ];
1686        let buf = Rsne {
1687            version: VERSION,
1688            group_data_cipher_suite: Some(cipher::Cipher::new_dot11(cipher::CCMP_128)),
1689            rsn_capabilities: None,
1690            group_mgmt_cipher_suite: Some(cipher::Cipher::new_dot11(cipher::BIP_CMAC_128)),
1691            ..Default::default()
1692        }
1693        .into_bytes();
1694        assert_eq!(&buf[..], &expected_frame[..]);
1695    }
1696}