1 /*
2  * Copyright (c) 2018, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 /**
36  * @file
37  *   This file implements an enhanced acknowledgement (Enh-Ack) generator for 802.15.4 radio driver.
38  *
39  */
40 
41 #include "nrf_802154_enh_ack_generator.h"
42 
43 #include "nrf_802154_assert.h"
44 #include <string.h>
45 
46 #include "mac_features/nrf_802154_frame_parser.h"
47 #include "mac_features/nrf_802154_ie_writer.h"
48 #include "mac_features/nrf_802154_security_pib.h"
49 #include "nrf_802154_ack_data.h"
50 #include "nrf_802154_encrypt.h"
51 #include "nrf_802154_const.h"
52 #include "nrf_802154_pib.h"
53 #include "nrf_802154_utils_byteorder.h"
54 
55 #define ENH_ACK_MAX_SIZE MAX_PACKET_SIZE
56 
57 typedef enum
58 {
59     ACK_STATE_RESET,
60     ACK_STATE_INVALID,
61     ACK_STATE_PROCESSING,
62     ACK_STATE_COMPLETE,
63 } ack_state_t;
64 
65 static ack_state_t m_ack_state;
66 
67 static uint8_t                        m_ack[ENH_ACK_MAX_SIZE + PHR_SIZE];
68 static nrf_802154_frame_parser_data_t m_ack_data;
69 static const uint8_t                * mp_ie_data;
70 static uint8_t                        m_ie_data_len;
71 
ack_state_set(ack_state_t state_to_set)72 static void ack_state_set(ack_state_t state_to_set)
73 {
74     m_ack_state = state_to_set;
75 }
76 
ack_state_get(void)77 static inline ack_state_t ack_state_get(void)
78 {
79     return m_ack_state;
80 }
81 
sequence_number_set(const nrf_802154_frame_parser_data_t * p_frame_data)82 static uint8_t sequence_number_set(const nrf_802154_frame_parser_data_t * p_frame_data)
83 {
84     const uint8_t * p_frame_dsn = nrf_802154_frame_parser_dsn_get(p_frame_data);
85 
86     if (p_frame_dsn != NULL)
87     {
88         m_ack[DSN_OFFSET] = *p_frame_dsn;
89 
90         return DSN_SIZE;
91     }
92 
93     return 0U;
94 }
95 
96 /***************************************************************************************************
97  * @section Frame control field functions
98  **************************************************************************************************/
99 
fcf_frame_type_set(void)100 static void fcf_frame_type_set(void)
101 {
102     m_ack[FRAME_TYPE_OFFSET] |= FRAME_TYPE_ACK;
103 }
104 
fcf_security_enabled_set(const nrf_802154_frame_parser_data_t * p_frame_data)105 static void fcf_security_enabled_set(const nrf_802154_frame_parser_data_t * p_frame_data)
106 {
107     if (nrf_802154_frame_parser_security_enabled_bit_is_set(p_frame_data))
108     {
109         m_ack[SECURITY_ENABLED_OFFSET] |= SECURITY_ENABLED_BIT;
110     }
111 }
112 
fcf_frame_pending_set(const nrf_802154_frame_parser_data_t * p_frame_data)113 static void fcf_frame_pending_set(const nrf_802154_frame_parser_data_t * p_frame_data)
114 {
115     if (nrf_802154_ack_data_pending_bit_should_be_set(p_frame_data))
116     {
117         m_ack[FRAME_PENDING_OFFSET] |= FRAME_PENDING_BIT;
118     }
119 }
120 
fcf_panid_compression_set(const nrf_802154_frame_parser_data_t * p_frame_data)121 static void fcf_panid_compression_set(const nrf_802154_frame_parser_data_t * p_frame_data)
122 {
123     if (nrf_802154_frame_parser_panid_compression_is_set(p_frame_data))
124     {
125         m_ack[PAN_ID_COMPR_OFFSET] |= PAN_ID_COMPR_MASK;
126     }
127 }
128 
fcf_sequence_number_suppression_set(const nrf_802154_frame_parser_data_t * p_frame_data)129 static void fcf_sequence_number_suppression_set(const nrf_802154_frame_parser_data_t * p_frame_data)
130 {
131     if (nrf_802154_frame_parser_dsn_suppress_bit_is_set(p_frame_data))
132     {
133         m_ack[DSN_SUPPRESS_OFFSET] |= DSN_SUPPRESS_BIT;
134     }
135 }
136 
fcf_ie_present_set(bool ie_present)137 static void fcf_ie_present_set(bool ie_present)
138 {
139     if (ie_present)
140     {
141         m_ack[IE_PRESENT_OFFSET] |= IE_PRESENT_BIT;
142     }
143 }
144 
fcf_dst_addressing_mode_set(const nrf_802154_frame_parser_data_t * p_frame_data)145 static void fcf_dst_addressing_mode_set(const nrf_802154_frame_parser_data_t * p_frame_data)
146 {
147     if (nrf_802154_frame_parser_src_addr_is_extended(p_frame_data))
148     {
149         m_ack[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_EXTENDED;
150     }
151     else if (nrf_802154_frame_parser_src_addr_is_short(p_frame_data))
152     {
153         m_ack[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_SHORT;
154     }
155     else
156     {
157         m_ack[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_NONE;
158     }
159 }
160 
fcf_src_addressing_mode_set(void)161 static void fcf_src_addressing_mode_set(void)
162 {
163     m_ack[SRC_ADDR_TYPE_OFFSET] |= SRC_ADDR_TYPE_NONE;
164 }
165 
fcf_frame_version_set(void)166 static void fcf_frame_version_set(void)
167 {
168     m_ack[FRAME_VERSION_OFFSET] |= FRAME_VERSION_2;
169 }
170 
frame_control_set(const nrf_802154_frame_parser_data_t * p_frame_data,bool ie_present)171 static uint8_t frame_control_set(const nrf_802154_frame_parser_data_t * p_frame_data,
172                                  bool                                   ie_present)
173 {
174     nrf_802154_frame_parser_level_t level = nrf_802154_frame_parser_parse_level_get(p_frame_data);
175 
176     if (level >= PARSE_LEVEL_FCF_OFFSETS)
177     {
178         fcf_frame_type_set();
179         fcf_security_enabled_set(p_frame_data);
180         fcf_panid_compression_set(p_frame_data);
181         fcf_sequence_number_suppression_set(p_frame_data);
182         fcf_ie_present_set(ie_present);
183         fcf_dst_addressing_mode_set(p_frame_data);
184         fcf_frame_version_set();
185         fcf_src_addressing_mode_set();
186     }
187 
188     if (level >= PARSE_LEVEL_FULL)
189     {
190         // As some frame pending bit setting algorithms depend on MAC payload,
191         // the entire frame must be known to set this field.
192         fcf_frame_pending_set(p_frame_data);
193     }
194 
195     return FCF_SIZE;
196 }
197 
198 /***************************************************************************************************
199  * @section Addressing fields functions
200  **************************************************************************************************/
201 
destination_set(const nrf_802154_frame_parser_data_t * p_frame_data,nrf_802154_frame_parser_data_t * p_ack_data)202 static uint8_t destination_set(const nrf_802154_frame_parser_data_t * p_frame_data,
203                                nrf_802154_frame_parser_data_t       * p_ack_data)
204 {
205     uint8_t   bytes_written   = 0U;
206     uint8_t * p_ack_dst_panid = (uint8_t *)nrf_802154_frame_parser_dst_panid_get(p_ack_data);
207     uint8_t * p_ack_dst_addr  = (uint8_t *)nrf_802154_frame_parser_dst_addr_get(p_ack_data);
208 
209     const uint8_t * p_frame_src_panid = nrf_802154_frame_parser_src_panid_get(p_frame_data);
210     const uint8_t * p_frame_dst_panid = nrf_802154_frame_parser_dst_panid_get(p_frame_data);
211     const uint8_t * p_frame_src_addr  = nrf_802154_frame_parser_src_addr_get(p_frame_data);
212 
213     uint8_t src_addr_size = nrf_802154_frame_parser_src_addr_size_get(p_frame_data);
214 
215     // Fill the Ack destination PAN ID field.
216     if (p_ack_dst_panid != NULL)
217     {
218         const uint8_t * p_dst_panid;
219 
220         if (p_frame_src_panid != NULL)
221         {
222             p_dst_panid = p_frame_src_panid;
223         }
224         else if (p_frame_dst_panid != NULL)
225         {
226             p_dst_panid = p_frame_dst_panid;
227         }
228         else
229         {
230             p_dst_panid = nrf_802154_pib_pan_id_get();
231         }
232 
233         memcpy(p_ack_dst_panid, p_dst_panid, PAN_ID_SIZE);
234         bytes_written += PAN_ID_SIZE;
235     }
236 
237     // Fill the Ack destination address field.
238     if ((p_ack_dst_addr != NULL) && (p_frame_src_addr != NULL))
239     {
240         NRF_802154_ASSERT(nrf_802154_frame_parser_dst_addr_is_extended(p_ack_data) ==
241                           nrf_802154_frame_parser_src_addr_is_extended(p_frame_data));
242 
243         memcpy(p_ack_dst_addr, p_frame_src_addr, src_addr_size);
244         bytes_written += src_addr_size;
245     }
246 
247     return bytes_written;
248 }
249 
source_set(void)250 static void source_set(void)
251 {
252     // Intentionally empty: source address type is None.
253 }
254 
255 /***************************************************************************************************
256  * @section Auxiliary security header functions
257  **************************************************************************************************/
258 
security_header_size(const nrf_802154_frame_parser_data_t * p_frame_data)259 static uint8_t security_header_size(const nrf_802154_frame_parser_data_t * p_frame_data)
260 {
261     uint8_t sec_ctrl_offset = nrf_802154_frame_parser_sec_ctrl_offset_get(p_frame_data);
262     uint8_t aux_sec_hdr_end = nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(p_frame_data);
263 
264     return aux_sec_hdr_end - sec_ctrl_offset;
265 }
266 
key_id_size_get(uint8_t key_id_mode)267 static uint8_t key_id_size_get(uint8_t key_id_mode)
268 {
269     switch (key_id_mode)
270     {
271         case KEY_ID_MODE_1:
272             return KEY_ID_MODE_1_SIZE;
273 
274         case KEY_ID_MODE_2:
275             return KEY_ID_MODE_2_SIZE;
276 
277         case KEY_ID_MODE_3:
278             return KEY_ID_MODE_3_SIZE;
279 
280         default:
281             return 0U;
282     }
283 }
284 
security_key_id_set(const nrf_802154_frame_parser_data_t * p_frame_data,nrf_802154_frame_parser_data_t * p_ack_data)285 static uint8_t security_key_id_set(const nrf_802154_frame_parser_data_t * p_frame_data,
286                                    nrf_802154_frame_parser_data_t       * p_ack_data)
287 {
288     const uint8_t * p_frame_key_id = nrf_802154_frame_parser_key_id_get(p_frame_data);
289     uint8_t       * p_ack_key_id   = (uint8_t *)nrf_802154_frame_parser_key_id_get(p_ack_data);
290     uint8_t         key_id_size    = key_id_size_get(nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(
291                                                          p_ack_data));
292 
293     if ((p_ack_key_id != NULL) && (p_frame_key_id != NULL))
294     {
295         memcpy(p_ack_key_id, p_frame_key_id, key_id_size);
296     }
297 
298     return key_id_size;
299 }
300 
frame_counter_set(nrf_802154_frame_parser_data_t * p_ack_data,uint8_t * p_bytes_written)301 static bool frame_counter_set(nrf_802154_frame_parser_data_t * p_ack_data,
302                               uint8_t                        * p_bytes_written)
303 {
304     nrf_802154_key_id_t ack_key_id;
305     uint32_t            new_fc_value;
306     uint8_t           * p_frame_counter = (uint8_t *)nrf_802154_frame_parser_frame_counter_get(
307         p_ack_data);
308 
309     if (p_frame_counter == NULL)
310     {
311         // The frame counter is suppressed
312         *p_bytes_written = 0;
313         return true;
314     }
315 
316     ack_key_id.mode     = nrf_802154_frame_parser_sec_ctrl_key_id_mode_get(p_ack_data);
317     ack_key_id.p_key_id = (uint8_t *)nrf_802154_frame_parser_key_id_get(p_ack_data);
318 
319     if (NRF_802154_SECURITY_ERROR_NONE !=
320         nrf_802154_security_pib_frame_counter_get_next(&new_fc_value, &ack_key_id))
321     {
322         *p_bytes_written = 0;
323         return false;
324     }
325 
326     // Set the frame counter value in security header of the ACK frame
327     host_32_to_little(new_fc_value, p_frame_counter);
328     *p_bytes_written = FRAME_COUNTER_SIZE;
329 
330     return true;
331 }
332 
security_header_set(const nrf_802154_frame_parser_data_t * p_frame_data,nrf_802154_frame_parser_data_t * p_ack_data,uint8_t * p_bytes_written)333 static bool security_header_set(const nrf_802154_frame_parser_data_t * p_frame_data,
334                                 nrf_802154_frame_parser_data_t       * p_ack_data,
335                                 uint8_t                              * p_bytes_written)
336 {
337     bool security_header_prepared;
338     bool result;
339 
340     uint8_t bytes_written       = 0U;
341     uint8_t fc_bytes_written    = 0U;
342     uint8_t ack_sec_ctrl_offset = nrf_802154_frame_parser_addressing_end_offset_get(
343         p_ack_data);
344     uint8_t * ack_sec_ctrl = (uint8_t *)nrf_802154_frame_parser_addressing_end_get(
345         p_ack_data);
346     const uint8_t * frame_sec_ctrl = nrf_802154_frame_parser_sec_ctrl_get(p_frame_data);
347 
348     if ((ack_sec_ctrl == NULL) || (frame_sec_ctrl == NULL))
349     {
350         *p_bytes_written = bytes_written;
351         return true;
352     }
353 
354     // All the bits in the security control byte can be copied.
355     *ack_sec_ctrl  = *frame_sec_ctrl;
356     bytes_written += SECURITY_CONTROL_SIZE;
357 
358     // Security control field is now ready. The parsing of the frame can advance.
359     result = nrf_802154_frame_parser_valid_data_extend(p_ack_data,
360                                                        ack_sec_ctrl_offset + PHR_SIZE,
361                                                        PARSE_LEVEL_SEC_CTRL_OFFSETS);
362     NRF_802154_ASSERT(result);
363     (void)result;
364 
365     if (nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_frame_data) == SECURITY_LEVEL_NONE)
366     {
367         // The security level value is zero, therefore no auxiliary security header processing
368         // is performed according to 802.15.4 specification. This also applies to the frame counter,
369         // the value of which is left as it is in the message to which the ACK responds.
370         // The entire auxiliary security header content is simply copied to ACK.
371         uint8_t sec_hdr_size = security_header_size(p_frame_data) - SECURITY_CONTROL_SIZE;
372 
373         memcpy(ack_sec_ctrl + SECURITY_CONTROL_SIZE,
374                frame_sec_ctrl + SECURITY_CONTROL_SIZE,
375                sec_hdr_size);
376         bytes_written           += sec_hdr_size;
377         security_header_prepared = true;
378     }
379     else
380     {
381         bytes_written           += security_key_id_set(p_frame_data, p_ack_data);
382         security_header_prepared = frame_counter_set(p_ack_data, &fc_bytes_written);
383         bytes_written           += fc_bytes_written;
384     }
385 
386     bytes_written   += nrf_802154_frame_parser_mic_size_get(p_ack_data);
387     *p_bytes_written = bytes_written;
388 
389     return security_header_prepared;
390 }
391 
392 /***************************************************************************************************
393  * @section Information Elements
394  **************************************************************************************************/
395 
ie_header_set(const uint8_t * p_ie_data,uint8_t ie_data_len,nrf_802154_frame_parser_data_t * p_ack_data)396 static void ie_header_set(const uint8_t                  * p_ie_data,
397                           uint8_t                          ie_data_len,
398                           nrf_802154_frame_parser_data_t * p_ack_data)
399 {
400     uint8_t   ie_offset = p_ack_data->helper.aux_sec_hdr_end_offset;
401     uint8_t * p_ack_ie;
402 
403     p_ack_ie = (uint8_t *)p_ack_data->p_frame + ie_offset;
404 
405     if (p_ie_data == NULL)
406     {
407         return;
408     }
409 
410     NRF_802154_ASSERT(p_ack_ie != NULL);
411 
412     memcpy(p_ack_ie, p_ie_data, ie_data_len);
413 
414 #if NRF_802154_IE_WRITER_ENABLED
415     nrf_802154_ie_writer_prepare(p_ack_ie, p_ack_ie + ie_data_len);
416 #endif
417 }
418 
ie_header_terminate(const uint8_t * p_ie_data,uint8_t ie_data_len,nrf_802154_frame_parser_data_t * p_ack_data)419 static uint8_t ie_header_terminate(const uint8_t                  * p_ie_data,
420                                    uint8_t                          ie_data_len,
421                                    nrf_802154_frame_parser_data_t * p_ack_data)
422 {
423     if (p_ie_data == NULL)
424     {
425         // No IEs to terminate.
426         return 0U;
427     }
428 
429     if ((nrf_802154_frame_parser_security_enabled_bit_is_set(p_ack_data) == false) ||
430         (nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_ack_data) == SECURITY_LEVEL_NONE))
431     {
432         // This code assumes that neither regular frame payload nor Payload IEs can be set by the
433         // driver. Therefore without security, the Ack has no payload, so termination is not necessary.
434         return 0U;
435     }
436 
437     uint8_t * p_ack_ie = (uint8_t *)p_ack_data->p_frame + p_ack_data->helper.aux_sec_hdr_end_offset;
438     uint8_t   ie_hdr_term[IE_HEADER_SIZE];
439 
440     NRF_802154_ASSERT(p_ack_ie != NULL);
441 
442     host_16_to_little((IE_HT2) << IE_HEADER_ELEMENT_ID_OFFSET, ie_hdr_term);
443 
444     memcpy(p_ack_ie + ie_data_len, ie_hdr_term, sizeof(ie_hdr_term));
445     return sizeof(ie_hdr_term);
446 }
447 
448 /***************************************************************************************************
449  * @section Authentication and encryption transformation
450  **************************************************************************************************/
451 
encryption_prepare(const nrf_802154_frame_parser_data_t * p_ack_data)452 static bool encryption_prepare(const nrf_802154_frame_parser_data_t * p_ack_data)
453 {
454 #if NRF_802154_ENCRYPTION_ENABLED
455     nrf_802154_encrypt_ack_reset();
456 
457     if (nrf_802154_frame_parser_security_enabled_bit_is_set(p_ack_data) == false)
458     {
459         return true;
460     }
461 
462     if (nrf_802154_frame_parser_sec_ctrl_sec_lvl_get(p_ack_data) == SECURITY_LEVEL_NONE)
463     {
464         return true;
465     }
466 
467     return nrf_802154_encrypt_ack_prepare(p_ack_data);
468 #else // NRF_802154_ENCRYPTION_ENABLED
469     return true;
470 #endif  // NRF_802154_ENCRYPTION_ENABLED
471 }
472 
473 /***************************************************************************************************
474  * @section Enhanced ACK generation
475  **************************************************************************************************/
476 
fcf_process(const nrf_802154_frame_parser_data_t * p_frame_data)477 static void fcf_process(const nrf_802154_frame_parser_data_t * p_frame_data)
478 {
479     // Set Frame Control field bits.
480     // Some of them might require correction when higher parse level is available
481     m_ack[PHR_OFFSET] += frame_control_set(p_frame_data, false);
482 
483     bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data,
484                                                             m_ack[PHR_OFFSET] + PHR_SIZE,
485                                                             PARSE_LEVEL_FCF_OFFSETS);
486 
487     NRF_802154_ASSERT(result);
488     (void)result;
489 }
490 
addr_end_process(const nrf_802154_frame_parser_data_t * p_frame_data)491 static void addr_end_process(const nrf_802154_frame_parser_data_t * p_frame_data)
492 {
493     // Set valid sequence number in ACK frame.
494     m_ack[PHR_OFFSET] += sequence_number_set(p_frame_data);
495     // Set destination address and PAN ID.
496     m_ack[PHR_OFFSET] += destination_set(p_frame_data, &m_ack_data);
497 
498     // Set source address and PAN ID.
499     source_set();
500 
501     // Having the frame's source address, presence of IEs can be determined.
502     // coverity[unchecked_value]
503     mp_ie_data = nrf_802154_ack_data_ie_get(
504         nrf_802154_frame_parser_src_addr_get(p_frame_data),
505         nrf_802154_frame_parser_src_addr_is_extended(p_frame_data),
506         &m_ie_data_len);
507 
508     // Update the IE present bit in Frame Control field knowing if IEs should be present.
509     fcf_ie_present_set(mp_ie_data != NULL);
510 
511     bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data,
512                                                             m_ack[PHR_OFFSET] + PHR_SIZE,
513                                                             PARSE_LEVEL_ADDRESSING_END);
514 
515     NRF_802154_ASSERT(result);
516     (void)result;
517 }
518 
aux_sec_hdr_process(const nrf_802154_frame_parser_data_t * p_frame_data)519 static bool aux_sec_hdr_process(const nrf_802154_frame_parser_data_t * p_frame_data)
520 {
521     uint8_t bytes_written;
522 
523     if (security_header_set(p_frame_data, &m_ack_data, &bytes_written) == false)
524     {
525         return false;
526     }
527 
528     m_ack[PHR_OFFSET] += bytes_written;
529 
530     bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data,
531                                                             m_ack[PHR_OFFSET] + PHR_SIZE,
532                                                             PARSE_LEVEL_AUX_SEC_HDR_END);
533 
534     NRF_802154_ASSERT(result);
535     (void)result;
536 
537     return true;
538 }
539 
ie_process(const nrf_802154_frame_parser_data_t * p_frame_data)540 static void ie_process(const nrf_802154_frame_parser_data_t * p_frame_data)
541 {
542     // Set IE header.
543     ie_header_set(mp_ie_data, m_ie_data_len, &m_ack_data);
544     m_ack[PHR_OFFSET] += m_ie_data_len;
545 
546     // Terminate the IE header if needed.
547     m_ack[PHR_OFFSET] += ie_header_terminate(mp_ie_data, m_ie_data_len, &m_ack_data) + FCS_SIZE;
548 
549     bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data,
550                                                             m_ack[PHR_OFFSET] + PHR_SIZE,
551                                                             PARSE_LEVEL_FULL);
552 
553     NRF_802154_ASSERT(result);
554     (void)result;
555 }
556 
encryption_process(void)557 static bool encryption_process(void)
558 {
559     return encryption_prepare(&m_ack_data);
560 }
561 
ack_process(const nrf_802154_frame_parser_data_t * p_frame_data,bool * p_processing_done)562 static uint8_t * ack_process(
563     const nrf_802154_frame_parser_data_t * p_frame_data,
564     bool                                 * p_processing_done)
565 {
566     nrf_802154_frame_parser_level_t frame_parse_level = nrf_802154_frame_parser_parse_level_get(
567         p_frame_data);
568     nrf_802154_frame_parser_level_t ack_parse_level = nrf_802154_frame_parser_parse_level_get(
569         &m_ack_data);
570 
571     *p_processing_done = false;
572 
573     if ((frame_parse_level >= PARSE_LEVEL_FCF_OFFSETS) &&
574         (ack_parse_level < PARSE_LEVEL_FCF_OFFSETS))
575     {
576         fcf_process(p_frame_data);
577     }
578 
579     if ((frame_parse_level >= PARSE_LEVEL_ADDRESSING_END) &&
580         (ack_parse_level < PARSE_LEVEL_ADDRESSING_END))
581     {
582         addr_end_process(p_frame_data);
583     }
584 
585     if ((frame_parse_level >= PARSE_LEVEL_AUX_SEC_HDR_END) &&
586         (ack_parse_level < PARSE_LEVEL_AUX_SEC_HDR_END))
587     {
588         if (!aux_sec_hdr_process(p_frame_data))
589         {
590             // Failure to set auxiliary security header, the ACK cannot be created. Exit immediately
591             *p_processing_done = true;
592             return NULL;
593         }
594 
595         ie_process(p_frame_data);
596     }
597 
598     if (frame_parse_level == PARSE_LEVEL_FULL)
599     {
600         // With the entire frame validated update the Frame Pending bit in Frame Control field
601         fcf_frame_pending_set(p_frame_data);
602 
603         if (encryption_process())
604         {
605             // Success. Processing completed
606             *p_processing_done = true;
607             return m_ack;
608         }
609         else
610         {
611             // Failure to prepare encryption even though it's required, the ACK cannot be created.
612             // Exit immediately
613             *p_processing_done = true;
614             return NULL;
615         }
616     }
617 
618     return NULL;
619 }
620 
621 /***************************************************************************************************
622  * @section Public API implementation
623  **************************************************************************************************/
624 
nrf_802154_enh_ack_generator_init(void)625 void nrf_802154_enh_ack_generator_init(void)
626 {
627     // Intentionally empty.
628 }
629 
nrf_802154_enh_ack_generator_reset(void)630 void nrf_802154_enh_ack_generator_reset(void)
631 {
632     memset(m_ack, 0U, sizeof(m_ack));
633     (void)nrf_802154_frame_parser_data_init(m_ack, 0U, PARSE_LEVEL_NONE, &m_ack_data);
634     mp_ie_data    = 0U;
635     m_ie_data_len = 0U;
636     m_ack_state   = ACK_STATE_RESET;
637 }
638 
nrf_802154_enh_ack_generator_create(const nrf_802154_frame_parser_data_t * p_frame_data)639 uint8_t * nrf_802154_enh_ack_generator_create(
640     const nrf_802154_frame_parser_data_t * p_frame_data)
641 {
642     switch (ack_state_get())
643     {
644         case ACK_STATE_RESET:
645         #if NRF_802154_IE_WRITER_ENABLED
646             // The IE writer module can be in the IE_WRITER_PREPARE state if
647             // the previous transmission failed at an early stage.
648             // Reset it, to avoid data corruption in case this ACK
649             // does not contain information elements. Otherwise, the
650             // IE writer would commit data in nrf_802154_ie_writer_tx_ack_started_hook
651             // regardless if writing of IE elements is needed or not.
652             nrf_802154_ie_writer_reset();
653         #endif
654 
655             ack_state_set(ACK_STATE_PROCESSING);
656         // Fallthrough
657 
658         case ACK_STATE_PROCESSING:
659         {
660             bool      processing_done;
661             uint8_t * p_ack = ack_process(p_frame_data, &processing_done);
662 
663             if (processing_done)
664             {
665                 ack_state_set(p_ack ? ACK_STATE_COMPLETE : ACK_STATE_INVALID);
666             }
667 
668             return processing_done ? p_ack : NULL;
669         }
670 
671         case ACK_STATE_INVALID:
672             return NULL;
673 
674         case ACK_STATE_COMPLETE:
675             return m_ack;
676 
677         default:
678             NRF_802154_ASSERT(false);
679             return NULL;
680     }
681 }
682