wlan_common/ie/rsn/
cipher.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_usage {
11 ($e:expr) => {
12 if !$e.has_known_usage() {
13 return None;
14 }
15 };
16}
17
18pub const GROUP_CIPHER_SUITE: u8 = 0;
20pub const WEP_40: u8 = 1;
21pub const TKIP: u8 = 2;
22pub const CCMP_128: u8 = 4;
24pub const WEP_104: u8 = 5;
25pub const BIP_CMAC_128: u8 = 6;
26pub const GROUP_ADDRESSED_TRAFFIC_NOT_ALLOWED: u8 = 7;
27pub const GCMP_128: u8 = 8;
28pub const GCMP_256: u8 = 9;
29pub const CCMP_256: u8 = 10;
30pub const BIP_GMAC_128: u8 = 11;
31pub const BIP_GMAC_256: u8 = 12;
32pub const BIP_CMAC_256: u8 = 13;
33pub const CIPHER_TKIP: Cipher = Cipher::new_dot11(TKIP);
37pub const CIPHER_CCMP_128: Cipher = Cipher::new_dot11(CCMP_128);
38pub const CIPHER_BIP_CMAC_128: Cipher = Cipher::new_dot11(BIP_CMAC_128);
39pub const CIPHER_GCMP_256: Cipher = Cipher::new_dot11(GCMP_256);
40pub const CIPHER_BIP_CMAC_256: Cipher = Cipher::new_dot11(BIP_CMAC_256);
41
42#[derive(PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
43pub struct Cipher {
44 pub oui: Oui,
45 pub suite_type: u8,
46}
47
48impl Cipher {
49 pub const fn new_dot11(suite_type: u8) -> Self {
52 Cipher { oui: OUI, suite_type }
53 }
54
55 pub fn has_known_usage(&self) -> bool {
58 if self.is_vendor_specific() {
59 self.oui == Oui::MSFT && (self.suite_type == TKIP || self.suite_type == CCMP_128)
61 } else {
62 !self.is_reserved()
63 }
64 }
65
66 pub fn is_vendor_specific(&self) -> bool {
67 !self.oui.eq(&OUI)
69 }
70
71 pub fn is_reserved(&self) -> bool {
72 (self.suite_type == 3 || self.suite_type >= 14) && !self.is_vendor_specific()
74 }
75
76 pub fn is_enhanced(&self) -> bool {
77 if !self.has_known_usage() {
79 false
80 } else {
81 match self.suite_type {
82 GROUP_CIPHER_SUITE | WEP_40 | WEP_104 | GROUP_ADDRESSED_TRAFFIC_NOT_ALLOWED => {
83 false
84 }
85 _ => true,
86 }
87 }
88 }
89
90 pub fn supports_gtk(&self) -> Option<bool> {
91 return_none_if_unknown_usage!(self);
92
93 match self.suite_type {
95 1..=5 | 8..=10 => Some(true),
96 0 | 6 | 11..=13 => Some(false),
97 _ => None,
98 }
99 }
100
101 pub fn supports_ptk(&self) -> Option<bool> {
102 return_none_if_unknown_usage!(self);
103
104 match self.suite_type {
106 0 | 2..=4 | 8..=10 => Some(true),
107 1 | 5 | 6 | 11..=13 => Some(false),
108 _ => None,
109 }
110 }
111
112 pub fn supports_igtk(&self) -> Option<bool> {
113 return_none_if_unknown_usage!(self);
114
115 match self.suite_type {
117 6 | 11..=13 => Some(true),
118 0 | 1..=5 | 8..=10 => Some(false),
119 _ => None,
120 }
121 }
122
123 pub fn tk_bytes(&self) -> Option<u8> {
124 return_none_if_unknown_usage!(self);
125
126 match self.suite_type {
128 1 => Some(5),
129 5 => Some(13),
130 4 | 6 | 8 | 11 => Some(16),
131 2 | 9 | 10 | 12 | 13 => Some(32),
132 _ => None,
133 }
134 }
135
136 pub fn tk_bits(&self) -> Option<u16> {
137 self.tk_bytes().map(|x| 8 * u16::from(x))
138 }
139}
140
141impl suite_selector::Factory for Cipher {
142 type Suite = Cipher;
143
144 fn new(oui: Oui, suite_type: u8) -> Self::Suite {
145 Cipher { oui, suite_type }
146 }
147}
148
149impl fmt::Debug for Cipher {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 write!(f, "{:02X}-{:02X}-{:02X}:{}", self.oui[0], self.oui[1], self.oui[2], self.suite_type)
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn test_new_dot11() {
161 let ccmp = CIPHER_CCMP_128;
162 assert!(!ccmp.is_vendor_specific());
163 assert!(ccmp.has_known_usage());
164 assert!(ccmp.is_enhanced());
165 assert!(!ccmp.is_reserved());
166 }
167}