diff --git a/boards/components/src/ieee802154.rs b/boards/components/src/ieee802154.rs index 6fa0048fd1..9a541749e8 100644 --- a/boards/components/src/ieee802154.rs +++ b/boards/components/src/ieee802154.rs @@ -324,6 +324,7 @@ impl< )); mac_device.set_transmit_client(mux_mac); mac_device.set_receive_client(mux_mac); + mac_device.set_receive_secured_frame_no_decrypt_client(mux_mac); let userspace_mac = static_buffer @@ -347,6 +348,7 @@ impl< mac_device.set_device_procedure(radio_driver); userspace_mac.set_transmit_client(radio_driver); userspace_mac.set_receive_client(radio_driver); + userspace_mac.set_receive_secured_frame_no_decrypt_client(radio_driver); userspace_mac.set_pan(self.pan_id); userspace_mac.set_address(self.short_addr); userspace_mac.set_address_long(self.long_addr); diff --git a/capsules/extra/src/ieee802154/device.rs b/capsules/extra/src/ieee802154/device.rs index b4cfc3557c..b7f0e52294 100644 --- a/capsules/extra/src/ieee802154/device.rs +++ b/capsules/extra/src/ieee802154/device.rs @@ -24,6 +24,11 @@ pub trait MacDevice<'a> { fn set_transmit_client(&self, client: &'a dyn TxClient); /// Sets the receive client of this MAC device fn set_receive_client(&self, client: &'a dyn RxClient); + /// Sets the secure frame no decrypt receive client of this MAC device + fn set_receive_secured_frame_no_decrypt_client( + &self, + client: &'a dyn SecuredFrameNoDecryptRxClient, + ); /// The short 16-bit address of the MAC device fn get_address(&self) -> u16; @@ -124,8 +129,8 @@ pub trait RxClient { /// unsecured frames that have passed the incoming security procedure are /// exposed to the client. /// - /// - `buf`: The entire buffer containing the frame, including extra bytes - /// in front used for the physical layer. + /// - `buf`: The entire buffer containing the frame, potentially also + /// including extra bytes in front used for the physical layer. /// - `header`: A fully-parsed representation of the MAC header, with the /// caveat that the auxiliary security header is still included if the frame /// was previously secured. @@ -135,3 +140,32 @@ pub trait RxClient { /// - `data_len`: Length of the data payload fn receive<'a>(&self, buf: &'a [u8], header: Header<'a>, data_offset: usize, data_len: usize); } + +/// Trait to be implemented by users of the IEEE 802.15.4 device that wish to +/// receive frames possessing link layer security that remain secured (i.e. +/// have not been decrypted). This allows the client to perform decryption +/// on the frame. The callback is trigger whenever a valid frame is received. +/// In this context, raw refers to receiving frames without processing the +/// security of the frame. The SecuredFrameNoDecryptRxClient should not be +/// used to pass frames to the higher layers of the network stack that expect +/// unsecured frames. +pub trait SecuredFrameNoDecryptRxClient { + /// When a frame is received, this callback is triggered. The client only + /// receives an immutable borrow of the buffer. All frames, regardless of + /// their secured state, are exposed to the client. + /// + /// - `buf`: The entire buffer containing the frame, potentially also + /// including extra bytes in front used for the physical layer. + /// - `header`: A fully-parsed representation of the MAC header. + /// - `data_offset`: Offset of the data payload relative to + /// `buf`, so that the payload of the frame is contained in + /// `buf[data_offset..data_offset + data_len]`. + /// - `data_len`: Length of the data payload + fn receive_secured_frame<'a>( + &self, + buf: &'a [u8], + header: Header<'a>, + data_offset: usize, + data_len: usize, + ); +} diff --git a/capsules/extra/src/ieee802154/driver.rs b/capsules/extra/src/ieee802154/driver.rs index a2ca926c3a..8d19a33625 100644 --- a/capsules/extra/src/ieee802154/driver.rs +++ b/capsules/extra/src/ieee802154/driver.rs @@ -56,6 +56,7 @@ use crate::ieee802154::{device, framer}; use crate::net::ieee802154::{AddressMode, Header, KeyId, MacAddress, PanID, SecurityLevel}; use crate::net::stream::{decode_bytes, decode_u8, encode_bytes, encode_u8, SResult}; +use device::RxClient; use core::cell::Cell; @@ -1083,6 +1084,21 @@ fn encode_address(addr: &Option) -> usize { ((AddressMode::from(addr) as usize) << 16) | short_addr_only } +impl<'a, M: device::MacDevice<'a>> device::SecuredFrameNoDecryptRxClient for RadioDriver<'a, M> { + fn receive_secured_frame<'b>( + &self, + buf: &'b [u8], + header: Header<'b>, + data_offset: usize, + data_len: usize, + ) { + // The current 15.4 userspace receive accepts both secured and + // unsecured frames. As such, we can simply call the standard + // receive method of the RxClient trait. + self.receive(buf, header, data_offset, data_len) + } +} + impl<'a, M: device::MacDevice<'a>> device::RxClient for RadioDriver<'a, M> { fn receive<'b>(&self, buf: &'b [u8], header: Header<'b>, data_offset: usize, data_len: usize) { self.apps.each(|_, _, kernel_data| { diff --git a/capsules/extra/src/ieee802154/framer.rs b/capsules/extra/src/ieee802154/framer.rs index 948dc8501e..f38f0b1267 100644 --- a/capsules/extra/src/ieee802154/framer.rs +++ b/capsules/extra/src/ieee802154/framer.rs @@ -75,7 +75,7 @@ // TODO: Channel scanning // -use crate::ieee802154::device::{MacDevice, RxClient, TxClient}; +use crate::ieee802154::device::{MacDevice, RxClient, SecuredFrameNoDecryptRxClient, TxClient}; use crate::ieee802154::mac::Mac; use crate::net::ieee802154::{ FrameType, FrameVersion, Header, KeyId, MacAddress, PanID, Security, SecurityLevel, @@ -394,6 +394,7 @@ pub struct Framer<'a, M: Mac<'a>, A: AES128CCM<'a>> { /// `None`, except when transitioning between states. rx_state: MapCell, rx_client: OptionalCell<&'a dyn RxClient>, + secured_frame_no_decrypt_rx_client: OptionalCell<&'a dyn SecuredFrameNoDecryptRxClient>, crypt_buf: MapCell>, } @@ -413,6 +414,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { tx_client: OptionalCell::empty(), rx_state: MapCell::new(RxState::Idle), rx_client: OptionalCell::empty(), + secured_frame_no_decrypt_rx_client: OptionalCell::empty(), crypt_buf: MapCell::new(crypt_buf), } } @@ -498,8 +500,8 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { Some(key) => key, None => { // Key not found -- pass raw encrypted packet to client - self.rx_client.map(|client| { - client.receive(&buf[PSDU_OFFSET..], header, data_offset, data_len); + self.secured_frame_no_decrypt_rx_client.map(|client| { + client.receive_secured_frame(&buf[PSDU_OFFSET..], header, data_offset, data_len); }); return None; } @@ -780,6 +782,13 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> { self.rx_client.set(client); } + fn set_receive_secured_frame_no_decrypt_client( + &self, + client: &'a dyn super::device::SecuredFrameNoDecryptRxClient, + ) { + self.secured_frame_no_decrypt_rx_client.set(client); + } + fn get_address(&self) -> u16 { self.mac.get_address() } diff --git a/capsules/extra/src/ieee802154/virtual_mac.rs b/capsules/extra/src/ieee802154/virtual_mac.rs index 3d669892f2..2e94eaf265 100644 --- a/capsules/extra/src/ieee802154/virtual_mac.rs +++ b/capsules/extra/src/ieee802154/virtual_mac.rs @@ -35,8 +35,6 @@ use crate::ieee802154::{device, framer}; use crate::net::ieee802154::{Header, KeyId, MacAddress, PanID, SecurityLevel}; -use core::cell::Cell; - use kernel::collections::list::{List, ListLink, ListNode}; use kernel::utilities::cells::{MapCell, OptionalCell}; use kernel::ErrorCode; @@ -67,6 +65,20 @@ impl<'a, M: device::MacDevice<'a>> device::RxClient for MuxMac<'a, M> { } } +impl<'a, M: device::MacDevice<'a>> device::SecuredFrameNoDecryptRxClient for MuxMac<'a, M> { + fn receive_secured_frame<'b>( + &self, + buf: &'b [u8], + header: Header<'b>, + data_offset: usize, + data_len: usize, + ) { + for user in self.users.iter() { + user.receive_secured_frame(buf, header, data_offset, data_len); + } + } +} + impl<'a, M: device::MacDevice<'a>> MuxMac<'a, M> { pub const fn new(mac: &'a M) -> MuxMac<'a, M> { MuxMac { @@ -196,8 +208,9 @@ pub struct MacUser<'a, M: device::MacDevice<'a>> { mux: &'a MuxMac<'a, M>, operation: MapCell, next: ListLink<'a, MacUser<'a, M>>, - tx_client: Cell>, - rx_client: Cell>, + tx_client: OptionalCell<&'a dyn device::TxClient>, + rx_client: OptionalCell<&'a dyn device::RxClient>, + secure_frame_no_decrypt_rx_client: OptionalCell<&'a dyn device::SecuredFrameNoDecryptRxClient>, } impl<'a, M: device::MacDevice<'a>> MacUser<'a, M> { @@ -206,8 +219,9 @@ impl<'a, M: device::MacDevice<'a>> MacUser<'a, M> { mux: mux, operation: MapCell::new(Op::Idle), next: ListLink::empty(), - tx_client: Cell::new(None), - rx_client: Cell::new(None), + tx_client: OptionalCell::empty(), + rx_client: OptionalCell::empty(), + secure_frame_no_decrypt_rx_client: OptionalCell::empty(), } } } @@ -224,6 +238,18 @@ impl<'a, M: device::MacDevice<'a>> MacUser<'a, M> { .get() .map(move |client| client.receive(buf, header, data_offset, data_len)); } + + fn receive_secured_frame<'b>( + &self, + buf: &'b [u8], + header: Header<'b>, + data_offset: usize, + data_len: usize, + ) { + self.secure_frame_no_decrypt_rx_client + .get() + .map(move |client| client.receive_secured_frame(buf, header, data_offset, data_len)); + } } impl<'a, M: device::MacDevice<'a>> ListNode<'a, MacUser<'a, M>> for MacUser<'a, M> { @@ -234,11 +260,18 @@ impl<'a, M: device::MacDevice<'a>> ListNode<'a, MacUser<'a, M>> for MacUser<'a, impl<'a, M: device::MacDevice<'a>> device::MacDevice<'a> for MacUser<'a, M> { fn set_transmit_client(&self, client: &'a dyn device::TxClient) { - self.tx_client.set(Some(client)); + self.tx_client.set(client); } fn set_receive_client(&self, client: &'a dyn device::RxClient) { - self.rx_client.set(Some(client)); + self.rx_client.set(client); + } + + fn set_receive_secured_frame_no_decrypt_client( + &self, + client: &'a dyn device::SecuredFrameNoDecryptRxClient, + ) { + self.secure_frame_no_decrypt_rx_client.set(client); } fn get_address(&self) -> u16 {