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