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