1 /***************************************************************************//**
2 * @file
3 * @brief Accelerated cryptographic primitives using the RADIOAES peripheral.
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30 #include "em_device.h"
31
32 #if defined(RADIOAES_PRESENT)
33 /// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
34
35 #include "sli_radioaes_management.h"
36 #include "sli_protocol_crypto.h"
37 #include "em_core.h"
38
39 #define AES_BLOCK_BYTES 16U
40 #define AES_128_KEY_BYTES 16U
41 #define AES_256_KEY_BYTES 32U
42
43 #define RADIOAES_CONFIG_BYTES 4U
44
45 #ifndef RADIOAES_BLE_RPA_MAX_KEYS
46 #define RADIOAES_BLE_RPA_MAX_KEYS 32
47 #endif
48
49 /// value for sli_radioaes_dma_sg_descr.tag to direct data to parameters
50 #define DMA_SG_TAG_ISCONFIG 0x00000010
51 /// value for sli_radioaes_dma_sg_descr.tag to direct data to processing
52 #define DMA_SG_TAG_ISDATA 0x00000000
53 /// value for sli_radioaes_dma_sg_descr.tag specifying data as last
54 #define DMA_SG_TAG_ISLAST 0x00000020
55
56 /// macro to set the offset in the configuration for sli_radioaes_dma_sg_descr.tag
57 #define DMA_SG_TAG_SETCFGOFFSET(a) ((((a) & 0xFF) << 8))
58
59 /// value for sli_radioaes_dma_sg_descr.tag specifying data type payload (will be encrypted/decrypted and authenticated)
60 #define DMA_SG_TAG_DATATYPE_AESPAYLOAD 0x00000000
61 /// value for sli_radioaes_dma_sg_descr.tag specifying data type header (will only be authenticated, not encrypted/decrypted)
62 #define DMA_SG_TAG_DATATYPE_AESHEADER 0x00000040
63
64 /// macro to set the amount of invalid bytes in for sli_radioaes_dma_sg_descr.tag
65 #define DMA_SG_TAG_SETINVALIDBYTES(a) ((((a) & 0x1F) << 8))
66
67 #define DMA_AXI_DESCR_CONST_ADDR 0x10000000
68 #define DMA_AXI_DESCR_REALIGN 0x20000000
69 #define DMA_AXI_DESCR_DISCARD 0x40000000
70 #define DMA_AXI_DESCR_INT_ENABLE 0x80000000
71 #define DMA_AXI_DESCR_INT_DISABLE 0x00000000
72
73 #define DMA_AXI_DESCR_NEXT_STOP 0x00000001
74 #define DMA_AXI_DESCR_NEXT_CONTINUE 0x00000000
75 #define DMA_AXI_DESCR_MASK_NEXT_ADD 0xFFFFFFFC
76
77 /// value of flags to discard the data
78 #define BLOCK_S_DISCARD_DATA 0x40000000
79 /// value of flags to realign the data
80 #define BLOCK_S_REALIGN_DATA 0x20000000
81 /// value of flags to set addressing in constant mode (pointing to a FIFO)
82 #define BLOCK_S_CONST_ADDR 0x10000000
83 /// value of flags to set addressing in increment mode (pointing to a buffer)
84 #define BLOCK_S_INCR_ADDR 0x00000000
85 /// mask for flags to only get DMA-related options
86 #define BLOCK_S_FLAG_MASK_DMA_PROPS 0x70000000
87 /// value of flags mask for fetcher location destination
88 #define BLOCK_S_MASK_LOC_DEST 0x00FFFFFF
89
90 /// Config ///
91
92 /// BA411E offset for Configuration word in DMA Scatter-Gather Tag
93 #define AES_OFFSET_CFG 0
94 /// BA411E offset for Configuration word in DMA Scatter-Gather Tag
95 #define AES_OFFSET_KEY 8
96 /// BA411E offset for Configuration word in DMA Scatter-Gather Tag
97 #define AES_OFFSET_IV 40
98 /// BA411E offset for Configuration word in DMA Scatter-Gather Tag
99 #define AES_OFFSET_IV2 56
100 /// BA411E offset for Configuration word in DMA Scatter-Gather Tag
101 #define AES_OFFSET_KEY2 72
102 /// BA411E offset for Configuration word in DMA Scatter-Gather Tag
103 #define AES_OFFSET_MASK 104
104
105 /// BA411E Mode Register value for ECB mode of operation
106 #define AES_MODEID_ECB 0x00000100
107 /// BA411E Mode Register value for CBC mode of operation
108 #define AES_MODEID_CBC 0x00000200
109 /// BA411E Mode Register value for CTR mode of operation
110 #define AES_MODEID_CTR 0x00000400
111 /// BA411E Mode Register value for CCM mode of operation
112 #define AES_MODEID_CCM 0x00002000
113 /// BA411E Mode Register value for CMAC mode of operation
114 #define AES_MODEID_CMA 0x00010000
115
116 /// BA411E Mode Register value for AES context saving
117 #define AES_MODEID_CX_SAVE 0x00000020
118 /// BA411E Mode Register value for AES context loading
119 #define AES_MODEID_CX_LOAD 0x00000010
120 /// BA411E Mode Register value for AES no context
121 #define AES_MODEID_NO_CX 0x00000000
122
123 /// BA411E Mode Register value for AES keysize of 128 bits
124 #define AES_MODEID_AES128 0x00000000
125 /// BA411E Mode Register value for AES keysize of 256 bits
126 #define AES_MODEID_AES256 0x00000004
127 /// BA411E Mode Register value for AES keysize of 192 bits
128 #define AES_MODEID_AES192 0x00000008
129
130 /// BA411E Mode Register value for encryption mode
131 #define AES_MODEID_ENCRYPT 0x00000000
132 /// BA411E Mode Register value for decryption mode
133 #define AES_MODEID_DECRYPT 0x00000001
134
135 /// BA411E Size for IV in GCM mode
136 #define AES_IV_GCM_SIZE 12
137 /// BA411E Size for IV in all modes except GCM
138 #define AES_IV_SIZE 16
139 /// BA411E Size for Context in GCM and CCM modes
140 #define AES_CTX_xCM_SIZE 32
141 /// BA411E Size for Context in all modes except GCM and CCM
142 #define AES_CTX_SIZE 16
143
144 ///
145 /// @brief Select which IP core the DMA will use. To set in descriptor sli_radioaes_dma_sg_descr.tag.
146 ///
147 typedef enum {
148 DMA_SG_ENGINESELECT_BYPASS = 0x00, ///< direct bypass from input to output
149 DMA_SG_ENGINESELECT_BA411E = 0x01, ///< data flow through BA411E AES
150 DMA_SG_ENGINESELECT_BA412 = 0x02, ///< data flow through BA412 DES
151 DMA_SG_ENGINESELECT_BA413 = 0x03, ///< data flow through BA413 Hash
152 DMA_SG_ENGINESELECT_BA417 = 0x04 ///< data flow through BA417 ChaChaPoly
153 } dma_engine_select_t;
154
155 ///
156 /// @brief Structure that represent a descriptor for the DMA module
157 /// (in scatter-gather mode).
158 ///
159 typedef struct {
160 volatile uint32_t address;
161 volatile uint32_t nextDescr;
162 volatile uint32_t lengthAndIrq;
163 volatile uint32_t tag;
164 } sli_radioaes_dma_descr_t;
165
166 #if defined(SLI_RADIOAES_REQUIRES_MASKING)
167 #define SLI_RADIOAES_MASK_DESCRIPTOR(next_descr_addr) \
168 { \
169 .address = (uint32_t) &sli_radioaes_mask, \
170 .nextDescr = next_descr_addr, \
171 .lengthAndIrq = 0x20000004UL, \
172 .tag = 0x00006811UL \
173 };
174 #endif
175
176 #define DMA_AXI_DESCR_END_POINTER ((sli_radioaes_dma_descr_t*) DMA_AXI_DESCR_NEXT_STOP)
177
178 // Local CCM variables
179 static const uint32_t aes_ccm_config_encrypt = AES_MODEID_CCM
180 | AES_MODEID_NO_CX
181 | AES_MODEID_AES128
182 | AES_MODEID_ENCRYPT;
183
184 static const uint32_t aes_ccm_config_decrypt = AES_MODEID_CCM
185 | AES_MODEID_NO_CX
186 | AES_MODEID_AES128
187 | AES_MODEID_DECRYPT;
188 static const uint32_t zeros = 0;
189
sli_radioaes_run_operation(sli_radioaes_dma_descr_t * first_fetch_descriptor,sli_radioaes_dma_descr_t * first_push_descriptor)190 static sl_status_t sli_radioaes_run_operation(sli_radioaes_dma_descr_t *first_fetch_descriptor,
191 sli_radioaes_dma_descr_t *first_push_descriptor)
192 {
193 sli_radioaes_state_t aes_ctx;
194 #if defined(SLI_RADIOAES_REQUIRES_MASKING)
195 sli_radioaes_dma_descr_t mask_descr = SLI_RADIOAES_MASK_DESCRIPTOR((uint32_t)first_fetch_descriptor);
196 #endif
197
198 sl_status_t status = sli_radioaes_acquire();
199 if (status == SL_STATUS_ISR) {
200 sli_radioaes_save_state(&aes_ctx);
201 } else if (status != SL_STATUS_OK) {
202 return status;
203 }
204
205 RADIOAES->CTRL = AES_CTRL_FETCHERSCATTERGATHER | AES_CTRL_PUSHERSCATTERGATHER;
206
207 #if defined(SLI_RADIOAES_REQUIRES_MASKING)
208 RADIOAES->FETCHADDR = (uint32_t) &mask_descr;
209 #else
210 RADIOAES->FETCHADDR = (uint32_t) first_fetch_descriptor;
211 #endif
212 RADIOAES->PUSHADDR = (uint32_t) first_push_descriptor;
213
214 RADIOAES->CMD = AES_CMD_STARTPUSHER | AES_CMD_STARTFETCHER;
215 while (RADIOAES->STATUS & (AES_STATUS_FETCHERBSY | AES_STATUS_PUSHERBSY)) {
216 // Wait for completion
217 }
218
219 if (status == SL_STATUS_ISR) {
220 sli_radioaes_restore_state(&aes_ctx);
221 }
222
223 return sli_radioaes_release();
224 }
225
226 // CCM (and CCM-star) implementation
aes_ccm_radio(bool encrypt,const unsigned char * add_data,size_t add_length,const unsigned char * data_in,unsigned char * data_out,size_t length,const unsigned char * key,const unsigned char * header,size_t header_length,unsigned char * tag,size_t tag_length)227 static sl_status_t aes_ccm_radio(bool encrypt,
228 const unsigned char *add_data,
229 size_t add_length,
230 const unsigned char *data_in,
231 unsigned char *data_out,
232 size_t length,
233 const unsigned char *key,
234 const unsigned char *header,
235 size_t header_length,
236 unsigned char *tag,
237 size_t tag_length)
238
239 {
240 // Assumptions:
241 // * There is always header input, but the header input may be block-aligned (BLE-CCM)
242 // * There may not always be ADD input (e.g. BLE-CCM)
243 // * There may not always be data input (e.g. CCM in authenticated-only mode)
244 // * The header input is pre-calculated by the caller of this function
245 // * Data output may be NULL (in which case it is discarded)
246 // * Tag length may be 0 (CCM-star), in which case the tag pointer is also allowed to be NULL
247
248 // Setup ver_failed output buffer and initialize it in case of decryption to an invalid value
249 volatile uint8_t ver_failed[AES_BLOCK_BYTES] = {[0 ... AES_BLOCK_BYTES - 1] = 0xFF };
250
251 // Calculate padding bytes. Since the accelerator expects to see the AESPAYLOAD data type
252 // at least once during the operation, ensure that we're emitting a padding block in case
253 // no input data is present.
254 size_t header_pad_bytes = (AES_BLOCK_BYTES - ((header_length + add_length) % AES_BLOCK_BYTES)) % AES_BLOCK_BYTES;
255 size_t data_pad_bytes = (length > 0 ? (AES_BLOCK_BYTES - (length % AES_BLOCK_BYTES)) % AES_BLOCK_BYTES : 16);
256
257 // Fetchers
258
259 // Tag output. If used, always the last descriptor. Not used for CCM-* without tag, the
260 // accelerator actually looks at the header and figures out whether or not to take in
261 // tag input.
262 sli_radioaes_dma_descr_t ccm_desc_fetcher_tag = {
263 .address = (uint32_t) tag,
264 .nextDescr = (uint32_t) DMA_AXI_DESCR_END_POINTER,
265 .lengthAndIrq = (uint32_t) tag_length
266 | BLOCK_S_INCR_ADDR
267 | BLOCK_S_REALIGN_DATA,
268 .tag = DMA_SG_ENGINESELECT_BA411E
269 | DMA_SG_TAG_ISDATA
270 | DMA_SG_TAG_ISLAST
271 | DMA_SG_TAG_DATATYPE_AESPAYLOAD
272 | DMA_SG_TAG_SETINVALIDBYTES(AES_BLOCK_BYTES - tag_length)
273 };
274
275 // Data input. Can be zero-length, in which case we'll issue a bogus descriptor instead.
276 sli_radioaes_dma_descr_t ccm_desc_fetcher_data = {
277 .address = (uint32_t) (length > 0 ? data_in : ver_failed),
278 .nextDescr = (uint32_t) ((encrypt || tag_length == 0) ? DMA_AXI_DESCR_END_POINTER : &ccm_desc_fetcher_tag),
279 .lengthAndIrq = (uint32_t) (length > 0 ? length : data_pad_bytes)
280 | BLOCK_S_INCR_ADDR
281 | BLOCK_S_REALIGN_DATA,
282 .tag = DMA_SG_ENGINESELECT_BA411E
283 | DMA_SG_TAG_ISDATA
284 | DMA_SG_TAG_DATATYPE_AESPAYLOAD
285 | ((encrypt || tag_length == 0) ? DMA_SG_TAG_ISLAST : 0)
286 | DMA_SG_TAG_SETINVALIDBYTES(data_pad_bytes),
287 };
288
289 // Possible CCM AAD block (concatenated with the header). Can be zero-length, in which case
290 // this descriptor should not be referenced but rather bypassed to data.
291 sli_radioaes_dma_descr_t ccm_desc_fetcher_add = {
292 .address = (uint32_t) add_data,
293 .nextDescr = (uint32_t) &ccm_desc_fetcher_data,
294 .lengthAndIrq = (uint32_t) add_length
295 | BLOCK_S_INCR_ADDR
296 | BLOCK_S_REALIGN_DATA,
297 .tag = DMA_SG_ENGINESELECT_BA411E
298 | DMA_SG_TAG_ISDATA
299 | DMA_SG_TAG_DATATYPE_AESHEADER
300 | DMA_SG_TAG_SETINVALIDBYTES(header_pad_bytes)
301 };
302
303 // Header input block. Always present.
304 sli_radioaes_dma_descr_t ccm_desc_fetcher_header = {
305 .address = (uint32_t) header,
306 .nextDescr = (uint32_t) (add_length > 0 ? &ccm_desc_fetcher_add : &ccm_desc_fetcher_data),
307 .lengthAndIrq = (uint32_t) header_length
308 | BLOCK_S_INCR_ADDR
309 | (add_length > 0 ? 0 : BLOCK_S_REALIGN_DATA),
310 .tag = DMA_SG_ENGINESELECT_BA411E
311 | DMA_SG_TAG_ISDATA
312 | DMA_SG_TAG_DATATYPE_AESHEADER
313 | (add_length > 0 ? 0 : DMA_SG_TAG_SETINVALIDBYTES(header_pad_bytes))
314 };
315
316 // Key input block. Always present.
317 sli_radioaes_dma_descr_t ccm_desc_fetcher_key = {
318 .address = (uint32_t) key,
319 .nextDescr = (uint32_t) &ccm_desc_fetcher_header,
320 .lengthAndIrq = (uint32_t) AES_128_KEY_BYTES
321 | BLOCK_S_INCR_ADDR
322 | BLOCK_S_REALIGN_DATA,
323 .tag = DMA_SG_ENGINESELECT_BA411E
324 | DMA_SG_TAG_ISCONFIG
325 | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
326 };
327
328 // Operation configuration word block. Always present.
329 sli_radioaes_dma_descr_t ccm_desc_fetcher_config = {
330 .address = (uint32_t) (encrypt ? &aes_ccm_config_encrypt : &aes_ccm_config_decrypt),
331 .nextDescr = (uint32_t) &ccm_desc_fetcher_key,
332 .lengthAndIrq = (uint32_t) RADIOAES_CONFIG_BYTES
333 | BLOCK_S_INCR_ADDR
334 | BLOCK_S_REALIGN_DATA,
335 .tag = DMA_SG_ENGINESELECT_BA411E
336 | DMA_SG_TAG_ISCONFIG
337 | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
338 };
339
340 // Pushers
341
342 // Tag / verification output padding, only if 0 < tag length < 16 bytes.
343 sli_radioaes_dma_descr_t ccm_desc_pusher_final_padding = {
344 .address = (uint32_t) NULL,
345 .nextDescr = (uint32_t) DMA_AXI_DESCR_END_POINTER,
346 .lengthAndIrq = (uint32_t) (AES_BLOCK_BYTES - tag_length)
347 | DMA_AXI_DESCR_DISCARD
348 };
349
350 // Tag output. Direct into tag buffer for encrypt, into local buffer for
351 // decrypt-and-verify. This descriptor is not referenced with tag_length == 0 (CCM-*)
352 sli_radioaes_dma_descr_t ccm_desc_pusher_tag = {
353 .address = (uint32_t) (encrypt ? tag : (unsigned char *)ver_failed),
354 .nextDescr = (uint32_t) ((AES_BLOCK_BYTES - tag_length) > 0 ? &ccm_desc_pusher_final_padding : DMA_AXI_DESCR_END_POINTER),
355 .lengthAndIrq = (uint32_t) tag_length
356 };
357
358 // Data padding output. There's guaranteed always at least one of data or data padding.
359 sli_radioaes_dma_descr_t ccm_desc_pusher_data_padding = {
360 .address = (uint32_t) NULL,
361 .nextDescr = (uint32_t) (tag_length > 0 ? &ccm_desc_pusher_tag : DMA_AXI_DESCR_END_POINTER),
362 .lengthAndIrq = (uint32_t) data_pad_bytes
363 | DMA_AXI_DESCR_DISCARD,
364 };
365
366 // Data (ciphertext/plaintext) output. Pointer can be NULL, in which case we tell the
367 // DMA to discard the data.
368 sli_radioaes_dma_descr_t ccm_desc_pusher_data = {
369 .address = (uint32_t) data_out,
370 .nextDescr = (uint32_t) (data_pad_bytes > 0 ? &ccm_desc_pusher_data_padding : (tag_length > 0 ? &ccm_desc_pusher_tag : DMA_AXI_DESCR_END_POINTER)),
371 .lengthAndIrq = (uint32_t) length
372 | (data_out == NULL ? DMA_AXI_DESCR_DISCARD : 0),
373 };
374
375 // Discard all AAD input (which is reflected back to the output). There's guaranteed always a header.
376 sli_radioaes_dma_descr_t ccm_desc_pusher_header_add = {
377 .address = (uint32_t) NULL,
378 .nextDescr = (uint32_t) (length > 0 ? &ccm_desc_pusher_data : &ccm_desc_pusher_data_padding),
379 .lengthAndIrq = (uint32_t) (header_length + add_length + header_pad_bytes)
380 | DMA_AXI_DESCR_DISCARD
381 };
382
383 sl_status_t status = sli_radioaes_run_operation(&ccm_desc_fetcher_config, &ccm_desc_pusher_header_add);
384
385 if (status != SL_STATUS_OK) {
386 return status;
387 }
388
389 // Check MIC
390 if (!encrypt) {
391 uint32_t accumulator = 0;
392 for (size_t i = 0; i < tag_length; i++) {
393 accumulator |= ver_failed[i];
394 }
395 if (accumulator != 0) {
396 return SL_STATUS_INVALID_SIGNATURE;
397 }
398 }
399 return SL_STATUS_OK;
400 }
401
402 // Perform a CCM encrypt/decrypt operation with BLE parameters and input.
403 // This means:
404 // * 13 bytes IV
405 // * 1 byte AAD (parameter 'header')
406 // * AES-128 key (16 byte key)
407 // * in-place encrypt/decrypt with variable length plain/ciphertext
408 // (up to 64 kB, uint16 overflow)
409 // * 4 byte tag
aes_ccm_ble(bool encrypt,unsigned char * data,size_t length,const unsigned char * key,const unsigned char * iv,unsigned char header,unsigned char * tag)410 static sl_status_t aes_ccm_ble(bool encrypt,
411 unsigned char *data,
412 size_t length,
413 const unsigned char *key,
414 const unsigned char *iv,
415 unsigned char header,
416 unsigned char *tag)
417
418 {
419 uint8_t b0b1[19];
420
421 // Fill in B0 block according to BLE spec
422 b0b1[0] = 0x49U;
423
424 // Copy in the 13 bytes of nonce
425 for (size_t i = 0; i < 13; i++) {
426 b0b1[i + 1] = iv[i];
427 }
428
429 b0b1[14] = (uint8_t) length >> 8;
430 b0b1[15] = (uint8_t) length;
431 b0b1[16] = 0; // upper octet of AAD length
432 b0b1[17] = 1; // lower octet of AAD length (BLE CCM always has only one byte of AAD)
433 b0b1[18] = header; // AAD
434
435 return aes_ccm_radio(encrypt,
436 NULL, 0,
437 data, data, length,
438 key,
439 b0b1, sizeof(b0b1),
440 tag, 4);
441 }
442
sli_aes_crypt_ctr_radio(const unsigned char * key,unsigned int keybits,const unsigned char input[AES_BLOCK_BYTES],const unsigned char iv_in[AES_BLOCK_BYTES],volatile unsigned char iv_out[AES_BLOCK_BYTES],volatile unsigned char output[AES_BLOCK_BYTES])443 sl_status_t sli_aes_crypt_ctr_radio(const unsigned char *key,
444 unsigned int keybits,
445 const unsigned char input[AES_BLOCK_BYTES],
446 const unsigned char iv_in[AES_BLOCK_BYTES],
447 volatile unsigned char iv_out[AES_BLOCK_BYTES],
448 volatile unsigned char output[AES_BLOCK_BYTES])
449 {
450 uint32_t aes_config;
451 static const uint32_t zero = 0;
452
453 switch (keybits) {
454 case 256:
455 aes_config = AES_MODEID_CTR | AES_MODEID_CX_LOAD | (((uint32_t)iv_out != 0) ? AES_MODEID_CX_SAVE : 0) | AES_MODEID_AES256;
456 break;
457 case 192:
458 return SL_STATUS_NOT_SUPPORTED;
459 case 128:
460 aes_config = AES_MODEID_CTR | AES_MODEID_CX_LOAD | (((uint32_t)iv_out != 0) ? AES_MODEID_CX_SAVE : 0) | AES_MODEID_AES128;
461 break;
462 default:
463 return SL_STATUS_INVALID_KEY;
464 }
465
466 sli_radioaes_dma_descr_t aes_desc_pusher_ctx = {
467 .address = (uint32_t) iv_out,
468 .nextDescr = DMA_AXI_DESCR_NEXT_STOP,
469 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
470 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST
471 };
472
473 sli_radioaes_dma_descr_t aes_desc_pusher_data = {
474 .address = (uint32_t) output,
475 .nextDescr = (((uint32_t)iv_out != 0) ? (uint32_t) &aes_desc_pusher_ctx : DMA_AXI_DESCR_NEXT_STOP),
476 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
477 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISDATA
478 };
479
480 sli_radioaes_dma_descr_t aes_desc_fetcher_data = {
481 .address = (uint32_t) input,
482 .nextDescr = DMA_AXI_DESCR_NEXT_STOP,
483 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
484 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST | DMA_SG_TAG_ISDATA | DMA_SG_TAG_DATATYPE_AESPAYLOAD
485 };
486
487 sli_radioaes_dma_descr_t aes_desc_fetcher_no_ctx = {
488 .address = (uint32_t) &zero,
489 .nextDescr = (uint32_t) &aes_desc_fetcher_data,
490 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_CONST_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
491 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_IV)
492 };
493
494 sli_radioaes_dma_descr_t aes_desc_fetcher_ctx = {
495 .address = (uint32_t) iv_in,
496 .nextDescr = (uint32_t) &aes_desc_fetcher_data,
497 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
498 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_IV)
499 };
500
501 sli_radioaes_dma_descr_t aes_desc_fetcher_config = {
502 .address = (uint32_t) &aes_config,
503 .nextDescr = (((uint32_t)iv_in != 0) ? (uint32_t) &aes_desc_fetcher_ctx : (uint32_t) &aes_desc_fetcher_no_ctx),
504 .lengthAndIrq = sizeof(aes_config),
505 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
506 };
507
508 sli_radioaes_dma_descr_t aes_desc_fetcher_key = {
509 .address = (uint32_t) key,
510 .nextDescr = (uint32_t) &aes_desc_fetcher_config,
511 .lengthAndIrq = (uint32_t) (keybits / 8) | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
512 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
513 };
514
515 // Start operation
516 return sli_radioaes_run_operation(&aes_desc_fetcher_key, &aes_desc_pusher_data);
517 }
518
sli_aes_crypt_ecb_radio(bool encrypt,const unsigned char * key,unsigned int keybits,const unsigned char input[AES_BLOCK_BYTES],volatile unsigned char output[AES_BLOCK_BYTES])519 sl_status_t sli_aes_crypt_ecb_radio(bool encrypt,
520 const unsigned char *key,
521 unsigned int keybits,
522 const unsigned char input[AES_BLOCK_BYTES],
523 volatile unsigned char output[AES_BLOCK_BYTES])
524 {
525 uint32_t aes_config;
526
527 switch (keybits) {
528 case 256:
529 aes_config = AES_MODEID_ECB | AES_MODEID_NO_CX | AES_MODEID_AES256;
530 break;
531 case 192:
532 return SL_STATUS_NOT_SUPPORTED;
533 case 128:
534 aes_config = AES_MODEID_ECB | AES_MODEID_NO_CX | AES_MODEID_AES128;
535 break;
536 default:
537 return SL_STATUS_INVALID_KEY;
538 }
539
540 aes_config |= encrypt ? AES_MODEID_ENCRYPT : AES_MODEID_DECRYPT;
541
542 sli_radioaes_dma_descr_t aes_desc_pusher_data = {
543 .address = (uint32_t) output,
544 .nextDescr = DMA_AXI_DESCR_NEXT_STOP,
545 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
546 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST
547 };
548
549 sli_radioaes_dma_descr_t aes_desc_fetcher_data = {
550 .address = (uint32_t) input,
551 .nextDescr = DMA_AXI_DESCR_NEXT_STOP,
552 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
553 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST | DMA_SG_TAG_ISDATA | DMA_SG_TAG_DATATYPE_AESPAYLOAD
554 };
555
556 sli_radioaes_dma_descr_t aes_desc_fetcher_config = {
557 .address = (uint32_t) &aes_config,
558 .nextDescr = (uint32_t) &aes_desc_fetcher_data,
559 .lengthAndIrq = sizeof(aes_config),
560 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
561 };
562
563 sli_radioaes_dma_descr_t aes_desc_fetcher_key = {
564 .address = (uint32_t) key,
565 .nextDescr = (uint32_t) &aes_desc_fetcher_config,
566 .lengthAndIrq = (uint32_t) (keybits / 8) | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
567 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
568 };
569
570 // Start operation
571 return sli_radioaes_run_operation(&aes_desc_fetcher_key, &aes_desc_pusher_data);
572 }
573
sli_aes_cmac_radio(const unsigned char * key,unsigned int keybits,const unsigned char * input,unsigned int length,volatile unsigned char output[16])574 sl_status_t sli_aes_cmac_radio(const unsigned char *key,
575 unsigned int keybits,
576 const unsigned char *input,
577 unsigned int length,
578 volatile unsigned char output[16])
579 {
580 uint32_t aes_config;
581
582 switch (keybits) {
583 case 256:
584 aes_config = AES_MODEID_CMA | AES_MODEID_NO_CX | AES_MODEID_AES256 | AES_MODEID_ENCRYPT;
585 break;
586 case 192:
587 return SL_STATUS_NOT_SUPPORTED;
588 case 128:
589 aes_config = AES_MODEID_CMA | AES_MODEID_NO_CX | AES_MODEID_AES128 | AES_MODEID_ENCRYPT;
590 break;
591 default:
592 return SL_STATUS_INVALID_KEY;
593 }
594
595 size_t pad_len = 16 - (length % 16);
596 if (pad_len == 16 && length > 0) {
597 pad_len = 0;
598 }
599
600 if (length == 0) {
601 length = 16UL;
602 input = (const unsigned char *)&zeros;
603 } else {
604 length = (length + 15) & ~0xFUL;
605 }
606
607 sli_radioaes_dma_descr_t aes_desc_pusher_data = {
608 .address = (uint32_t) output,
609 .nextDescr = DMA_AXI_DESCR_NEXT_STOP,
610 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
611 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST
612 };
613
614 sli_radioaes_dma_descr_t aes_desc_fetcher_data = {
615 .address = (uint32_t) input,
616 .nextDescr = DMA_AXI_DESCR_NEXT_STOP,
617 .lengthAndIrq = length | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
618 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST | DMA_SG_TAG_ISDATA | DMA_SG_TAG_DATATYPE_AESPAYLOAD | DMA_SG_TAG_SETINVALIDBYTES(pad_len)
619 };
620
621 sli_radioaes_dma_descr_t aes_desc_fetcher_config = {
622 .address = (uint32_t) &aes_config,
623 .nextDescr = (uint32_t) &aes_desc_fetcher_data,
624 .lengthAndIrq = sizeof(aes_config),
625 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
626 };
627
628 sli_radioaes_dma_descr_t aes_desc_fetcher_key = {
629 .address = (uint32_t) key,
630 .nextDescr = (uint32_t) &aes_desc_fetcher_config,
631 .lengthAndIrq = (uint32_t) (keybits / 8) | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
632 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
633 };
634
635 // Start operation
636 return sli_radioaes_run_operation(&aes_desc_fetcher_key, &aes_desc_pusher_data);
637 }
638
639 //
640 // CCM buffer authenticated decryption optimized for BLE
641 //
sli_ccm_auth_decrypt_ble(unsigned char * data,size_t length,const unsigned char * key,const unsigned char * iv,unsigned char header,unsigned char * tag)642 sl_status_t sli_ccm_auth_decrypt_ble(unsigned char *data,
643 size_t length,
644 const unsigned char *key,
645 const unsigned char *iv,
646 unsigned char header,
647 unsigned char *tag)
648 {
649 return aes_ccm_ble(false,
650 data,
651 length,
652 key,
653 iv,
654 header,
655 (uint8_t *) tag);
656 }
657
658 //
659 // CCM buffer encryption optimized for BLE
660 //
sli_ccm_encrypt_and_tag_ble(unsigned char * data,size_t length,const unsigned char * key,const unsigned char * iv,unsigned char header,unsigned char * tag)661 sl_status_t sli_ccm_encrypt_and_tag_ble(unsigned char *data,
662 size_t length,
663 const unsigned char *key,
664 const unsigned char *iv,
665 unsigned char header,
666 unsigned char *tag)
667 {
668 return aes_ccm_ble(true,
669 data,
670 length,
671 key,
672 iv,
673 header,
674 tag);
675 }
676
sli_ccm_zigbee(bool encrypt,const unsigned char * data_in,unsigned char * data_out,size_t length,const unsigned char * key,const unsigned char * iv,const unsigned char * aad,size_t aad_len,unsigned char * tag,size_t tag_len)677 sl_status_t sli_ccm_zigbee(bool encrypt,
678 const unsigned char *data_in,
679 unsigned char *data_out,
680 size_t length,
681 const unsigned char *key,
682 const unsigned char *iv,
683 const unsigned char *aad,
684 size_t aad_len,
685 unsigned char *tag,
686 size_t tag_len)
687 {
688 // Validated assumption: for ZigBee, the authenticated data
689 // length will always fit into a 16-bit length field, meaning
690 // the header will always be either 16 or 18 bytes long.
691 uint8_t header[18];
692
693 // Start with the 'flags' byte. It encodes whether there is AAD,
694 // and the length of the tag fields
695 header[0] = 0x01 // always 2 bytes of message length
696 | ((aad_len > 0) ? 0x40 : 0x00) // Set 'aflag' bit if there is AAD
697 | ((tag_len >= 4) ? (((tag_len - 2) / 2) << 3) : 0); // Encode tag length
698
699 for (size_t i = 0; i < 13; i++) {
700 header[i + 1] = iv[i];
701 }
702
703 header[14] = (uint8_t) length >> 8;
704 header[15] = (uint8_t) length;
705 if (aad_len > 0) {
706 header[16] = (uint8_t) aad_len >> 8; // upper octet of AAD length
707 header[17] = (uint8_t) aad_len; // lower octet of AAD length
708 }
709
710 return aes_ccm_radio(encrypt,
711 aad,
712 aad_len,
713 data_in,
714 data_out,
715 length,
716 key,
717 header,
718 (aad_len > 0 ? 18 : 16),
719 tag,
720 tag_len);
721 }
722
723 //
724 // Process a table of BLE RPA device keys and look for a
725 // match against the supplied hash. Algorithm is AES-128.
726 //
sli_process_ble_rpa(const unsigned char keytable[],uint32_t keymask,uint32_t prand,uint32_t hash)727 int sli_process_ble_rpa(const unsigned char keytable[],
728 uint32_t keymask,
729 uint32_t prand,
730 uint32_t hash)
731 {
732 int block;
733 int previous_block = -1, result = -1;
734 static const uint32_t aes_rpa_config = AES_MODEID_ECB
735 | AES_MODEID_NO_CX
736 | AES_MODEID_AES128
737 | AES_MODEID_ENCRYPT;
738
739 uint32_t rpa_data_in[AES_BLOCK_BYTES / sizeof(uint32_t)] = { 0 };
740 volatile uint32_t rpa_data_out[AES_BLOCK_BYTES / sizeof(uint32_t)];
741 sli_radioaes_state_t aes_ctx;
742 CORE_DECLARE_IRQ_STATE;
743
744 rpa_data_in[3] = __REV(prand);
745
746 sli_radioaes_dma_descr_t aes_desc_pusher_data = {
747 .address = (uint32_t) rpa_data_out,
748 .nextDescr = DMA_AXI_DESCR_NEXT_STOP,
749 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
750 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST
751 };
752
753 sli_radioaes_dma_descr_t aes_desc_fetcher_data = {
754 .address = (uint32_t) rpa_data_in,
755 .nextDescr = DMA_AXI_DESCR_NEXT_STOP,
756 .lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
757 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST | DMA_SG_TAG_ISDATA | DMA_SG_TAG_DATATYPE_AESPAYLOAD
758 };
759
760 sli_radioaes_dma_descr_t aes_desc_fetcher_config = {
761 .address = (uint32_t) &aes_rpa_config,
762 .nextDescr = (uint32_t) &aes_desc_fetcher_data,
763 .lengthAndIrq = sizeof(aes_rpa_config),
764 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
765 };
766
767 volatile sli_radioaes_dma_descr_t aes_desc_fetcher_key = {
768 .address = (uint32_t) NULL, // Filled out in each round of RPA check
769 .nextDescr = (uint32_t) &aes_desc_fetcher_config,
770 .lengthAndIrq = (uint32_t) AES_128_KEY_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
771 .tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
772 };
773
774 // Start operation
775 sl_status_t status = sli_radioaes_acquire();
776 if (status == SL_STATUS_ISR) {
777 sli_radioaes_save_state(&aes_ctx);
778 } else if (status != SL_STATUS_OK) {
779 return -1;
780 }
781
782 RADIOAES->CTRL = AES_CTRL_FETCHERSCATTERGATHER | AES_CTRL_PUSHERSCATTERGATHER;
783
784 #if defined(SLI_RADIOAES_REQUIRES_MASKING)
785 // Start with feeding the mask input
786 sli_radioaes_dma_descr_t mask_descr = SLI_RADIOAES_MASK_DESCRIPTOR(DMA_AXI_DESCR_NEXT_STOP);
787 RADIOAES->FETCHADDR = (uint32_t) &mask_descr;
788 RADIOAES->CMD = AES_CMD_STARTFETCHER;
789 #endif
790
791 // Start a critical section to avoid preemption in-between loading of the RPA key
792 // and starting the corresponding data pusher.
793 CORE_ENTER_CRITICAL();
794
795 // Data output contains hash in the most significant word (WORD3).
796 // Descriptors for blocks that are not included in key mask will be skipped.
797 for (block = 0; block < RADIOAES_BLE_RPA_MAX_KEYS; block++) {
798 if ( keymask & (1U << block) ) { // Skip masked keys
799 // Handle pending interrupts while the peripheral is in 'preemptable' state
800 CORE_YIELD_CRITICAL();
801 // Write key address and start operation
802 while (RADIOAES->STATUS & AES_STATUS_FETCHERBSY) {
803 // Wait for completion
804 }
805 aes_desc_fetcher_key.address = (uint32_t) &keytable[block * AES_128_KEY_BYTES];
806 RADIOAES->FETCHADDR = (uint32_t) &aes_desc_fetcher_key;
807
808 RADIOAES->CMD = AES_CMD_STARTFETCHER;
809
810 // Wait for pusher from previous round to finish
811 while (RADIOAES->STATUS & AES_STATUS_PUSHERBSY) {
812 // Wait for completion
813 }
814 RADIOAES->PUSHADDR = (uint32_t) &aes_desc_pusher_data;
815
816 // Check previous results while AES is processing
817 if ((previous_block >= 0) && ((rpa_data_out[3] & 0xFFFFFF00) == __REV(hash)) ) {
818 // Make sure AES is finished before returning
819 RADIOAES->CMD = AES_CMD_STARTPUSHER;
820 result = previous_block;
821 break;
822 }
823
824 // Start pusher so it is ready to push results when encryption is done
825 RADIOAES->CMD = AES_CMD_STARTPUSHER;
826 previous_block = block;
827 }
828 }
829
830 CORE_EXIT_CRITICAL();
831
832 // Wait for last data and check it
833 while (RADIOAES->STATUS & AES_STATUS_PUSHERBSY) {
834 // Wait for completion
835 }
836
837 if (status == SL_STATUS_ISR) {
838 sli_radioaes_restore_state(&aes_ctx);
839 }
840
841 sli_radioaes_release();
842
843 if (result >= 0) {
844 return result;
845 }
846
847 if ((rpa_data_out[3] & 0xFFFFFF00) == __REV(hash) ) {
848 return previous_block;
849 }
850
851 // No match
852 return -1;
853 }
854
sli_aes_seed_mask(void)855 void sli_aes_seed_mask(void)
856 {
857 // Acquiring and releasing the peripheral should ensure the mask is properly
858 // set.
859 (void) sli_radioaes_acquire();
860 (void) sli_radioaes_release();
861 }
862
863 /// @endcond
864 #endif // defined(RADIOAES_PRESENT)
865