wlan_common/ie/rsn/
akm.rs
1use 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 AKM_EAP: Akm = Akm::new_dot11(EAP);
37pub const AKM_PSK: Akm = Akm::new_dot11(PSK);
38pub const AKM_FT_PSK: Akm = Akm::new_dot11(FT_PSK);
39pub const AKM_SAE: Akm = Akm::new_dot11(SAE);
40
41#[derive(PartialOrd, PartialEq, Eq, Clone)]
42pub struct Akm {
43 pub oui: Oui,
44 pub suite_type: u8,
45}
46
47impl Akm {
48 pub const fn new_dot11(suite_type: u8) -> Self {
51 Akm { oui: OUI, suite_type }
52 }
53
54 pub fn has_known_algorithm(&self) -> bool {
56 if self.is_reserved() || self.is_vendor_specific() {
57 self.oui == Oui::MSFT && self.suite_type == PSK
59 } else {
60 self.suite_type != 7 && self.suite_type != 10
61 }
62 }
63
64 pub fn is_vendor_specific(&self) -> bool {
65 !self.oui.eq(&OUI)
67 }
68
69 pub fn is_reserved(&self) -> bool {
70 (self.suite_type == 0 || self.suite_type >= 14) && !self.is_vendor_specific()
72 }
73
74 pub fn mic_bytes(&self) -> Option<u16> {
75 return_none_if_unknown_algo!(self);
76
77 match self.suite_type {
79 1..=11 => Some(16),
80 12 | 13 => Some(24),
81 _ => None,
82 }
83 }
84
85 pub fn kck_bytes(&self) -> Option<u16> {
86 return_none_if_unknown_algo!(self);
87
88 match self.suite_type {
90 1..=11 => Some(16),
91 12 | 13 => Some(24),
92 _ => None,
93 }
94 }
95
96 pub fn kek_bytes(&self) -> Option<u16> {
97 return_none_if_unknown_algo!(self);
98
99 match self.suite_type {
101 1..=11 => Some(16),
102 12 | 13 => Some(32),
103 _ => None,
104 }
105 }
106
107 pub fn pmk_bytes(&self) -> Option<u16> {
108 return_none_if_unknown_algo!(self);
109
110 match self.suite_type {
112 1..=11 | 13 => Some(32),
113 12 => Some(48),
114 _ => None,
115 }
116 }
117
118 #[deprecated(note = "use `kck_bytes` instead")]
119 pub fn kck_bits(&self) -> Option<u16> {
120 return_none_if_unknown_algo!(self);
121
122 match self.suite_type {
124 1..=11 => Some(128),
125 12 | 13 => Some(192),
126 _ => None,
127 }
128 }
129
130 #[deprecated(note = "use `kek_bytes` instead")]
131 pub fn kek_bits(&self) -> Option<u16> {
132 return_none_if_unknown_algo!(self);
133
134 match self.suite_type {
136 1..=11 => Some(128),
137 12 | 13 => Some(256),
138 _ => None,
139 }
140 }
141
142 #[deprecated(note = "use `pmk_bytes` instead")]
143 pub fn pmk_bits(&self) -> Option<u16> {
144 return_none_if_unknown_algo!(self);
145
146 match self.suite_type {
148 1..=11 | 13 => Some(256),
149 12 => Some(384),
150 _ => None,
151 }
152 }
153}
154
155impl suite_selector::Factory for Akm {
156 type Suite = Akm;
157
158 fn new(oui: Oui, suite_type: u8) -> Self::Suite {
159 Akm { oui, suite_type }
160 }
161}
162
163impl fmt::Debug for Akm {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 write!(f, "{:02X}-{:02X}-{:02X}:{}", self.oui[0], self.oui[1], self.oui[2], self.suite_type)
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn test_new_dot11() {
175 let psk = AKM_PSK;
176 assert!(!psk.is_vendor_specific());
177 assert!(psk.has_known_algorithm());
178 assert!(!psk.is_reserved());
179 }
180
181 #[test]
182 fn test_msft_akm() {
183 let psk = Akm { oui: Oui::MSFT, suite_type: PSK };
184 assert!(psk.is_vendor_specific());
185 assert!(psk.has_known_algorithm());
186 assert!(!psk.is_reserved());
187 }
188}