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