wlan_common/ie/rsn/
suite_filter.rs1use super::akm::{self, Akm, AKM_EAP};
6use super::cipher::{self, Cipher, CIPHER_BIP_CMAC_128, CIPHER_CCMP_128};
7use crate::ie;
8
9pub const DEFAULT_GROUP_DATA_CIPHER: Cipher = CIPHER_CCMP_128;
13
14pub const DEFAULT_PAIRWISE_CIPHER: [Cipher; 1] = [CIPHER_CCMP_128];
18
19pub const DEFAULT_AKM: [Akm; 1] = [AKM_EAP];
23
24pub const DEFAULT_GROUP_MGMT_CIPHER: Cipher = CIPHER_BIP_CMAC_128;
28
29pub struct SuiteFilter<'a> {
30 known_group_data_ciphers: &'a [u8],
31 known_akms: &'a [u8],
32 known_pairwise_ciphers: &'a [u8],
33 required_group_mgmt_cipher: Option<u8>,
34}
35
36impl<'a> SuiteFilter<'a> {
37 pub fn is_satisfied(&self, rsne: &ie::rsn::rsne::Rsne) -> bool {
38 let group_data_cipher =
39 rsne.group_data_cipher_suite.as_ref().unwrap_or(&DEFAULT_GROUP_DATA_CIPHER);
40 let group_data_satisfied = group_data_cipher.has_known_usage()
41 && self.known_group_data_ciphers.contains(&group_data_cipher.suite_type);
42
43 let akms = if rsne.akm_suites.is_empty() { &DEFAULT_AKM[..] } else { &rsne.akm_suites[..] };
44 let akm_satisfied =
45 akms.iter().any(|a| a.has_known_algorithm() && self.known_akms.contains(&a.suite_type));
46
47 let pairwise_ciphers = if rsne.pairwise_cipher_suites.is_empty() {
48 &DEFAULT_PAIRWISE_CIPHER[..]
49 } else {
50 &rsne.pairwise_cipher_suites[..]
51 };
52 let pairwise_satisfied = pairwise_ciphers
53 .iter()
54 .any(|c| c.has_known_usage() && self.known_pairwise_ciphers.contains(&c.suite_type));
55
56 let group_mgmt_cipher =
57 rsne.group_mgmt_cipher_suite.as_ref().unwrap_or(&DEFAULT_GROUP_MGMT_CIPHER);
58 let group_mgmt_satisfied = self
59 .required_group_mgmt_cipher
60 .map(|s| group_mgmt_cipher.suite_type == s)
61 .unwrap_or(true);
62
63 group_data_satisfied && akm_satisfied && pairwise_satisfied && group_mgmt_satisfied
64 }
65}
66
67pub const WPA1_PERSONAL: SuiteFilter<'_> = SuiteFilter {
69 known_group_data_ciphers: &[cipher::TKIP, cipher::CCMP_128],
70 known_akms: &[akm::PSK],
71 known_pairwise_ciphers: &[cipher::TKIP, cipher::CCMP_128],
72 required_group_mgmt_cipher: None,
73};
74
75pub const WPA2_PERSONAL_TKIP_ONLY: SuiteFilter<'_> = SuiteFilter {
76 known_group_data_ciphers: &[cipher::TKIP],
77 known_akms: &[akm::PSK],
78 known_pairwise_ciphers: &[cipher::TKIP],
79 required_group_mgmt_cipher: None,
80};
81
82pub const WPA2_PERSONAL: SuiteFilter<'_> = SuiteFilter {
88 known_group_data_ciphers: &[cipher::CCMP_128, cipher::TKIP],
89 known_akms: &[akm::PSK, akm::FT_PSK, akm::PSK_SHA256],
94 known_pairwise_ciphers: &[cipher::CCMP_128],
101 required_group_mgmt_cipher: None,
102};
103
104pub const WPA3_PERSONAL: SuiteFilter<'_> = SuiteFilter {
106 known_group_data_ciphers: &[cipher::CCMP_128, cipher::TKIP],
107 known_akms: &[akm::SAE],
111 known_pairwise_ciphers: &[cipher::CCMP_128],
112 required_group_mgmt_cipher: None,
113};
114
115pub const WPA2_ENTERPRISE: SuiteFilter<'_> = SuiteFilter {
119 known_group_data_ciphers: &[cipher::CCMP_128],
120 known_akms: &[akm::EAP, akm::FT_EAP, akm::EAP_SHA256],
125 known_pairwise_ciphers: &[cipher::CCMP_128],
126 required_group_mgmt_cipher: None,
127};
128
129pub const WPA3_ENTERPRISE_192_BIT: SuiteFilter<'_> = SuiteFilter {
131 known_group_data_ciphers: &[cipher::GCMP_256],
132 known_akms: &[akm::EAP_SUITEB_SHA384],
133 known_pairwise_ciphers: &[cipher::GCMP_256],
134 required_group_mgmt_cipher: Some(cipher::BIP_GMAC_256),
135};
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use crate::test_utils::fake_frames::{fake_wpa2_rsne, fake_wpa3_enterprise_192_bit_rsne};
141
142 #[test]
143 fn test_suite_filter() {
144 let wpa2_rsne = ie::rsn::rsne::from_bytes(&fake_wpa2_rsne()[..]).unwrap().1;
145 assert!(WPA2_PERSONAL.is_satisfied(&wpa2_rsne));
146 assert!(!WPA3_PERSONAL.is_satisfied(&wpa2_rsne));
147 }
148
149 #[test]
150 fn test_suite_filter_with_required_group_mgmt() {
151 let mut wpa3_ent_rsne =
152 ie::rsn::rsne::from_bytes(&fake_wpa3_enterprise_192_bit_rsne()[..]).unwrap().1;
153 assert!(WPA3_ENTERPRISE_192_BIT.is_satisfied(&wpa3_ent_rsne));
154 wpa3_ent_rsne.group_mgmt_cipher_suite = None;
155 assert!(!WPA3_ENTERPRISE_192_BIT.is_satisfied(&wpa3_ent_rsne));
156 }
157
158 #[test]
159 fn test_suite_filter_empty_rsne() {
160 let rsne = ie::rsn::rsne::Rsne::default();
161 assert!(WPA2_ENTERPRISE.is_satisfied(&rsne));
162 assert!(!WPA2_PERSONAL.is_satisfied(&rsne));
163 }
164}