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 pub fn new(offset: usize) -> Self {
41 Self { offset }
42 }
43
44 pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
46 if buf.len() < offset + WEP_HEADER_LEN {
47 return Err(FieldError::BufferTooShort {
48 offset,
49 need: WEP_HEADER_LEN,
50 have: buf.len().saturating_sub(offset),
51 });
52 }
53 Ok(())
54 }
55
56 pub fn iv(&self, buf: &[u8]) -> Result<[u8; 3], FieldError> {
58 if buf.len() < self.offset + WEP_HEADER_LEN {
59 return Err(FieldError::BufferTooShort {
60 offset: self.offset,
61 need: WEP_HEADER_LEN,
62 have: buf.len().saturating_sub(self.offset),
63 });
64 }
65 Ok([buf[self.offset], buf[self.offset + 1], buf[self.offset + 2]])
66 }
67
68 pub fn iv_u32(&self, buf: &[u8]) -> Result<u32, FieldError> {
70 let iv = self.iv(buf)?;
71 Ok(((iv[0] as u32) << 16) | ((iv[1] as u32) << 8) | (iv[2] as u32))
72 }
73
74 pub fn key_id(&self, buf: &[u8]) -> Result<u8, FieldError> {
76 if buf.len() < self.offset + WEP_HEADER_LEN {
77 return Err(FieldError::BufferTooShort {
78 offset: self.offset,
79 need: WEP_HEADER_LEN,
80 have: buf.len().saturating_sub(self.offset),
81 });
82 }
83 Ok((buf[self.offset + 3] >> 6) & 0x03)
84 }
85
86 pub fn key_id_byte(&self, buf: &[u8]) -> Result<u8, FieldError> {
88 if buf.len() < self.offset + WEP_HEADER_LEN {
89 return Err(FieldError::BufferTooShort {
90 offset: self.offset,
91 need: WEP_HEADER_LEN,
92 have: buf.len().saturating_sub(self.offset),
93 });
94 }
95 Ok(buf[self.offset + 3])
96 }
97
98 pub fn icv(&self, buf: &[u8], frame_end: usize) -> Result<u32, FieldError> {
101 if frame_end < WEP_TRAILER_LEN || buf.len() < frame_end {
102 return Err(FieldError::BufferTooShort {
103 offset: frame_end.saturating_sub(WEP_TRAILER_LEN),
104 need: WEP_TRAILER_LEN,
105 have: 0,
106 });
107 }
108 let off = frame_end - WEP_TRAILER_LEN;
109 Ok(u32::from_le_bytes([
110 buf[off],
111 buf[off + 1],
112 buf[off + 2],
113 buf[off + 3],
114 ]))
115 }
116
117 pub fn encrypted_data<'a>(
119 &self,
120 buf: &'a [u8],
121 frame_end: usize,
122 ) -> Result<&'a [u8], FieldError> {
123 let start = self.offset + WEP_HEADER_LEN;
124 let end = frame_end.saturating_sub(WEP_TRAILER_LEN);
125 if start > end || buf.len() < frame_end {
126 return Err(FieldError::BufferTooShort {
127 offset: start,
128 need: 0,
129 have: 0,
130 });
131 }
132 Ok(&buf[start..end])
133 }
134
135 pub fn header_len(&self) -> usize {
137 WEP_HEADER_LEN
138 }
139
140 pub fn trailer_len(&self) -> usize {
142 WEP_TRAILER_LEN
143 }
144
145 pub fn build_header(iv: [u8; 3], key_id: u8) -> Vec<u8> {
147 vec![iv[0], iv[1], iv[2], (key_id & 0x03) << 6]
148 }
149
150 pub fn build_icv(icv: u32) -> Vec<u8> {
152 icv.to_le_bytes().to_vec()
153 }
154}
155
156pub const TKIP_HEADER_SHORT: usize = 4;
162
163pub const TKIP_HEADER_LONG: usize = 8;
165
166pub const TKIP_ICV_LEN: usize = 4;
170
171#[derive(Debug, Clone)]
189pub struct Dot11TKIP {
190 pub offset: usize,
191}
192
193impl Dot11TKIP {
194 pub fn new(offset: usize) -> Self {
195 Self { offset }
196 }
197
198 pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
200 if buf.len() < offset + TKIP_HEADER_SHORT {
201 return Err(FieldError::BufferTooShort {
202 offset,
203 need: TKIP_HEADER_SHORT,
204 have: buf.len().saturating_sub(offset),
205 });
206 }
207 Ok(())
208 }
209
210 pub fn tsc1(&self, buf: &[u8]) -> Result<u8, FieldError> {
212 if buf.len() <= self.offset {
213 return Err(FieldError::BufferTooShort {
214 offset: self.offset,
215 need: 1,
216 have: 0,
217 });
218 }
219 Ok(buf[self.offset])
220 }
221
222 pub fn wep_seed(&self, buf: &[u8]) -> Result<u8, FieldError> {
224 if buf.len() <= self.offset + 1 {
225 return Err(FieldError::BufferTooShort {
226 offset: self.offset + 1,
227 need: 1,
228 have: 0,
229 });
230 }
231 Ok(buf[self.offset + 1])
232 }
233
234 pub fn tsc0(&self, buf: &[u8]) -> Result<u8, FieldError> {
236 if buf.len() <= self.offset + 2 {
237 return Err(FieldError::BufferTooShort {
238 offset: self.offset + 2,
239 need: 1,
240 have: 0,
241 });
242 }
243 Ok(buf[self.offset + 2])
244 }
245
246 pub fn ext_iv(&self, buf: &[u8]) -> Result<bool, FieldError> {
248 if buf.len() < self.offset + TKIP_HEADER_SHORT {
249 return Err(FieldError::BufferTooShort {
250 offset: self.offset,
251 need: TKIP_HEADER_SHORT,
252 have: buf.len().saturating_sub(self.offset),
253 });
254 }
255 Ok(buf[self.offset + 3] & 0x20 != 0)
256 }
257
258 pub fn key_id(&self, buf: &[u8]) -> Result<u8, FieldError> {
260 if buf.len() < self.offset + TKIP_HEADER_SHORT {
261 return Err(FieldError::BufferTooShort {
262 offset: self.offset,
263 need: TKIP_HEADER_SHORT,
264 have: buf.len().saturating_sub(self.offset),
265 });
266 }
267 Ok((buf[self.offset + 3] >> 6) & 0x03)
268 }
269
270 pub fn tsc_high(&self, buf: &[u8]) -> Result<[u8; 4], FieldError> {
272 if buf.len() < self.offset + TKIP_HEADER_LONG {
273 return Err(FieldError::BufferTooShort {
274 offset: self.offset + 4,
275 need: 4,
276 have: buf.len().saturating_sub(self.offset + 4),
277 });
278 }
279 Ok([
280 buf[self.offset + 4],
281 buf[self.offset + 5],
282 buf[self.offset + 6],
283 buf[self.offset + 7],
284 ])
285 }
286
287 pub fn tsc(&self, buf: &[u8]) -> Result<u64, FieldError> {
290 let tsc0 = self.tsc0(buf)? as u64;
291 let tsc1 = self.tsc1(buf)? as u64;
292 let high = self.tsc_high(buf)?;
293 let tsc2 = high[0] as u64;
294 let tsc3 = high[1] as u64;
295 let tsc4 = high[2] as u64;
296 let tsc5 = high[3] as u64;
297 Ok(tsc0 | (tsc1 << 8) | (tsc2 << 16) | (tsc3 << 24) | (tsc4 << 32) | (tsc5 << 40))
298 }
299
300 pub fn header_len(&self, buf: &[u8]) -> usize {
302 if self.ext_iv(buf).unwrap_or(false) {
303 TKIP_HEADER_LONG
304 } else {
305 TKIP_HEADER_SHORT
306 }
307 }
308
309 pub fn trailer_len(&self) -> usize {
311 TKIP_ICV_LEN
312 }
313
314 pub fn build_header(tsc: u64, key_id: u8) -> Vec<u8> {
316 let tsc0 = (tsc & 0xFF) as u8;
317 let tsc1 = ((tsc >> 8) & 0xFF) as u8;
318 let tsc2 = ((tsc >> 16) & 0xFF) as u8;
319 let tsc3 = ((tsc >> 24) & 0xFF) as u8;
320 let tsc4 = ((tsc >> 32) & 0xFF) as u8;
321 let tsc5 = ((tsc >> 40) & 0xFF) as u8;
322 let wep_seed = (tsc1 | 0x20) & 0x7F;
324 let key_id_byte = ((key_id & 0x03) << 6) | 0x20; vec![tsc1, wep_seed, tsc0, key_id_byte, tsc2, tsc3, tsc4, tsc5]
326 }
327}
328
329pub const CCMP_HEADER_LEN: usize = 8;
335
336pub const CCMP_MIC_LEN: usize = 8;
338
339#[derive(Debug, Clone)]
359pub struct Dot11CCMP {
360 pub offset: usize,
361}
362
363impl Dot11CCMP {
364 pub fn new(offset: usize) -> Self {
365 Self { offset }
366 }
367
368 pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
370 if buf.len() < offset + CCMP_HEADER_LEN {
371 return Err(FieldError::BufferTooShort {
372 offset,
373 need: CCMP_HEADER_LEN,
374 have: buf.len().saturating_sub(offset),
375 });
376 }
377 Ok(())
378 }
379
380 pub fn pn0(&self, buf: &[u8]) -> Result<u8, FieldError> {
382 if buf.len() <= self.offset {
383 return Err(FieldError::BufferTooShort {
384 offset: self.offset,
385 need: 1,
386 have: 0,
387 });
388 }
389 Ok(buf[self.offset])
390 }
391
392 pub fn pn1(&self, buf: &[u8]) -> Result<u8, FieldError> {
394 if buf.len() <= self.offset + 1 {
395 return Err(FieldError::BufferTooShort {
396 offset: self.offset + 1,
397 need: 1,
398 have: 0,
399 });
400 }
401 Ok(buf[self.offset + 1])
402 }
403
404 pub fn reserved(&self, buf: &[u8]) -> Result<u8, FieldError> {
406 if buf.len() <= self.offset + 2 {
407 return Err(FieldError::BufferTooShort {
408 offset: self.offset + 2,
409 need: 1,
410 have: 0,
411 });
412 }
413 Ok(buf[self.offset + 2])
414 }
415
416 pub fn key_id(&self, buf: &[u8]) -> Result<u8, FieldError> {
418 if buf.len() < self.offset + CCMP_HEADER_LEN {
419 return Err(FieldError::BufferTooShort {
420 offset: self.offset,
421 need: CCMP_HEADER_LEN,
422 have: buf.len().saturating_sub(self.offset),
423 });
424 }
425 Ok((buf[self.offset + 3] >> 6) & 0x03)
426 }
427
428 pub fn ext_iv(&self, buf: &[u8]) -> Result<bool, FieldError> {
430 if buf.len() < self.offset + CCMP_HEADER_LEN {
431 return Err(FieldError::BufferTooShort {
432 offset: self.offset,
433 need: CCMP_HEADER_LEN,
434 have: buf.len().saturating_sub(self.offset),
435 });
436 }
437 Ok(buf[self.offset + 3] & 0x20 != 0)
438 }
439
440 pub fn pn_high(&self, buf: &[u8]) -> Result<[u8; 4], FieldError> {
442 if buf.len() < self.offset + CCMP_HEADER_LEN {
443 return Err(FieldError::BufferTooShort {
444 offset: self.offset + 4,
445 need: 4,
446 have: buf.len().saturating_sub(self.offset + 4),
447 });
448 }
449 Ok([
450 buf[self.offset + 4],
451 buf[self.offset + 5],
452 buf[self.offset + 6],
453 buf[self.offset + 7],
454 ])
455 }
456
457 pub fn pn(&self, buf: &[u8]) -> Result<u64, FieldError> {
460 let pn0 = self.pn0(buf)? as u64;
461 let pn1 = self.pn1(buf)? as u64;
462 let high = self.pn_high(buf)?;
463 let pn2 = high[0] as u64;
464 let pn3 = high[1] as u64;
465 let pn4 = high[2] as u64;
466 let pn5 = high[3] as u64;
467 Ok(pn0 | (pn1 << 8) | (pn2 << 16) | (pn3 << 24) | (pn4 << 32) | (pn5 << 40))
468 }
469
470 pub fn mic(&self, buf: &[u8], frame_end: usize) -> Result<[u8; 8], FieldError> {
472 if frame_end < CCMP_MIC_LEN || buf.len() < frame_end {
473 return Err(FieldError::BufferTooShort {
474 offset: frame_end.saturating_sub(CCMP_MIC_LEN),
475 need: CCMP_MIC_LEN,
476 have: 0,
477 });
478 }
479 let off = frame_end - CCMP_MIC_LEN;
480 let mut mic = [0u8; 8];
481 mic.copy_from_slice(&buf[off..frame_end]);
482 Ok(mic)
483 }
484
485 pub fn header_len(&self) -> usize {
487 CCMP_HEADER_LEN
488 }
489
490 pub fn trailer_len(&self) -> usize {
492 CCMP_MIC_LEN
493 }
494
495 pub fn build_header(pn: u64, key_id: u8) -> Vec<u8> {
497 let pn0 = (pn & 0xFF) as u8;
498 let pn1 = ((pn >> 8) & 0xFF) as u8;
499 let pn2 = ((pn >> 16) & 0xFF) as u8;
500 let pn3 = ((pn >> 24) & 0xFF) as u8;
501 let pn4 = ((pn >> 32) & 0xFF) as u8;
502 let pn5 = ((pn >> 40) & 0xFF) as u8;
503 let key_id_byte = ((key_id & 0x03) << 6) | 0x20; vec![pn0, pn1, 0x00, key_id_byte, pn2, pn3, pn4, pn5]
505 }
506
507 pub fn build_mic(mic: [u8; 8]) -> Vec<u8> {
509 mic.to_vec()
510 }
511}
512
513#[derive(Debug, Clone, Copy, PartialEq, Eq)]
519pub enum SecurityType {
520 WEP,
522 TKIP,
524 CCMP,
526}
527
528pub fn detect_security_type(buf: &[u8], offset: usize) -> Option<SecurityType> {
538 if buf.len() < offset + 4 {
539 return None;
540 }
541 let ext_iv = buf[offset + 3] & 0x20 != 0;
542 if !ext_iv {
543 return Some(SecurityType::WEP);
544 }
545 if buf[offset + 2] == 0 {
548 Some(SecurityType::CCMP)
549 } else {
550 Some(SecurityType::TKIP)
551 }
552}
553
554#[cfg(test)]
559mod tests {
560 use super::*;
561
562 #[test]
563 fn test_wep_parse() {
564 let mut buf = vec![0x01, 0x02, 0x03, 0x40];
566 buf.extend_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD]); buf.extend_from_slice(&0x12345678u32.to_le_bytes()); let wep = Dot11WEP::new(0);
571 assert_eq!(wep.iv(&buf).unwrap(), [0x01, 0x02, 0x03]);
572 assert_eq!(wep.key_id(&buf).unwrap(), 1);
573 assert_eq!(wep.header_len(), 4);
574 assert_eq!(wep.trailer_len(), 4);
575 assert_eq!(wep.icv(&buf, buf.len()).unwrap(), 0x12345678);
576
577 let encrypted = wep.encrypted_data(&buf, buf.len()).unwrap();
578 assert_eq!(encrypted, &[0xAA, 0xBB, 0xCC, 0xDD]);
579 }
580
581 #[test]
582 fn test_wep_build() {
583 let header = Dot11WEP::build_header([0x11, 0x22, 0x33], 2);
584 assert_eq!(header, vec![0x11, 0x22, 0x33, 0x80]); let wep = Dot11WEP::new(0);
587 assert_eq!(wep.iv(&header).unwrap(), [0x11, 0x22, 0x33]);
588 assert_eq!(wep.key_id(&header).unwrap(), 2);
589
590 let icv = Dot11WEP::build_icv(0xDEADBEEF);
591 assert_eq!(icv, 0xDEADBEEFu32.to_le_bytes().to_vec());
592 }
593
594 #[test]
595 fn test_wep_iv_u32() {
596 let buf = vec![0x01, 0x02, 0x03, 0x00];
597 let wep = Dot11WEP::new(0);
598 assert_eq!(wep.iv_u32(&buf).unwrap(), 0x010203);
599 }
600
601 #[test]
602 fn test_tkip_parse() {
603 let buf = vec![
606 0x00, 0x20, 0x01, 0x20, 0x02, 0x03, 0x04, 0x05, ];
609
610 let tkip = Dot11TKIP::new(0);
611 assert!(tkip.ext_iv(&buf).unwrap());
612 assert_eq!(tkip.key_id(&buf).unwrap(), 0);
613 assert_eq!(tkip.tsc0(&buf).unwrap(), 0x01);
614 assert_eq!(tkip.tsc1(&buf).unwrap(), 0x00);
615 assert_eq!(tkip.wep_seed(&buf).unwrap(), 0x20);
616 assert_eq!(tkip.tsc_high(&buf).unwrap(), [0x02, 0x03, 0x04, 0x05]);
617 assert_eq!(tkip.header_len(&buf), 8);
618 assert_eq!(tkip.trailer_len(), 4);
619
620 let tsc = tkip.tsc(&buf).unwrap();
622 assert_eq!(tsc & 0xFF, 0x01);
623 assert_eq!((tsc >> 8) & 0xFF, 0x00);
624 assert_eq!((tsc >> 16) & 0xFF, 0x02);
625 assert_eq!((tsc >> 24) & 0xFF, 0x03);
626 assert_eq!((tsc >> 32) & 0xFF, 0x04);
627 assert_eq!((tsc >> 40) & 0xFF, 0x05);
628 }
629
630 #[test]
631 fn test_tkip_build_roundtrip() {
632 let tsc: u64 = 0x050403020001; let header = Dot11TKIP::build_header(tsc, 1);
634 assert_eq!(header.len(), 8);
635
636 let tkip = Dot11TKIP::new(0);
637 assert!(tkip.ext_iv(&header).unwrap());
638 assert_eq!(tkip.key_id(&header).unwrap(), 1);
639 assert_eq!(tkip.tsc(&header).unwrap(), tsc);
640 }
641
642 #[test]
643 fn test_ccmp_parse() {
644 let buf = vec![
647 0x01, 0x02, 0x00, 0x20, 0x03, 0x04, 0x05, 0x06, ];
650
651 let ccmp = Dot11CCMP::new(0);
652 assert_eq!(ccmp.pn0(&buf).unwrap(), 0x01);
653 assert_eq!(ccmp.pn1(&buf).unwrap(), 0x02);
654 assert_eq!(ccmp.reserved(&buf).unwrap(), 0x00);
655 assert!(ccmp.ext_iv(&buf).unwrap());
656 assert_eq!(ccmp.key_id(&buf).unwrap(), 0);
657 assert_eq!(ccmp.pn_high(&buf).unwrap(), [0x03, 0x04, 0x05, 0x06]);
658 assert_eq!(ccmp.header_len(), 8);
659 assert_eq!(ccmp.trailer_len(), 8);
660
661 let pn = ccmp.pn(&buf).unwrap();
662 assert_eq!(pn & 0xFF, 0x01);
663 assert_eq!((pn >> 8) & 0xFF, 0x02);
664 assert_eq!((pn >> 16) & 0xFF, 0x03);
665 assert_eq!((pn >> 24) & 0xFF, 0x04);
666 assert_eq!((pn >> 32) & 0xFF, 0x05);
667 assert_eq!((pn >> 40) & 0xFF, 0x06);
668 }
669
670 #[test]
671 fn test_ccmp_build_roundtrip() {
672 let pn: u64 = 0x060504030201;
673 let header = Dot11CCMP::build_header(pn, 2);
674 assert_eq!(header.len(), 8);
675
676 let ccmp = Dot11CCMP::new(0);
677 assert!(ccmp.ext_iv(&header).unwrap());
678 assert_eq!(ccmp.key_id(&header).unwrap(), 2);
679 assert_eq!(ccmp.pn(&header).unwrap(), pn);
680 }
681
682 #[test]
683 fn test_ccmp_mic() {
684 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);
689 let mic = ccmp.mic(&buf, buf.len()).unwrap();
690 assert_eq!(mic, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
691 }
692
693 #[test]
694 fn test_detect_security_type() {
695 let wep_buf = vec![0x01, 0x02, 0x03, 0x00];
697 assert_eq!(detect_security_type(&wep_buf, 0), Some(SecurityType::WEP));
698
699 let ccmp_buf = vec![0x01, 0x02, 0x00, 0x20];
701 assert_eq!(detect_security_type(&ccmp_buf, 0), Some(SecurityType::CCMP));
702
703 let tkip_buf = vec![0x01, 0x20, 0x03, 0x20];
705 assert_eq!(detect_security_type(&tkip_buf, 0), Some(SecurityType::TKIP));
706
707 assert_eq!(detect_security_type(&[0x01, 0x02], 0), None);
709 }
710
711 #[test]
712 fn test_wep_validate() {
713 assert!(Dot11WEP::validate(&[0u8; 4], 0).is_ok());
714 assert!(Dot11WEP::validate(&[0u8; 3], 0).is_err());
715 }
716
717 #[test]
718 fn test_tkip_validate() {
719 assert!(Dot11TKIP::validate(&[0u8; 4], 0).is_ok());
720 assert!(Dot11TKIP::validate(&[0u8; 3], 0).is_err());
721 }
722
723 #[test]
724 fn test_ccmp_validate() {
725 assert!(Dot11CCMP::validate(&[0u8; 8], 0).is_ok());
726 assert!(Dot11CCMP::validate(&[0u8; 7], 0).is_err());
727 }
728}