From 913a2e0c7600d147b1b51b437a1288535dbbfbd7 Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 19:18:29 -0300 Subject: [PATCH 01/11] build: makes security an optional feature for less dependencies --- .github/workflows/run-test.yml | 22 +++++++++++++-- Cargo.toml | 7 ++--- src/lib.rs | 2 ++ src/mac/frame/header.rs | 17 +++++++---- src/mac/frame/mod.rs | 19 +++++++++++-- .../security/auxiliary_security_header.rs | 8 ++++-- src/mac/frame/security/default.rs | 7 +++++ src/mac/frame/security/mod.rs | 28 ++++++++++++++++++- src/mac/mod.rs | 4 ++- 9 files changed, 95 insertions(+), 19 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 81b2a92..77389a9 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -17,7 +17,12 @@ jobs: uses: actions-rs/cargo@v1 with: command: clippy - format: + args: --all-features + - name: Clippy no security + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --no-default-features runs-on: ubuntu-latest steps: - name: Checkout sources @@ -33,6 +38,11 @@ jobs: with: command: fmt args: --all -- --check + - name: Check Format no security + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --no-default-features --all -- --check build-armv6m: runs-on: ubuntu-latest steps: @@ -49,6 +59,10 @@ jobs: run: | set -ex cargo build + - name: Build no security + run: | + set -ex + cargo build --no-default-features test: runs-on: ubuntu-latest steps: @@ -63,4 +77,8 @@ jobs: - name: Test run: | set -ex - cargo test \ No newline at end of file + cargo test + - name: Test no security + run: | + set -ex + cargo test --no-default-features \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 6b159d3..e70c72a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,21 +17,20 @@ categories = ["embedded", "network-programming", "no-std"] keywords = ["WPAN"] [features] +default = ["security"] +security = ["cipher"] [dependencies] hash32 = "0.2.1" hash32-derive = "0.1" byte = "0.2.7" defmt = { version = ">=0.2.0,<0.4", optional = true } +cipher = {version = "0.3.0", default-features = false, optional = true} [dependencies.ccm] version = "0.4.0" default-features = false -[dependencies.cipher] -version = "0.3.0" -default-features = false - [dependencies.serde] version = "1.0" default-features = false diff --git a/src/lib.rs b/src/lib.rs index 2061832..580d7e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,4 +25,6 @@ #[macro_use] mod utils; +#[allow(unused_imports)] pub mod mac; + diff --git a/src/mac/frame/header.rs b/src/mac/frame/header.rs index a8bf7f0..b7ec118 100644 --- a/src/mac/frame/header.rs +++ b/src/mac/frame/header.rs @@ -5,16 +5,20 @@ //! [`Header`]: struct.Header.html use byte::{check_len, BytesExt, TryRead, TryWrite, LE}; -use cipher::{consts::U16, BlockCipher, NewBlockCipher}; use hash32_derive::Hash32; +use super::frame_control::{mask, offset}; pub use super::frame_control::{AddressMode, FrameType, FrameVersion}; +use super::security::AuxiliarySecurityHeader; use super::DecodeError; -use super::{ - frame_control::{mask, offset}, - security::{KeyDescriptorLookup, SecurityContext}, +#[cfg(feature = "security")] +use { + super::{ + security::{KeyDescriptorLookup, SecurityContext}, + EncodeError, + }, + cipher::{consts::U16, BlockCipher, NewBlockCipher}, }; -use super::{security::AuxiliarySecurityHeader, EncodeError}; /// MAC frame header /// @@ -230,6 +234,7 @@ impl TryRead<'_> for Header { } } +#[cfg(feature = "security")] impl TryWrite<&Option<&mut SecurityContext>> for Header where @@ -442,11 +447,13 @@ pub enum Address { #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[cfg(feature = "security")] enum AddressEncoding { Normal, Compressed, } +#[cfg(feature = "security")] impl TryWrite for Address { fn try_write( self, diff --git a/src/mac/frame/mod.rs b/src/mac/frame/mod.rs index e290f8c..4d403be 100644 --- a/src/mac/frame/mod.rs +++ b/src/mac/frame/mod.rs @@ -18,14 +18,17 @@ mod frame_control; pub mod header; pub mod security; use byte::{ctx::Bytes, BytesExt, TryRead, TryWrite, LE}; +#[cfg(feature = "security")] use ccm::aead::generic_array::typenum::consts::U16; +#[cfg(feature = "security")] use cipher::{BlockCipher, BlockEncrypt, NewBlockCipher}; use header::FrameType; pub use header::Header; +#[cfg(feature = "security")] use self::security::{ default::Unimplemented, DeviceDescriptorLookup, KeyDescriptorLookup, - SecurityContext, SecurityError, + SecurityError, SecurityContext }; /// An IEEE 802.15.4 MAC frame @@ -176,6 +179,7 @@ pub struct Frame<'p> { /// A context that is used for serializing and deserializing frames, which also /// stores the frame counter +#[cfg(feature = "security")] pub struct FrameSerDesContext<'a, AEADBLKCIPH, KEYDESCLO> where AEADBLKCIPH: NewBlockCipher + BlockCipher, @@ -187,6 +191,7 @@ where security_ctx: Option<&'a mut SecurityContext>, } +#[cfg(feature = "security")] impl<'a, AEADBLKCIPH, KEYDESCLO> FrameSerDesContext<'a, AEADBLKCIPH, KEYDESCLO> where AEADBLKCIPH: NewBlockCipher + BlockCipher, @@ -205,6 +210,7 @@ where } } +#[cfg(feature = "security")] impl FrameSerDesContext<'_, Unimplemented, Unimplemented> { /// Create a new frame serialization/deserialization context with the specified footer mode, /// that does not facilitate any security functionality @@ -216,6 +222,7 @@ impl FrameSerDesContext<'_, Unimplemented, Unimplemented> { } } +#[cfg(feature = "security")] impl TryWrite<&mut FrameSerDesContext<'_, AEADBLKCIPH, KEYDESCLO>> for Frame<'_> where @@ -277,6 +284,7 @@ impl<'a> Frame<'a> { /// /// Use [`FrameSerDesContext::no_security`] and/or [`Unimplemented`] if you /// do not want to use any security, or simply [`Frame::try_read`] + #[cfg(feature = "security")] pub fn try_read_and_unsecure( buf: &'a mut [u8], ctx: &mut FrameSerDesContext<'_, AEADBLKCIPH, KEYDESCLO>, @@ -553,8 +561,8 @@ impl From for byte::Error { #[cfg(test)] mod tests { - use crate::mac::beacon; - use crate::mac::command; + #[cfg(feature = "security")] + use crate::mac::{beacon, command}; use crate::mac::frame::*; use crate::mac::{ Address, ExtendedAddress, FrameVersion, PanId, ShortAddress, @@ -644,6 +652,7 @@ mod tests { assert_eq!(frame.payload.len(), 3); } + #[cfg(feature = "security")] #[test] fn encode_ver0_short() { let frame = Frame { @@ -688,6 +697,7 @@ mod tests { ); } + #[cfg(feature = "security")] #[test] fn encode_ver1_extended() { let frame = Frame { @@ -745,6 +755,7 @@ mod tests { ); } + #[cfg(feature = "security")] #[test] fn encode_ver0_pan_compress() { let frame = Frame { @@ -789,6 +800,7 @@ mod tests { ); } + #[cfg(feature = "security")] #[test] fn encode_ver2_none() { let frame = Frame { @@ -827,6 +839,7 @@ mod tests { ); } + #[cfg(feature = "security")] #[test] fn empty_addressing_and_panid_compress() { let mut frame_data = [0u8; 127]; diff --git a/src/mac/frame/security/auxiliary_security_header.rs b/src/mac/frame/security/auxiliary_security_header.rs index 1e771f2..06eab1d 100644 --- a/src/mac/frame/security/auxiliary_security_header.rs +++ b/src/mac/frame/security/auxiliary_security_header.rs @@ -1,9 +1,10 @@ //! All auxiliary security header structs and functions -use super::{ - KeyDescriptorLookup, KeyIdentifierMode, SecurityContext, SecurityControl, -}; +#[cfg(feature = "security")] +use super::{KeyDescriptorLookup, SecurityContext}; +use super::{KeyIdentifierMode, SecurityControl}; use byte::{BytesExt, TryRead, TryWrite, LE}; +#[cfg(feature = "security")] use cipher::{consts::U16, BlockCipher, NewBlockCipher}; /// A struct describing the Auxiliary Security Header @@ -115,6 +116,7 @@ impl TryRead<'_> for AuxiliarySecurityHeader { } } +#[cfg(feature = "security")] impl TryWrite<&SecurityContext> for AuxiliarySecurityHeader where diff --git a/src/mac/frame/security/default.rs b/src/mac/frame/security/default.rs index d54542a..45e9b07 100644 --- a/src/mac/frame/security/default.rs +++ b/src/mac/frame/security/default.rs @@ -6,10 +6,12 @@ use super::{ DeviceDescriptorLookup, KeyDescriptorLookup, }; use crate::mac::Address; +#[cfg(feature = "security")] use ccm::aead::generic_array::{ typenum::consts::{U1, U16}, GenericArray, }; +#[cfg(feature="security")] use cipher::{ Block, BlockCipher, BlockCipherKey, BlockDecrypt, BlockEncrypt, NewBlockCipher, @@ -19,6 +21,7 @@ use cipher::{ /// actually capable of performing any of the operations pub struct Unimplemented; +#[cfg(feature = "security")] impl KeyDescriptorLookup for Unimplemented { fn lookup_key_descriptor( &self, @@ -30,20 +33,24 @@ impl KeyDescriptorLookup for Unimplemented { } } +#[cfg(feature="security")] impl BlockCipher for Unimplemented { type BlockSize = U16; type ParBlocks = U1; } +#[cfg(feature="security")] impl BlockEncrypt for Unimplemented { fn encrypt_block(&self, _block: &mut Block) {} } +#[cfg(feature="security")] impl BlockDecrypt for Unimplemented { fn decrypt_block(&self, _block: &mut Block) {} } +#[cfg(feature="security")] impl NewBlockCipher for Unimplemented { type KeySize = U16; diff --git a/src/mac/frame/security/mod.rs b/src/mac/frame/security/mod.rs index 52d878f..61c9f3d 100644 --- a/src/mac/frame/security/mod.rs +++ b/src/mac/frame/security/mod.rs @@ -164,7 +164,6 @@ pub mod default; mod security_control; use self::default::Unimplemented; - use super::{FooterMode, Frame, Header}; use crate::mac::{Address, FrameType, FrameVersion}; use byte::BytesExt; @@ -183,6 +182,7 @@ use core::marker::PhantomData; pub use auxiliary_security_header::{ AuxiliarySecurityHeader, KeyIdentifier, KeySource, }; +#[cfg(feature = "security")] pub use cipher::{ generic_array::typenum::consts::U16, BlockCipher, BlockEncrypt, NewBlockCipher, @@ -249,6 +249,7 @@ pub trait DeviceDescriptorLookup { /// /// NONCEGEN is the type that will convert the nonce created using the 802.15.4 standard /// into a nonce of the size that can be accepted by the provided AEAD algorithm +#[cfg(feature = "security")] #[derive(Clone, Copy)] pub struct SecurityContext where @@ -268,6 +269,7 @@ where phantom_data: PhantomData, } +#[cfg(feature = "security")] impl SecurityContext where AEADBLKCIPH: NewBlockCipher + BlockCipher, @@ -285,6 +287,7 @@ where } } +#[cfg(feature = "security")] impl SecurityContext { /// A security context that is not actually capable of providing any security pub fn no_security() -> Self { @@ -297,6 +300,7 @@ impl SecurityContext { } } +#[cfg(feature = "security")] fn calculate_nonce( source_addr: u64, frame_counter: u32, @@ -326,6 +330,7 @@ fn calculate_nonce( /// /// # Panics /// if footer_mode is not None due to currently absent implementation of explicit footers +#[cfg(feature = "security")] pub(crate) fn secure_frame<'a, AEADBLKCIPH, KEYDESCLO>( frame: Frame<'_>, context: &mut SecurityContext, @@ -510,6 +515,7 @@ where /// /// # Panics /// if footer_mode is not None due to currently absent implementation of explicit footers +#[cfg(feature = "security")] pub(crate) fn unsecure_frame<'a, AEADBLKCIPH, KEYDESCLO, DEVDESCLO>( header: &Header, buffer: &mut [u8], @@ -789,6 +795,7 @@ impl From for byte::Error { } #[cfg(test)] +#[cfg(feature = "security")] mod tests { use crate::mac::frame::header::*; use crate::mac::frame::security::{security_control::*, *}; @@ -797,8 +804,10 @@ mod tests { use aes::Aes128; use rand::Rng; + struct StaticKeyLookup(); + impl KeyDescriptorLookup for StaticKeyLookup { fn lookup_key_descriptor( &self, @@ -816,16 +825,20 @@ mod tests { } } } + + struct BasicDevDescriptorLookup<'a> { descriptor: &'a mut DeviceDescriptor, } + impl<'a> BasicDevDescriptorLookup<'a> { pub fn new(descriptor: &'a mut DeviceDescriptor) -> Self { Self { descriptor } } } + impl<'a> DeviceDescriptorLookup for BasicDevDescriptorLookup<'a> { fn lookup_device( &mut self, @@ -836,9 +849,11 @@ mod tests { } } + const STATIC_KEY_LOOKUP: StaticKeyLookup = StaticKeyLookup(); const FRAME_CTR: u32 = 0x03030303; + fn aes_sec_ctx<'a>( source_euid: u64, frame_counter: u32, @@ -881,6 +896,7 @@ mod tests { (src_u64, source, destination) } + macro_rules! test_security_level { ($level:expr) => { let (source_u64, source, destination) = get_rand_addrpair(); @@ -953,6 +969,7 @@ mod tests { }; } + #[test] fn encode_unsecured() { let (source_euid, source, destination) = get_rand_addrpair(); @@ -985,36 +1002,44 @@ mod tests { } } + #[test] #[should_panic] fn test_enc() { test_security_level!(SecurityLevel::ENC); } + #[test] fn test_mic32() { test_security_level!(SecurityLevel::MIC32); } + #[test] fn test_mic64() { test_security_level!(SecurityLevel::MIC64); } + #[test] fn test_mic128() { test_security_level!(SecurityLevel::MIC128); } + #[test] fn test_encmic32() { test_security_level!(SecurityLevel::ENCMIC32); } + #[test] fn test_encmic64() { test_security_level!(SecurityLevel::ENCMIC64); } + #[test] fn test_encmic128() { test_security_level!(SecurityLevel::ENCMIC128); } + #[test] fn encode_decode_secured_frame() { let source_euid = 0x08; @@ -1131,6 +1156,7 @@ mod tests { assert_eq!(device_desc.frame_counter, sec_ctx.frame_counter); } + #[test] fn encode_fail_decode_secured_frame() { let source_euid = 0x08; diff --git a/src/mac/mod.rs b/src/mac/mod.rs index 51ed3e5..0235b94 100644 --- a/src/mac/mod.rs +++ b/src/mac/mod.rs @@ -9,5 +9,7 @@ pub use frame::header::{ PanId, ShortAddress, }; pub use frame::{ - security, DecodeError, FooterMode, Frame, FrameContent, FrameSerDesContext, + security, DecodeError, FooterMode, Frame, FrameContent, }; +#[cfg(feature="security")] +pub use crate::mac::frame::FrameSerDesContext; From d8ac53d34b0755ea236ca1a4741e1f357727b06e Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 19:23:35 -0300 Subject: [PATCH 02/11] build: removes ccm dependency as well, making it optional --- Cargo.toml | 6 ++---- src/mac/frame/security/default.rs | 28 +++++++++++++++------------- src/mac/frame/security/mod.rs | 2 ++ 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e70c72a..1b7f638 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ keywords = ["WPAN"] [features] default = ["security"] -security = ["cipher"] +security = ["cipher", "ccm"] [dependencies] hash32 = "0.2.1" @@ -26,10 +26,8 @@ hash32-derive = "0.1" byte = "0.2.7" defmt = { version = ">=0.2.0,<0.4", optional = true } cipher = {version = "0.3.0", default-features = false, optional = true} +ccm = { version = "0.4.0", default-features = false, optional = true} -[dependencies.ccm] -version = "0.4.0" -default-features = false [dependencies.serde] version = "1.0" diff --git a/src/mac/frame/security/default.rs b/src/mac/frame/security/default.rs index 45e9b07..82bf29e 100644 --- a/src/mac/frame/security/default.rs +++ b/src/mac/frame/security/default.rs @@ -3,18 +3,20 @@ use super::{ auxiliary_security_header::KeyIdentifier, AddressingMode, DeviceDescriptor, - DeviceDescriptorLookup, KeyDescriptorLookup, + DeviceDescriptorLookup, }; use crate::mac::Address; #[cfg(feature = "security")] -use ccm::aead::generic_array::{ - typenum::consts::{U1, U16}, - GenericArray, -}; -#[cfg(feature="security")] -use cipher::{ - Block, BlockCipher, BlockCipherKey, BlockDecrypt, BlockEncrypt, - NewBlockCipher, +use { + ccm::aead::generic_array::{ + typenum::consts::{U1, U16}, + GenericArray, + }, + cipher::{ + Block, BlockCipher, BlockCipherKey, BlockDecrypt, BlockEncrypt, + NewBlockCipher, + }, + super::KeyDescriptorLookup }; /// A struct that fullfills all of the trait bounds for serialization and deserializtion, but is not @@ -33,24 +35,24 @@ impl KeyDescriptorLookup for Unimplemented { } } -#[cfg(feature="security")] +#[cfg(feature = "security")] impl BlockCipher for Unimplemented { type BlockSize = U16; type ParBlocks = U1; } -#[cfg(feature="security")] +#[cfg(feature = "security")] impl BlockEncrypt for Unimplemented { fn encrypt_block(&self, _block: &mut Block) {} } -#[cfg(feature="security")] +#[cfg(feature = "security")] impl BlockDecrypt for Unimplemented { fn decrypt_block(&self, _block: &mut Block) {} } -#[cfg(feature="security")] +#[cfg(feature = "security")] impl NewBlockCipher for Unimplemented { type KeySize = U16; diff --git a/src/mac/frame/security/mod.rs b/src/mac/frame/security/mod.rs index 61c9f3d..6f4c1d2 100644 --- a/src/mac/frame/security/mod.rs +++ b/src/mac/frame/security/mod.rs @@ -167,6 +167,7 @@ use self::default::Unimplemented; use super::{FooterMode, Frame, Header}; use crate::mac::{Address, FrameType, FrameVersion}; use byte::BytesExt; +#[cfg(feature = "security")] use ccm::{ aead::{ generic_array::{ @@ -207,6 +208,7 @@ pub struct DeviceDescriptor { pub exempt: bool, } +#[cfg(feature = "security")] /// Used to create a KeyDescriptor from a KeyIdentifier and device address pub trait KeyDescriptorLookup where From 573f4133b3646ec3231dc6f361ed044d91dfc927 Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 19:27:12 -0300 Subject: [PATCH 03/11] fix: workflow --- .github/workflows/run-test.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 77389a9..b2f8f85 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -16,13 +16,11 @@ jobs: - name: Clippy uses: actions-rs/cargo@v1 with: - command: clippy - args: --all-features + command: clippy --all-features - name: Clippy no security uses: actions-rs/cargo@v1 with: - command: clippy - args: --no-default-features + command: clippy --no-default-features runs-on: ubuntu-latest steps: - name: Checkout sources @@ -36,13 +34,11 @@ jobs: - name: Check Format uses: actions-rs/cargo@v1 with: - command: fmt - args: --all -- --check + command: fmt --all -- --check - name: Check Format no security uses: actions-rs/cargo@v1 with: - command: fmt - args: --no-default-features --all -- --check + command: fmt --no-default-features --all -- --check build-armv6m: runs-on: ubuntu-latest steps: From 556f6ef4dca555556b90ef4c4043946052ea318b Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 19:29:56 -0300 Subject: [PATCH 04/11] build: workflow fix --- .github/workflows/run-test.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index b2f8f85..01cf90c 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -18,9 +18,9 @@ jobs: with: command: clippy --all-features - name: Clippy no security - uses: actions-rs/cargo@v1 - with: - command: clippy --no-default-features + run: | + set -ex + cargo clippy --no-default-features runs-on: ubuntu-latest steps: - name: Checkout sources @@ -35,10 +35,10 @@ jobs: uses: actions-rs/cargo@v1 with: command: fmt --all -- --check - - name: Check Format no security - uses: actions-rs/cargo@v1 - with: - command: fmt --no-default-features --all -- --check + - name: Check no security + run: | + set -ex + cargo fmt --no-default-features --all -- --check build-armv6m: runs-on: ubuntu-latest steps: From ed3ad6121239ad1c073b4a319e44d6a2484fc513 Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 19:31:47 -0300 Subject: [PATCH 05/11] fix: workflow --- .github/workflows/run-test.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 01cf90c..13df8d8 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -17,10 +17,11 @@ jobs: uses: actions-rs/cargo@v1 with: command: clippy --all-features - - name: Clippy no security - run: | - set -ex - cargo clippy --no-default-features + - name: Clippy + uses: actions-rs/cargo@v1 + with: + command: clippy --no-default-features + format: runs-on: ubuntu-latest steps: - name: Checkout sources @@ -35,10 +36,10 @@ jobs: uses: actions-rs/cargo@v1 with: command: fmt --all -- --check - - name: Check no security - run: | - set -ex - cargo fmt --no-default-features --all -- --check + - name: Check Format No security + uses: actions-rs/cargo@v1 + with: + command: fmt --no-default-features --all -- --check build-armv6m: runs-on: ubuntu-latest steps: From e26693e2de8fd7e7f7228932214127df25c66eb8 Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 19:50:11 -0300 Subject: [PATCH 06/11] clippy fixes --- src/mac/beacon.rs | 44 +++++++++++----- src/mac/command.rs | 16 +++--- src/mac/frame/header.rs | 21 +++----- .../security/auxiliary_security_header.rs | 21 +++----- src/mac/frame/security/mod.rs | 50 +++++++------------ src/mac/frame/security/security_control.rs | 2 + src/utils.rs | 24 ++++----- 7 files changed, 88 insertions(+), 90 deletions(-) diff --git a/src/mac/beacon.rs b/src/mac/beacon.rs index fadf991..1a9b15b 100644 --- a/src/mac/beacon.rs +++ b/src/mac/beacon.rs @@ -102,7 +102,7 @@ const ASSOCIATION_PERMIT: u8 = 0b1000_0000; impl TryRead<'_> for SuperframeSpecification { fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> { let offset = &mut 0; - check_len(&bytes, 2)?; + check_len(bytes, 2)?; let byte: u8 = bytes.read(offset)?; let beacon_order = BeaconOrder::from(byte & 0x0f); let superframe_order = SuperframeOrder::from((byte >> 4) & 0x0f); @@ -130,8 +130,8 @@ impl TryRead<'_> for SuperframeSpecification { impl TryWrite for SuperframeSpecification { fn try_write(self, bytes: &mut [u8], _ctx: ()) -> byte::Result { let offset = &mut 0; - let bo = u8::from(self.beacon_order.clone()); - let so = u8::from(self.superframe_order.clone()); + let bo = u8::from(self.beacon_order); + let so = u8::from(self.superframe_order); bytes.write(offset, (bo & 0x0f) | (so << 4))?; let ble = if self.battery_life_extension { BATTERY_LIFE_EXTENSION @@ -189,10 +189,16 @@ impl GuaranteedTimeSlotDescriptor { } } +impl Default for GuaranteedTimeSlotDescriptor { + fn default() -> Self { + Self::new() + } +} + impl TryRead<'_> for GuaranteedTimeSlotDescriptor { fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> { let offset = &mut 0; - check_len(&bytes, 3)?; + check_len(bytes, 3)?; let short_address = bytes.read(offset)?; let byte: u8 = bytes.read(offset)?; let starting_slot = byte & 0x0f; @@ -259,6 +265,12 @@ impl GuaranteedTimeSlotInformation { } } +impl Default for GuaranteedTimeSlotInformation { + fn default() -> Self { + Self::new() + } +} + impl TryWrite for GuaranteedTimeSlotInformation { fn try_write(self, bytes: &mut [u8], _ctx: ()) -> byte::Result { let offset = &mut 0; @@ -275,9 +287,9 @@ impl TryWrite for GuaranteedTimeSlotInformation { for n in 0..self.slot_count { let slot = self.slots[n]; if slot.direction_transmit() { - direction_mask = direction_mask | dir; + direction_mask |= dir; } - dir = dir << 1; + dir <<= 1; } direction_mask }; @@ -307,7 +319,7 @@ impl TryRead<'_> for GuaranteedTimeSlotInformation { if slot_count > 0 { check_len(&bytes[*offset..], 2 + (3 * slot_count))?; let mut direction_mask: u8 = bytes.read(offset)?; - for n in 0..slot_count { + for slot_target in slots.iter_mut().take(slot_count) { let mut slot: GuaranteedTimeSlotDescriptor = bytes.read(offset)?; let direction = if direction_mask & 0b1 == 0b1 { @@ -316,8 +328,8 @@ impl TryRead<'_> for GuaranteedTimeSlotInformation { Direction::Receive }; slot.set_direction(direction); - direction_mask = direction_mask >> 1; - slots[n] = slot; + direction_mask >>= direction_mask; + *slot_target = slot; } } Ok(( @@ -383,6 +395,12 @@ impl PendingAddress { } } +impl Default for PendingAddress { + fn default() -> Self { + Self::new() + } +} + impl TryRead<'_> for PendingAddress { fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> { let offset = &mut 0; @@ -393,12 +411,12 @@ impl TryRead<'_> for PendingAddress { let el = ((byte & EXTENDED_MASK) >> 4) as usize; check_len(&bytes[*offset..], (sl * ss) + (el * es))?; let mut short_addresses = [ShortAddress::broadcast(); 7]; - for n in 0..sl { - short_addresses[n] = bytes.read(offset)?; + for short_address in short_addresses.iter_mut().take(sl) { + *short_address = bytes.read(offset)?; } let mut extended_addresses = [ExtendedAddress::broadcast(); 7]; - for n in 0..el { - extended_addresses[n] = bytes.read(offset)?; + for extended_address in extended_addresses.iter_mut().take(el) { + *extended_address = bytes.read(offset)?; } Ok(( Self { diff --git a/src/mac/command.rs b/src/mac/command.rs index cc1c76c..1885725 100644 --- a/src/mac/command.rs +++ b/src/mac/command.rs @@ -80,19 +80,19 @@ impl From for u8 { fn from(ar: CapabilityInformation) -> Self { let mut byte = 0u8; if ar.full_function_device { - byte = byte | CAP_FFD; + byte |= CAP_FFD } if ar.mains_power { - byte = byte | CAP_MAINS_POWER; + byte |= CAP_MAINS_POWER } if ar.idle_receive { - byte = byte | CAP_IDLE_RECEIVE; + byte |= CAP_IDLE_RECEIVE } if ar.frame_protection { - byte = byte | CAP_FRAME_PROTECTION; + byte |= CAP_FRAME_PROTECTION } if ar.allocate_address { - byte = byte | CAP_ALLOCATE_ADDRESS; + byte |= CAP_ALLOCATE_ADDRESS } byte } @@ -157,7 +157,7 @@ impl TryWrite for CoordinatorRealignmentData { impl TryRead<'_> for CoordinatorRealignmentData { fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> { let offset = &mut 0; - check_len(&bytes, 7)?; + check_len(bytes, 7)?; let pan_id = bytes.read(offset)?; let coordinator_address = bytes.read(offset)?; let channel = bytes.read(offset)?; @@ -213,10 +213,10 @@ impl From for u8 { fn from(gtsc: GuaranteedTimeSlotCharacteristics) -> Self { let mut byte = gtsc.count & 0x0f; if gtsc.receive_only { - byte = byte | GTSC_RECEIVE_ONLY; + byte |= GTSC_RECEIVE_ONLY } if gtsc.allocation { - byte = byte | GTSC_ALLOCATION; + byte |= GTSC_ALLOCATION; } byte } diff --git a/src/mac/frame/header.rs b/src/mac/frame/header.rs index b7ec118..1a74e68 100644 --- a/src/mac/frame/header.rs +++ b/src/mac/frame/header.rs @@ -92,18 +92,13 @@ impl Header { // Frame control + sequence number let mut len = 3; - for i in [self.destination, self.source].iter() { - match i { - Some(addr) => { - // pan ID - len += 2; - // Address length - match addr { - Address::Short(..) => len += 2, - Address::Extended(..) => len += 8, - } - } - _ => {} + for addr in [self.destination, self.source].iter().flatten() { + // pan ID + len += 2; + // Address length + match addr { + Address::Short(..) => len += 2, + Address::Extended(..) => len += 8, } } len @@ -119,7 +114,7 @@ impl TryRead<'_> for Header { fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> { let offset = &mut 0; // Make sure we have enough buffer for the Frame Control field - check_len(&bytes, 3)?; + check_len(bytes, 3)?; /* Decode Frame Control Field */ let bits: u16 = bytes.read_with(offset, LE)?; diff --git a/src/mac/frame/security/auxiliary_security_header.rs b/src/mac/frame/security/auxiliary_security_header.rs index 06eab1d..514745d 100644 --- a/src/mac/frame/security/auxiliary_security_header.rs +++ b/src/mac/frame/security/auxiliary_security_header.rs @@ -26,8 +26,7 @@ impl AuxiliarySecurityHeader { /// Get the size of this security header, in octets pub fn get_octet_size(&self) -> usize { // SecurityControl length + FrameCounter length - let length = 1 - + 4 + 1 + 4 + match self.key_identifier { Some(key_id) => match key_id.key_source { Some(source) => match source { @@ -37,8 +36,7 @@ impl AuxiliarySecurityHeader { None => 1, }, None => 0, - }; - length + } } /// Create a new Auxiliary Security Header with the specified control and key identifier @@ -55,6 +53,7 @@ impl AuxiliarySecurityHeader { /// Create a new Auxiliary Security Header with the specified control, key identifier, and frame counter. /// + /// # Safety /// This function is unsafe because the frame_counter is almost always set when parsing a frame from a buffer, /// or by the security context at the time of actually writing a secured frame. pub unsafe fn new_unsafe( @@ -145,11 +144,8 @@ where bytes.write(offset, self.control)?; bytes.write(offset, sec_ctx.frame_counter)?; - match self.key_identifier { - Some(key_identifier) => { - bytes.write(offset, key_identifier)?; - } - _ => {} + if let Some(key_identifier) = self.key_identifier { + bytes.write(offset, key_identifier)?; } Ok(*offset) } @@ -168,12 +164,11 @@ pub struct KeyIdentifier { impl TryWrite for KeyIdentifier { fn try_write(self, bytes: &mut [u8], _ctx: ()) -> byte::Result { let offset = &mut 0; - match self.key_source { - Some(source) => match source { + if let Some(source) = self.key_source { + match source { KeySource::Short(src) => bytes.write(offset, src)?, KeySource::Long(src) => bytes.write(offset, src)?, - }, - _ => {} + } } bytes.write(offset, self.key_index)?; diff --git a/src/mac/frame/security/mod.rs b/src/mac/frame/security/mod.rs index 6f4c1d2..5743d63 100644 --- a/src/mac/frame/security/mod.rs +++ b/src/mac/frame/security/mod.rs @@ -309,8 +309,8 @@ fn calculate_nonce( sec_level: SecurityLevel, ) -> [u8; 13] { let mut output = [0u8; 13]; - for i in 0..8 { - output[i] = (source_addr >> (8 * i) & 0xFF) as u8; + for (i, output) in output.iter_mut().enumerate().take(8) { + *output = (source_addr >> (8 * i) & 0xFF) as u8; } for i in 0..4 { @@ -333,7 +333,7 @@ fn calculate_nonce( /// # Panics /// if footer_mode is not None due to currently absent implementation of explicit footers #[cfg(feature = "security")] -pub(crate) fn secure_frame<'a, AEADBLKCIPH, KEYDESCLO>( +pub(crate) fn secure_frame( frame: Frame<'_>, context: &mut SecurityContext, footer_mode: FooterMode, @@ -354,7 +354,7 @@ where } } - let mut offset = 0 as usize; + let mut offset = 0; let header = frame.header; if header.has_security() { @@ -375,12 +375,12 @@ where // If frame size plus AuthLen plus AuxLen plus FCS is bigger than aMaxPHYPacketSize // 7.2.1b4 - if !(frame.payload.len() + if frame.payload.len() + frame.header.get_octet_size() + aux_len + auth_len + 2 - <= 127) + > 127 { return Err(SecurityError::FrameTooLong); } @@ -489,15 +489,15 @@ where #[allow(unreachable_patterns)] _ => {} }; - return Ok(offset); + Ok(offset) } else { - return Err(SecurityError::UnavailableKey); + Err(SecurityError::UnavailableKey) } } else { - return Err(SecurityError::AuxSecHeaderAbsent); + Err(SecurityError::AuxSecHeaderAbsent) } } else { - return Err(SecurityError::SecurityNotEnabled); + Err(SecurityError::SecurityNotEnabled) } } @@ -518,7 +518,7 @@ where /// # Panics /// if footer_mode is not None due to currently absent implementation of explicit footers #[cfg(feature = "security")] -pub(crate) fn unsecure_frame<'a, AEADBLKCIPH, KEYDESCLO, DEVDESCLO>( +pub(crate) fn unsecure_frame( header: &Header, buffer: &mut [u8], context: &mut SecurityContext, @@ -678,9 +678,9 @@ where } else { return Err(SecurityError::UnavailableKey); } - return Ok(taglen); + Ok(taglen) } else { - return Err(SecurityError::SecurityNotEnabled); + Err(SecurityError::SecurityNotEnabled) } } @@ -806,10 +806,8 @@ mod tests { use aes::Aes128; use rand::Rng; - struct StaticKeyLookup(); - impl KeyDescriptorLookup for StaticKeyLookup { fn lookup_key_descriptor( &self, @@ -828,19 +826,16 @@ mod tests { } } - struct BasicDevDescriptorLookup<'a> { descriptor: &'a mut DeviceDescriptor, } - impl<'a> BasicDevDescriptorLookup<'a> { pub fn new(descriptor: &'a mut DeviceDescriptor) -> Self { Self { descriptor } } } - impl<'a> DeviceDescriptorLookup for BasicDevDescriptorLookup<'a> { fn lookup_device( &mut self, @@ -851,11 +846,9 @@ mod tests { } } - const STATIC_KEY_LOOKUP: StaticKeyLookup = StaticKeyLookup(); const FRAME_CTR: u32 = 0x03030303; - fn aes_sec_ctx<'a>( source_euid: u64, frame_counter: u32, @@ -898,7 +891,6 @@ mod tests { (src_u64, source, destination) } - macro_rules! test_security_level { ($level:expr) => { let (source_u64, source, destination) = get_rand_addrpair(); @@ -971,7 +963,6 @@ mod tests { }; } - #[test] fn encode_unsecured() { let (source_euid, source, destination) = get_rand_addrpair(); @@ -1004,44 +995,42 @@ mod tests { } } - #[test] #[should_panic] fn test_enc() { test_security_level!(SecurityLevel::ENC); } - + #[test] fn test_mic32() { test_security_level!(SecurityLevel::MIC32); } - + #[test] fn test_mic64() { test_security_level!(SecurityLevel::MIC64); } - + #[test] fn test_mic128() { test_security_level!(SecurityLevel::MIC128); } - + #[test] fn test_encmic32() { test_security_level!(SecurityLevel::ENCMIC32); } - + #[test] fn test_encmic64() { test_security_level!(SecurityLevel::ENCMIC64); } - + #[test] fn test_encmic128() { test_security_level!(SecurityLevel::ENCMIC128); } - #[test] fn encode_decode_secured_frame() { let source_euid = 0x08; @@ -1158,7 +1147,6 @@ mod tests { assert_eq!(device_desc.frame_counter, sec_ctx.frame_counter); } - #[test] fn encode_fail_decode_secured_frame() { let source_euid = 0x08; diff --git a/src/mac/frame/security/security_control.rs b/src/mac/frame/security/security_control.rs index dbca01b..891f346 100644 --- a/src/mac/frame/security/security_control.rs +++ b/src/mac/frame/security/security_control.rs @@ -101,6 +101,7 @@ impl SecurityLevel { } } + #[allow(clippy::wrong_self_convention)] pub(crate) fn to_bits(&self) -> u8 { match self { SecurityLevel::None => 0b000, @@ -150,6 +151,7 @@ impl KeyIdentifierMode { _ => None, } } + #[allow(clippy::wrong_self_convention)] fn to_bits(&self) -> u8 { match self { KeyIdentifierMode::None => 0b00, diff --git a/src/utils.rs b/src/utils.rs index 1225f73..ee0340d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -49,18 +49,18 @@ macro_rules! extended_enum { } } - impl PartialEq<$name> for $ty { - fn eq(&self, other: &$name) -> bool { - match *other { - $( $name::$var => *self == $val, )* - } - } + // impl PartialEq<$name> for $ty { + // fn eq(&self, other: &$name) -> bool { + // match *other { + // $( $name::$var => *self == $val, )* + // } + // } - fn ne(&self, other: &$name) -> bool { - match *other { - $( $name::$var => *self != $val, )* - } - } - } + // fn ne(&self, other: &$name) -> bool { + // match *other { + // $( $name::$var => *self != $val, )* + // } + // } + // } ); } From d99470799699d385b6e115b68dc214e369a5c6cc Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 19:54:42 -0300 Subject: [PATCH 07/11] workflow + fmt --- .github/workflows/run-test.yml | 14 +++++++++----- src/lib.rs | 1 - src/mac/frame/mod.rs | 4 ++-- src/mac/frame/security/default.rs | 2 +- src/mac/mod.rs | 8 +++----- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 13df8d8..6b8fce0 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -16,11 +16,13 @@ jobs: - name: Clippy uses: actions-rs/cargo@v1 with: - command: clippy --all-features + command: clippy + args: --all-features - name: Clippy uses: actions-rs/cargo@v1 with: - command: clippy --no-default-features + command: clippy + args: --no-default-features format: runs-on: ubuntu-latest steps: @@ -35,11 +37,13 @@ jobs: - name: Check Format uses: actions-rs/cargo@v1 with: - command: fmt --all -- --check - - name: Check Format No security + command: fmt + args: --all -- --check + - name: Check Format uses: actions-rs/cargo@v1 with: - command: fmt --no-default-features --all -- --check + command: fmt + args: --no-default-features --all -- --check build-armv6m: runs-on: ubuntu-latest steps: diff --git a/src/lib.rs b/src/lib.rs index 580d7e2..84284d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,4 +27,3 @@ mod utils; #[allow(unused_imports)] pub mod mac; - diff --git a/src/mac/frame/mod.rs b/src/mac/frame/mod.rs index 4d403be..195f7ba 100644 --- a/src/mac/frame/mod.rs +++ b/src/mac/frame/mod.rs @@ -28,7 +28,7 @@ pub use header::Header; #[cfg(feature = "security")] use self::security::{ default::Unimplemented, DeviceDescriptorLookup, KeyDescriptorLookup, - SecurityError, SecurityContext + SecurityContext, SecurityError, }; /// An IEEE 802.15.4 MAC frame @@ -561,9 +561,9 @@ impl From for byte::Error { #[cfg(test)] mod tests { + use crate::mac::frame::*; #[cfg(feature = "security")] use crate::mac::{beacon, command}; - use crate::mac::frame::*; use crate::mac::{ Address, ExtendedAddress, FrameVersion, PanId, ShortAddress, }; diff --git a/src/mac/frame/security/default.rs b/src/mac/frame/security/default.rs index 82bf29e..aed086f 100644 --- a/src/mac/frame/security/default.rs +++ b/src/mac/frame/security/default.rs @@ -8,6 +8,7 @@ use super::{ use crate::mac::Address; #[cfg(feature = "security")] use { + super::KeyDescriptorLookup, ccm::aead::generic_array::{ typenum::consts::{U1, U16}, GenericArray, @@ -16,7 +17,6 @@ use { Block, BlockCipher, BlockCipherKey, BlockDecrypt, BlockEncrypt, NewBlockCipher, }, - super::KeyDescriptorLookup }; /// A struct that fullfills all of the trait bounds for serialization and deserializtion, but is not diff --git a/src/mac/mod.rs b/src/mac/mod.rs index 0235b94..fbec3de 100644 --- a/src/mac/mod.rs +++ b/src/mac/mod.rs @@ -4,12 +4,10 @@ pub mod beacon; pub mod command; pub mod frame; +#[cfg(feature = "security")] +pub use crate::mac::frame::FrameSerDesContext; pub use frame::header::{ Address, AddressMode, ExtendedAddress, FrameType, FrameVersion, Header, PanId, ShortAddress, }; -pub use frame::{ - security, DecodeError, FooterMode, Frame, FrameContent, -}; -#[cfg(feature="security")] -pub use crate::mac::frame::FrameSerDesContext; +pub use frame::{security, DecodeError, FooterMode, Frame, FrameContent}; From 7c7cf564b4de964b223cbf10dad08053f206e40a Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 19:58:21 -0300 Subject: [PATCH 08/11] fix test --- .github/workflows/run-test.yml | 5 ----- src/mac/beacon.rs | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 6b8fce0..917d195 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -39,11 +39,6 @@ jobs: with: command: fmt args: --all -- --check - - name: Check Format - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --no-default-features --all -- --check build-armv6m: runs-on: ubuntu-latest steps: diff --git a/src/mac/beacon.rs b/src/mac/beacon.rs index 1a9b15b..025cae0 100644 --- a/src/mac/beacon.rs +++ b/src/mac/beacon.rs @@ -328,7 +328,7 @@ impl TryRead<'_> for GuaranteedTimeSlotInformation { Direction::Receive }; slot.set_direction(direction); - direction_mask >>= direction_mask; + direction_mask >>= 1; *slot_target = slot; } } From 4246f468752c35495e0492284d1f507da62b2539 Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 21:07:49 -0300 Subject: [PATCH 09/11] fix docs + features --- src/mac/frame/header.rs | 75 ++++++++++++++++++++++++++++++----- src/mac/frame/mod.rs | 70 +++++++++++++++++++++++++++----- src/mac/frame/security/mod.rs | 10 ++++- 3 files changed, 132 insertions(+), 23 deletions(-) diff --git a/src/mac/frame/header.rs b/src/mac/frame/header.rs index 1a74e68..8f2d6c9 100644 --- a/src/mac/frame/header.rs +++ b/src/mac/frame/header.rs @@ -4,22 +4,21 @@ //! //! [`Header`]: struct.Header.html -use byte::{check_len, BytesExt, TryRead, TryWrite, LE}; -use hash32_derive::Hash32; - use super::frame_control::{mask, offset}; pub use super::frame_control::{AddressMode, FrameType, FrameVersion}; use super::security::AuxiliarySecurityHeader; use super::DecodeError; +use crate::mac::frame::EncodeError; +#[cfg(not(feature = "security"))] +use crate::mac::frame::FrameSerDesContext; +use byte::{check_len, BytesExt, TryRead, TryWrite, LE}; +use hash32_derive::Hash32; +use super::security::SecurityContext; #[cfg(feature = "security")] use { - super::{ - security::{KeyDescriptorLookup, SecurityContext}, - EncodeError, - }, + super::security::KeyDescriptorLookup, cipher::{consts::U16, BlockCipher, NewBlockCipher}, }; - /// MAC frame header /// /// External documentation for [MAC frame format start at 5.2] @@ -306,6 +305,64 @@ where } } +#[cfg(not(feature = "security"))] +impl TryWrite<&Option<&mut SecurityContext>> for Header { + fn try_write( + self, + bytes: &mut [u8], + _sec_ctx: &Option<&mut SecurityContext>, + ) -> byte::Result { + let offset = &mut 0; + let dest_addr_mode = AddressMode::from(self.destination); + let src_addr_mode = AddressMode::from(self.source); + + let security = self.auxiliary_security_header.is_some(); + + let frame_control_raw = (self.frame_type as u16) << offset::FRAME_TYPE + | (security as u16) << offset::SECURITY + | (self.frame_pending as u16) << offset::PENDING + | (self.ack_request as u16) << offset::ACK + | (self.pan_id_compress as u16) << offset::PAN_ID_COMPRESS + | (dest_addr_mode as u16) << offset::DEST_ADDR_MODE + | (self.version as u16) << offset::VERSION + | (src_addr_mode as u16) << offset::SRC_ADDR_MODE; + + bytes.write_with(offset, frame_control_raw, LE)?; + + // Write Sequence Number + bytes.write(offset, self.seq)?; + + if (self.destination.is_none() || self.source.is_none()) + && self.pan_id_compress + { + return Err(EncodeError::DisallowedPanIdCompress)?; + } + + // Write addresses + if let Some(destination) = self.destination { + bytes.write_with(offset, destination, AddressEncoding::Normal)?; + } + + match (self.source, self.pan_id_compress) { + (Some(source), true) => { + bytes.write_with( + offset, + source, + AddressEncoding::Compressed, + )?; + } + (Some(source), false) => { + bytes.write_with(offset, source, AddressEncoding::Normal)?; + } + (None, true) => { + panic!("frame control request compress source address without contain this address") + } + (None, false) => (), + } + Ok(*offset) + } +} + /// Personal Area Network Identifier /// /// A 16-bit value that identifies a PAN @@ -442,13 +499,11 @@ pub enum Address { #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[cfg(feature = "security")] enum AddressEncoding { Normal, Compressed, } -#[cfg(feature = "security")] impl TryWrite for Address { fn try_write( self, diff --git a/src/mac/frame/mod.rs b/src/mac/frame/mod.rs index 195f7ba..7cc78c9 100644 --- a/src/mac/frame/mod.rs +++ b/src/mac/frame/mod.rs @@ -17,7 +17,7 @@ use crate::mac::command::Command; mod frame_control; pub mod header; pub mod security; -use byte::{ctx::Bytes, BytesExt, TryRead, TryWrite, LE}; +use byte::{ctx::Bytes, BytesExt, Error, TryRead, TryWrite, LE}; #[cfg(feature = "security")] use ccm::aead::generic_array::typenum::consts::U16; #[cfg(feature = "security")] @@ -25,10 +25,10 @@ use cipher::{BlockCipher, BlockEncrypt, NewBlockCipher}; use header::FrameType; pub use header::Header; +use self::security::{default::Unimplemented, SecurityContext}; #[cfg(feature = "security")] use self::security::{ - default::Unimplemented, DeviceDescriptorLookup, KeyDescriptorLookup, - SecurityContext, SecurityError, + DeviceDescriptorLookup, KeyDescriptorLookup, SecurityError, }; /// An IEEE 802.15.4 MAC frame @@ -53,7 +53,6 @@ use self::security::{ /// FrameType, /// FooterMode, /// PanId, -/// FrameSerDesContext, /// }; /// use byte::BytesExt; /// @@ -111,7 +110,7 @@ use self::security::{ /// FrameVersion, /// Header, /// PanId, -/// FrameSerDesContext, +/// frame::FrameSerDesContext /// }; /// use byte::BytesExt; /// @@ -139,7 +138,7 @@ use self::security::{ /// let mut bytes = [0u8; 32]; /// let mut len = 0usize; /// -/// bytes.write_with(&mut len, frame, &mut FrameSerDesContext::no_security(FooterMode::Explicit)).unwrap(); +/// bytes.write_with(&mut len, frame, &mut FrameSerDesContext::no_security(FooterMode::Explicit)).unwrap(); /// /// let expected_bytes = [ /// 0x01, 0x98, // frame control @@ -210,6 +209,27 @@ where } } +#[cfg(not(feature = "security"))] +/// A context that is used for serializing and deserializing frames, which also +/// stores the frame counter +pub struct FrameSerDesContext<'a> { + /// The footer mode to use when handling frames + footer_mode: FooterMode, + /// The security context for handling frames (if any) + security_ctx: Option<&'a mut SecurityContext>, +} +#[cfg(not(feature = "security"))] +impl FrameSerDesContext<'_> { + /// Create a new frame serialization/deserialization context with the specified footer mode, + /// that does not facilitate any security functionality + pub fn no_security(mode: FooterMode) -> Self { + FrameSerDesContext { + footer_mode: mode, + security_ctx: None, + } + } +} + #[cfg(feature = "security")] impl FrameSerDesContext<'_, Unimplemented, Unimplemented> { /// Create a new frame serialization/deserialization context with the specified footer mode, @@ -275,6 +295,35 @@ where } } +#[cfg(not(feature = "security"))] +impl TryWrite<&mut FrameSerDesContext<'_>> for Frame<'_> { + fn try_write( + self, + bytes: &mut [u8], + context: &mut FrameSerDesContext, + ) -> byte::Result { + let mode = context.footer_mode; + let offset = &mut 0; + + bytes.write_with(offset, self.header, &context.security_ctx)?; + bytes.write(offset, self.content)?; + + let security_enabled = false; + + if !security_enabled { + bytes.write(offset, self.payload.as_ref())?; + } + + match mode { + FooterMode::None => {} + // TODO: recalculate the footer after encryption? + FooterMode::Explicit => bytes.write(offset, &self.footer[..])?, + } + + Ok(*offset) + } +} + impl<'a> Frame<'a> { /// Try to read a frame. If the frame is secured, it will be unsecured /// @@ -562,7 +611,6 @@ impl From for byte::Error { #[cfg(test)] mod tests { use crate::mac::frame::*; - #[cfg(feature = "security")] use crate::mac::{beacon, command}; use crate::mac::{ Address, ExtendedAddress, FrameVersion, PanId, ShortAddress, @@ -652,7 +700,7 @@ mod tests { assert_eq!(frame.payload.len(), 3); } - #[cfg(feature = "security")] + #[cfg(not(feature = "security"))] #[test] fn encode_ver0_short() { let frame = Frame { @@ -697,7 +745,7 @@ mod tests { ); } - #[cfg(feature = "security")] + #[cfg(not(feature = "security"))] #[test] fn encode_ver1_extended() { let frame = Frame { @@ -755,7 +803,7 @@ mod tests { ); } - #[cfg(feature = "security")] + #[cfg(not(feature = "security"))] #[test] fn encode_ver0_pan_compress() { let frame = Frame { @@ -800,7 +848,7 @@ mod tests { ); } - #[cfg(feature = "security")] + #[cfg(not(feature = "security"))] #[test] fn encode_ver2_none() { let frame = Frame { diff --git a/src/mac/frame/security/mod.rs b/src/mac/frame/security/mod.rs index 5743d63..a218691 100644 --- a/src/mac/frame/security/mod.rs +++ b/src/mac/frame/security/mod.rs @@ -4,8 +4,8 @@ //! //! # Example on how to use frames with security //! Note that the example below is _very insecure_, and should not be used in any production setting -//! -//! ```rust +#![cfg_attr(not(feature = "security"), doc = "```ignore")] +#![cfg_attr(feature = "security", doc = "```rust")] //! use ieee802154::mac::{ //! frame::security::{ //! KeyDescriptorLookup, @@ -271,6 +271,11 @@ where phantom_data: PhantomData, } +#[cfg(not(feature = "security"))] +/// A blank context for when no security is used, but we still want the same API +#[derive(Clone, Copy)] +pub struct SecurityContext {} + #[cfg(feature = "security")] impl SecurityContext where @@ -1031,6 +1036,7 @@ mod tests { test_security_level!(SecurityLevel::ENCMIC128); } + #[cfg(not(feature = "security"))] #[test] fn encode_decode_secured_frame() { let source_euid = 0x08; From 9b0213517191d006fcc50631eb290a83d3106c0b Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 21:08:23 -0300 Subject: [PATCH 10/11] fmt --- src/mac/frame/header.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mac/frame/header.rs b/src/mac/frame/header.rs index 8f2d6c9..48ee586 100644 --- a/src/mac/frame/header.rs +++ b/src/mac/frame/header.rs @@ -7,13 +7,13 @@ use super::frame_control::{mask, offset}; pub use super::frame_control::{AddressMode, FrameType, FrameVersion}; use super::security::AuxiliarySecurityHeader; +use super::security::SecurityContext; use super::DecodeError; use crate::mac::frame::EncodeError; #[cfg(not(feature = "security"))] use crate::mac::frame::FrameSerDesContext; use byte::{check_len, BytesExt, TryRead, TryWrite, LE}; use hash32_derive::Hash32; -use super::security::SecurityContext; #[cfg(feature = "security")] use { super::security::KeyDescriptorLookup, From 31ef6060ff54ca9fa81682f7b9705873ef6d8ca4 Mon Sep 17 00:00:00 2001 From: Lattice0 Date: Mon, 2 Sep 2024 21:13:07 -0300 Subject: [PATCH 11/11] fix comment --- src/utils.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index ee0340d..553e74a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -48,19 +48,5 @@ macro_rules! extended_enum { } } } - - // impl PartialEq<$name> for $ty { - // fn eq(&self, other: &$name) -> bool { - // match *other { - // $( $name::$var => *self == $val, )* - // } - // } - - // fn ne(&self, other: &$name) -> bool { - // match *other { - // $( $name::$var => *self != $val, )* - // } - // } - // } ); }