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}