capsules_extra/ieee802154/framer.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Implements IEEE 802.15.4 MAC device abstraction over a 802.15.4 MAC interface.
6//!
7//! Allows its users to prepare and send frames in plaintext, handling 802.15.4
8//! encoding and security procedures (in the future) transparently.
9//!
10//! However, certain IEEE 802.15.4 MAC device concepts are not implemented in
11//! this layer of abstraction and instead handled in hardware for performance
12//! purposes. These include CSMA-CA backoff, FCS generation and authentication,
13//! and automatic acknowledgement. Radio power management and channel selection
14//! is also passed down to the MAC control layer.
15//!
16//! Usage
17//! -----
18//!
19//! To use this capsule, we need an implementation of a hardware
20//! `capsules_extra::ieee802154::mac::Mac`. Suppose we have such an implementation of type
21//! `XMacDevice`.
22//!
23//! ```rust,ignore
24//! let xmac: &XMacDevice = /* ... */;
25//! let mac_device = static_init!(
26//! capsules_extra::ieee802154::mac::Framer<'static, XMacDevice>,
27//! capsules_extra::ieee802154::mac::Framer::new(xmac));
28//! xmac.set_transmit_client(mac_device);
29//! xmac.set_receive_client(mac_device, &mut MAC_RX_BUF);
30//! xmac.set_config_client(mac_device);
31//! ```
32//!
33//! The `mac_device` device is now set up. Users of the MAC device can now
34//! configure the underlying radio, prepare and send frames:
35//!
36//! ```rust,ignore
37//! mac_device.set_pan(0xABCD);
38//! mac_device.set_address(0x1008);
39//! mac_device.config_commit();
40//!
41//! let frame = mac_device
42//! .prepare_data_frame(&mut STATIC_BUFFER,
43//! 0xABCD, MacAddress::Short(0x1008),
44//! 0xABCD, MacAddress::Short(0x1009),
45//! None)
46//! .ok()
47//! .map(|frame| {
48//! let rval = frame.append_payload(&mut SOME_DATA[..10]);
49//! if rval == Ok(()) {
50//! let (rval, _) = mac_device.transmit(frame);
51//! rval
52//! } else {
53//! rval
54//! }
55//! });
56//! ```
57//!
58//! You should also be able to set up the userspace driver for receiving/sending
59//! 802.15.4 frames:
60//!
61//! ```rust,ignore
62//! use kernel::static_init;
63//!
64//! let radio_capsule = static_init!(
65//! capsules_extra::ieee802154::RadioDriver<'static>,
66//! capsules_extra::ieee802154::RadioDriver::new(mac_device, board_kernel.create_grant(&grant_cap), &mut RADIO_BUF));
67//! mac_device.set_key_procedure(radio_capsule);
68//! mac_device.set_device_procedure(radio_capsule);
69//! mac_device.set_transmit_client(radio_capsule);
70//! mac_device.set_receive_client(radio_capsule);
71//! ```
72
73//
74// TODO: Encryption/decryption
75// TODO: Sending beacon frames
76// TODO: Channel scanning
77//
78
79use crate::ieee802154::device::{MacDevice, RxClient, TxClient};
80use crate::ieee802154::mac::Mac;
81use crate::net::ieee802154::{
82 FrameType, FrameVersion, Header, KeyId, MacAddress, PanID, Security, SecurityLevel,
83};
84use crate::net::stream::SResult;
85use crate::net::stream::{encode_bytes, encode_u32, encode_u8};
86
87use core::cell::Cell;
88
89use kernel::hil::radio::{self, LQI_SIZE};
90use kernel::hil::symmetric_encryption::{CCMClient, AES128CCM};
91use kernel::processbuffer::ReadableProcessSlice;
92use kernel::utilities::cells::{MapCell, OptionalCell};
93use kernel::utilities::leasable_buffer::SubSliceMut;
94use kernel::ErrorCode;
95
96/// Wraps a static mutable byte slice along with header information
97/// for a payload.
98///
99/// This enables the user to abdicate any concerns about
100/// where the payload should be placed in the buffer.
101#[derive(Eq, PartialEq, Debug)]
102pub struct Frame {
103 buf: &'static mut [u8],
104 info: FrameInfo,
105}
106
107/// This contains just enough information about a frame to determine
108///
109/// 1. How to encode it once its payload has been finalized
110/// 2. The sizes of the mac header, payload and MIC tag length to be added
111///
112/// These offsets are relative to the PSDU or `buf[radio::PSDU_OFFSET..]` so
113/// that the mac frame length is `data_offset + data_len`
114#[derive(Copy, Clone, Eq, PartialEq, Debug)]
115struct FrameInfo {
116 frame_type: FrameType,
117
118 // The MAC payload, including Payload IEs
119 mac_payload_offset: usize,
120 // The data payload, not including Payload IEs
121 data_offset: usize,
122 // The length of the data payload, not including MIC and FCS
123 data_len: usize,
124 // The length of the MIC
125 mic_len: usize,
126
127 // Security level, key, and nonce
128 security_params: Option<(SecurityLevel, [u8; 16], [u8; 13])>,
129}
130
131impl Frame {
132 /// Consumes the frame and retrieves the buffer it wraps
133 pub fn into_buf(self) -> &'static mut [u8] {
134 self.buf
135 }
136
137 /// Calculates how much more data this frame can hold
138 pub fn remaining_data_capacity(&self) -> usize {
139 self.buf.len() - self.info.secured_length()
140 }
141
142 /// Appends payload bytes into the frame if possible
143 pub fn append_payload(&mut self, payload: &[u8]) -> Result<(), ErrorCode> {
144 if payload.len() > self.remaining_data_capacity() {
145 return Err(ErrorCode::NOMEM);
146 }
147 let begin = self.info.unsecured_length();
148 self.buf[begin..begin + payload.len()].copy_from_slice(payload);
149 self.info.data_len += payload.len();
150
151 Ok(())
152 }
153
154 /// Appends payload bytes from a process slice into the frame if
155 /// possible
156 pub fn append_payload_process(
157 &mut self,
158 payload_buf: &ReadableProcessSlice,
159 ) -> Result<(), ErrorCode> {
160 if payload_buf.len() > self.remaining_data_capacity() {
161 return Err(ErrorCode::NOMEM);
162 }
163 let begin = self.info.unsecured_length();
164 payload_buf.copy_to_slice(&mut self.buf[begin..begin + payload_buf.len()]);
165 self.info.data_len += payload_buf.len();
166
167 Ok(())
168 }
169}
170
171impl FrameInfo {
172 /// Current size of the frame, not including the MAC footer or the MIC
173 fn unsecured_length(&self) -> usize {
174 self.data_offset + self.data_len
175 }
176
177 /// Current size of the frame, not including the MAC footer but including
178 /// the MIC
179 fn secured_length(&self) -> usize {
180 self.data_offset + self.data_len + self.mic_len
181 }
182
183 /// Compute the offsets in the buffer for the a data and m data fields in
184 /// the CCM* authentication and encryption procedures which depends on the
185 /// frame type and security levels. Returns the (offset, len) of the m data
186 /// fields, not including the MIC. The a data is always the remaining prefix
187 /// of the header, so it can be determined implicitly.
188 #[allow(dead_code)]
189 fn ccm_encrypt_ranges(&self) -> (usize, usize) {
190 // IEEE 802.15.4-2015: Table 9-1. Exceptions to Private Payload field
191 // The boundary between open and private payload fields depends
192 // on the type of frame.
193 let private_payload_offset = match self.frame_type {
194 FrameType::Beacon => {
195 // Beginning of beacon payload field
196 unimplemented!()
197 }
198 FrameType::MACCommand => {
199 // Beginning of MAC command content field
200 unimplemented!()
201 }
202 _ => {
203 // MAC payload field, which includes payload IEs
204 self.mac_payload_offset
205 }
206 };
207
208 // IEEE 802.15.4-2015: Table 9-3. a data and m data
209 let encryption_needed = self
210 .security_params
211 .is_some_and(|(level, _, _)| level.encryption_needed());
212 if !encryption_needed {
213 // If only integrity is need, a data is the whole frame
214 (self.unsecured_length(), 0)
215 } else {
216 // Otherwise, a data is the header and the open payload, and
217 // m data is the private payload field; unsecured length is the end of
218 // private payload, length of private payload is difference between
219 // the offset and unsecured length
220 (
221 private_payload_offset, // m_offset
222 self.unsecured_length() - private_payload_offset, // m_len
223 )
224 }
225 }
226}
227
228/// Generate a 15.4 CCM nonce from the device address, frame counter, and SecurityLevel
229pub fn get_ccm_nonce(device_addr: &[u8; 8], frame_counter: u32, level: SecurityLevel) -> [u8; 13] {
230 let mut nonce = [0u8; 13];
231 let encode_ccm_nonce = |buf: &mut [u8]| {
232 let off = enc_consume!(buf; encode_bytes, device_addr.as_ref());
233 let off = enc_consume!(buf, off; encode_u32, frame_counter);
234 let off = enc_consume!(buf, off; encode_u8, level as u8);
235 stream_done!(off);
236 };
237 match encode_ccm_nonce(&mut nonce).done() {
238 None => {
239 // This should not be possible
240 panic!("Failed to produce ccm nonce");
241 }
242 Some(_) => nonce,
243 }
244}
245
246/// The needed buffer size might be bigger than an MTU, because
247/// the CCM* authentication procedure
248///
249/// - adds an extra 16-byte block in front of the a and m data
250/// - prefixes the a data with a length encoding and pads the result
251/// - pads the m data to 16-byte blocks
252pub const CRYPT_BUF_SIZE: usize = radio::MAX_MTU + 3 * 16;
253
254/// IEEE 802.15.4-2015, 9.2.2, KeyDescriptor lookup procedure.
255///
256/// Trait to be implemented by an upper layer that manages the list of 802.15.4
257/// key descriptors. This trait interface enables the lookup procedure to be
258/// implemented either explicitly (managing a list of KeyDescriptors) or
259/// implicitly with some equivalent logic.
260pub trait KeyProcedure {
261 /// Lookup the KeyDescriptor matching the provided security level and key ID
262 /// mode and return the key associated with it.
263 fn lookup_key(&self, level: SecurityLevel, key_id: KeyId) -> Option<[u8; 16]>;
264}
265
266/// IEEE 802.15.4-2015, 9.2.5, DeviceDescriptor lookup procedure.
267///
268/// Trait to be implemented by an upper layer that manages the list of 802.15.4
269/// device descriptors. This trait interface enables the lookup procedure to be
270/// implemented either explicitly (managing a list of DeviceDescriptors) or
271/// implicitly with some equivalent logic.
272pub trait DeviceProcedure {
273 /// Look up the extended MAC address of a device given either its short or
274 /// long address. As defined in the IEEE 802.15.4 spec, even if the provided
275 /// address is already long, a long address should be returned only if the
276 /// given address matches a known DeviceDescriptor.
277 fn lookup_addr_long(&self, addr: MacAddress) -> Option<[u8; 8]>;
278}
279
280/// This state enum describes the state of the transmission pipeline.
281/// Conditionally-present state is also included as fields in the enum variants.
282/// We can view the transmission process as a state machine driven by the
283/// following events:
284///
285/// - calls to `Mac#transmit`
286/// - `send_done` callbacks from the underlying radio
287/// - `config_done` callbacks from the underlying radio (if, for example,
288/// configuration was in progress when a transmission was requested)
289#[derive(Eq, PartialEq, Debug)]
290enum TxState {
291 /// There is no frame to be transmitted.
292 Idle,
293 /// There is a valid frame that needs to be secured before transmission.
294 ReadyToEncrypt(FrameInfo, &'static mut [u8]),
295 /// There is currently a frame being encrypted by the encryption facility.
296 #[allow(dead_code)]
297 Encrypting(FrameInfo),
298 /// There is a frame that is completely secured or does not require
299 /// security, and is waiting to be passed to the radio.
300 ReadyToTransmit(FrameInfo, &'static mut [u8]),
301}
302
303#[derive(Eq, PartialEq, Debug)]
304enum RxState {
305 /// There is no frame that has been received.
306 Idle,
307 /// There is a secured frame that needs to be decrypted.
308 /// ReadyToDecrypt(FrameInfo, buf, lqi)
309 ReadyToDecrypt(FrameInfo, &'static mut [u8], u8),
310 /// A secured frame is currently being decrypted by the decryption facility.
311 /// Decrypting(FrameInfo, lqi)
312 #[allow(dead_code)]
313 Decrypting(FrameInfo, u8),
314 /// There is an unsecured frame that needs to be re-parsed and exposed to
315 /// the client. ReadyToYield(FrameInfo, buf, lqi)
316 #[allow(dead_code)]
317 ReadyToYield(FrameInfo, &'static mut [u8], u8),
318}
319
320/// Wraps an IEEE 802.15.4 [kernel::hil::radio::Radio]
321/// and exposes [`capsules_extra::ieee802154::mac::Mac`](crate::ieee802154::mac::Mac) functionality.
322///
323/// It hides header preparation, transmission and processing logic
324/// from the user by essentially maintaining multiple state machines
325/// corresponding to the transmission, reception and
326/// encryption/decryption pipelines. See the documentation in
327/// `capsules/extra/src/ieee802154/mac.rs` for more details.
328pub struct Framer<'a, M: Mac<'a>, A: AES128CCM<'a>> {
329 mac: &'a M,
330 aes_ccm: &'a A,
331 data_sequence: Cell<u8>,
332
333 /// KeyDescriptor lookup procedure
334 key_procedure: OptionalCell<&'a dyn KeyProcedure>,
335 /// DeviceDescriptor lookup procedure
336 device_procedure: OptionalCell<&'a dyn DeviceProcedure>,
337
338 /// Transmission pipeline state. This should never be `None`, except when
339 /// transitioning between states. That is, any method that consumes the
340 /// current state should always remember to replace it along with the
341 /// associated state information.
342 tx_state: MapCell<TxState>,
343 tx_client: OptionalCell<&'a dyn TxClient>,
344
345 /// Reception pipeline state. Similar to the above, this should never be
346 /// `None`, except when transitioning between states.
347 rx_state: MapCell<RxState>,
348 rx_client: OptionalCell<&'a dyn RxClient>,
349 crypt_buf: MapCell<SubSliceMut<'static, u8>>,
350}
351
352impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> {
353 pub fn new(
354 mac: &'a M,
355 aes_ccm: &'a A,
356 crypt_buf: SubSliceMut<'static, u8>,
357 ) -> Framer<'a, M, A> {
358 Framer {
359 mac,
360 aes_ccm,
361 data_sequence: Cell::new(0),
362 key_procedure: OptionalCell::empty(),
363 device_procedure: OptionalCell::empty(),
364 tx_state: MapCell::new(TxState::Idle),
365 tx_client: OptionalCell::empty(),
366 rx_state: MapCell::new(RxState::Idle),
367 rx_client: OptionalCell::empty(),
368 crypt_buf: MapCell::new(crypt_buf),
369 }
370 }
371
372 /// Sets the IEEE 802.15.4 key lookup procedure to be used.
373 pub fn set_key_procedure(&self, key_procedure: &'a dyn KeyProcedure) {
374 self.key_procedure.set(key_procedure);
375 }
376
377 /// Sets the IEEE 802.15.4 key lookup procedure to be used.
378 pub fn set_device_procedure(&self, device_procedure: &'a dyn DeviceProcedure) {
379 self.device_procedure.set(device_procedure);
380 }
381
382 /// Look up the key using the IEEE 802.15.4 KeyDescriptor lookup procedure
383 /// implemented elsewhere.
384 fn lookup_key(&self, level: SecurityLevel, key_id: KeyId) -> Option<[u8; 16]> {
385 self.key_procedure
386 .and_then(|key_procedure| key_procedure.lookup_key(level, key_id))
387 }
388
389 /// IEEE 802.15.4-2015, 9.2.1, outgoing frame security procedure
390 /// Performs the first checks in the security procedure. The rest of the
391 /// steps are performed as part of the transmission pipeline.
392 /// Returns the next `TxState` to enter.
393 fn outgoing_frame_security(&self, buf: &'static mut [u8], frame_info: FrameInfo) -> TxState {
394 // IEEE 802.15.4-2015: 9.2.1, outgoing frame security
395 // Steps a-e have already been performed in the frame preparation step,
396 // so we only need to dispatch on the security parameters in the frame info
397 match frame_info.security_params {
398 Some((level, _, _)) => {
399 if level == SecurityLevel::None {
400 // This case should never occur if the FrameInfo was
401 // prepared by prepare_data_frame
402 TxState::ReadyToTransmit(frame_info, buf)
403 } else {
404 TxState::ReadyToEncrypt(frame_info, buf)
405 }
406 }
407 None => TxState::ReadyToTransmit(frame_info, buf),
408 }
409 }
410
411 /// IEEE 802.15.4-2015, 9.2.3, incoming frame security procedure
412 fn incoming_frame_security(
413 &self,
414 buf: &'static mut [u8],
415 frame_len: usize,
416 lqi: u8,
417 ) -> RxState {
418 // Try to decode the MAC header. Three possible results can occur:
419 // 1) The frame should be dropped and the buffer returned to the radio
420 // 2) The frame is unsecured. We immediately expose the frame to the
421 // user and queue the buffer for returning to the radio.
422 // 3) The frame needs to be unsecured.
423
424 // The buffer containing the 15.4 packet also contains the PSDU bytes and an LQI
425 // byte. We only pass the 15.4 packet up the stack and slice buf accordingly.
426 let frame_buffer = &buf[radio::PSDU_OFFSET..(buf.len() - LQI_SIZE)];
427
428 let result = Header::decode(frame_buffer, false)
429 .done()
430 .and_then(|(data_offset, (header, mac_payload_offset))| {
431 // Note: there is a complication here regarding the offsets.
432 // When the received frame has security enabled, the payload
433 // (including the payload IEs) is encrypted, and hence the data
434 // payload field includes the encrypted payload IEs too.
435 // However, when the frame is not encrypted, the data payload
436 // field does not include the payload IEs.
437 //
438 // This is fine because we re-parse the unsecured frame before
439 // exposing it to the user. At that time, the data payload field
440 // will not include the payload IEs.
441 let mic_len = header.security.map_or(0, |sec| sec.level.mic_len());
442 let data_len = frame_len - data_offset - mic_len;
443 if let Some(security) = header.security {
444 // IEEE 802.15.4-2015: 9.2.3, incoming frame security procedure
445 // for security-enabled headers
446 if header.version == FrameVersion::V2003 {
447 None
448 } else {
449 // Step e: Lookup the key.
450 let key = match self.lookup_key(security.level, security.key_id) {
451 Some(key) => key,
452 None => {
453 return None;
454 }
455 };
456
457 // Step f: Obtain the extended source address
458 // TODO: For Thread, when the frame's security header
459 // specifies `KeyIdMode::Source4Index`, the source
460 // address used for the nonce is actually a constant
461 // defined in their spec
462 let device_addr = match header.src_addr {
463 Some(mac) => match mac {
464 MacAddress::Long(val) => val,
465 MacAddress::Short(_) => {
466 kernel::debug!("[15.4] DROPPED PACKET - error only short address provided on encrypted packet.");
467 return None
468 },
469 },
470 None => {
471 kernel::debug!("[15.4] DROPPED PACKET - Malformed, no src address provided.");
472 return None
473 },
474 };
475
476 // Step g, h: Check frame counter
477 let frame_counter = match security.frame_counter {
478 Some(frame_counter) => {
479 if frame_counter == 0xffffffff {
480 // Counter error
481 return None;
482 }
483 // TODO: Check frame counter against source device
484 frame_counter
485 }
486 // TSCH mode, where ASN is used instead, not supported
487 None => {
488 return None;
489 }
490 };
491
492 // Compute ccm nonce
493 let nonce = get_ccm_nonce(&device_addr, frame_counter, security.level);
494
495 Some(FrameInfo {
496 frame_type: header.frame_type,
497 mac_payload_offset,
498 data_offset,
499 data_len,
500 mic_len,
501 security_params: Some((security.level, key, nonce)),
502 })
503 }
504 } else {
505 // No security needed, can yield the frame immediately
506
507 // The buffer containing the 15.4 packet also contains the PSDU bytes and an LQI
508 // byte. We only pass the 15.4 packet up the stack and slice buf accordingly.
509 let frame_buffer = &buf[radio::PSDU_OFFSET..(buf.len() - LQI_SIZE)];
510 self.rx_client.map(|client| {
511 client.receive(frame_buffer, header, lqi, data_offset, data_len);
512 });
513 None
514 }
515 });
516
517 match result {
518 None => {
519 // The packet was not encrypted, we completed the 15.4 framer procedure, and passed the packet to the
520 // client. We can now return the recv buffer to the radio driver and enter framer's idle state.
521 self.mac.set_receive_buffer(buf);
522 RxState::Idle
523 }
524 Some(frame_info) => RxState::ReadyToDecrypt(frame_info, buf, lqi),
525 }
526 }
527
528 /// Advances the transmission pipeline if it can be advanced.
529 fn step_transmit_state(&self) -> Result<(), (ErrorCode, &'static mut [u8])> {
530 self.tx_state.take().map_or_else(
531 || panic!("missing tx_state"),
532 |state| {
533 // This mechanism is a little more clunky, but makes it
534 // difficult to forget to replace `tx_state`.
535 let (next_state, result) = match state {
536 TxState::Idle => (TxState::Idle, Ok(())),
537 TxState::ReadyToEncrypt(info, buf) => {
538 match info.security_params {
539 None => {
540 // `ReadyToEncrypt` should only be entered when
541 // `security_params` is not `None`.
542 (TxState::Idle, Err((ErrorCode::FAIL, buf)))
543 }
544 Some((level, key, nonce)) => {
545 let (m_off, m_len) = info.ccm_encrypt_ranges();
546 let (a_off, m_off) =
547 (radio::PSDU_OFFSET, radio::PSDU_OFFSET + m_off);
548
549 // Crypto setup failed; fail sending packet and return to idle
550 if self.aes_ccm.set_key(&key) != Ok(())
551 || self.aes_ccm.set_nonce(&nonce) != Ok(())
552 {
553 (TxState::Idle, Err((ErrorCode::FAIL, buf)))
554 } else {
555 let res = self.aes_ccm.crypt(
556 buf,
557 a_off,
558 m_off,
559 m_len,
560 info.mic_len,
561 level.encryption_needed(),
562 true,
563 );
564 match res {
565 Ok(()) => (TxState::Encrypting(info), Ok(())),
566 Err((ErrorCode::BUSY, buf)) => {
567 (TxState::ReadyToEncrypt(info, buf), Ok(()))
568 }
569 Err((ecode, buf)) => (TxState::Idle, Err((ecode, buf))),
570 }
571 }
572 }
573 }
574 }
575 TxState::Encrypting(info) => {
576 // This state should be advanced only by the hardware
577 // encryption callback.
578 (TxState::Encrypting(info), Ok(()))
579 }
580 TxState::ReadyToTransmit(info, buf) => {
581 let res = self.mac.transmit(buf, info.secured_length());
582 match res {
583 // If the radio is busy, just wait for either a
584 // transmit_done or config_done callback to trigger
585 // this state transition again
586 Err((ErrorCode::BUSY, buf)) => {
587 (TxState::ReadyToTransmit(info, buf), Ok(()))
588 }
589 Ok(()) => (TxState::Idle, Ok(())),
590 Err((ecode, buf)) => (TxState::Idle, Err((ecode, buf))),
591 }
592 }
593 };
594 self.tx_state.replace(next_state);
595 result
596 },
597 )
598 }
599
600 /// Advances the reception pipeline if it can be advanced.
601 fn step_receive_state(&self) {
602 self.rx_state.take().map(|state| {
603 let next_state = match state {
604 RxState::Idle => RxState::Idle,
605 RxState::ReadyToDecrypt(info, buf, lqi) => {
606 match info.security_params {
607 None => {
608 // `ReadyToDecrypt` should only be entered when
609 // `security_params` is not `None`.
610 RxState::Idle
611 }
612 Some((level, key, nonce)) => {
613 let (m_off, m_len) = info.ccm_encrypt_ranges();
614 let (a_off, m_off) = (radio::PSDU_OFFSET, radio::PSDU_OFFSET + m_off);
615
616 // Crypto setup failed; fail receiving packet and return to idle
617 if self.aes_ccm.set_key(&key) != Ok(())
618 || self.aes_ccm.set_nonce(&nonce) != Ok(())
619 {
620 // No error is returned for the receive function because recv occurs implicitly
621 // Log debug statement here so that this error does not occur silently
622 kernel::debug!(
623 "[15.4 RECV FAIL] - Failed setting crypto key/nonce."
624 );
625 self.mac.set_receive_buffer(buf);
626 RxState::Idle
627 } else {
628 // The crypto operation requires multiple steps through the receiving pipeline and
629 // an unknown quanitity of time to perform decryption. Holding the 15.4 radio's
630 // receive buffer for this period of time is suboptimal as packets will be dropped.
631 // The radio driver assumes the mac.set_receive_buffer(...) function is called prior
632 // to returning from the framer. These constraints necessitate the creation of a seperate
633 // crypto buffer for the radio framer so that the framer can return the radio driver's
634 // receive buffer and then perform decryption using the copied packet in the crypto buffer.
635 let res = self.crypt_buf.take().map(|mut crypt_buf| {
636 crypt_buf[0..buf.len()].copy_from_slice(buf);
637 crypt_buf.slice(0..buf.len());
638
639 self.aes_ccm.crypt(
640 crypt_buf.take(),
641 a_off,
642 m_off,
643 m_len,
644 info.mic_len,
645 level.encryption_needed(),
646 true,
647 )
648 });
649
650 // The potential scenarios include:
651 // - (1) Successfully transfer packet to crypto buffer and succesfully begin crypto operation
652 // - (2) Succesfully transfer packet to crypto buffer, but the crypto operation aes_ccm.crypt(...)
653 // is busy so we do not advance the reception pipeline and retry on the next iteration
654 // - (3) Succesfully transfer packet to crypto buffer, but the crypto operation fails for some
655 // unknown reason (likely due to the crypto buffer's configuration or the offset/len parameters
656 // passed to the function. It is not possible to decrypt the packet so we drop the packet, return
657 // the radio drivers recv buffer and return the framer recv state machine to idle
658 // - (4) The crypto buffer is empty (in use elsewhere) and we are unable to copy the received
659 // packet. This packet is dropped and we must return the buffer to the radio driver. This
660 // scenario is handled in the None case
661 match res {
662 // Scenario 1
663 Some(Ok(())) => {
664 self.mac.set_receive_buffer(buf);
665 RxState::Decrypting(info, lqi)
666 }
667 // Scenario 2
668 Some(Err((ErrorCode::BUSY, buf))) => {
669 RxState::ReadyToDecrypt(info, buf, lqi)
670 }
671 // Scenario 3
672 Some(Err((_, fail_crypt_buf))) => {
673 self.mac.set_receive_buffer(buf);
674 self.crypt_buf.replace(SubSliceMut::new(fail_crypt_buf));
675 RxState::Idle
676 }
677 // Scenario 4
678 None => {
679 self.mac.set_receive_buffer(buf);
680 RxState::Idle
681 }
682 }
683 }
684 }
685 }
686 }
687 RxState::Decrypting(info, lqi) => {
688 // This state should be advanced only by the hardware
689 // encryption callback.
690 RxState::Decrypting(info, lqi)
691 }
692 RxState::ReadyToYield(info, buf, lqi) => {
693 // Between the secured and unsecured frames, the
694 // unsecured frame length remains constant but the data
695 // offsets may change due to the presence of PayloadIEs.
696 // Hence, we can only use the unsecured length from the
697 // frame info, but not the offsets.
698 let frame_len = info.unsecured_length();
699 if let Some((data_offset, (header, _))) = Header::decode(
700 &buf[radio::PSDU_OFFSET..(radio::PSDU_OFFSET + radio::MAX_FRAME_SIZE)],
701 true,
702 )
703 .done()
704 {
705 // IEEE 802.15.4-2015 specifies that unsecured
706 // frames do not have auxiliary security headers,
707 // but we do not remove the auxiliary security
708 // header before returning the frame to the client.
709 // This is so that it is possible to tell if the
710 // frame was secured or unsecured, while still
711 // always receiving the frame payload in plaintext.
712 //
713 // The buffer containing the 15.4 packet also contains
714 // the PSDU bytes and an LQI byte. We only pass the
715 // 15.4 packet up the stack and slice buf accordingly.
716 let frame_buffer = &buf[radio::PSDU_OFFSET..(buf.len() - LQI_SIZE)];
717 self.rx_client.map(|client| {
718 client.receive(
719 frame_buffer,
720 header,
721 lqi,
722 data_offset,
723 frame_len - data_offset,
724 );
725 });
726 self.crypt_buf.replace(SubSliceMut::new(buf));
727 }
728 RxState::Idle
729 }
730 };
731 self.rx_state.replace(next_state);
732 });
733 }
734}
735
736impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> {
737 fn set_transmit_client(&self, client: &'a dyn TxClient) {
738 self.tx_client.set(client);
739 }
740
741 fn set_receive_client(&self, client: &'a dyn RxClient) {
742 self.rx_client.set(client);
743 }
744
745 fn get_address(&self) -> u16 {
746 self.mac.get_address()
747 }
748
749 fn get_address_long(&self) -> [u8; 8] {
750 self.mac.get_address_long()
751 }
752
753 fn get_pan(&self) -> u16 {
754 self.mac.get_pan()
755 }
756
757 fn set_address(&self, addr: u16) {
758 self.mac.set_address(addr)
759 }
760
761 fn set_address_long(&self, addr: [u8; 8]) {
762 self.mac.set_address_long(addr)
763 }
764
765 fn set_pan(&self, id: u16) {
766 self.mac.set_pan(id)
767 }
768
769 fn config_commit(&self) {
770 self.mac.config_commit()
771 }
772
773 fn is_on(&self) -> bool {
774 self.mac.is_on()
775 }
776
777 fn start(&self) -> Result<(), ErrorCode> {
778 self.mac.start()
779 }
780
781 fn prepare_data_frame(
782 &self,
783 buf: &'static mut [u8],
784 dst_pan: PanID,
785 dst_addr: MacAddress,
786 src_pan: PanID,
787 src_addr: MacAddress,
788 security_needed: Option<(SecurityLevel, KeyId)>,
789 ) -> Result<Frame, &'static mut [u8]> {
790 // IEEE 802.15.4-2015: 9.2.1, outgoing frame security
791 // Steps a-e of the security procedure are implemented here.
792
793 // TODO: For Thread, in the case of `KeyIdMode::Source4Index`, the source
794 // address should instead be some constant defined in their
795 // specification.
796
797 let security_desc = security_needed.and_then(|(level, key_id)| {
798 // To decrypt the packet, we need the long addr.
799 // Without the long addr, we are unable to proceed
800 // and return None
801 let src_addr_long = match src_addr {
802 MacAddress::Long(addr) => addr,
803 MacAddress::Short(_) => return None,
804 };
805
806 self.lookup_key(level, key_id).map(|key| {
807 // TODO: lookup frame counter for device
808 let frame_counter = 0;
809 let nonce = get_ccm_nonce(&src_addr_long, frame_counter, level);
810 (
811 Security {
812 level,
813 asn_in_nonce: false,
814 frame_counter: Some(frame_counter),
815 key_id,
816 },
817 key,
818 nonce,
819 )
820 })
821 });
822 if security_needed.is_some() && security_desc.is_none() {
823 // If security was requested, fail when desired key was not found.
824 return Err(buf);
825 }
826
827 // Construct MAC header
828 let security = security_desc.map(|(sec, _, _)| sec);
829 let mic_len = security.map_or(0, |sec| sec.level.mic_len());
830 let header = Header {
831 frame_type: FrameType::Data,
832 /* TODO: determine this by looking at queue, and also set it in
833 * hardware so that ACKs set this flag to the right value. */
834 frame_pending: false,
835 // Unicast data frames request acknowledgement
836 ack_requested: true,
837 version: FrameVersion::V2006,
838 seq: Some(self.data_sequence.get()),
839 dst_pan: Some(dst_pan),
840 dst_addr: Some(dst_addr),
841 src_pan: Some(src_pan),
842 src_addr: Some(src_addr),
843 security,
844 header_ies: Default::default(),
845 header_ies_len: 0,
846 payload_ies: Default::default(),
847 payload_ies_len: 0,
848 };
849
850 match header.encode(buf, true).done() {
851 Some((data_offset, mac_payload_offset)) => Ok(Frame {
852 buf,
853 info: FrameInfo {
854 frame_type: FrameType::Data,
855 mac_payload_offset,
856 data_offset,
857 data_len: 0,
858 mic_len,
859 security_params: security_desc.map(|(sec, key, nonce)| (sec.level, key, nonce)),
860 },
861 }),
862 None => Err(buf),
863 }
864 }
865
866 fn transmit(&self, frame: Frame) -> Result<(), (ErrorCode, &'static mut [u8])> {
867 let Frame { buf, info } = frame;
868 let state = match self.tx_state.take() {
869 None => {
870 return Err((ErrorCode::FAIL, buf));
871 }
872 Some(state) => state,
873 };
874 match state {
875 TxState::Idle => {
876 let next_state = self.outgoing_frame_security(buf, info);
877 self.tx_state.replace(next_state);
878 self.step_transmit_state()
879 }
880 other_state => {
881 self.tx_state.replace(other_state);
882 Err((ErrorCode::BUSY, buf))
883 }
884 }
885 }
886}
887
888impl<'a, M: Mac<'a>, A: AES128CCM<'a>> radio::TxClient for Framer<'a, M, A> {
889 fn send_done(&self, buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>) {
890 self.data_sequence.set(self.data_sequence.get() + 1);
891 self.tx_client.map(move |client| {
892 client.send_done(buf, acked, result);
893 });
894 }
895}
896
897impl<'a, M: Mac<'a>, A: AES128CCM<'a>> radio::RxClient for Framer<'a, M, A> {
898 fn receive(
899 &self,
900 buf: &'static mut [u8],
901 frame_len: usize,
902 lqi: u8,
903 crc_valid: bool,
904 _: Result<(), ErrorCode>,
905 ) {
906 // Drop all frames with invalid CRC
907 if !crc_valid {
908 self.mac.set_receive_buffer(buf);
909 return;
910 }
911
912 self.rx_state.take().map(move |state| {
913 let next_state = match state {
914 RxState::Idle => {
915 // We can start processing a new received frame only if
916 // the reception pipeline is free
917 self.incoming_frame_security(buf, frame_len, lqi)
918 }
919 other_state => {
920 // This should never occur unless something other than
921 // this MAC layer provided a receive buffer to the
922 // radio, but if this occurs then we have no choice but
923 // to drop the frame.
924 self.mac.set_receive_buffer(buf);
925 other_state
926 }
927 };
928 self.rx_state.replace(next_state);
929 self.step_receive_state()
930 });
931 }
932}
933
934impl<'a, M: Mac<'a>, A: AES128CCM<'a>> radio::ConfigClient for Framer<'a, M, A> {
935 fn config_done(&self, _: Result<(), ErrorCode>) {
936 // The transmission pipeline is the only state machine that
937 // waits for the configuration procedure to complete before
938 // advancing.
939 let _ = self.step_transmit_state().map_err(|(ecode, buf)| {
940 // Return the buffer to the transmit client
941 self.tx_client.map(move |client| {
942 client.send_done(buf, false, Err(ecode));
943 });
944 });
945 }
946}
947
948impl<'a, M: Mac<'a>, A: AES128CCM<'a>> CCMClient for Framer<'a, M, A> {
949 fn crypt_done(&self, buf: &'static mut [u8], res: Result<(), ErrorCode>, tag_is_valid: bool) {
950 let mut tx_waiting = false;
951 let mut rx_waiting = false;
952
953 // The crypto operation was from the transmission pipeline.
954 let opt_buf = if let Some(state) = self.tx_state.take() {
955 match state {
956 TxState::Encrypting(info) => {
957 let res2 = match res {
958 Err(ecode) => {
959 self.tx_state.replace(TxState::Idle);
960 Err((ecode, buf))
961 }
962 Ok(()) => {
963 self.tx_state.replace(TxState::ReadyToTransmit(info, buf));
964 self.step_transmit_state()
965 }
966 };
967
968 if let Err((ecode, buf)) = res2 {
969 // Abort the transmission process. Return the buffer to the client.
970 self.tx_client.map(move |client| {
971 client.send_done(buf, false, Err(ecode));
972 });
973 }
974 None
975 }
976 other_state => {
977 tx_waiting = match other_state {
978 TxState::ReadyToEncrypt(_, _) => true,
979 _ => false,
980 };
981 self.tx_state.replace(other_state);
982 Some(buf)
983 }
984 }
985 } else {
986 Some(buf)
987 };
988
989 // The crypto operation was from the reception pipeline.
990 if let Some(buf) = opt_buf {
991 self.rx_state.take().map(|state| {
992 match state {
993 RxState::Decrypting(info, lqi) => {
994 let next_state = if tag_is_valid {
995 RxState::ReadyToYield(info, buf, lqi)
996 } else {
997 // The CRC tag is invalid, meaning the packet was corrupted. Drop this packet
998 // and reset reception pipeline
999 self.crypt_buf.replace(SubSliceMut::new(buf));
1000 RxState::Idle
1001 };
1002 self.rx_state.replace(next_state);
1003 self.step_receive_state()
1004 }
1005 other_state => {
1006 rx_waiting = match other_state {
1007 RxState::ReadyToDecrypt(_, _, _) => true,
1008 _ => false,
1009 };
1010 self.rx_state.replace(other_state);
1011 }
1012 }
1013 });
1014 }
1015
1016 // Now trigger the next crypto operation if one exists.
1017 if tx_waiting {
1018 let _ = self.step_transmit_state().map_err(|(ecode, buf)| {
1019 // Return the buffer to the client.
1020 self.tx_client.map(move |client| {
1021 client.send_done(buf, false, Err(ecode));
1022 });
1023 });
1024 } else if rx_waiting {
1025 self.step_receive_state()
1026 }
1027 }
1028}