1use crate::layer::field::FieldError;
9
10pub const WEP_HEADER_LEN: usize = 4;
16
17pub const WEP_TRAILER_LEN: usize = 4;
19
20#[derive(Debug, Clone)]
35pub struct Dot11WEP {
36 pub offset: usize,
37}
38
39impl Dot11WEP {
40 #[must_use]
41 pub fn new(offset: usize) -> Self {
42 Self { offset }
43 }
44
45 pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
47 if buf.len() < offset + WEP_HEADER_LEN {
48 return Err(FieldError::BufferTooShort {
49 offset,
50 need: WEP_HEADER_LEN,
51 have: buf.len().saturating_sub(offset),
52 });
53 }
54 Ok(())
55 }
56
57 pub fn iv(&self, buf: &[u8]) -> Result<[u8; 3], FieldError> {
59 if buf.len() < self.offset + WEP_HEADER_LEN {
60 return Err(FieldError::BufferTooShort {
61 offset: self.offset,
62 need: WEP_HEADER_LEN,
63 have: buf.len().saturating_sub(self.offset),
64 });
65 }
66 Ok([buf[self.offset], buf[self.offset + 1], buf[self.offset + 2]])
67 }
68
69 pub fn iv_u32(&self, buf: &[u8]) -> Result<u32, FieldError> {
71 let iv = self.iv(buf)?;
72 Ok((u32::from(iv[0]) << 16) | (u32::from(iv[1]) << 8) | u32::from(iv[2]))
73 }
74
75 pub fn key_id(&self, buf: &[u8]) -> Result<u8, FieldError> {
77 if buf.len() < self.offset + WEP_HEADER_LEN {
78 return Err(FieldError::BufferTooShort {
79 offset: self.offset,
80 need: WEP_HEADER_LEN,
81 have: buf.len().saturating_sub(self.offset),
82 });
83 }
84 Ok((buf[self.offset + 3] >> 6) & 0x03)
85 }
86
87 pub fn key_id_byte(&self, buf: &[u8]) -> Result<u8, FieldError> {
89 if buf.len() < self.offset + WEP_HEADER_LEN {
90 return Err(FieldError::BufferTooShort {
91 offset: self.offset,
92 need: WEP_HEADER_LEN,
93 have: buf.len().saturating_sub(self.offset),
94 });
95 }
96 Ok(buf[self.offset + 3])
97 }
98
99 pub fn icv(&self, buf: &[u8], frame_end: usize) -> Result<u32, FieldError> {
102 if frame_end < WEP_TRAILER_LEN || buf.len() < frame_end {
103 return Err(FieldError::BufferTooShort {
104 offset: frame_end.saturating_sub(WEP_TRAILER_LEN),
105 need: WEP_TRAILER_LEN,
106 have: 0,
107 });
108 }
109 let off = frame_end - WEP_TRAILER_LEN;
110 Ok(u32::from_le_bytes([
111 buf[off],
112 buf[off + 1],
113 buf[off + 2],
114 buf[off + 3],
115 ]))
116 }
117
118 pub fn encrypted_data<'a>(
120 &self,
121 buf: &'a [u8],
122 frame_end: usize,
123 ) -> Result<&'a [u8], FieldError> {
124 let start = self.offset + WEP_HEADER_LEN;
125 let end = frame_end.saturating_sub(WEP_TRAILER_LEN);
126 if start > end || buf.len() < frame_end {
127 return Err(FieldError::BufferTooShort {
128 offset: start,
129 need: 0,
130 have: 0,
131 });
132 }
133 Ok(&buf[start..end])
134 }
135
136 #[must_use]
138 pub fn header_len(&self) -> usize {
139 WEP_HEADER_LEN
140 }
141
142 #[must_use]
144 pub fn trailer_len(&self) -> usize {
145 WEP_TRAILER_LEN
146 }
147
148 #[must_use]
150 pub fn build_header(iv: [u8; 3], key_id: u8) -> Vec<u8> {
151 vec![iv[0], iv[1], iv[2], (key_id & 0x03) << 6]
152 }
153
154 #[must_use]
156 pub fn build_icv(icv: u32) -> Vec<u8> {
157 icv.to_le_bytes().to_vec()
158 }
159}
160
161pub const TKIP_HEADER_SHORT: usize = 4;
167
168pub const TKIP_HEADER_LONG: usize = 8;
170
171pub const TKIP_ICV_LEN: usize = 4;
175
176#[derive(Debug, Clone)]
194pub struct Dot11TKIP {
195 pub offset: usize,
196}
197
198impl Dot11TKIP {
199 #[must_use]
200 pub fn new(offset: usize) -> Self {
201 Self { offset }
202 }
203
204 pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
206 if buf.len() < offset + TKIP_HEADER_SHORT {
207 return Err(FieldError::BufferTooShort {
208 offset,
209 need: TKIP_HEADER_SHORT,
210 have: buf.len().saturating_sub(offset),
211 });
212 }
213 Ok(())
214 }
215
216 pub fn tsc1(&self, buf: &[u8]) -> Result<u8, FieldError> {
218 if buf.len() <= self.offset {
219 return Err(FieldError::BufferTooShort {
220 offset: self.offset,
221 need: 1,
222 have: 0,
223 });
224 }
225 Ok(buf[self.offset])
226 }
227
228 pub fn wep_seed(&self, buf: &[u8]) -> Result<u8, FieldError> {
230 if buf.len() <= self.offset + 1 {
231 return Err(FieldError::BufferTooShort {
232 offset: self.offset + 1,
233 need: 1,
234 have: 0,
235 });
236 }
237 Ok(buf[self.offset + 1])
238 }
239
240 pub fn tsc0(&self, buf: &[u8]) -> Result<u8, FieldError> {
242 if buf.len() <= self.offset + 2 {
243 return Err(FieldError::BufferTooShort {
244 offset: self.offset + 2,
245 need: 1,
246 have: 0,
247 });
248 }
249 Ok(buf[self.offset + 2])
250 }
251
252 pub fn ext_iv(&self, buf: &[u8]) -> Result<bool, FieldError> {
254 if buf.len() < self.offset + TKIP_HEADER_SHORT {
255 return Err(FieldError::BufferTooShort {
256 offset: self.offset,
257 need: TKIP_HEADER_SHORT,
258 have: buf.len().saturating_sub(self.offset),
259 });
260 }
261 Ok(buf[self.offset + 3] & 0x20 != 0)
262 }
263
264 pub fn key_id(&self, buf: &[u8]) -> Result<u8, FieldError> {
266 if buf.len() < self.offset + TKIP_HEADER_SHORT {
267 return Err(FieldError::BufferTooShort {
268 offset: self.offset,
269 need: TKIP_HEADER_SHORT,
270 have: buf.len().saturating_sub(self.offset),
271 });
272 }
273 Ok((buf[self.offset + 3] >> 6) & 0x03)
274 }
275
276 pub fn tsc_high(&self, buf: &[u8]) -> Result<[u8; 4], FieldError> {
278 if buf.len() < self.offset + TKIP_HEADER_LONG {
279 return Err(FieldError::BufferTooShort {
280 offset: self.offset + 4,
281 need: 4,
282 have: buf.len().saturating_sub(self.offset + 4),
283 });
284 }
285 Ok([
286 buf[self.offset + 4],
287 buf[self.offset + 5],
288 buf[self.offset + 6],
289 buf[self.offset + 7],
290 ])
291 }
292
293 pub fn tsc(&self, buf: &[u8]) -> Result<u64, FieldError> {
296 let tsc0 = u64::from(self.tsc0(buf)?);
297 let tsc1 = u64::from(self.tsc1(buf)?);
298 let high = self.tsc_high(buf)?;
299 let tsc2 = u64::from(high[0]);
300 let tsc3 = u64::from(high[1]);
301 let tsc4 = u64::from(high[2]);
302 let tsc5 = u64::from(high[3]);
303 Ok(tsc0 | (tsc1 << 8) | (tsc2 << 16) | (tsc3 << 24) | (tsc4 << 32) | (tsc5 << 40))
304 }
305
306 #[must_use]
308 pub fn header_len(&self, buf: &[u8]) -> usize {
309 if self.ext_iv(buf).unwrap_or(false) {
310 TKIP_HEADER_LONG
311 } else {
312 TKIP_HEADER_SHORT
313 }
314 }
315
316 #[must_use]
318 pub fn trailer_len(&self) -> usize {
319 TKIP_ICV_LEN
320 }
321
322 #[must_use]
324 pub fn build_header(tsc: u64, key_id: u8) -> Vec<u8> {
325 let tsc0 = (tsc & 0xFF) as u8;
326 let tsc1 = ((tsc >> 8) & 0xFF) as u8;
327 let tsc2 = ((tsc >> 16) & 0xFF) as u8;
328 let tsc3 = ((tsc >> 24) & 0xFF) as u8;
329 let tsc4 = ((tsc >> 32) & 0xFF) as u8;
330 let tsc5 = ((tsc >> 40) & 0xFF) as u8;
331 let wep_seed = (tsc1 | 0x20) & 0x7F;
333 let key_id_byte = ((key_id & 0x03) << 6) | 0x20; vec![tsc1, wep_seed, tsc0, key_id_byte, tsc2, tsc3, tsc4, tsc5]
335 }
336}
337
338pub const CCMP_HEADER_LEN: usize = 8;
344
345pub const CCMP_MIC_LEN: usize = 8;
347
348#[derive(Debug, Clone)]
368pub struct Dot11CCMP {
369 pub offset: usize,
370}
371
372impl Dot11CCMP {
373 #[must_use]
374 pub fn new(offset: usize) -> Self {
375 Self { offset }
376 }
377
378 pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
380 if buf.len() < offset + CCMP_HEADER_LEN {
381 return Err(FieldError::BufferTooShort {
382 offset,
383 need: CCMP_HEADER_LEN,
384 have: buf.len().saturating_sub(offset),
385 });
386 }
387 Ok(())
388 }
389
390 pub fn pn0(&self, buf: &[u8]) -> Result<u8, FieldError> {
392 if buf.len() <= self.offset {
393 return Err(FieldError::BufferTooShort {
394 offset: self.offset,
395 need: 1,
396 have: 0,
397 });
398 }
399 Ok(buf[self.offset])
400 }
401
402 pub fn pn1(&self, buf: &[u8]) -> Result<u8, FieldError> {
404 if buf.len() <= self.offset + 1 {
405 return Err(FieldError::BufferTooShort {
406 offset: self.offset + 1,
407 need: 1,
408 have: 0,
409 });
410 }
411 Ok(buf[self.offset + 1])
412 }
413
414 pub fn reserved(&self, buf: &[u8]) -> Result<u8, FieldError> {
416 if buf.len() <= self.offset + 2 {
417 return Err(FieldError::BufferTooShort {
418 offset: self.offset + 2,
419 need: 1,
420 have: 0,
421 });
422 }
423 Ok(buf[self.offset + 2])
424 }
425
426 pub fn key_id(&self, buf: &[u8]) -> Result<u8, FieldError> {
428 if buf.len() < self.offset + CCMP_HEADER_LEN {
429 return Err(FieldError::BufferTooShort {
430 offset: self.offset,
431 need: CCMP_HEADER_LEN,
432 have: buf.len().saturating_sub(self.offset),
433 });
434 }
435 Ok((buf[self.offset + 3] >> 6) & 0x03)
436 }
437
438 pub fn ext_iv(&self, buf: &[u8]) -> Result<bool, FieldError> {
440 if buf.len() < self.offset + CCMP_HEADER_LEN {
441 return Err(FieldError::BufferTooShort {
442 offset: self.offset,
443 need: CCMP_HEADER_LEN,
444 have: buf.len().saturating_sub(self.offset),
445 });
446 }
447 Ok(buf[self.offset + 3] & 0x20 != 0)
448 }
449
450 pub fn pn_high(&self, buf: &[u8]) -> Result<[u8; 4], FieldError> {
452 if buf.len() < self.offset + CCMP_HEADER_LEN {
453 return Err(FieldError::BufferTooShort {
454 offset: self.offset + 4,
455 need: 4,
456 have: buf.len().saturating_sub(self.offset + 4),
457 });
458 }
459 Ok([
460 buf[self.offset + 4],
461 buf[self.offset + 5],
462 buf[self.offset + 6],
463 buf[self.offset + 7],
464 ])
465 }
466
467 pub fn pn(&self, buf: &[u8]) -> Result<u64, FieldError> {
470 let pn0 = u64::from(self.pn0(buf)?);
471 let pn1 = u64::from(self.pn1(buf)?);
472 let high = self.pn_high(buf)?;
473 let pn2 = u64::from(high[0]);
474 let pn3 = u64::from(high[1]);
475 let pn4 = u64::from(high[2]);
476 let pn5 = u64::from(high[3]);
477 Ok(pn0 | (pn1 << 8) | (pn2 << 16) | (pn3 << 24) | (pn4 << 32) | (pn5 << 40))
478 }
479
480 pub fn mic(&self, buf: &[u8], frame_end: usize) -> Result<[u8; 8], FieldError> {
482 if frame_end < CCMP_MIC_LEN || buf.len() < frame_end {
483 return Err(FieldError::BufferTooShort {
484 offset: frame_end.saturating_sub(CCMP_MIC_LEN),
485 need: CCMP_MIC_LEN,
486 have: 0,
487 });
488 }
489 let off = frame_end - CCMP_MIC_LEN;
490 let mut mic = [0u8; 8];
491 mic.copy_from_slice(&buf[off..frame_end]);
492 Ok(mic)
493 }
494
495 #[must_use]
497 pub fn header_len(&self) -> usize {
498 CCMP_HEADER_LEN
499 }
500
501 #[must_use]
503 pub fn trailer_len(&self) -> usize {
504 CCMP_MIC_LEN
505 }
506
507 #[must_use]
509 pub fn build_header(pn: u64, key_id: u8) -> Vec<u8> {
510 let pn0 = (pn & 0xFF) as u8;
511 let pn1 = ((pn >> 8) & 0xFF) as u8;
512 let pn2 = ((pn >> 16) & 0xFF) as u8;
513 let pn3 = ((pn >> 24) & 0xFF) as u8;
514 let pn4 = ((pn >> 32) & 0xFF) as u8;
515 let pn5 = ((pn >> 40) & 0xFF) as u8;
516 let key_id_byte = ((key_id & 0x03) << 6) | 0x20; vec![pn0, pn1, 0x00, key_id_byte, pn2, pn3, pn4, pn5]
518 }
519
520 #[must_use]
522 pub fn build_mic(mic: [u8; 8]) -> Vec<u8> {
523 mic.to_vec()
524 }
525}
526
527#[derive(Debug, Clone, Copy, PartialEq, Eq)]
533pub enum SecurityType {
534 WEP,
536 TKIP,
538 CCMP,
540}
541
542#[must_use]
552pub fn detect_security_type(buf: &[u8], offset: usize) -> Option<SecurityType> {
553 if buf.len() < offset + 4 {
554 return None;
555 }
556 let ext_iv = buf[offset + 3] & 0x20 != 0;
557 if !ext_iv {
558 return Some(SecurityType::WEP);
559 }
560 if buf[offset + 2] == 0 {
563 Some(SecurityType::CCMP)
564 } else {
565 Some(SecurityType::TKIP)
566 }
567}
568
569#[cfg(test)]
574mod tests {
575 use super::*;
576
577 #[test]
578 fn test_wep_parse() {
579 let mut buf = vec![0x01, 0x02, 0x03, 0x40];
581 buf.extend_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD]); buf.extend_from_slice(&0x12345678u32.to_le_bytes()); let wep = Dot11WEP::new(0);
586 assert_eq!(wep.iv(&buf).unwrap(), [0x01, 0x02, 0x03]);
587 assert_eq!(wep.key_id(&buf).unwrap(), 1);
588 assert_eq!(wep.header_len(), 4);
589 assert_eq!(wep.trailer_len(), 4);
590 assert_eq!(wep.icv(&buf, buf.len()).unwrap(), 0x12345678);
591
592 let encrypted = wep.encrypted_data(&buf, buf.len()).unwrap();
593 assert_eq!(encrypted, &[0xAA, 0xBB, 0xCC, 0xDD]);
594 }
595
596 #[test]
597 fn test_wep_build() {
598 let header = Dot11WEP::build_header([0x11, 0x22, 0x33], 2);
599 assert_eq!(header, vec![0x11, 0x22, 0x33, 0x80]); let wep = Dot11WEP::new(0);
602 assert_eq!(wep.iv(&header).unwrap(), [0x11, 0x22, 0x33]);
603 assert_eq!(wep.key_id(&header).unwrap(), 2);
604
605 let icv = Dot11WEP::build_icv(0xDEADBEEF);
606 assert_eq!(icv, 0xDEADBEEFu32.to_le_bytes().to_vec());
607 }
608
609 #[test]
610 fn test_wep_iv_u32() {
611 let buf = vec![0x01, 0x02, 0x03, 0x00];
612 let wep = Dot11WEP::new(0);
613 assert_eq!(wep.iv_u32(&buf).unwrap(), 0x010203);
614 }
615
616 #[test]
617 fn test_tkip_parse() {
618 let buf = vec![
621 0x00, 0x20, 0x01, 0x20, 0x02, 0x03, 0x04, 0x05, ];
624
625 let tkip = Dot11TKIP::new(0);
626 assert!(tkip.ext_iv(&buf).unwrap());
627 assert_eq!(tkip.key_id(&buf).unwrap(), 0);
628 assert_eq!(tkip.tsc0(&buf).unwrap(), 0x01);
629 assert_eq!(tkip.tsc1(&buf).unwrap(), 0x00);
630 assert_eq!(tkip.wep_seed(&buf).unwrap(), 0x20);
631 assert_eq!(tkip.tsc_high(&buf).unwrap(), [0x02, 0x03, 0x04, 0x05]);
632 assert_eq!(tkip.header_len(&buf), 8);
633 assert_eq!(tkip.trailer_len(), 4);
634
635 let tsc = tkip.tsc(&buf).unwrap();
637 assert_eq!(tsc & 0xFF, 0x01);
638 assert_eq!((tsc >> 8) & 0xFF, 0x00);
639 assert_eq!((tsc >> 16) & 0xFF, 0x02);
640 assert_eq!((tsc >> 24) & 0xFF, 0x03);
641 assert_eq!((tsc >> 32) & 0xFF, 0x04);
642 assert_eq!((tsc >> 40) & 0xFF, 0x05);
643 }
644
645 #[test]
646 fn test_tkip_build_roundtrip() {
647 let tsc: u64 = 0x050403020001; let header = Dot11TKIP::build_header(tsc, 1);
649 assert_eq!(header.len(), 8);
650
651 let tkip = Dot11TKIP::new(0);
652 assert!(tkip.ext_iv(&header).unwrap());
653 assert_eq!(tkip.key_id(&header).unwrap(), 1);
654 assert_eq!(tkip.tsc(&header).unwrap(), tsc);
655 }
656
657 #[test]
658 fn test_ccmp_parse() {
659 let buf = vec![
662 0x01, 0x02, 0x00, 0x20, 0x03, 0x04, 0x05, 0x06, ];
665
666 let ccmp = Dot11CCMP::new(0);
667 assert_eq!(ccmp.pn0(&buf).unwrap(), 0x01);
668 assert_eq!(ccmp.pn1(&buf).unwrap(), 0x02);
669 assert_eq!(ccmp.reserved(&buf).unwrap(), 0x00);
670 assert!(ccmp.ext_iv(&buf).unwrap());
671 assert_eq!(ccmp.key_id(&buf).unwrap(), 0);
672 assert_eq!(ccmp.pn_high(&buf).unwrap(), [0x03, 0x04, 0x05, 0x06]);
673 assert_eq!(ccmp.header_len(), 8);
674 assert_eq!(ccmp.trailer_len(), 8);
675
676 let pn = ccmp.pn(&buf).unwrap();
677 assert_eq!(pn & 0xFF, 0x01);
678 assert_eq!((pn >> 8) & 0xFF, 0x02);
679 assert_eq!((pn >> 16) & 0xFF, 0x03);
680 assert_eq!((pn >> 24) & 0xFF, 0x04);
681 assert_eq!((pn >> 32) & 0xFF, 0x05);
682 assert_eq!((pn >> 40) & 0xFF, 0x06);
683 }
684
685 #[test]
686 fn test_ccmp_build_roundtrip() {
687 let pn: u64 = 0x060504030201;
688 let header = Dot11CCMP::build_header(pn, 2);
689 assert_eq!(header.len(), 8);
690
691 let ccmp = Dot11CCMP::new(0);
692 assert!(ccmp.ext_iv(&header).unwrap());
693 assert_eq!(ccmp.key_id(&header).unwrap(), 2);
694 assert_eq!(ccmp.pn(&header).unwrap(), pn);
695 }
696
697 #[test]
698 fn test_ccmp_mic() {
699 let mut buf = vec![0u8; 8]; buf.extend_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD]); buf.extend_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]); let ccmp = Dot11CCMP::new(0);
704 let mic = ccmp.mic(&buf, buf.len()).unwrap();
705 assert_eq!(mic, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
706 }
707
708 #[test]
709 fn test_detect_security_type() {
710 let wep_buf = vec![0x01, 0x02, 0x03, 0x00];
712 assert_eq!(detect_security_type(&wep_buf, 0), Some(SecurityType::WEP));
713
714 let ccmp_buf = vec![0x01, 0x02, 0x00, 0x20];
716 assert_eq!(detect_security_type(&ccmp_buf, 0), Some(SecurityType::CCMP));
717
718 let tkip_buf = vec![0x01, 0x20, 0x03, 0x20];
720 assert_eq!(detect_security_type(&tkip_buf, 0), Some(SecurityType::TKIP));
721
722 assert_eq!(detect_security_type(&[0x01, 0x02], 0), None);
724 }
725
726 #[test]
727 fn test_wep_validate() {
728 assert!(Dot11WEP::validate(&[0u8; 4], 0).is_ok());
729 assert!(Dot11WEP::validate(&[0u8; 3], 0).is_err());
730 }
731
732 #[test]
733 fn test_tkip_validate() {
734 assert!(Dot11TKIP::validate(&[0u8; 4], 0).is_ok());
735 assert!(Dot11TKIP::validate(&[0u8; 3], 0).is_err());
736 }
737
738 #[test]
739 fn test_ccmp_validate() {
740 assert!(Dot11CCMP::validate(&[0u8; 8], 0).is_ok());
741 assert!(Dot11CCMP::validate(&[0u8; 7], 0).is_err());
742 }
743}