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