blob: 49b8113fdda65feae394ee0981bd9995cf63bb6d [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#![feature(test)]
#![deny(warnings)]
#[macro_use]
extern crate bitfield;
#[macro_use]
extern crate nom;
extern crate test;
use nom::{be_u16, be_u64, be_u8};
// IEEE Std 802.1X-2010, 11.9, Table 11-5
pub enum KeyDescriptor {
Rc4 = 1,
Ieee802dot11 = 2,
}
// IEEE Std 802.1X-2010, 11.3.1
pub enum ProtocolVersion {
Ieee802dot1x2010 = 3,
}
// IEEE Std 802.1X-2010, 11.3.2, Table 11-3
pub enum PacketType {
Eap = 0,
Start = 1,
Logoff = 2,
Key = 3,
AsfAlert = 4,
Mka = 5,
AnnouncementGeneric = 6,
AnnouncementSpecific = 7,
AnnouncementReq = 8,
}
// IEEE Std 802.11-2016, 12.7.2, Figure 12-33
bitfield! {
pub struct KeyInformation(u16);
impl Debug;
pub key_descriptor_version, set_key_descriptor_version: 2, 0;
pub key_type, set_key_type: 3, 3;
// Bit 4-5 reserved.
pub install, set_install: 6;
pub key_ack, set_key_ack: 7;
pub key_mic, set_key_mic: 8;
pub secure, set_secure: 9;
pub error, set_error: 10;
pub request, set_request: 11;
pub encrypted_key_data, set_encrypted_key_data: 12;
pub smk_message, set_smk_message: 13;
value, _: 15,0;
// Bit 14-15 reserved.
}
impl Default for KeyInformation {
fn default() -> KeyInformation {
KeyInformation(0)
}
}
// IEEE Std 802.11-2016, 12.7.2, Figure 12-32
#[derive(Default, Debug)]
pub struct KeyFrame<'a> {
pub version: u8,
pub packet_type: u8,
pub packet_body_len: u16,
pub descriptor_type: u8,
pub key_info: KeyInformation,
pub key_len: u16,
pub key_replay_counter: u64,
pub key_nonce: &'a [u8], // 32 octets
pub key_iv: &'a [u8], // 16 octets
pub key_rsc: u64,
// 8 octests reserved.
pub key_mic: &'a [u8], // AKM dependent size
pub key_data_len: u16,
pub key_data: &'a [u8],
}
named_args!(pub key_frame_from_bytes(mic_size: u16) <KeyFrame>,
do_parse!(
version: be_u8 >>
packet_type: verify!(be_u8, |v:u8| v == PacketType::Key as u8) >>
packet_body_len: be_u16 >>
descriptor_type: be_u8 >>
key_info: map!(be_u16, KeyInformation) >>
key_len: be_u16 >>
key_replay_counter: be_u64 >>
key_nonce: take!(32) >>
key_iv: take!(16) >>
key_rsc: be_u64 >>
take!(8 /* reserved octets */) >>
key_mic: take!(mic_size) >>
key_data_len: be_u16 >>
key_data: take!(key_data_len) >>
eof!() >>
(KeyFrame{
version: version,
packet_type: packet_type,
packet_body_len: packet_body_len,
descriptor_type: descriptor_type,
key_info: key_info,
key_len: key_len,
key_replay_counter: key_replay_counter,
key_mic: key_mic,
key_rsc: key_rsc,
key_iv: key_iv,
key_nonce: key_nonce,
key_data_len: key_data_len,
key_data: key_data,
})
)
);
#[cfg(test)]
mod tests {
use super::*;
use test::{black_box, Bencher};
#[bench]
fn bench_key_frame_from_bytes(b: &mut Bencher) {
let frame: Vec<u8> = vec![
0x01, 0x03, 0x00, 0x5f, 0x02, 0x00, 0x8a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x39, 0x5c, 0xc7, 0x6e, 0x1a, 0xe9, 0x9f, 0xa0, 0xb1, 0x22, 0x79,
0xfe, 0xc3, 0xb9, 0xa9, 0x9e, 0x1d, 0x9a, 0x21, 0xb8, 0x47, 0x51, 0x38, 0x98, 0x25,
0xf8, 0xc7, 0xca, 0x55, 0x86, 0xbc, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x54, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01,
0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,
0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02,
0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01,
0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,
0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02,
0x03,
];
b.iter(|| key_frame_from_bytes(&frame, black_box(16)));
}
#[test]
fn test_no_key_frame() {
let frame: Vec<u8> = vec![
0x01, 0x01, 0x00, 0x5f, 0x02, 0x00, 0x8a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x39, 0x5c, 0xc7, 0x6e, 0x1a, 0xe9, 0x9f, 0xa0, 0xb1, 0x22, 0x79,
0xfe, 0xc3, 0xb9, 0xa9, 0x9e, 0x1d, 0x9a, 0x21, 0xb8, 0x47, 0x51, 0x38, 0x98, 0x25,
0xf8, 0xc7, 0xca, 0x55, 0x86, 0xbc, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
];
let result = key_frame_from_bytes(&frame, 16);
assert_eq!(result.is_done(), false);
}
#[test]
fn test_too_long() {
let frame: Vec<u8> = vec![
0x01, 0x03, 0x00, 0x5f, 0x02, 0x00, 0x8a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x39, 0x5c, 0xc7, 0x6e, 0x1a, 0xe9, 0x9f, 0xa0, 0xb1, 0x22, 0x79,
0xfe, 0xc3, 0xb9, 0xa9, 0x9e, 0x1d, 0x9a, 0x21, 0xb8, 0x47, 0x51, 0x38, 0x98, 0x25,
0xf8, 0xc7, 0xca, 0x55, 0x86, 0xbc, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x01, 0x02, 0x03, 0x04,
];
let result = key_frame_from_bytes(&frame, 16);
assert_eq!(result.is_done(), false);
}
#[test]
fn test_too_short() {
let frame: Vec<u8> = vec![
0x01, 0x03, 0x00, 0x5f, 0x02, 0x00, 0x8a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x39, 0x5c, 0xc7, 0x6e, 0x1a, 0xe9, 0x9f, 0xa0, 0xb1, 0x22, 0x79,
0xfe, 0xc3, 0xb9, 0xa9, 0x9e, 0x1d, 0x9a, 0x21, 0xb8, 0x47, 0x51, 0x38, 0x98, 0x25,
0xf8, 0xc7, 0xca, 0x55, 0x86, 0xbc, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x01,
];
let result = key_frame_from_bytes(&frame, 16);
assert_eq!(result.is_done(), false);
}
#[test]
fn test_correct_packet() {
let frame: Vec<u8> = vec![
0x01, 0x03, 0x00, 0x5f, 0x02, 0x00, 0x8a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x39, 0x5c, 0xc7, 0x6e, 0x1a, 0xe9, 0x9f, 0xa0, 0xb1, 0x22, 0x79,
0xfe, 0xc3, 0xb9, 0xa9, 0x9e, 0x1d, 0x9a, 0x21, 0xb8, 0x47, 0x51, 0x38, 0x98, 0x25,
0xf8, 0xc7, 0xca, 0x55, 0x86, 0xbc, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x01, 0x02, 0x03,
];
let result = key_frame_from_bytes(&frame, 16);
assert_eq!(result.is_done(), true);
let keyframe: KeyFrame = result.unwrap().1;
assert_eq!(keyframe.version, 1);
assert_eq!(keyframe.packet_type, 3);
assert_eq!(keyframe.packet_body_len, 95);
assert_eq!(keyframe.descriptor_type, 2);
assert_eq!(keyframe.key_info.value(), 0x008a);
assert_eq!(keyframe.key_info.key_descriptor_version(), 2);
assert_eq!(keyframe.key_info.key_ack(), true);
assert_eq!(keyframe.key_len, 16);
assert_eq!(keyframe.key_replay_counter, 1);
let nonce: Vec<u8> = vec![
0x39, 0x5c, 0xc7, 0x6e, 0x1a, 0xe9, 0x9f, 0xa0, 0xb1, 0x22, 0x79, 0xfe, 0xc3, 0xb9,
0xa9, 0x9e, 0x1d, 0x9a, 0x21, 0xb8, 0x47, 0x51, 0x38, 0x98, 0x25, 0xf8, 0xc7, 0xca,
0x55, 0x86, 0xbc, 0xda,
];
assert_eq!(&keyframe.key_nonce[..], &nonce[..]);
assert_eq!(keyframe.key_rsc, 0);
let mic = [0; 16];
assert_eq!(&keyframe.key_mic[..], mic);
assert_eq!(keyframe.key_data_len, 3);
let data: Vec<u8> = vec![0x01, 0x02, 0x03];
assert_eq!(&keyframe.key_data[..], &data[..]);
}
}