wlan_common/ie/rsn/
akm.rs1use super::suite_selector;
6use crate::ie::rsn::suite_selector::OUI;
7use crate::organization::Oui;
8use std::fmt;
9
10macro_rules! return_none_if_unknown_algo {
11 ($e:expr) => {
12 if !$e.has_known_algorithm() {
13 return None;
14 }
15 };
16}
17
18pub const EAP: u8 = 1;
21pub const PSK: u8 = 2;
22pub const FT_EAP: u8 = 3;
23pub const FT_PSK: u8 = 4;
24pub const EAP_SHA256: u8 = 5;
25pub const PSK_SHA256: u8 = 6;
26pub const TDLS: u8 = 7;
27pub const SAE: u8 = 8;
28pub const FT_SAE: u8 = 9;
29pub const AP_PEERKEY: u8 = 10;
30pub const EAP_SUITEB: u8 = 11;
31pub const EAP_SUITEB_SHA384: u8 = 12;
32pub const FT_EAP_SHA384: u8 = 13;
33pub const OWE: u8 = 18;
35pub const AKM_EAP: Akm = Akm::new_dot11(EAP);
39pub const AKM_PSK: Akm = Akm::new_dot11(PSK);
40pub const AKM_FT_PSK: Akm = Akm::new_dot11(FT_PSK);
41pub const AKM_SAE: Akm = Akm::new_dot11(SAE);
42pub const AKM_OWE: Akm = Akm::new_dot11(OWE);
43
44#[derive(PartialOrd, PartialEq, Eq, Clone)]
45pub struct Akm {
46 pub oui: Oui,
47 pub suite_type: u8,
48}
49
50impl Akm {
51 pub const fn new_dot11(suite_type: u8) -> Self {
54 Akm { oui: OUI, suite_type }
55 }
56
57 pub fn has_known_algorithm(&self) -> bool {
59 if self.is_reserved() || self.is_vendor_specific() {
60 self.oui == Oui::MSFT && self.suite_type == PSK
62 } else {
63 self.suite_type != 7 && self.suite_type != 10
64 }
65 }
66
67 pub fn is_vendor_specific(&self) -> bool {
68 !self.oui.eq(&OUI)
70 }
71
72 pub fn is_reserved(&self) -> bool {
73 !((EAP..=FT_EAP_SHA384).contains(&self.suite_type)
76 || self.suite_type == OWE
77 || self.is_vendor_specific())
78 }
79
80 pub fn mic_bytes(&self) -> Option<u16> {
81 return_none_if_unknown_algo!(self);
82
83 match self.suite_type {
86 1..=11 | 18 => Some(16),
87 12 | 13 => Some(24),
88 _ => None,
89 }
90 }
91
92 pub fn kck_bytes(&self) -> Option<u16> {
93 return_none_if_unknown_algo!(self);
94
95 match self.suite_type {
98 1..=11 | 18 => Some(16),
99 12 | 13 => Some(24),
100 _ => None,
101 }
102 }
103
104 pub fn kek_bytes(&self) -> Option<u16> {
105 return_none_if_unknown_algo!(self);
106
107 match self.suite_type {
110 1..=11 | 18 => Some(16),
111 12 | 13 => Some(32),
112 _ => None,
113 }
114 }
115
116 pub fn pmk_bytes(&self) -> Option<u16> {
117 return_none_if_unknown_algo!(self);
118
119 match self.suite_type {
122 1..=11 | 13 | 18 => Some(32),
123 12 => Some(48),
124 _ => None,
125 }
126 }
127
128 #[deprecated(note = "use `kck_bytes` instead")]
129 pub fn kck_bits(&self) -> Option<u16> {
130 return_none_if_unknown_algo!(self);
131
132 match self.suite_type {
135 1..=11 | 18 => Some(128),
136 12 | 13 => Some(192),
137 _ => None,
138 }
139 }
140
141 #[deprecated(note = "use `kek_bytes` instead")]
142 pub fn kek_bits(&self) -> Option<u16> {
143 return_none_if_unknown_algo!(self);
144
145 match self.suite_type {
148 1..=11 | 18 => Some(128),
149 12 | 13 => Some(256),
150 _ => None,
151 }
152 }
153
154 #[deprecated(note = "use `pmk_bytes` instead")]
155 pub fn pmk_bits(&self) -> Option<u16> {
156 return_none_if_unknown_algo!(self);
157
158 match self.suite_type {
161 1..=11 | 13 | 18 => Some(256),
162 12 => Some(384),
163 _ => None,
164 }
165 }
166}
167
168impl suite_selector::Factory for Akm {
169 type Suite = Akm;
170
171 fn new(oui: Oui, suite_type: u8) -> Self::Suite {
172 Akm { oui, suite_type }
173 }
174}
175
176impl fmt::Debug for Akm {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 write!(f, "{:02X}-{:02X}-{:02X}:{}", self.oui[0], self.oui[1], self.oui[2], self.suite_type)
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185
186 #[test]
187 fn test_new_dot11() {
188 let psk = AKM_PSK;
189 assert!(!psk.is_vendor_specific());
190 assert!(psk.has_known_algorithm());
191 assert!(!psk.is_reserved());
192 }
193
194 #[test]
195 fn test_msft_akm() {
196 let psk = Akm { oui: Oui::MSFT, suite_type: PSK };
197 assert!(psk.is_vendor_specific());
198 assert!(psk.has_known_algorithm());
199 assert!(!psk.is_reserved());
200 }
201}