1 /*
2 * Copyright (c) 2021, 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 #include "nrf_802154_config.h"
36
37 #if NRF_802154_ENCRYPTION_ACCELERATOR_ECB
38
39 #include "nrf_802154_aes_ccm.h"
40
41 #include "nrf_802154_assert.h"
42 #include <string.h>
43
44 #include "nrf_802154_const.h"
45 #include "nrf_802154_config.h"
46 #include "nrf_802154_tx_work_buffer.h"
47 #if defined(CONFIG_MPSL)
48 #include "mpsl_ecb.h"
49 #else
50 #include "hal/nrf_ecb.h"
51 #endif
52
53 #ifndef MIN
54 #define MIN(a, b) ((a) < (b) ? (a) : (b)) ///< Leaves the minimum of the two arguments
55 #endif
56
57 #define NRF_802154_AES_CCM_BLOCK_SIZE 16 // Annex B4 Specification of generic CCM* a)
58
59 #define NRF_802154_AES_CCM_ADATA_AUTH_FLAG (0x40) // Annex B4.1.2 - Adata flag for authentication transform
60 #define NRF_802154_AES_CCM_M_BITS_AUTH_FLAG 3 // Annex B4.1.2 - Nr of bits for MIC flag for authentication transform
61
62 #define NRF_802154_AES_CCM_AI_FIELD_FLAG_OCTET 0 // AnnnexB4.1.3b) - Position of octet for flags in Ai field
63 #define NRF_802154_AES_CCM_AI_FIELD_NONCE_OCTET 1 // AnnnexB4.1.3b) - Position of octet for nonce in Ai field
64 #define NRF_802154_AES_CCM_B0_FIELD_FLAG_OCTET 0 // AnnnexB4.1.2b) - Position of octet for flags in B0 field
65 #define NRF_802154_AES_CCM_B0_FIELD_NONCE_OCTET 1 // AnnnexB4.1.2b) - Position of octet for nonce in B0 field
66 #define NRF_802154_AES_CCM_AUTH_DATA_LENGTH_OCTET 0 // AnnnexB4.1.1b) - Position of octet for length of auth data in AddAuthData
67 #define NRF_802154_AES_CCM_AUTH_DATA_OCTET 2 // AnnnexB4.1.1b) - Position of octet for data of auth data in AddAuthData
68
69 /**
70 * @brief Steps of AES-CCM* algorithm.
71 */
72 typedef enum
73 {
74 ADD_AUTH_DATA_AUTH,
75 PLAIN_TEXT_AUTH,
76 PLAIN_TEXT_ENCRYPT,
77 CALCULATE_ENCRYPTED_TAG
78 } ccm_steps_t;
79
80 /**
81 * @brief Actual state of perfomed AES-CCM* algorithm.
82 */
83 typedef struct
84 {
85 ccm_steps_t transformation; // Actual step of transformation
86 uint8_t iteration; // Iteration of actual step of transformation
87 } ccm_state_t;
88
89 static nrf_802154_aes_ccm_data_t m_aes_ccm_data; ///< AES CCM Frame
90 static uint8_t m_x[NRF_802154_AES_CCM_BLOCK_SIZE]; ///< CBC-MAC value - Annex B4.1.2 d)
91 static uint8_t m_b[NRF_802154_AES_CCM_BLOCK_SIZE]; ///< B[i] octet for Authorization Transformatino - Annex B4.1.2 b)
92 static uint8_t m_m[NRF_802154_AES_CCM_BLOCK_SIZE]; ///< M[i] octet as parsed plaintext blocks - Annex B4.1.3 c)
93 static uint8_t m_a[NRF_802154_AES_CCM_BLOCK_SIZE]; ///< A[i] octet for Encryption Transformation - Annex B4.1.3 b)
94 static ccm_state_t m_state; ///< State of AES-CCM* transformation
95 static uint8_t m_auth_tag[MIC_128_SIZE]; ///< Authorization Tag
96 static uint8_t * mp_ciphertext; ///< Pointer to ciphertext destination buffer.
97 static uint8_t * mp_work_buffer; ///< Pointer to work buffer that stores the frame being transformed.
98
99 static const uint8_t m_mic_size[] = { 0, MIC_32_SIZE, MIC_64_SIZE, MIC_128_SIZE }; ///< Security level - 802.15.4-2015 Standard Table 9.6
100
101 typedef struct
102 {
103 uint32_t key[NRF_802154_AES_CCM_BLOCK_SIZE / sizeof(uint32_t)];
104 uint8_t cleartext[NRF_802154_AES_CCM_BLOCK_SIZE];
105 uint8_t ciphertext[NRF_802154_AES_CCM_BLOCK_SIZE];
106 } nrf_802154_hal_ecb_data_t;
107
108 /******************************************************************************/
109 /******************************************************************************/
110 /******************************************************************************/
111
112 static nrf_802154_hal_ecb_data_t m_ecb_hal_data;
113 static bool m_ecb_hal_req_run;
114
115 #if defined(CONFIG_MPSL)
ecb_block_encrypt(nrf_802154_hal_ecb_data_t * p_ecb_data)116 static inline void ecb_block_encrypt(nrf_802154_hal_ecb_data_t * p_ecb_data)
117 {
118 /* Note: nrf_802154_hal_ecb_data_t and mpsl_ecb_hal_data_t are equivalent
119 * and pointers to them can be safely cast.
120 */
121 mpsl_ecb_block_encrypt((mpsl_ecb_hal_data_t *)p_ecb_data);
122 }
123
124 #else
125
126 #define ECB_INST NRF_ECB
127
sleep_wfe(void)128 static inline void sleep_wfe(void)
129 {
130 #if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
131 void z_impl_k_busy_wait();
132 z_impl_k_busy_wait(10);
133 #elif defined(CONFIG_SOC_COMPATIBLE_NRF52X)
134 __WFE();
135 #else
136 /* Do-nothing. This includes nRF5340 series due multiple sleep-related anomalies (160, 165, 168) */
137 #endif
138 }
139
wait_for_ecb_end(void)140 static void wait_for_ecb_end(void)
141 {
142 while (!nrf_ecb_event_check(ECB_INST, NRF_ECB_EVENT_ENDECB) &&
143 !nrf_ecb_event_check(ECB_INST, NRF_ECB_EVENT_ERRORECB))
144 {
145 #if !defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
146 if ((SCB->SCR & SCB_SCR_SEVONPEND_Msk) == SCB_SCR_SEVONPEND_Msk)
147 #endif
148 {
149 NVIC_ClearPendingIRQ(ECB_IRQn);
150
151 uint32_t irq_was_masked = __get_PRIMASK();
152
153 __disable_irq();
154
155 nrf_ecb_int_enable(ECB_INST, NRF_ECB_INT_ENDECB_MASK | NRF_ECB_INT_ERRORECB_MASK);
156 if (!nrf_ecb_event_check(ECB_INST, NRF_ECB_EVENT_ENDECB) &&
157 !nrf_ecb_event_check(ECB_INST, NRF_ECB_EVENT_ERRORECB))
158 {
159 sleep_wfe();
160 }
161
162 if (!irq_was_masked)
163 {
164 __enable_irq();
165 }
166 }
167 }
168 }
169
ecb_block_encrypt(nrf_802154_hal_ecb_data_t * p_ecb_data)170 static void ecb_block_encrypt(nrf_802154_hal_ecb_data_t * p_ecb_data)
171 {
172 nrf_ecb_int_disable(ECB_INST, NRF_ECB_INT_ENDECB_MASK | NRF_ECB_INT_ERRORECB_MASK);
173
174 do
175 {
176 nrf_ecb_task_trigger(ECB_INST, NRF_ECB_TASK_STOPECB);
177 nrf_ecb_event_clear(ECB_INST, NRF_ECB_EVENT_ENDECB);
178 nrf_ecb_event_clear(ECB_INST, NRF_ECB_EVENT_ERRORECB);
179 nrf_ecb_data_pointer_set(ECB_INST, p_ecb_data);
180
181 nrf_ecb_task_trigger(ECB_INST, NRF_ECB_TASK_STARTECB);
182 wait_for_ecb_end();
183 }
184 while (nrf_ecb_event_check(ECB_INST, NRF_ECB_EVENT_ERRORECB));
185
186 nrf_ecb_int_disable(ECB_INST, NRF_ECB_INT_ENDECB_MASK | NRF_ECB_INT_ERRORECB_MASK);
187 nrf_ecb_event_clear(ECB_INST, NRF_ECB_EVENT_ERRORECB);
188 nrf_ecb_event_clear(ECB_INST, NRF_ECB_EVENT_ENDECB);
189 NVIC_ClearPendingIRQ(ECB_IRQn);
190 }
191
192 #endif /* defined(CONFIG_MPSL) */
193
ecb_hal_cleartext_ptr_get(void)194 static inline uint8_t * ecb_hal_cleartext_ptr_get(void)
195 {
196 return (uint8_t *)m_ecb_hal_data.cleartext;
197 }
198
ecb_hal_ciphertext_ptr_get(void)199 static inline uint8_t * ecb_hal_ciphertext_ptr_get(void)
200 {
201 return (uint8_t *)m_ecb_hal_data.ciphertext;
202 }
203
ecb_hal_key_set(const uint8_t * p_key)204 static void ecb_hal_key_set(const uint8_t * p_key)
205 {
206 memcpy(m_ecb_hal_data.key, p_key, NRF_802154_AES_CCM_BLOCK_SIZE);
207 }
208
209 /******************************************************************************/
210 /******************************************************************************/
211 /******************************************************************************/
212
213 /**
214 * @brief Calculates XOR of two blocks of data
215 *
216 * @param[inout] p_first First block of data
217 * @param[in] p_second Second block of data
218 * @param[in] len Length of blocks
219 */
two_blocks_xor(uint8_t * p_first,const uint8_t * p_second,uint8_t len)220 static void two_blocks_xor(uint8_t * p_first, const uint8_t * p_second, uint8_t len)
221 {
222 for (uint8_t i = 0; i < len; i++)
223 {
224 p_first[i] ^= p_second[i];
225 }
226 }
227
228 /**
229 * @brief Forms 16-octet Ai field
230 * IEEE std 802.15.4-2015, B.4.1.3 Encryption transformation
231 *
232 * @param[in] p_frame pointer to AES CCM frame structure
233 * @param[in] iter counter of actual iteration
234 * @param[out] p_a pointer to memory for Ai
235 */
ai_format(const nrf_802154_aes_ccm_data_t * p_frame,uint16_t iter,uint8_t * p_a)236 static void ai_format(const nrf_802154_aes_ccm_data_t * p_frame,
237 uint16_t iter,
238 uint8_t * p_a)
239 {
240 uint8_t enc_flags = NRF_802154_AES_CCM_L_VALUE - 1;
241
242 p_a[NRF_802154_AES_CCM_AI_FIELD_FLAG_OCTET] = enc_flags;
243 memcpy(&p_a[NRF_802154_AES_CCM_AI_FIELD_NONCE_OCTET],
244 p_frame->nonce,
245 NRF_802154_AES_CCM_NONCE_SIZE);
246 p_a[NRF_802154_AES_CCM_BLOCK_SIZE - 1] = iter;
247 p_a[NRF_802154_AES_CCM_BLOCK_SIZE - 2] = iter >> 8;
248 }
249
250 /**
251 * @brief Forms 16-octet B0 field
252 * IEEE std 802.15.4-2015, B.4.1.2b Encryption transformation
253 *
254 * @param[in] p_frame pointer to AES CCM frame structure
255 * @param[in] flags flags for injection to B0 field
256 * @param[out] p_b pointer to memory for B0
257 */
b0_format(const nrf_802154_aes_ccm_data_t * p_frame,const uint8_t flags,uint8_t * p_b)258 static void b0_format(const nrf_802154_aes_ccm_data_t * p_frame,
259 const uint8_t flags,
260 uint8_t * p_b)
261 {
262 p_b[NRF_802154_AES_CCM_B0_FIELD_FLAG_OCTET] = flags;
263 memcpy(&p_b[NRF_802154_AES_CCM_B0_FIELD_NONCE_OCTET],
264 p_frame->nonce,
265 NRF_802154_AES_CCM_NONCE_SIZE);
266 p_b[NRF_802154_AES_CCM_BLOCK_SIZE - 1] = (p_frame->plain_text_data_len & 0xFF);
267 p_b[NRF_802154_AES_CCM_BLOCK_SIZE - 2] = 0;
268 }
269
270 /**
271 * @brief Forms authentication flag
272 * IEEE std 802.15.4-2015, B.4.1.2 Authentication transformation
273 *
274 * @param[in] p_frame pointer to AES CCM frame structure
275 *
276 * @return Formatted authorization flags
277 */
auth_flags_format(const nrf_802154_aes_ccm_data_t * p_frame)278 static uint8_t auth_flags_format(const nrf_802154_aes_ccm_data_t * p_frame)
279 {
280 uint8_t auth_flags = 0;
281 uint8_t m;
282
283 auth_flags |= (p_frame->auth_data_len == 0) ? 0 : NRF_802154_AES_CCM_ADATA_AUTH_FLAG;
284
285 m = m_mic_size[p_frame->mic_level];
286 m = (m > 0) ? (m - 2) >> 1 : 0;
287 auth_flags |= (m << NRF_802154_AES_CCM_M_BITS_AUTH_FLAG);
288
289 auth_flags |= NRF_802154_AES_CCM_L_VALUE - 1; // l value
290
291 return auth_flags;
292 }
293
294 /**
295 * @brief Forms additional authentication data from octet string a by 16-octet chunks
296 * IEEE std 802.15.4-2015, B.4.1.1 Input transformation
297 *
298 * @param[in] p_frame pointer to AES CCM frame structure
299 * @param[in] iter number of chunk
300 * @param[out] p_b pointer to memory for Bi
301 *
302 * @retval true Chunk was formated
303 * @retval false Otherwise
304 */
add_auth_data_get(const nrf_802154_aes_ccm_data_t * p_frame,uint8_t iter,uint8_t * p_b)305 static bool add_auth_data_get(const nrf_802154_aes_ccm_data_t * p_frame,
306 uint8_t iter,
307 uint8_t * p_b)
308 {
309 uint8_t offset = 0;
310 uint8_t len;
311
312 if (p_frame->auth_data_len == 0)
313 {
314 return false;
315 }
316
317 memset(p_b, 0, NRF_802154_AES_CCM_BLOCK_SIZE);
318
319 if (iter == 0)
320 {
321 len = MIN(p_frame->auth_data_len, NRF_802154_AES_CCM_BLOCK_SIZE - sizeof(uint16_t));
322 p_b[NRF_802154_AES_CCM_AUTH_DATA_LENGTH_OCTET] = (p_frame->auth_data_len & 0xFF00) >> 8;
323 p_b[NRF_802154_AES_CCM_AUTH_DATA_LENGTH_OCTET + 1] = (p_frame->auth_data_len & 0xFF);
324 memcpy(&p_b[NRF_802154_AES_CCM_AUTH_DATA_OCTET], p_frame->auth_data, len);
325 return true;
326 }
327
328 offset += NRF_802154_AES_CCM_BLOCK_SIZE - sizeof(uint16_t);
329 offset += NRF_802154_AES_CCM_BLOCK_SIZE * (iter - 1);
330 if (offset >= p_frame->auth_data_len)
331 {
332 return false;
333 }
334
335 len = MIN(p_frame->auth_data_len - offset, NRF_802154_AES_CCM_BLOCK_SIZE);
336 memcpy(p_b, p_frame->auth_data + offset, len);
337 return true;
338 }
339
340 /**
341 * @brief Forms plain/cipher text data from octet string m/c by 16-octet chunks
342 * IEEE std 802.15.4-2015, B.4.1.1 Input transformation
343 *
344 * @param[in] p_frame pointer to AES CCM frame structure
345 * @param[in] iter number of chunk
346 * @param[out] p_b pointer to memory for Bi
347 *
348 * @retval true Chunk was formated
349 * @retval false Otherwise
350 */
plain_text_data_get(const nrf_802154_aes_ccm_data_t * p_frame,uint8_t iter,uint8_t * p_b)351 static bool plain_text_data_get(const nrf_802154_aes_ccm_data_t * p_frame,
352 uint8_t iter,
353 uint8_t * p_b)
354 {
355 uint8_t offset = 0;
356 uint8_t len;
357
358 if (p_frame->plain_text_data_len == 0)
359 {
360 return false;
361 }
362
363 memset(p_b, 0, NRF_802154_AES_CCM_BLOCK_SIZE);
364
365 offset += NRF_802154_AES_CCM_BLOCK_SIZE * iter;
366 if (offset >= p_frame->plain_text_data_len)
367 {
368 return false;
369 }
370
371 len = MIN(p_frame->plain_text_data_len - offset, NRF_802154_AES_CCM_BLOCK_SIZE);
372 memcpy(p_b, p_frame->plain_text_data + offset, len);
373
374 return true;
375 }
376
377 /**
378 * @brief Block of Authorization Transformation iteration
379 */
process_ecb_auth_iteration(void)380 static inline void process_ecb_auth_iteration(void)
381 {
382 m_state.iteration++;
383 two_blocks_xor(ecb_hal_ciphertext_ptr_get(), m_b, NRF_802154_AES_CCM_BLOCK_SIZE);
384 memcpy(ecb_hal_cleartext_ptr_get(),
385 ecb_hal_ciphertext_ptr_get(),
386 NRF_802154_AES_CCM_BLOCK_SIZE);
387 m_ecb_hal_req_run = true;
388 }
389
390 /**
391 * @brief Block of Encryption Transformation iteration
392 */
process_ecb_encrypt_iteration(void)393 static inline void process_ecb_encrypt_iteration(void)
394 {
395 ai_format(&m_aes_ccm_data, m_state.iteration, m_a);
396 memcpy(ecb_hal_cleartext_ptr_get(), m_a, NRF_802154_AES_CCM_BLOCK_SIZE);
397 m_ecb_hal_req_run = true;
398 }
399
400 /**
401 * @brief helper function for plain text encryption in ECB IRQ
402 */
perform_plain_text_encryption(void)403 static void perform_plain_text_encryption(void)
404 {
405 memcpy(m_auth_tag, ecb_hal_ciphertext_ptr_get(), m_mic_size[m_aes_ccm_data.mic_level]);
406
407 m_state.iteration = 0;
408 m_state.transformation = PLAIN_TEXT_ENCRYPT;
409
410 if (plain_text_data_get(&m_aes_ccm_data, m_state.iteration, m_m))
411 {
412 m_state.iteration++;
413 process_ecb_encrypt_iteration();
414 }
415 else
416 {
417 if (m_mic_size[m_aes_ccm_data.mic_level] != 0)
418 {
419 process_ecb_encrypt_iteration();
420 m_state.transformation = CALCULATE_ENCRYPTED_TAG;
421 }
422 }
423 }
424
425 /**
426 * @brief helper function for plain text auth in ECB IRQ
427 */
perform_plain_text_authorization(void)428 static void perform_plain_text_authorization(void)
429 {
430 if (plain_text_data_get(&m_aes_ccm_data, m_state.iteration, m_b))
431 {
432 process_ecb_auth_iteration();
433 }
434 else
435 {
436 perform_plain_text_encryption();
437 }
438 }
439
transformation_finished(void)440 static void transformation_finished(void)
441 {
442 nrf_802154_tx_work_buffer_is_secured_set();
443 m_aes_ccm_data.raw_frame = NULL;
444 }
445
ecb_hal_block_encrypted_handler(void)446 static void ecb_hal_block_encrypted_handler(void)
447 {
448 uint8_t len = 0;
449 uint8_t offset;
450
451 switch (m_state.transformation)
452 {
453 case ADD_AUTH_DATA_AUTH:
454 if (add_auth_data_get(&m_aes_ccm_data, m_state.iteration, m_b))
455 {
456 process_ecb_auth_iteration();
457 }
458 else
459 {
460 m_state.iteration = 0;
461 m_state.transformation = PLAIN_TEXT_AUTH;
462 perform_plain_text_authorization();
463 }
464 break;
465
466 case PLAIN_TEXT_AUTH:
467 perform_plain_text_authorization();
468 break;
469
470 case PLAIN_TEXT_ENCRYPT:
471 two_blocks_xor(m_m, ecb_hal_ciphertext_ptr_get(), NRF_802154_AES_CCM_BLOCK_SIZE);
472
473 offset = (m_state.iteration - 1) * NRF_802154_AES_CCM_BLOCK_SIZE;
474 len = MIN(m_aes_ccm_data.plain_text_data_len - offset,
475 NRF_802154_AES_CCM_BLOCK_SIZE);
476 memcpy(mp_ciphertext + offset, m_m, len);
477 if (plain_text_data_get(&m_aes_ccm_data, m_state.iteration, m_m))
478 {
479 m_state.iteration++;
480 process_ecb_encrypt_iteration();
481 }
482 else
483 {
484 if (m_mic_size[m_aes_ccm_data.mic_level] != 0)
485 {
486 m_state.iteration = 0;
487 m_state.transformation = CALCULATE_ENCRYPTED_TAG;
488 process_ecb_encrypt_iteration();
489 }
490 else
491 {
492 transformation_finished();
493 }
494 }
495 break;
496
497 case CALCULATE_ENCRYPTED_TAG:
498 two_blocks_xor(m_auth_tag,
499 ecb_hal_ciphertext_ptr_get(),
500 m_mic_size[m_aes_ccm_data.mic_level]);
501 memcpy(mp_work_buffer +
502 (mp_work_buffer[PHR_OFFSET] - FCS_SIZE -
503 m_mic_size[m_aes_ccm_data.mic_level] +
504 PHR_SIZE),
505 m_auth_tag,
506 m_mic_size[m_aes_ccm_data.mic_level]);
507 transformation_finished();
508 break;
509
510 default:
511 break;
512 }
513 }
514
515 /**
516 * @brief Start AES-CCM* Authorization Transformation
517 */
start_ecb_auth_transformation(void)518 static void start_ecb_auth_transformation(void)
519 {
520 ecb_hal_key_set(m_aes_ccm_data.key);
521 memcpy(ecb_hal_cleartext_ptr_get(), m_x, NRF_802154_AES_CCM_BLOCK_SIZE);
522 m_state.iteration = 0;
523 m_state.transformation = ADD_AUTH_DATA_AUTH;
524 m_ecb_hal_req_run = true;
525
526 while (m_ecb_hal_req_run)
527 {
528 m_ecb_hal_req_run = false;
529 ecb_block_encrypt(&m_ecb_hal_data);
530 ecb_hal_block_encrypted_handler();
531 }
532 }
533
nrf_802154_aes_ccm_transform_reset(void)534 void nrf_802154_aes_ccm_transform_reset(void)
535 {
536 m_aes_ccm_data.raw_frame = NULL;
537 }
538
nrf_802154_aes_ccm_transform_prepare(const nrf_802154_aes_ccm_data_t * p_aes_ccm_data)539 bool nrf_802154_aes_ccm_transform_prepare(const nrf_802154_aes_ccm_data_t * p_aes_ccm_data)
540 {
541 // Verify that all necessary data is available
542 if (p_aes_ccm_data->raw_frame == NULL)
543 {
544 return false;
545 }
546
547 // Verify that the optional data, if exists, is complete
548 if (((p_aes_ccm_data->auth_data_len != 0) && (p_aes_ccm_data->auth_data == NULL)) ||
549 ((p_aes_ccm_data->plain_text_data_len != 0) && (p_aes_ccm_data->plain_text_data == NULL)))
550 {
551 return false;
552 }
553
554 // Verify that the MIC level is valid
555 if (p_aes_ccm_data->mic_level > SECURITY_LEVEL_MIC_LEVEL_MASK)
556 {
557 return false;
558 }
559
560 // Store the encryption data for future use
561 memcpy(&m_aes_ccm_data, p_aes_ccm_data, sizeof(nrf_802154_aes_ccm_data_t));
562
563 ptrdiff_t offset = p_aes_ccm_data->raw_frame[PHR_OFFSET] + PHR_SIZE;
564
565 if (p_aes_ccm_data->plain_text_data)
566 {
567 offset = p_aes_ccm_data->plain_text_data - p_aes_ccm_data->raw_frame;
568 }
569
570 NRF_802154_ASSERT((offset >= 0) && (offset <= MAX_PACKET_SIZE + PHR_SIZE));
571
572 nrf_802154_tx_work_buffer_plain_text_offset_set(offset);
573 mp_work_buffer = nrf_802154_tx_work_buffer_enable_for(p_aes_ccm_data->raw_frame);
574 mp_ciphertext = mp_work_buffer + offset;
575
576 memcpy(mp_work_buffer, p_aes_ccm_data->raw_frame, offset);
577 memset(mp_ciphertext, 0, p_aes_ccm_data->raw_frame[PHR_OFFSET] + PHR_SIZE - offset);
578
579 return true;
580 }
581
nrf_802154_aes_ccm_transform_start(uint8_t * p_frame)582 void nrf_802154_aes_ccm_transform_start(uint8_t * p_frame)
583 {
584 // Verify that the algorithm's inputs were prepared properly
585 if ((p_frame != m_aes_ccm_data.raw_frame) || (m_aes_ccm_data.raw_frame == NULL))
586 {
587 return;
588 }
589
590 uint8_t auth_flags = auth_flags_format(&m_aes_ccm_data);
591 uint8_t * p_x = m_x;
592 uint8_t * p_b = m_b;
593 ptrdiff_t offset = mp_ciphertext - mp_work_buffer;
594
595 // Copy updated part of the frame
596 memcpy(mp_work_buffer, p_frame, offset);
597
598 // initial settings
599 memset(p_x, 0, NRF_802154_AES_CCM_BLOCK_SIZE);
600 b0_format(&m_aes_ccm_data, auth_flags, p_b);
601
602 two_blocks_xor(p_x, p_b, NRF_802154_AES_CCM_BLOCK_SIZE);
603 start_ecb_auth_transformation();
604 }
605
nrf_802154_aes_ccm_transform_abort(uint8_t * p_frame)606 void nrf_802154_aes_ccm_transform_abort(uint8_t * p_frame)
607 {
608 // Verify that the encryption of the correct frame is being aborted.
609 if (p_frame != m_aes_ccm_data.raw_frame)
610 {
611 return;
612 }
613
614 m_aes_ccm_data.raw_frame = NULL;
615 }
616
617 #endif /* NRF_802154_ENCRYPTION_ACCELERATOR_ECB */
618