1 /***************************************************************************//**
2 * @file
3 * @brief Silicon Labs Secure Engine Manager API.
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
31 #include "sl_se_manager.h"
32 #if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
33
34 #include "sli_se_manager_internal.h"
35 #include "em_se.h"
36 #include "sl_assert.h"
37 #include <string.h>
38
39 /// @addtogroup sl_se_manager
40 /// @{
41
memcmp_time_cst(uint8_t * in1,uint8_t * in2,uint32_t size)42 uint32_t memcmp_time_cst(uint8_t *in1, uint8_t *in2, uint32_t size)
43 {
44 //Don't try to optimise this function for performance, it's time constant for security reasons
45 uint32_t diff = 0;
46 uint32_t i = 0;
47 for (i = 0; i < size; i++) {
48 diff |= (*(in1 + i) ^ (*(in2 + i)));
49 }
50
51 return (diff > 0);
52 }
53
54 // -----------------------------------------------------------------------------
55 // Global Functions
56
57 /***************************************************************************//**
58 * AES-ECB block encryption/decryption.
59 ******************************************************************************/
sl_se_aes_crypt_ecb(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_cipher_operation_t mode,size_t length,const unsigned char * input,unsigned char * output)60 sl_status_t sl_se_aes_crypt_ecb(sl_se_command_context_t *cmd_ctx,
61 const sl_se_key_descriptor_t *key,
62 sl_se_cipher_operation_t mode,
63 size_t length,
64 const unsigned char *input,
65 unsigned char *output)
66 {
67 if (cmd_ctx == NULL || key == NULL || input == NULL || output == NULL
68 || (length & 0xFU) != 0U) {
69 return SL_STATUS_INVALID_PARAMETER;
70 }
71
72 SE_Command_t *se_cmd = &cmd_ctx->command;
73 sl_status_t status;
74
75 sli_se_command_init(cmd_ctx,
76 (mode == SL_SE_ENCRYPT
77 ? SLI_SE_COMMAND_AES_ENCRYPT : SLI_SE_COMMAND_AES_DECRYPT)
78 | SLI_SE_COMMAND_OPTION_MODE_ECB
79 | SLI_SE_COMMAND_OPTION_CONTEXT_WHOLE);
80
81 // Add key parameters to command
82 sli_add_key_parameters(cmd_ctx, key, status);
83 // Message size (number of bytes)
84 SE_addParameter(se_cmd, length);
85
86 // Add key metadata block to command
87 sli_add_key_metadata(cmd_ctx, key, status);
88 // Add key input block to command
89 sli_add_key_input(cmd_ctx, key, status);
90
91 SE_DataTransfer_t in = SE_DATATRANSFER_DEFAULT(input, length);
92 SE_addDataInput(se_cmd, &in);
93
94 SE_DataTransfer_t out = SE_DATATRANSFER_DEFAULT(output, length);
95 SE_addDataOutput(se_cmd, &out);
96
97 return sli_se_execute_and_wait(cmd_ctx);
98 }
99
100 /***************************************************************************//**
101 * AES-CBC buffer encryption/decryption.
102 ******************************************************************************/
sl_se_aes_crypt_cbc(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_cipher_operation_t mode,size_t length,unsigned char iv[16],const unsigned char * input,unsigned char * output)103 sl_status_t sl_se_aes_crypt_cbc(sl_se_command_context_t *cmd_ctx,
104 const sl_se_key_descriptor_t *key,
105 sl_se_cipher_operation_t mode,
106 size_t length,
107 unsigned char iv[16],
108 const unsigned char *input,
109 unsigned char *output)
110 {
111 if (cmd_ctx == NULL || key == NULL || input == NULL || output == NULL
112 || iv == NULL) {
113 return SL_STATUS_INVALID_PARAMETER;
114 }
115
116 SE_Command_t *se_cmd = &cmd_ctx->command;
117 sl_status_t status;
118
119 // Input length must be a multiple of 16 bytes which is the AES block length
120 if (length & 0xf) {
121 return SL_STATUS_INVALID_PARAMETER;
122 }
123
124 sli_se_command_init(cmd_ctx,
125 (mode == SL_SE_ENCRYPT
126 ? SLI_SE_COMMAND_AES_ENCRYPT : SLI_SE_COMMAND_AES_DECRYPT)
127 | SLI_SE_COMMAND_OPTION_MODE_CBC
128 | SLI_SE_COMMAND_OPTION_CONTEXT_ADD);
129
130 // Add key parameters to command
131 sli_add_key_parameters(cmd_ctx, key, status);
132 // Message size (number of bytes)
133 SE_addParameter(se_cmd, length);
134
135 // Add key metadata block to command
136 sli_add_key_metadata(cmd_ctx, key, status);
137 // Add key input block to command
138 sli_add_key_input(cmd_ctx, key, status);
139
140 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(iv, 16);
141 SE_DataTransfer_t in = SE_DATATRANSFER_DEFAULT(input, length);
142 SE_addDataInput(se_cmd, &iv_in);
143 SE_addDataInput(se_cmd, &in);
144
145 SE_DataTransfer_t out = SE_DATATRANSFER_DEFAULT(output, length);
146 SE_DataTransfer_t iv_out = SE_DATATRANSFER_DEFAULT(iv, 16);
147 SE_addDataOutput(se_cmd, &out);
148 SE_addDataOutput(se_cmd, &iv_out);
149
150 return sli_se_execute_and_wait(cmd_ctx);
151 }
152
153 /***************************************************************************//**
154 * AES-CFB128 buffer encryption/decryption.
155 ******************************************************************************/
sl_se_aes_crypt_cfb128(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_cipher_operation_t mode,size_t length,uint32_t * iv_off,unsigned char iv[16],const unsigned char * input,unsigned char * output)156 sl_status_t sl_se_aes_crypt_cfb128(sl_se_command_context_t *cmd_ctx,
157 const sl_se_key_descriptor_t *key,
158 sl_se_cipher_operation_t mode,
159 size_t length,
160 uint32_t *iv_off,
161 unsigned char iv[16],
162 const unsigned char *input,
163 unsigned char *output)
164 {
165 if (cmd_ctx == NULL || key == NULL || input == NULL || output == NULL
166 || iv == NULL) {
167 return SL_STATUS_INVALID_PARAMETER;
168 }
169
170 SE_Command_t *se_cmd = &cmd_ctx->command;
171 uint32_t n = iv_off ? *iv_off : 0;
172 uint32_t processed = 0;
173 sl_status_t command_status = SL_STATUS_OK;
174
175 while (processed < length) {
176 if (n > 0) {
177 // start by filling up the IV
178 if (mode == SL_SE_ENCRYPT) {
179 iv[n] = output[processed] = (unsigned char)(iv[n] ^ input[processed]);
180 } else {
181 int c = input[processed];
182 output[processed] = (unsigned char)(c ^ iv[n]);
183 iv[n] = (unsigned char) c;
184 }
185 n = (n + 1) & 0x0F;
186 processed++;
187 } else {
188 // process one ore more blocks of data
189 uint32_t iterations = (length - processed) / 16;
190
191 if (iterations > 0) {
192 sli_se_command_init(cmd_ctx,
193 (mode == SL_SE_ENCRYPT
194 ? SLI_SE_COMMAND_AES_ENCRYPT : SLI_SE_COMMAND_AES_DECRYPT)
195 | SLI_SE_COMMAND_OPTION_MODE_CFB
196 | SLI_SE_COMMAND_OPTION_CONTEXT_ADD);
197
198 // Add key parameters to command
199 sli_add_key_parameters(cmd_ctx, key, command_status);
200 // Message size (number of bytes)
201 SE_addParameter(se_cmd, iterations * 16);
202
203 // Add key metadata block to command
204 sli_add_key_metadata(cmd_ctx, key, command_status);
205 // Add key input block to command
206 sli_add_key_input(cmd_ctx, key, command_status);
207
208 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(iv, 16);
209 SE_DataTransfer_t in = SE_DATATRANSFER_DEFAULT(&input[processed], iterations * 16);
210 SE_addDataInput(se_cmd, &iv_in);
211 SE_addDataInput(se_cmd, &in);
212
213 SE_DataTransfer_t out = SE_DATATRANSFER_DEFAULT(&output[processed], iterations * 16);
214 SE_DataTransfer_t iv_out = SE_DATATRANSFER_DEFAULT(iv, 16);
215 SE_addDataOutput(se_cmd, &out);
216 SE_addDataOutput(se_cmd, &iv_out);
217
218 command_status = sli_se_execute_and_wait(cmd_ctx);
219 processed += iterations * 16;
220 if (command_status != SL_STATUS_OK) {
221 return command_status;
222 }
223 }
224
225 while ((length - processed) > 0) {
226 if (n == 0) {
227 // Need to update the IV but don't have a full block of input to pass
228 // to the SE.
229 command_status = sl_se_aes_crypt_ecb(cmd_ctx, key, SL_SE_ENCRYPT, 16U, iv, iv);
230 if (command_status != SL_STATUS_OK) {
231 return command_status;
232 }
233 }
234 // Save remainder to IV
235 if (mode == SL_SE_ENCRYPT) {
236 iv[n] = output[processed] = (unsigned char)(iv[n] ^ input[processed]);
237 } else {
238 int c = input[processed];
239 output[processed] = (unsigned char)(c ^ iv[n]);
240 iv[n] = (unsigned char) c;
241 }
242 n = (n + 1) & 0x0F;
243 processed++;
244 }
245 }
246 }
247
248 if ( iv_off ) {
249 *iv_off = n;
250 }
251
252 return command_status;
253 }
254
255 /***************************************************************************//**
256 * AES-CFB8 buffer encryption/decryption.
257 ******************************************************************************/
sl_se_aes_crypt_cfb8(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_cipher_operation_t mode,size_t length,unsigned char iv[16],const unsigned char * input,unsigned char * output)258 sl_status_t sl_se_aes_crypt_cfb8(sl_se_command_context_t *cmd_ctx,
259 const sl_se_key_descriptor_t *key,
260 sl_se_cipher_operation_t mode,
261 size_t length,
262 unsigned char iv[16],
263 const unsigned char *input,
264 unsigned char *output)
265 {
266 unsigned char c;
267 unsigned char ov[17];
268 sl_status_t ret = SL_STATUS_OK;
269
270 if (cmd_ctx == NULL || key == NULL || input == NULL || output == NULL
271 || iv == NULL) {
272 return SL_STATUS_INVALID_PARAMETER;
273 }
274
275 while (length--) {
276 memcpy(ov, iv, 16U);
277 if ((ret = sl_se_aes_crypt_ecb(cmd_ctx, key, SL_SE_ENCRYPT, 16U, iv, iv))
278 != SL_STATUS_OK) {
279 return ret;
280 }
281
282 if (mode == SL_SE_DECRYPT) {
283 ov[16] = *input;
284 }
285
286 c = *output++ = (unsigned char)(iv[0] ^ *input++);
287
288 if (mode == SL_SE_ENCRYPT) {
289 ov[16] = c;
290 }
291
292 memcpy(iv, ov + 1, 16U);
293 }
294
295 return ret;
296 }
297
298 /***************************************************************************//**
299 * Increment the input nonce counter by one
300 ******************************************************************************/
increment_nonce_counter(uint8_t block_end,unsigned char nonce_counter[])301 static void increment_nonce_counter(uint8_t block_end, unsigned char nonce_counter[])
302 {
303 for (size_t i = 0u; i < SL_SE_AES_BLOCK_SIZE; i++) {
304 nonce_counter[block_end - i] = nonce_counter[block_end - i] + 1u;
305 if (nonce_counter[block_end - i] != 0u) {
306 // did not overflow so no need to increment the value at next index
307 break;
308 }
309 }
310 }
311
312 #if (SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED > 1)
313 /***************************************************************************//**
314 * Prepare the SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED * SL_SE_AES_BLOCK_SIZE byte
315 * wide stream block buffer that will be used as nonce counter for
316 * encryption/decryption.
317 ******************************************************************************/
prepare_nonce_counter(unsigned char nonce_counter[],unsigned char stream_block[])318 static void prepare_nonce_counter(unsigned char nonce_counter[],
319 unsigned char stream_block[])
320 {
321 uint8_t no_of_blocks = ((SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED * SL_SE_AES_BLOCK_SIZE) / SL_SE_AES_BLOCK_SIZE);
322 // place the most recent counter in the first stream block
323 memcpy(stream_block,
324 nonce_counter,
325 SL_SE_AES_BLOCK_SIZE);
326
327 for (size_t i = 0; i < no_of_blocks - 1u; i++) {
328 // Use the first block's reference counter to update the other
329 // blocks since it holds the most recent counter information.
330 memcpy(&stream_block[i * SL_SE_AES_BLOCK_SIZE + SL_SE_AES_BLOCK_SIZE],
331 &stream_block[i * SL_SE_AES_BLOCK_SIZE],
332 SL_SE_AES_BLOCK_SIZE);
333 increment_nonce_counter(((i + 2u) * SL_SE_AES_BLOCK_SIZE) - 1u, stream_block);
334 }
335
336 // Store the largest counter back in the nonce counter buffer
337 memcpy(nonce_counter,
338 &stream_block[(no_of_blocks - 1u) * SL_SE_AES_BLOCK_SIZE],
339 SL_SE_AES_BLOCK_SIZE);
340 }
341 #endif // SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED > 1
342
343 /***************************************************************************//**
344 * AES-CTR buffer encryption/decryption.
345 ******************************************************************************/
sl_se_aes_crypt_ctr(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,size_t length,uint32_t * nc_off,unsigned char nonce_counter[16],unsigned char stream_block[SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED * SL_SE_AES_BLOCK_SIZE],const unsigned char * input,unsigned char * output)346 sl_status_t sl_se_aes_crypt_ctr(sl_se_command_context_t *cmd_ctx,
347 const sl_se_key_descriptor_t *key,
348 size_t length,
349 uint32_t *nc_off,
350 unsigned char nonce_counter[16],
351 unsigned char stream_block[SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED * SL_SE_AES_BLOCK_SIZE],
352 const unsigned char *input,
353 unsigned char *output)
354 {
355 if (cmd_ctx == NULL || key == NULL
356 || (length != 0 && (input == NULL || output == NULL))
357 || nonce_counter == NULL || stream_block == NULL) {
358 return SL_STATUS_INVALID_PARAMETER;
359 }
360
361 SE_Command_t *se_cmd = &cmd_ctx->command;
362 uint32_t n = nc_off ? *nc_off : 0;
363 uint32_t processed = 0;
364 sl_status_t command_status = SL_STATUS_OK;
365
366 while (processed < length) {
367 if (n > 0) {
368 // start by filling up the IV
369 output[processed] = (unsigned char)(input[processed] ^ stream_block[n]);
370 n = (n + 1) & ((SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED * SL_SE_AES_BLOCK_SIZE) - 1u);
371 processed++;
372 } else {
373 // process one or more blocks of data
374 uint32_t iterations = (length - processed) / SL_SE_AES_BLOCK_SIZE;
375
376 if (iterations > 0) {
377 sli_se_command_init(cmd_ctx,
378 SLI_SE_COMMAND_AES_ENCRYPT
379 | SLI_SE_COMMAND_OPTION_MODE_CTR
380 | SLI_SE_COMMAND_OPTION_CONTEXT_ADD);
381
382 // Add key parameters to command
383 sli_add_key_parameters(cmd_ctx, key, command_status);
384 // Message size (number of bytes)
385 SE_addParameter(se_cmd, iterations * SL_SE_AES_BLOCK_SIZE);
386
387 // Add key metadata block to command
388 sli_add_key_metadata(cmd_ctx, key, command_status);
389 // Add key input block to command
390 sli_add_key_input(cmd_ctx, key, command_status);
391
392 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(nonce_counter, SL_SE_AES_BLOCK_SIZE);
393 SE_DataTransfer_t in = SE_DATATRANSFER_DEFAULT(&input[processed], iterations * SL_SE_AES_BLOCK_SIZE);
394 SE_addDataInput(se_cmd, &iv_in);
395 SE_addDataInput(se_cmd, &in);
396
397 SE_DataTransfer_t out = SE_DATATRANSFER_DEFAULT(&output[processed], iterations * SL_SE_AES_BLOCK_SIZE);
398 SE_DataTransfer_t iv_out = SE_DATATRANSFER_DEFAULT(nonce_counter, SL_SE_AES_BLOCK_SIZE);
399 SE_addDataOutput(se_cmd, &out);
400 SE_addDataOutput(se_cmd, &iv_out);
401
402 command_status = sli_se_execute_and_wait(cmd_ctx);
403 processed += iterations * SL_SE_AES_BLOCK_SIZE;
404 if (command_status != SL_STATUS_OK) {
405 return command_status;
406 }
407 }
408
409 while ((length - processed) > 0) {
410 if (n == 0) {
411 // Get a new stream block
412 unsigned char *counter_ptr = NULL;
413 #if (SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED > 1)
414 // Use the nonce counter buffer as the reference to create nonce counter blocks
415 // needed to compute the key stream blocks. Also, update the nonce counter buffer
416 // to store the latest block.
417 prepare_nonce_counter(nonce_counter, stream_block);
418 // The key stream buffer now holds the nonce counter
419 counter_ptr = stream_block;
420 #else
421 counter_ptr = nonce_counter;
422 #endif // SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED > 1
423
424 command_status = sl_se_aes_crypt_ecb(cmd_ctx,
425 key,
426 SL_SE_ENCRYPT,
427 SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED * SL_SE_AES_BLOCK_SIZE,
428 counter_ptr,
429 stream_block);
430 if (command_status != SL_STATUS_OK) {
431 return command_status;
432 }
433 increment_nonce_counter(SL_SE_AES_BLOCK_SIZE - 1u, nonce_counter);
434 }
435 // Save remainder to IV
436 output[processed] = (unsigned char)(input[processed] ^ stream_block[n]);
437 n = (n + 1) & ((SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED * SL_SE_AES_BLOCK_SIZE) - 1u);
438 processed++;
439 }
440 }
441 }
442
443 if ( nc_off ) {
444 *nc_off = n;
445 }
446
447 return command_status;
448 }
449
450 /***************************************************************************//**
451 * AES-CCM buffer encryption.
452 ******************************************************************************/
sl_se_ccm_encrypt_and_tag(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,unsigned char * tag,size_t tag_len)453 sl_status_t sl_se_ccm_encrypt_and_tag(sl_se_command_context_t *cmd_ctx,
454 const sl_se_key_descriptor_t *key,
455 size_t length,
456 const unsigned char *iv, size_t iv_len,
457 const unsigned char *add, size_t add_len,
458 const unsigned char *input,
459 unsigned char *output,
460 unsigned char *tag, size_t tag_len)
461 {
462 if (cmd_ctx == NULL || key == NULL || (tag_len > 0 && tag == NULL) || iv == NULL) {
463 return SL_STATUS_INVALID_PARAMETER;
464 }
465 if (add_len > 0 && add == NULL) {
466 return SL_STATUS_INVALID_PARAMETER;
467 }
468 if (length > 0 && (input == NULL || output == NULL)) {
469 return SL_STATUS_INVALID_PARAMETER;
470 }
471
472 SE_Command_t *se_cmd = &cmd_ctx->command;
473 unsigned char q;
474 sl_status_t command_status = SL_STATUS_OK;
475
476 // Test for invalid (too long) message length. This test is included here because
477 // the SE does not implement the test. When the SE ultimately implements the test
478 // the following test can be removed.
479 q = 16 - 1 - (unsigned char) iv_len;
480 if ((q < sizeof(length)) && (length >= (1UL << (q * 8)))) {
481 return SL_STATUS_INVALID_PARAMETER;
482 }
483
484 if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) {
485 return SL_STATUS_INVALID_PARAMETER;
486 }
487
488 // Also implies q is within bounds
489 if (iv_len < 7 || iv_len > 13) {
490 return SL_STATUS_INVALID_PARAMETER;
491 }
492
493 #if !defined(SLI_SE_MANAGER_HOST_SYSTEM)
494 if ((uint32_t)output + length > RAM_MEM_END) {
495 return SL_STATUS_INVALID_PARAMETER;
496 }
497 #endif // SLI_SE_MANAGER_HOST_SYSTEM
498
499 sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_AES_CCM_ENCRYPT);
500
501 // Add key parameters to command
502 sli_add_key_parameters(cmd_ctx, key, command_status);
503 // Message size (number of bytes)
504 SE_addParameter(se_cmd, ((iv_len & 0xFFFF) << 16) | (tag_len & 0xFFFF));
505 SE_addParameter(se_cmd, add_len);
506 SE_addParameter(se_cmd, length);
507
508 // Add key metadata block to command
509 sli_add_key_metadata(cmd_ctx, key, command_status);
510 // Add key input block to command
511 sli_add_key_input(cmd_ctx, key, command_status);
512
513 SE_DataTransfer_t in_data = SE_DATATRANSFER_DEFAULT(input, length);
514 SE_DataTransfer_t in_add = SE_DATATRANSFER_DEFAULT(add, add_len);
515 SE_DataTransfer_t in_nonce = SE_DATATRANSFER_DEFAULT(iv, iv_len);
516 SE_addDataInput(se_cmd, &in_nonce);
517 SE_addDataInput(se_cmd, &in_add);
518 SE_addDataInput(se_cmd, &in_data);
519
520 SE_DataTransfer_t out_data = SE_DATATRANSFER_DEFAULT(output, length);
521 SE_DataTransfer_t out_tag = SE_DATATRANSFER_DEFAULT(tag, tag_len);
522 SE_addDataOutput(se_cmd, &out_data);
523 SE_addDataOutput(se_cmd, &out_tag);
524
525 command_status = sli_se_execute_and_wait(cmd_ctx);
526 return command_status;
527 }
528
529 /***************************************************************************//**
530 * AES-CCM buffer decryption.
531 ******************************************************************************/
sl_se_ccm_auth_decrypt(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,const unsigned char * tag,size_t tag_len)532 sl_status_t sl_se_ccm_auth_decrypt(sl_se_command_context_t *cmd_ctx,
533 const sl_se_key_descriptor_t *key,
534 size_t length,
535 const unsigned char *iv, size_t iv_len,
536 const unsigned char *add, size_t add_len,
537 const unsigned char *input,
538 unsigned char *output,
539 const unsigned char *tag, size_t tag_len)
540 {
541 if (cmd_ctx == NULL || key == NULL || tag == NULL || iv == NULL) {
542 return SL_STATUS_INVALID_PARAMETER;
543 }
544 if (add_len > 0 && add == NULL) {
545 return SL_STATUS_INVALID_PARAMETER;
546 }
547 if (length > 0 && (input == NULL || output == NULL)) {
548 return SL_STATUS_INVALID_PARAMETER;
549 }
550
551 SE_Command_t *se_cmd = &cmd_ctx->command;
552 unsigned char q;
553 sl_status_t command_status = SL_STATUS_OK;
554
555 // Test for invalid (too long) message length. This test is included here because
556 // the SE does not implement the test. When the SE ultimately implements the test
557 // the following test can be removed.
558 q = 16 - 1 - (unsigned char) iv_len;
559 if ((q < sizeof(length)) && (length >= (1UL << (q * 8)))) {
560 return SL_STATUS_INVALID_PARAMETER;
561 }
562
563 if (tag_len == 2 || tag_len == 0 || tag_len > 16 || tag_len % 2 != 0) {
564 return SL_STATUS_INVALID_PARAMETER;
565 }
566
567 // Also implies q is within bounds */
568 if (iv_len < 7 || iv_len > 13) {
569 return SL_STATUS_INVALID_PARAMETER;
570 }
571
572 #if !defined(SLI_SE_MANAGER_HOST_SYSTEM)
573 if ((uint32_t)output + length > RAM_MEM_END) {
574 return SL_STATUS_INVALID_PARAMETER;
575 }
576 #endif // SLI_SE_MANAGER_HOST_SYSTEM
577
578 sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_AES_CCM_DECRYPT);
579
580 // Add key parameters to command
581 sli_add_key_parameters(cmd_ctx, key, command_status);
582 // Message size (number of bytes)
583 SE_addParameter(se_cmd, ((iv_len & 0xFFFF) << 16) | (tag_len & 0xFFFF));
584 SE_addParameter(se_cmd, add_len);
585 SE_addParameter(se_cmd, length);
586
587 // Add key metadata block to command
588 sli_add_key_metadata(cmd_ctx, key, command_status);
589 // Add key input block to command
590 sli_add_key_input(cmd_ctx, key, command_status);
591
592 SE_DataTransfer_t in_data = SE_DATATRANSFER_DEFAULT(input, length);
593 SE_DataTransfer_t in_add = SE_DATATRANSFER_DEFAULT(add, add_len);
594 SE_DataTransfer_t in_nonce = SE_DATATRANSFER_DEFAULT(iv, iv_len);
595 SE_addDataInput(se_cmd, &in_nonce);
596 SE_addDataInput(se_cmd, &in_add);
597 SE_addDataInput(se_cmd, &in_data);
598
599 SE_DataTransfer_t out_data = SE_DATATRANSFER_DEFAULT(output, length);
600 SE_addDataOutput(se_cmd, &out_data);
601 SE_DataTransfer_t in_tag = SE_DATATRANSFER_DEFAULT(tag, tag_len);
602 SE_addDataInput(se_cmd, &in_tag);
603
604 command_status = sli_se_execute_and_wait(cmd_ctx);
605 if (command_status == SL_STATUS_OK) {
606 return SL_STATUS_OK;
607 } else {
608 memset(output, 0, length);
609 return command_status;
610 }
611 }
612
613 #if defined(SLI_SE_MAJOR_VERSION_ONE)
sl_se_ccm_multipart_starts(sl_se_ccm_multipart_context_t * ccm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_cipher_operation_t mode,uint32_t total_message_length,const uint8_t * iv,size_t iv_len,const uint8_t * aad,size_t aad_len,size_t tag_len)614 sl_status_t sl_se_ccm_multipart_starts(sl_se_ccm_multipart_context_t *ccm_ctx,
615 sl_se_command_context_t *cmd_ctx,
616 const sl_se_key_descriptor_t *key,
617 sl_se_cipher_operation_t mode,
618 uint32_t total_message_length,
619 const uint8_t *iv,
620 size_t iv_len,
621 const uint8_t *aad,
622 size_t aad_len,
623 size_t tag_len)
624 {
625 sl_status_t status = SL_STATUS_OK;
626 uint8_t q;
627 uint8_t b[SL_SE_AES_BLOCK_SIZE] = { 0 };
628 uint8_t tag_out[SL_SE_AES_BLOCK_SIZE] = { 0 };
629 uint8_t cbc_mac_state[SL_SE_AES_BLOCK_SIZE] = { 0 };
630 uint8_t nonce_counter[SL_SE_AES_BLOCK_SIZE] = { 0 };
631 uint32_t len_left;
632
633 //Check input parameters
634 if (ccm_ctx == NULL || cmd_ctx == NULL || key == NULL || iv == NULL) {
635 return SL_STATUS_INVALID_PARAMETER;
636 }
637 if (aad_len > 0 && aad == NULL) {
638 return SL_STATUS_INVALID_PARAMETER;
639 }
640
641 if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) {
642 return SL_STATUS_INVALID_PARAMETER;
643 }
644
645 if (iv_len < 7 || iv_len > 13) {
646 return SL_STATUS_INVALID_PARAMETER;
647 }
648
649 // q is the the octet length of Q which again is a bit string representation of
650 // the octet length of the payload.
651 q = 16 - 1 - (uint8_t) iv_len;
652
653 // The parameter q determines the maximum length of the payload: by definition, p<2^(8*q),
654 // where p is payload.
655 if ((q < sizeof(total_message_length)) && (total_message_length >= (1UL << (q * 8)))) {
656 return SL_STATUS_INVALID_PARAMETER;
657 }
658 memset(ccm_ctx, 0, sizeof(sl_se_ccm_multipart_context_t));
659
660 // Format first input block B_O according to the formatting function:
661
662 // 0 .. 0 flags
663 // 1 .. iv_len nonce (aka iv)
664 // iv_len+1 .. 15 length
665 //
666 // With flags as (bits):
667 // 7 0
668 // 6 add present?
669 // 5 .. 3 (t - 2) / 2
670 // 2 .. 0 q - 1
671
672 b[0] = 0;
673 b[0] |= (aad_len > 0) << 6;
674 b[0] |= ((tag_len - 2) / 2) << 3;
675 b[0] |= q - 1;
676
677 memcpy(b + 1, iv, iv_len);
678
679 len_left = total_message_length;
680 for (uint32_t i = 0; i < q; i++, len_left >>= 8) {
681 b[15 - i] = (unsigned char)(len_left & 0xFF);
682 }
683
684 ccm_ctx->mode = mode;
685 ccm_ctx->processed_message_length = 0;
686 ccm_ctx->total_message_length = total_message_length;
687 ccm_ctx->tag_len = tag_len;
688 ccm_ctx->mode = mode;
689 ccm_ctx->iv_len = iv_len;
690 memcpy(ccm_ctx->iv, iv, iv_len);
691
692 status = sl_se_aes_crypt_cbc(cmd_ctx,
693 key,
694 SL_SE_ENCRYPT,
695 SL_SE_AES_BLOCK_SIZE,
696 cbc_mac_state,
697 b,
698 tag_out);
699
700 if (status != SL_STATUS_OK) {
701 return status;
702 }
703
704 // If there is additional data, update using CBC. Must be done
705 // blockwise to achieve the same behaviour as CBC-MAC.
706 if (aad_len > 0) {
707 uint8_t use_len;
708 len_left = aad_len;
709 memset(b, 0, sizeof(b));
710 // First block.
711 b[0] = (unsigned char)((aad_len >> 8) & 0xFF);
712 b[1] = (unsigned char)((aad_len) & 0xFF);
713 use_len = len_left < SL_SE_AES_BLOCK_SIZE - 2 ? len_left : 16 - 2;
714 memcpy(b + 2, aad, use_len);
715 len_left -= use_len;
716 aad += use_len;
717
718 status = sl_se_aes_crypt_cbc(cmd_ctx,
719 key,
720 SL_SE_ENCRYPT,
721 SL_SE_AES_BLOCK_SIZE,
722 cbc_mac_state,
723 b,
724 tag_out);
725 if (status != SL_STATUS_OK) {
726 return status;
727 }
728
729 while (len_left) {
730 use_len = len_left > 16 ? 16 : len_left;
731
732 memset(b, 0, sizeof(b));
733 memcpy(b, aad, use_len);
734 status = sl_se_aes_crypt_cbc(cmd_ctx,
735 key,
736 SL_SE_ENCRYPT,
737 SL_SE_AES_BLOCK_SIZE,
738 cbc_mac_state,
739 b,
740 tag_out);
741
742 if (status != SL_STATUS_OK) {
743 return status;
744 }
745 len_left -= use_len;
746 aad += use_len;
747 }
748 }
749
750 memcpy(ccm_ctx->cbc_mac_state, cbc_mac_state, sizeof(cbc_mac_state));
751
752 // Prepare nonce counter for encryption/decryption operation.
753 nonce_counter[0] = q - 1;
754 memcpy(nonce_counter + 1, iv, iv_len);
755 memset(nonce_counter + 1 + iv_len, 0, q);
756 nonce_counter[15] = 1;
757
758 memcpy(ccm_ctx->nonce_counter, nonce_counter, sizeof(ccm_ctx->nonce_counter));
759
760 return SL_STATUS_OK;
761 }
762
sl_se_ccm_multipart_update(sl_se_ccm_multipart_context_t * ccm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,size_t length,const uint8_t * input,uint8_t * output,size_t * output_length)763 sl_status_t sl_se_ccm_multipart_update(sl_se_ccm_multipart_context_t *ccm_ctx,
764 sl_se_command_context_t *cmd_ctx,
765 const sl_se_key_descriptor_t *key,
766 size_t length,
767 const uint8_t *input,
768 uint8_t *output,
769 size_t *output_length)
770 {
771 sl_status_t status = SL_STATUS_OK;
772 *output_length = 0;
773
774 uint8_t out_buf[SL_SE_AES_BLOCK_SIZE] = { 0 };
775 uint8_t empty[SL_SE_AES_BLOCK_SIZE * SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED] = { 0 };
776 uint8_t b[SL_SE_AES_BLOCK_SIZE] = { 0 };
777
778 size_t len_left;
779
780 // Check input parameters.
781 if (ccm_ctx == NULL || cmd_ctx == NULL || key == NULL) {
782 return SL_STATUS_INVALID_PARAMETER;
783 }
784
785 if (length == 0) {
786 return SL_STATUS_OK;
787 }
788
789 // Check variable overflow
790 if (ccm_ctx->processed_message_length > 0xFFFFFFFF - length) {
791 return SL_STATUS_INVALID_PARAMETER;
792 }
793
794 if (ccm_ctx->processed_message_length + length > ccm_ctx->total_message_length) {
795 return SL_STATUS_INVALID_PARAMETER;
796 }
797
798 if (length > 0 && (input == NULL || output == NULL)) {
799 return SL_STATUS_INVALID_PARAMETER;
800 }
801
802 if ((uint32_t)output + length > RAM_MEM_END) {
803 return SL_STATUS_INVALID_PARAMETER;
804 }
805
806 // Support partial overlap.
807 if ((output > input) && (output < (input + length))) {
808 memmove(output, input, length);
809 input = output;
810 }
811
812 if (length + ccm_ctx->final_data_length < SL_SE_AES_BLOCK_SIZE && length < SL_SE_AES_BLOCK_SIZE && ccm_ctx->processed_message_length + length != ccm_ctx->total_message_length ) {
813 if (ccm_ctx->final_data_length > SL_SE_AES_BLOCK_SIZE) {
814 // Context is not valid.
815 return SL_STATUS_INVALID_PARAMETER;
816 }
817 memcpy(ccm_ctx->final_data + ccm_ctx->final_data_length, input, length);
818 ccm_ctx->final_data_length += length;
819 *output_length = 0;
820 return SL_STATUS_OK;
821 }
822
823 len_left = length + ccm_ctx->final_data_length;
824
825 // Authenticate and {en,de}crypt the message.
826
827 // The only difference between encryption and decryption is
828 // the respective order of authentication and {en,de}cryption.
829 while (len_left > 0 ) {
830 uint8_t use_len = len_left > SL_SE_AES_BLOCK_SIZE ? SL_SE_AES_BLOCK_SIZE : len_left;
831
832 memset(b, 0, sizeof(b));
833
834 // Process data stored in context first.
835 if (ccm_ctx->final_data_length > 0) {
836 if (ccm_ctx->final_data_length > SL_SE_AES_BLOCK_SIZE) {
837 // Context is not valid.
838 return SL_STATUS_INVALID_PARAMETER;
839 }
840 memcpy(b, ccm_ctx->final_data, ccm_ctx->final_data_length);
841 memcpy(b + ccm_ctx->final_data_length, input, SL_SE_AES_BLOCK_SIZE - ccm_ctx->final_data_length);
842 input += SL_SE_AES_BLOCK_SIZE - ccm_ctx->final_data_length;
843 ccm_ctx->final_data_length = 0;
844 } else {
845 memcpy(b, input, use_len);
846 input += use_len;
847 }
848 if (ccm_ctx->mode == SL_SE_ENCRYPT) {
849 // Authenticate input.
850 status = sl_se_aes_crypt_cbc(cmd_ctx,
851 key,
852 SL_SE_ENCRYPT,
853 SL_SE_AES_BLOCK_SIZE,
854 ccm_ctx->cbc_mac_state,
855 b,
856 out_buf);
857
858 if (status != SL_STATUS_OK) {
859 return status;
860 }
861 }
862 // Encrypt/decrypt data with CTR.
863 status = sl_se_aes_crypt_ctr(cmd_ctx,
864 key,
865 use_len,
866 NULL,
867 ccm_ctx->nonce_counter,
868 empty,
869 b,
870 output);
871
872 if (ccm_ctx->mode == SL_SE_DECRYPT) {
873 // Authenticate output.
874 memset(b, 0, sizeof(b));
875 memcpy(b, output, use_len);
876 status = sl_se_aes_crypt_cbc(cmd_ctx,
877 key,
878 SL_SE_ENCRYPT,
879 SL_SE_AES_BLOCK_SIZE,
880 ccm_ctx->cbc_mac_state,
881 b,
882 out_buf);
883
884 if (status != SL_STATUS_OK) {
885 return status;
886 }
887 }
888 ccm_ctx->processed_message_length += use_len;
889 *output_length += use_len;
890 len_left -= use_len;
891 output += use_len;
892
893 if (len_left < SL_SE_AES_BLOCK_SIZE && ((ccm_ctx->processed_message_length + len_left) != ccm_ctx->total_message_length)) {
894 memcpy(ccm_ctx->final_data, input, len_left);
895 ccm_ctx->final_data_length = len_left;
896 break;
897 }
898 }
899
900 if (status != SL_STATUS_OK) {
901 return status;
902 }
903
904 return SL_STATUS_OK;
905 }
906
sl_se_ccm_multipart_finish(sl_se_ccm_multipart_context_t * ccm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,uint8_t * tag,uint8_t tag_size,uint8_t * output,uint8_t output_size,uint8_t * output_length)907 sl_status_t sl_se_ccm_multipart_finish(sl_se_ccm_multipart_context_t *ccm_ctx,
908 sl_se_command_context_t *cmd_ctx,
909 const sl_se_key_descriptor_t *key,
910 uint8_t *tag,
911 uint8_t tag_size,
912 uint8_t *output,
913 uint8_t output_size,
914 uint8_t *output_length)
915 {
916 (void)output;
917 uint8_t q;
918 uint8_t ctr[SL_SE_AES_BLOCK_SIZE] = { 0 };
919 uint8_t out_tag[SL_SE_AES_BLOCK_SIZE] = { 0 };
920 //Check input parameters
921 if (ccm_ctx == NULL || cmd_ctx == NULL || key == NULL || tag == NULL) {
922 return SL_STATUS_INVALID_PARAMETER;
923 }
924
925 if (tag_size < ccm_ctx->tag_len || output_size < ccm_ctx->final_data_length) {
926 return SL_STATUS_INVALID_PARAMETER;
927 }
928
929 sl_status_t status = SL_STATUS_OK;
930
931 // Reset CTR counter.
932 q = 16 - 1 - (unsigned char) ccm_ctx->iv_len;
933
934 ctr[0] = q - 1;
935 memcpy(ctr + 1, ccm_ctx->iv, ccm_ctx->iv_len);
936
937 // Encrypt the tag with CTR.
938 uint8_t empty[SL_SE_AES_BLOCK_SIZE * SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED] = { 0 };
939 status = sl_se_aes_crypt_ctr(cmd_ctx,
940 key,
941 ccm_ctx->tag_len,
942 NULL,
943 ctr,
944 empty,
945 ccm_ctx->cbc_mac_state,
946 out_tag);
947
948 if (status != SL_STATUS_OK) {
949 memset(out_tag, 0, sizeof(out_tag));
950 return status;
951 }
952
953 if (ccm_ctx->mode == SL_SE_DECRYPT) {
954 if (memcmp_time_cst(tag, out_tag, ccm_ctx->tag_len) != 0) {
955 memset(tag, 0, ccm_ctx->tag_len);
956 return SL_STATUS_INVALID_SIGNATURE;
957 }
958 } else {
959 memcpy(tag, out_tag, ccm_ctx->tag_len);
960 }
961
962 *output_length = 0;
963 return SL_STATUS_OK;
964 }
965 #endif // SLI_SE_MAJOR_VERSION_ONE
966
967 #if defined(SLI_SE_MAJOR_VERSION_TWO)
968 /***************************************************************************//**
969 * Prepare a CCM streaming command context object to be used in subsequent
970 * CCM streaming function calls.
971 ******************************************************************************/
sl_se_ccm_multipart_starts(sl_se_ccm_multipart_context_t * ccm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_cipher_operation_t mode,uint32_t total_message_length,const uint8_t * iv,size_t iv_len,const uint8_t * add,size_t add_len,size_t tag_len)972 sl_status_t sl_se_ccm_multipart_starts(sl_se_ccm_multipart_context_t *ccm_ctx,
973 sl_se_command_context_t *cmd_ctx,
974 const sl_se_key_descriptor_t *key,
975 sl_se_cipher_operation_t mode,
976 uint32_t total_message_length,
977 const uint8_t *iv,
978 size_t iv_len,
979 const uint8_t *add,
980 size_t add_len,
981 size_t tag_len)
982
983 {
984 sl_status_t status = SL_STATUS_OK;
985 uint8_t q;
986
987 //Check input parameters
988 if (ccm_ctx == NULL || cmd_ctx == NULL || key == NULL || iv == NULL) {
989 return SL_STATUS_INVALID_PARAMETER;
990 }
991 if (add_len > 0 && add == NULL) {
992 return SL_STATUS_INVALID_PARAMETER;
993 }
994
995 if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) {
996 return SL_STATUS_INVALID_PARAMETER;
997 }
998
999 if (iv_len < 7 || iv_len > 13) {
1000 return SL_STATUS_INVALID_PARAMETER;
1001 }
1002
1003 q = 16 - 1 - (unsigned char) iv_len;
1004 if ((q < sizeof(ccm_ctx->total_message_length)) && (ccm_ctx->total_message_length >= (1UL << (q * 8)))) {
1005 return SL_STATUS_INVALID_PARAMETER;
1006 }
1007
1008 memset(ccm_ctx, 0, sizeof(sl_se_ccm_multipart_context_t));
1009
1010 ccm_ctx->mode = mode;
1011 ccm_ctx->processed_message_length = 0;
1012 ccm_ctx->total_message_length = total_message_length;
1013 ccm_ctx->tag_len = tag_len;
1014 memcpy(ccm_ctx->iv, iv, iv_len);
1015
1016 SE_Command_t *se_cmd = &cmd_ctx->command;
1017
1018 if (total_message_length == 0) {
1019 // The first encryption precomputes the tag in the event there is no more data.
1020 // For decryption, the pre-computed is compared to the input tag in
1021 // sl_se_ccm_multipart_finish.
1022 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(iv, iv_len);
1023 SE_DataTransfer_t add_in = SE_DATATRANSFER_DEFAULT(add, add_len);
1024 SE_DataTransfer_t tag_out = SE_DATATRANSFER_DEFAULT(ccm_ctx->mode_specific_buffer.tagbuf,
1025 tag_len);
1026
1027 sli_se_command_init(cmd_ctx,
1028 SLI_SE_COMMAND_AES_CCM_ENCRYPT
1029 | SLI_SE_COMMAND_OPTION_CONTEXT_WHOLE);
1030
1031 sli_add_key_parameters(cmd_ctx, key, status);
1032 SE_addParameter(se_cmd, ((iv_len & 0xFFFF) << 16) | (tag_len & 0xFFFF));
1033 SE_addParameter(se_cmd, add_len);
1034 SE_addParameter(se_cmd, 0);
1035
1036 // Add key metadata block to command
1037 sli_add_key_metadata(cmd_ctx, key, status);
1038 // Add key input block to command
1039 sli_add_key_input(cmd_ctx, key, status);
1040
1041 SE_addDataInput(se_cmd, &iv_in);
1042 SE_addDataInput(se_cmd, &add_in);
1043
1044 SE_addDataOutput(se_cmd, &tag_out);
1045
1046 status = sli_se_execute_and_wait(cmd_ctx);
1047 if (status != SL_STATUS_OK) {
1048 memset(ccm_ctx->mode_specific_buffer.tagbuf, 0, sizeof(ccm_ctx->mode_specific_buffer.tagbuf));
1049 }
1050 return status;
1051 }
1052 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(iv, iv_len);
1053 SE_DataTransfer_t add_in = SE_DATATRANSFER_DEFAULT(add, add_len);
1054 SE_DataTransfer_t ctx_out = SE_DATATRANSFER_DEFAULT(ccm_ctx->se_ctx, sizeof(ccm_ctx->se_ctx));
1055
1056 SE_DataTransfer_t message_length_in = SE_DATATRANSFER_DEFAULT(&total_message_length, sizeof(uint32_t));
1057
1058 sli_se_command_init(cmd_ctx,
1059 ((ccm_ctx->mode == SL_SE_DECRYPT)
1060 ? SLI_SE_COMMAND_AES_CCM_DECRYPT : SLI_SE_COMMAND_AES_CCM_ENCRYPT)
1061 | SLI_SE_COMMAND_OPTION_CONTEXT_START);
1062
1063 sli_add_key_parameters(cmd_ctx, key, status);
1064
1065 SE_addParameter(se_cmd, ((iv_len & 0xFFFF) << 16) | (tag_len & 0xFFFF));
1066 SE_addParameter(se_cmd, add_len);
1067 SE_addParameter(se_cmd, 0);
1068
1069 sli_add_key_metadata(cmd_ctx, key, status);
1070 sli_add_key_input(cmd_ctx, key, status);
1071
1072 SE_addDataInput(se_cmd, &message_length_in);
1073
1074 SE_addDataInput(se_cmd, &iv_in);
1075 SE_addDataInput(se_cmd, &add_in);
1076 SE_addDataOutput(se_cmd, &ctx_out);
1077
1078 status = sli_se_execute_and_wait(cmd_ctx);
1079 if (status != SL_STATUS_OK) {
1080 memset(ccm_ctx->se_ctx, 0, sizeof(ccm_ctx->se_ctx));
1081 return status;
1082 }
1083
1084 return status;
1085 }
1086 #endif
1087
1088 /***************************************************************************//**
1089 * This function feeds an input buffer into an ongoing CCM computation.
1090 * It is called between sl_se_ccm_multipart_starts() and sl_se_ccm_multipart_finish().
1091 * Can be called repeatedly.
1092 ******************************************************************************/
1093 #if defined(SLI_SE_MAJOR_VERSION_TWO)
sl_se_ccm_multipart_update(sl_se_ccm_multipart_context_t * ccm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,size_t length,const uint8_t * input,uint8_t * output,size_t * output_length)1094 sl_status_t sl_se_ccm_multipart_update(sl_se_ccm_multipart_context_t *ccm_ctx,
1095 sl_se_command_context_t *cmd_ctx,
1096 const sl_se_key_descriptor_t *key,
1097 size_t length,
1098 const uint8_t *input,
1099 uint8_t *output,
1100 size_t *output_length)
1101 {
1102 sl_status_t status = SL_STATUS_OK;
1103
1104 // Check input parameters.
1105 if (ccm_ctx == NULL || cmd_ctx == NULL || key == NULL) {
1106 return SL_STATUS_INVALID_PARAMETER;
1107 }
1108
1109 if (length == 0) {
1110 return SL_STATUS_OK;
1111 }
1112
1113 if (ccm_ctx->processed_message_length + length > ccm_ctx->total_message_length) {
1114 return SL_STATUS_INVALID_PARAMETER;
1115 }
1116
1117 // Check variable overflow
1118 if (ccm_ctx->processed_message_length > 0xFFFFFFFF - length) {
1119 return SL_STATUS_INVALID_PARAMETER;
1120 }
1121
1122 if (length > 0 && (input == NULL || output == NULL)) {
1123 return SL_STATUS_INVALID_PARAMETER;
1124 }
1125
1126 #if !defined(SLI_SE_MANAGER_HOST_SYSTEM)
1127 if ((uint32_t)output + length > RAM_MEM_END) {
1128 return SL_STATUS_INVALID_PARAMETER;
1129 }
1130 #endif // SLI_SE_MANAGER_HOST_SYSTEM
1131
1132 SE_Command_t *se_cmd = &cmd_ctx->command;
1133 *output_length = 0;
1134
1135 // Approach:
1136 // Encrypt or decrypt regularly with context store. The crypto DMA must have input data in the 'END' operation, thus,
1137 // some data must be saved in the context.
1138
1139 if ((ccm_ctx->final_data_length + length) < 16 && length < 16) {
1140 if (ccm_ctx->final_data_length > 16) {
1141 // Context is not valid.
1142 return SL_STATUS_INVALID_PARAMETER;
1143 }
1144
1145 memcpy(ccm_ctx->mode_specific_buffer.final_data + ccm_ctx->final_data_length, input, length);
1146 ccm_ctx->final_data_length += length;
1147 return SL_STATUS_OK;
1148 }
1149
1150 // If there is data in final_data, this must be processed first
1151 if (ccm_ctx->final_data_length) {
1152 if (ccm_ctx->final_data_length > 16) {
1153 // Context is not valid.
1154 return SL_STATUS_INVALID_PARAMETER;
1155 }
1156
1157 // Fill up the remainder of the buffer.
1158 memcpy(ccm_ctx->mode_specific_buffer.final_data + ccm_ctx->final_data_length, input, 16 - ccm_ctx->final_data_length);
1159
1160 if (ccm_ctx->processed_message_length + 16 == ccm_ctx->total_message_length ) {
1161 // The finish operation must have some data or the SE fails.
1162 ccm_ctx->final_data_length = 16;
1163 return SL_STATUS_OK;
1164 }
1165
1166 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT(ccm_ctx->se_ctx, sizeof(ccm_ctx->se_ctx));
1167
1168 SE_DataTransfer_t data_in =
1169 SE_DATATRANSFER_DEFAULT(ccm_ctx->mode_specific_buffer.final_data, 16);
1170 SE_DataTransfer_t data_out =
1171 SE_DATATRANSFER_DEFAULT(output, 16);
1172
1173 SE_DataTransfer_t ctx_out = SE_DATATRANSFER_DEFAULT(ccm_ctx->se_ctx, sizeof(ccm_ctx->se_ctx));
1174
1175 sli_se_command_init(cmd_ctx,
1176 ((ccm_ctx->mode == SL_SE_DECRYPT)
1177 ? SLI_SE_COMMAND_AES_CCM_DECRYPT : SLI_SE_COMMAND_AES_CCM_ENCRYPT)
1178 | SLI_SE_COMMAND_OPTION_CONTEXT_ADD);
1179
1180 sli_add_key_parameters(cmd_ctx, key, status);
1181
1182 SE_addParameter(se_cmd, 16);
1183
1184 sli_add_key_metadata(cmd_ctx, key, status);
1185 sli_add_key_input(cmd_ctx, key, status);
1186
1187 SE_addDataInput(se_cmd, &iv_ctx_in);
1188 SE_addDataInput(se_cmd, &data_in);
1189
1190 SE_addDataOutput(se_cmd, &data_out);
1191 SE_addDataOutput(se_cmd, &ctx_out);
1192
1193 status = sli_se_execute_and_wait(cmd_ctx);
1194 if (status != SL_STATUS_OK) {
1195 memset(output, 0, length);
1196 memset(ccm_ctx->se_ctx, 0, sizeof(ccm_ctx->se_ctx));
1197 *output_length = 0;
1198 return status;
1199 }
1200 ccm_ctx->processed_message_length += 16;
1201 output += 16;
1202 length -= (16 - ccm_ctx->final_data_length);
1203 input += (16 - ccm_ctx->final_data_length);
1204 ccm_ctx->final_data_length = 0;
1205 *output_length += 16;
1206 }
1207
1208 if (length < 16) {
1209 memcpy(ccm_ctx->mode_specific_buffer.final_data, input, length);
1210 ccm_ctx->final_data_length += length;
1211 return SL_STATUS_OK;
1212 }
1213
1214 // Run only multiples of 16 and store residue data in context
1215 if (length % 16 != 0) {
1216 uint8_t residue_data_length = length % 16;
1217 memcpy(ccm_ctx->mode_specific_buffer.final_data, input + (length - residue_data_length), residue_data_length);
1218 length -= residue_data_length;
1219 ccm_ctx->final_data_length = residue_data_length;
1220 }
1221
1222 if ((ccm_ctx->total_message_length == ccm_ctx->processed_message_length + length) && !ccm_ctx->final_data_length) {
1223 // The finish operation must have some data or the SE fails.
1224 memcpy(ccm_ctx->mode_specific_buffer.final_data, input + (length - 16), 16);
1225 ccm_ctx->final_data_length = 16;
1226 length -= 16;
1227 if (!length) {
1228 return SL_STATUS_OK;
1229 }
1230 }
1231
1232 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT(ccm_ctx->se_ctx, sizeof(ccm_ctx->se_ctx));
1233
1234 SE_DataTransfer_t data_in =
1235 SE_DATATRANSFER_DEFAULT(input, length);
1236 SE_DataTransfer_t data_out =
1237 SE_DATATRANSFER_DEFAULT(output, length);
1238
1239 SE_DataTransfer_t ctx_out = SE_DATATRANSFER_DEFAULT(ccm_ctx->se_ctx, sizeof(ccm_ctx->se_ctx));
1240
1241 sli_se_command_init(cmd_ctx,
1242 ((ccm_ctx->mode == SL_SE_DECRYPT)
1243 ? SLI_SE_COMMAND_AES_CCM_DECRYPT : SLI_SE_COMMAND_AES_CCM_ENCRYPT)
1244 | SLI_SE_COMMAND_OPTION_CONTEXT_ADD);
1245
1246 sli_add_key_parameters(cmd_ctx, key, status);
1247
1248 SE_addParameter(se_cmd, length);
1249
1250 sli_add_key_metadata(cmd_ctx, key, status);
1251 sli_add_key_input(cmd_ctx, key, status);
1252
1253 SE_addDataInput(se_cmd, &iv_ctx_in);
1254 SE_addDataInput(se_cmd, &data_in);
1255
1256 SE_addDataOutput(se_cmd, &data_out);
1257 SE_addDataOutput(se_cmd, &ctx_out);
1258
1259 status = sli_se_execute_and_wait(cmd_ctx);
1260 if (status != SL_STATUS_OK) {
1261 memset(output, 0, length);
1262 memset(ccm_ctx->se_ctx, 0, sizeof(ccm_ctx->se_ctx));
1263 return status;
1264 }
1265
1266 *output_length += length;
1267 ccm_ctx->processed_message_length += length;
1268
1269 return status;
1270 }
1271 #endif
1272
1273 /***************************************************************************//**
1274 * Finish a CCM streaming operation and return the resulting CCM tag.
1275 * It is called after sl_se_ccm_multipart_update().
1276 ******************************************************************************/
1277 #if defined(SLI_SE_MAJOR_VERSION_TWO)
sl_se_ccm_multipart_finish(sl_se_ccm_multipart_context_t * ccm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,uint8_t * tag,uint8_t tag_size,uint8_t * output,uint8_t output_size,uint8_t * output_length)1278 sl_status_t sl_se_ccm_multipart_finish(sl_se_ccm_multipart_context_t *ccm_ctx,
1279 sl_se_command_context_t *cmd_ctx,
1280 const sl_se_key_descriptor_t *key,
1281 uint8_t *tag,
1282 uint8_t tag_size,
1283 uint8_t *output,
1284 uint8_t output_size,
1285 uint8_t *output_length)
1286 {
1287 //Check input parameters
1288 if (ccm_ctx == NULL || cmd_ctx == NULL || key == NULL || tag == NULL) {
1289 return SL_STATUS_INVALID_PARAMETER;
1290 }
1291
1292 if (tag_size < ccm_ctx->tag_len || output_size < ccm_ctx->final_data_length) {
1293 return SL_STATUS_INVALID_PARAMETER;
1294 }
1295
1296 sl_status_t status = SL_STATUS_OK;
1297
1298 if (ccm_ctx->total_message_length == 0) {
1299 if (ccm_ctx->mode == SL_SE_DECRYPT) {
1300 if (memcmp_time_cst(tag, ccm_ctx->mode_specific_buffer.tagbuf, ccm_ctx->tag_len) != 0) {
1301 memset(tag, 0, ccm_ctx->tag_len);
1302 return SL_STATUS_INVALID_SIGNATURE;
1303 }
1304 } else {
1305 memcpy(tag, ccm_ctx->mode_specific_buffer.tagbuf, ccm_ctx->tag_len);
1306 }
1307 return SL_STATUS_OK;
1308 }
1309
1310 SE_Command_t *se_cmd = &cmd_ctx->command;
1311
1312 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT(ccm_ctx->se_ctx, sizeof(ccm_ctx->se_ctx));
1313
1314 SE_DataTransfer_t data_in =
1315 SE_DATATRANSFER_DEFAULT(ccm_ctx->mode_specific_buffer.final_data, ccm_ctx->final_data_length);
1316
1317 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, ccm_ctx->final_data_length);
1318 SE_DataTransfer_t tag_buf = SE_DATATRANSFER_DEFAULT(tag,
1319 ccm_ctx->tag_len);
1320
1321 sli_se_command_init(cmd_ctx,
1322 ((ccm_ctx->mode == SL_SE_DECRYPT)
1323 ? SLI_SE_COMMAND_AES_CCM_DECRYPT : SLI_SE_COMMAND_AES_CCM_ENCRYPT)
1324 | SLI_SE_COMMAND_OPTION_CONTEXT_END);
1325
1326 sli_add_key_parameters(cmd_ctx, key, status);
1327
1328 SE_addParameter(se_cmd, (ccm_ctx->tag_len & 0xFFFF));
1329
1330 SE_addParameter(se_cmd, ccm_ctx->final_data_length);
1331
1332 sli_add_key_metadata(cmd_ctx, key, status);
1333 sli_add_key_input(cmd_ctx, key, status);
1334
1335 SE_addDataInput(se_cmd, &iv_ctx_in);
1336 SE_addDataInput(se_cmd, &data_in);
1337
1338 SE_addDataOutput(se_cmd, &data_out);
1339 if (ccm_ctx->mode == SL_SE_DECRYPT) {
1340 SE_addDataInput(se_cmd, &tag_buf);
1341 } else {
1342 SE_addDataOutput(se_cmd, &tag_buf);
1343 }
1344 status = sli_se_execute_and_wait(cmd_ctx);
1345
1346 if (status != SL_STATUS_OK) {
1347 memset(tag, 0, ccm_ctx->tag_len);
1348 *output_length = 0;
1349 return status;
1350 }
1351
1352 *output_length = ccm_ctx->final_data_length;
1353
1354 return SL_STATUS_OK;
1355 }
1356 #endif
1357
1358 /***************************************************************************//**
1359 * This function calculates the full generic CMAC on the input buffer with
1360 * the provided key.
1361 ******************************************************************************/
sl_se_cmac(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,const unsigned char * input,size_t input_len,unsigned char * output)1362 sl_status_t sl_se_cmac(sl_se_command_context_t *cmd_ctx,
1363 const sl_se_key_descriptor_t *key,
1364 const unsigned char *input,
1365 size_t input_len,
1366 unsigned char *output)
1367 {
1368 if (cmd_ctx == NULL || key == NULL || input == NULL || output == NULL) {
1369 return SL_STATUS_INVALID_PARAMETER;
1370 }
1371
1372 SE_Command_t *se_cmd = &cmd_ctx->command;
1373 sl_status_t status = SL_STATUS_OK;
1374
1375 switch (key->type) {
1376 case SL_SE_KEY_TYPE_AES_128:
1377 case SL_SE_KEY_TYPE_AES_192:
1378 case SL_SE_KEY_TYPE_AES_256:
1379 break;
1380
1381 default:
1382 return SL_STATUS_INVALID_PARAMETER;
1383 }
1384
1385 sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_AES_CMAC);
1386
1387 // Add key parameter to command.
1388 sli_add_key_parameters(cmd_ctx, key, status);
1389
1390 // Message size parameter.
1391 SE_addParameter(se_cmd, input_len);
1392
1393 // Key metadata.
1394 sli_add_key_metadata(cmd_ctx, key, status);
1395 sli_add_key_input(cmd_ctx, key, status);
1396
1397 // Data input.
1398 SE_DataTransfer_t in_data = SE_DATATRANSFER_DEFAULT(input, input_len);
1399 SE_addDataInput(se_cmd, &in_data);
1400
1401 // Data output.
1402 SE_DataTransfer_t out_tag = SE_DATATRANSFER_DEFAULT(output, 16);
1403 SE_addDataOutput(se_cmd, &out_tag);
1404
1405 return sli_se_execute_and_wait(cmd_ctx);
1406 }
1407
1408 /***************************************************************************//**
1409 * Finish a CMAC streaming operation and return the resulting CMAC tag.
1410 * It is called after sl_se_cmac_update().
1411 ******************************************************************************/
sl_se_cmac_multipart_finish(sl_se_cmac_multipart_context_t * cmac_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,uint8_t * output)1412 sl_status_t sl_se_cmac_multipart_finish(sl_se_cmac_multipart_context_t *cmac_ctx,
1413 sl_se_command_context_t *cmd_ctx,
1414 const sl_se_key_descriptor_t *key,
1415 uint8_t *output)
1416 {
1417 sl_status_t status = SL_STATUS_OK;
1418
1419 if (cmac_ctx == NULL || cmd_ctx == NULL || key == NULL || output == NULL) {
1420 return SL_STATUS_INVALID_PARAMETER;
1421 }
1422
1423 if (cmac_ctx->length >= 16U) {
1424 // Compute previous input block by decryption of current data.
1425 status = sl_se_aes_crypt_ecb(cmd_ctx,
1426 key,
1427 SL_SE_DECRYPT,
1428 16U,
1429 cmac_ctx->data_out,
1430 cmac_ctx->state); // Keep decrypted data in 'state'
1431 }
1432
1433 if (status == SL_STATUS_OK) {
1434 // Feed previous block and unprocessed data (if any) to CMAC,
1435 // or on data < 16 just use accumulated data in context.
1436 SE_Command_t *se_cmd = &cmd_ctx->command;
1437 sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_AES_CMAC);
1438
1439 // Add key parameter to command.
1440 sli_add_key_parameters(cmd_ctx, key, status);
1441
1442 // Message size parameter.
1443 if (cmac_ctx->length >= 16U) {
1444 SE_addParameter(se_cmd, 16U + (cmac_ctx->length & 0xFU));
1445 } else {
1446 SE_addParameter(se_cmd, cmac_ctx->length);
1447 }
1448
1449 // Key metadata.
1450 sli_add_key_metadata(cmd_ctx, key, status);
1451 sli_add_key_input(cmd_ctx, key, status);
1452
1453 SE_DataTransfer_t in_data1 = SE_DATATRANSFER_DEFAULT(cmac_ctx->state, 16U);
1454 SE_DataTransfer_t in_data2 = SE_DATATRANSFER_DEFAULT(cmac_ctx->data_in,
1455 cmac_ctx->length & 0xFU);
1456 SE_DataTransfer_t in_data = SE_DATATRANSFER_DEFAULT(cmac_ctx->data_in,
1457 cmac_ctx->length);
1458 // Data input.
1459 if (cmac_ctx->length >= 16U) {
1460 // Collect data from two sources.
1461 in_data1.length &= ~SE_DATATRANSFER_REALIGN;
1462 SE_addDataInput(se_cmd, &in_data1);
1463 SE_addDataInput(se_cmd, &in_data2);
1464 } else {
1465 SE_addDataInput(se_cmd, &in_data);
1466 }
1467
1468 // Data output.
1469 SE_DataTransfer_t out_tag = SE_DATATRANSFER_DEFAULT(output, 16U);
1470 SE_addDataOutput(se_cmd, &out_tag);
1471
1472 status = sli_se_execute_and_wait(cmd_ctx);
1473 }
1474 return status;
1475 }
1476
1477 /***************************************************************************//**
1478 * Prepare a CMAC streaming command context object to be used in subsequent
1479 * CMAC streaming function calls.
1480 ******************************************************************************/
sl_se_cmac_multipart_starts(sl_se_cmac_multipart_context_t * cmac_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key)1481 sl_status_t sl_se_cmac_multipart_starts(sl_se_cmac_multipart_context_t *cmac_ctx,
1482 sl_se_command_context_t *cmd_ctx,
1483 const sl_se_key_descriptor_t *key)
1484 {
1485 if (cmac_ctx == NULL || cmd_ctx == NULL || key == NULL) {
1486 return SL_STATUS_INVALID_PARAMETER;
1487 }
1488
1489 switch (key->type) {
1490 case SL_SE_KEY_TYPE_AES_128:
1491 case SL_SE_KEY_TYPE_AES_192:
1492 case SL_SE_KEY_TYPE_AES_256:
1493 break;
1494
1495 default:
1496 return SL_STATUS_INVALID_PARAMETER;
1497 }
1498
1499 memset(cmac_ctx, 0, sizeof(sl_se_cmac_multipart_context_t));
1500 return SL_STATUS_OK;
1501 }
1502
1503 /***************************************************************************//**
1504 * This function feeds an input buffer into an ongoing CMAC computation.
1505 * It is called between sl_se_cmac_starts() and sl_se_cmac_finish().
1506 * Can be called repeatedly.
1507 ******************************************************************************/
sl_se_cmac_multipart_update(sl_se_cmac_multipart_context_t * cmac_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,const uint8_t * input,size_t input_len)1508 sl_status_t sl_se_cmac_multipart_update(sl_se_cmac_multipart_context_t *cmac_ctx,
1509 sl_se_command_context_t *cmd_ctx,
1510 const sl_se_key_descriptor_t *key,
1511 const uint8_t *input,
1512 size_t input_len)
1513 {
1514 sl_status_t status = SL_STATUS_OK;
1515
1516 if (cmac_ctx == NULL || cmd_ctx == NULL || key == NULL || input == NULL) {
1517 return SL_STATUS_INVALID_PARAMETER;
1518 }
1519
1520 size_t pending = cmac_ctx->length & 0xFU;
1521
1522 if ((cmac_ctx->length / 16U) != ((cmac_ctx->length + input_len) / 16U)) {
1523 // Process one or more 16 byte blocks.
1524 size_t bytes_to_process = (pending + input_len) & 0xFFFFFFF0U;
1525
1526 SE_Command_t *se_cmd = &cmd_ctx->command;
1527 sli_se_command_init(cmd_ctx,
1528 SLI_SE_COMMAND_AES_ENCRYPT
1529 | SLI_SE_COMMAND_OPTION_MODE_CBC
1530 | SLI_SE_COMMAND_OPTION_CONTEXT_ADD);
1531
1532 // Add key parameters to command.
1533 sli_add_key_parameters(cmd_ctx, key, status);
1534 // Message size (number of bytes)
1535 SE_addParameter(se_cmd, bytes_to_process);
1536
1537 // Add key metadata block to command.
1538 sli_add_key_metadata(cmd_ctx, key, status);
1539 // Add key input block to command.
1540 sli_add_key_input(cmd_ctx, key, status);
1541
1542 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(cmac_ctx->state, 16U);
1543 SE_addDataInput(se_cmd, &iv_in);
1544
1545 // Data input, collect data from two sources.
1546 SE_DataTransfer_t in1 = SE_DATATRANSFER_DEFAULT(cmac_ctx->data_in, pending);
1547 SE_DataTransfer_t in2 = SE_DATATRANSFER_DEFAULT(input, bytes_to_process - pending);
1548 in1.length &= ~SE_DATATRANSFER_REALIGN;
1549 SE_addDataInput(se_cmd, &in1);
1550 SE_addDataInput(se_cmd, &in2);
1551
1552 // Data output, discard everything except the last 16 bytes.
1553 SE_DataTransfer_t out1 = SE_DATATRANSFER_DEFAULT(NULL, bytes_to_process - 16U);
1554 SE_DataTransfer_t out2 = SE_DATATRANSFER_DEFAULT(cmac_ctx->data_out, 16U);
1555 out1.length |= SE_DATATRANSFER_DISCARD;
1556 out1.length &= ~SE_DATATRANSFER_REALIGN;
1557 SE_addDataOutput(se_cmd, &out1);
1558 SE_addDataOutput(se_cmd, &out2);
1559
1560 SE_DataTransfer_t iv_out = SE_DATATRANSFER_DEFAULT(cmac_ctx->state, 16U);
1561 SE_addDataOutput(se_cmd, &iv_out);
1562
1563 status = sli_se_execute_and_wait(cmd_ctx);
1564
1565 // Store leftover data.
1566 size_t leftover = pending + input_len - bytes_to_process;
1567 memcpy(cmac_ctx->data_in, input + input_len - leftover, leftover);
1568 } else {
1569 // Not a complete 16 byte block yet, save input data for later.
1570 memcpy(cmac_ctx->data_in + pending, input, input_len);
1571 }
1572 cmac_ctx->length += input_len;
1573 return status;
1574 }
1575
1576 /***************************************************************************//**
1577 * Compute a HMAC on a full message.
1578 ******************************************************************************/
sl_se_hmac(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_hash_type_t hash_type,const uint8_t * message,size_t message_len,uint8_t * output,size_t output_len)1579 sl_status_t sl_se_hmac(sl_se_command_context_t *cmd_ctx,
1580 const sl_se_key_descriptor_t *key,
1581 sl_se_hash_type_t hash_type,
1582 const uint8_t *message,
1583 size_t message_len,
1584 uint8_t *output,
1585 size_t output_len)
1586 {
1587 if (cmd_ctx == NULL || key == NULL || message == NULL || output == NULL) {
1588 return SL_STATUS_INVALID_PARAMETER;
1589 }
1590
1591 SE_Command_t *se_cmd = &cmd_ctx->command;
1592 sl_status_t status = SL_STATUS_OK;
1593 uint32_t command_word;
1594 size_t hmac_len;
1595
1596 switch (hash_type) {
1597 case SL_SE_HASH_SHA1:
1598 command_word = SLI_SE_COMMAND_HMAC | SLI_SE_COMMAND_OPTION_HASH_SHA1;
1599 // SHA1 digest size is 20 bytes
1600 hmac_len = 20;
1601 break;
1602
1603 case SL_SE_HASH_SHA224:
1604 command_word = SLI_SE_COMMAND_HMAC | SLI_SE_COMMAND_OPTION_HASH_SHA224;
1605 // SHA224 digest size is 28 bytes
1606 hmac_len = 28;
1607 break;
1608
1609 case SL_SE_HASH_SHA256:
1610 command_word = SLI_SE_COMMAND_HMAC | SLI_SE_COMMAND_OPTION_HASH_SHA256;
1611 // SHA256 digest size is 32 bytes
1612 hmac_len = 32;
1613 break;
1614
1615 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
1616 case SL_SE_HASH_SHA384:
1617 command_word = SLI_SE_COMMAND_HMAC | SLI_SE_COMMAND_OPTION_HASH_SHA384;
1618 // SHA384 digest size is 48 bytes
1619 hmac_len = 48;
1620 break;
1621
1622 case SL_SE_HASH_SHA512:
1623 command_word = SLI_SE_COMMAND_HMAC | SLI_SE_COMMAND_OPTION_HASH_SHA512;
1624 // SHA512 digest size is 64 bytes
1625 hmac_len = 64;
1626 break;
1627
1628 #endif
1629 default:
1630 return SL_STATUS_INVALID_PARAMETER;
1631 }
1632
1633 if (output_len < hmac_len) {
1634 return SL_STATUS_INVALID_PARAMETER;
1635 }
1636
1637 sli_se_command_init(cmd_ctx, command_word);
1638
1639 // Add key parameter to command.
1640 sli_add_key_parameters(cmd_ctx, key, status);
1641
1642 // Message size parameter.
1643 SE_addParameter(se_cmd, message_len);
1644
1645 // Key metadata.
1646 sli_add_key_metadata(cmd_ctx, key, status);
1647
1648 sli_add_key_input(cmd_ctx, key, status);
1649
1650 // Data input.
1651 SE_DataTransfer_t in_data = SE_DATATRANSFER_DEFAULT(message, message_len);
1652 SE_addDataInput(se_cmd, &in_data);
1653
1654 // Data output.
1655 SE_DataTransfer_t out_hmac = SE_DATATRANSFER_DEFAULT(output, hmac_len);
1656 SE_addDataOutput(se_cmd, &out_hmac);
1657
1658 return sli_se_execute_and_wait(cmd_ctx);
1659 }
1660
1661 /***************************************************************************//**
1662 * GCM buffer encryption or decryption.
1663 ******************************************************************************/
sl_se_gcm_crypt_and_tag(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_cipher_operation_t mode,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,size_t tag_len,unsigned char * tag)1664 sl_status_t sl_se_gcm_crypt_and_tag(sl_se_command_context_t *cmd_ctx,
1665 const sl_se_key_descriptor_t *key,
1666 sl_se_cipher_operation_t mode,
1667 size_t length,
1668 const unsigned char *iv,
1669 size_t iv_len,
1670 const unsigned char *add,
1671 size_t add_len,
1672 const unsigned char *input,
1673 unsigned char *output,
1674 size_t tag_len,
1675 unsigned char *tag)
1676 {
1677 // Check input parameters.
1678 if (cmd_ctx == NULL || key == NULL || iv == NULL || tag == NULL
1679 || ((add_len > 0) && (add == NULL))
1680 || ((length > 0) && (input == NULL || output == NULL))
1681 || ((tag_len < 4) || (tag_len > 16))) {
1682 return SL_STATUS_INVALID_PARAMETER;
1683 }
1684
1685 SE_Command_t *se_cmd = &cmd_ctx->command;
1686 uint8_t tagbuf[16];
1687 sl_status_t status = SL_STATUS_OK;
1688
1689 if (// IV length is required to be 96 bits for SE.
1690 (iv_len != 96 / 8)
1691 // AD is limited to 2^64 bits, so 2^61 bytes.
1692 // However, on 32 bit platforms, that amount of continous data cannot be
1693 // available.
1694 // || (((uint64_t)add_len) >> 61 != 0)
1695 ) {
1696 return SL_STATUS_INVALID_PARAMETER;
1697 }
1698 switch (key->type) {
1699 case SL_SE_KEY_TYPE_AES_128:
1700 case SL_SE_KEY_TYPE_AES_192:
1701 case SL_SE_KEY_TYPE_AES_256:
1702 break;
1703
1704 default:
1705 return SL_STATUS_INVALID_PARAMETER;
1706 }
1707
1708 if (mode == SL_SE_DECRYPT) {
1709 // Extract plaintext first.
1710 sli_se_command_init(cmd_ctx,
1711 SLI_SE_COMMAND_AES_GCM_DECRYPT | ((tag_len & 0xFF) << 8));
1712
1713 sli_add_key_parameters(cmd_ctx, key, status);
1714 SE_addParameter(se_cmd, add_len);
1715 SE_addParameter(se_cmd, length);
1716
1717 sli_add_key_metadata(cmd_ctx, key, status);
1718 sli_add_key_input(cmd_ctx, key, status);
1719
1720 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(iv, iv_len);
1721 SE_addDataInput(se_cmd, &iv_in);
1722
1723 SE_DataTransfer_t aad_in = SE_DATATRANSFER_DEFAULT(add, add_len);
1724 SE_addDataInput(se_cmd, &aad_in);
1725
1726 SE_DataTransfer_t data_in = SE_DATATRANSFER_DEFAULT(input, length);
1727 SE_addDataInput(se_cmd, &data_in);
1728
1729 SE_DataTransfer_t tag_in = SE_DATATRANSFER_DEFAULT(tag, tag_len);
1730 SE_addDataInput(se_cmd, &tag_in);
1731
1732 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, length);
1733 if (output == NULL) {
1734 data_out.length |= SE_DATATRANSFER_DISCARD;
1735 }
1736 SE_addDataOutput(se_cmd, &data_out);
1737
1738 // Execute GCM operation.
1739 status = sli_se_execute_and_wait(cmd_ctx);
1740 if ((status != SL_STATUS_OK) && (status != SL_STATUS_INVALID_SIGNATURE)) {
1741 memset(output, 0, length);
1742 return status;
1743 }
1744
1745 // Re-encrypt the extracted plaintext to generate the tag to match.
1746 input = output;
1747 output = NULL;
1748 }
1749
1750 sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_AES_GCM_ENCRYPT);
1751
1752 sli_add_key_parameters(cmd_ctx, key, status);
1753 SE_addParameter(se_cmd, add_len);
1754 SE_addParameter(se_cmd, length);
1755
1756 sli_add_key_metadata(cmd_ctx, key, status);
1757 sli_add_key_input(cmd_ctx, key, status);
1758
1759 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(iv, iv_len);
1760 SE_addDataInput(se_cmd, &iv_in);
1761
1762 SE_DataTransfer_t aad_in = SE_DATATRANSFER_DEFAULT(add, add_len);
1763 SE_addDataInput(se_cmd, &aad_in);
1764
1765 SE_DataTransfer_t data_in = SE_DATATRANSFER_DEFAULT(input, length);
1766 SE_addDataInput(se_cmd, &data_in);
1767
1768 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, length);
1769 if (output == NULL) {
1770 data_out.length |= SE_DATATRANSFER_DISCARD;
1771 }
1772 SE_addDataOutput(se_cmd, &data_out);
1773
1774 SE_DataTransfer_t mac_out = SE_DATATRANSFER_DEFAULT(tagbuf, sizeof(tagbuf));
1775 SE_addDataOutput(se_cmd, &mac_out);
1776
1777 // Execute GCM operation.
1778 status = sli_se_execute_and_wait(cmd_ctx);
1779 if (status == SL_STATUS_OK) {
1780 // For encryption, copy requested tag size to output tag buffer.
1781 memcpy(tag, tagbuf, tag_len);
1782 } else {
1783 memset(output, 0, length);
1784 }
1785
1786 return status;
1787 }
1788
1789 /***************************************************************************//**
1790 * GCM buffer decryption and authentication.
1791 ******************************************************************************/
sl_se_gcm_auth_decrypt(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,size_t tag_len,const unsigned char * tag)1792 sl_status_t sl_se_gcm_auth_decrypt(sl_se_command_context_t *cmd_ctx,
1793 const sl_se_key_descriptor_t *key,
1794 size_t length,
1795 const unsigned char *iv,
1796 size_t iv_len,
1797 const unsigned char *add,
1798 size_t add_len,
1799 const unsigned char *input,
1800 unsigned char *output,
1801 size_t tag_len,
1802 const unsigned char *tag)
1803 {
1804 // Check input parameters.
1805 if (cmd_ctx == NULL || key == NULL || iv == NULL || tag == NULL
1806 || ((add_len > 0) && (add == NULL))
1807 || ((length > 0) && (input == NULL || output == NULL))
1808 || ((tag_len < 4) || (tag_len > 16))) {
1809 return SL_STATUS_INVALID_PARAMETER;
1810 }
1811
1812 SE_Command_t *se_cmd = &cmd_ctx->command;
1813 sl_status_t status = SL_STATUS_OK;
1814
1815 if (// IV length is required to be 96 bits for SE.
1816 (iv_len != 96 / 8)
1817 // AD is limited to 2^64 bits, so 2^61 bytes.
1818 // However, on 32 bit platforms, that amount of continous data cannot be
1819 // available.
1820 // || (((uint64_t)add_len) >> 61 != 0)
1821 ) {
1822 return SL_STATUS_INVALID_PARAMETER;
1823 }
1824 switch (key->type) {
1825 case SL_SE_KEY_TYPE_AES_128: // Fallthrough
1826 case SL_SE_KEY_TYPE_AES_192: // Fallthrough
1827 case SL_SE_KEY_TYPE_AES_256:
1828 break;
1829
1830 default:
1831 return SL_STATUS_INVALID_PARAMETER;
1832 }
1833
1834 sli_se_command_init(cmd_ctx,
1835 SLI_SE_COMMAND_AES_GCM_DECRYPT | ((tag_len & 0xFF) << 8));
1836
1837 sli_add_key_parameters(cmd_ctx, key, status);
1838 SE_addParameter(se_cmd, add_len);
1839 SE_addParameter(se_cmd, length);
1840
1841 sli_add_key_metadata(cmd_ctx, key, status);
1842 sli_add_key_input(cmd_ctx, key, status);
1843
1844 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(iv, iv_len);
1845 SE_addDataInput(se_cmd, &iv_in);
1846
1847 SE_DataTransfer_t aad_in = SE_DATATRANSFER_DEFAULT(add, add_len);
1848 SE_addDataInput(se_cmd, &aad_in);
1849
1850 SE_DataTransfer_t data_in = SE_DATATRANSFER_DEFAULT(input, length);
1851 SE_addDataInput(se_cmd, &data_in);
1852
1853 SE_DataTransfer_t tag_in = SE_DATATRANSFER_DEFAULT(tag, tag_len);
1854 SE_addDataInput(se_cmd, &tag_in);
1855
1856 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, length);
1857 if (output == NULL) {
1858 data_out.length |= SE_DATATRANSFER_DISCARD;
1859 }
1860 SE_addDataOutput(se_cmd, &data_out);
1861
1862 // Execute GCM operation.
1863 status = sli_se_execute_and_wait(cmd_ctx);
1864
1865 if (status != SL_STATUS_OK) {
1866 memset(output, 0, length);
1867 }
1868
1869 return status;
1870 }
1871
1872 #if defined(SLI_SE_MAJOR_VERSION_TWO)
1873 /***************************************************************************//**
1874 * GCM multipart encryption/decryption, initial stage.
1875 ******************************************************************************/
sl_se_gcm_multipart_starts(sl_se_gcm_multipart_context_t * gcm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_cipher_operation_t mode,const uint8_t * iv,size_t iv_len,const uint8_t * add,size_t add_len)1876 sl_status_t sl_se_gcm_multipart_starts(sl_se_gcm_multipart_context_t *gcm_ctx,
1877 sl_se_command_context_t *cmd_ctx,
1878 const sl_se_key_descriptor_t *key,
1879 sl_se_cipher_operation_t mode,
1880 const uint8_t *iv,
1881 size_t iv_len,
1882 const uint8_t *add,
1883 size_t add_len)
1884 {
1885 sl_status_t status = SL_STATUS_OK;
1886
1887 // Check input parameters.
1888 if (gcm_ctx == NULL || cmd_ctx == NULL || key == NULL || iv == NULL
1889 || (add_len > 0 && add == NULL)) {
1890 return SL_STATUS_INVALID_PARAMETER;
1891 }
1892 if ((iv_len != 12)
1893 // AD are limited to 2^64 bits, so 2^61 bytes.
1894 // However, on 32 bit platforms, that amount of continous data cannot be
1895 // available.
1896 // || (((uint64_t)add_len) >> 61 != 0)
1897 ) {
1898 return SL_STATUS_INVALID_PARAMETER;
1899 }
1900
1901 memset(gcm_ctx, 0, sizeof(sl_se_gcm_multipart_context_t));
1902
1903 gcm_ctx->mode = mode;
1904 gcm_ctx->len = 0;
1905 gcm_ctx->add_len = add_len;
1906
1907 SE_Command_t *se_cmd = &cmd_ctx->command;
1908
1909 // The start context requires some data, either additional data or input data.
1910 // Case add_len > 0: Run start command with additonal data to create ctx_out.
1911 // Case add_len = 0: Store iv in gcm_ctx and run start function with input data
1912 // in sl_se_gcm_multipart_update. In the case of zero input data or
1913 // input data < 16 run sl_se_gcm_auth_decrypt()/sl_se_gcm_crypt_and_tag() in
1914 // sl_se_gcm_multipart_finish.
1915 if ( add_len > 0 ) {
1916 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(iv, iv_len);
1917 SE_DataTransfer_t add_in = SE_DATATRANSFER_DEFAULT(add, add_len);
1918 SE_DataTransfer_t ctx_out =
1919 SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx, sizeof(gcm_ctx->se_ctx));
1920
1921 sli_se_command_init(cmd_ctx,
1922 (gcm_ctx->mode == SL_SE_DECRYPT ? SLI_SE_COMMAND_AES_GCM_DECRYPT
1923 : SLI_SE_COMMAND_AES_GCM_ENCRYPT)
1924 | SLI_SE_COMMAND_OPTION_CONTEXT_START);
1925
1926 sli_add_key_parameters(cmd_ctx, key, status);
1927 SE_addParameter(se_cmd, add_len);
1928 SE_addParameter(se_cmd, 0);
1929
1930 sli_add_key_metadata(cmd_ctx, key, status);
1931 sli_add_key_input(cmd_ctx, key, status);
1932
1933 SE_addDataInput(se_cmd, &iv_in);
1934 SE_addDataInput(se_cmd, &add_in);
1935 SE_addDataOutput(se_cmd, &ctx_out);
1936
1937 status = sli_se_execute_and_wait(cmd_ctx);
1938 if (status != SL_STATUS_OK) {
1939 memset(gcm_ctx->se_ctx, 0, sizeof(gcm_ctx->se_ctx));
1940 return status;
1941 }
1942 gcm_ctx->first_operation = false;
1943 } else {
1944 memcpy(gcm_ctx->se_ctx, iv, iv_len);
1945 gcm_ctx->first_operation = true;
1946 }
1947 return SL_STATUS_OK;
1948 }
1949
1950 #else
1951 /***************************************************************************//**
1952 * GCM multipart encryption/decryption, initial stage.
1953 ******************************************************************************/
sl_se_gcm_multipart_starts(sl_se_gcm_multipart_context_t * gcm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,sl_se_cipher_operation_t mode,const uint8_t * iv,size_t iv_len,const uint8_t * add,size_t add_len)1954 sl_status_t sl_se_gcm_multipart_starts(sl_se_gcm_multipart_context_t *gcm_ctx,
1955 sl_se_command_context_t *cmd_ctx,
1956 const sl_se_key_descriptor_t *key,
1957 sl_se_cipher_operation_t mode,
1958 const uint8_t *iv,
1959 size_t iv_len,
1960 const uint8_t *add,
1961 size_t add_len)
1962 {
1963 sl_status_t status = SL_STATUS_OK;
1964
1965 // Check input parameters.
1966 if (gcm_ctx == NULL || cmd_ctx == NULL || key == NULL || iv == NULL
1967 || (add_len > 0 && add == NULL)) {
1968 return SL_STATUS_INVALID_PARAMETER;
1969 }
1970 if ((iv_len != 12)
1971 // AD are limited to 2^64 bits, so 2^61 bytes.
1972 // However, on 32 bit platforms, that amount of continous data cannot be
1973 // available.
1974 // || (((uint64_t)add_len) >> 61 != 0)
1975 ) {
1976 return SL_STATUS_INVALID_PARAMETER;
1977 }
1978
1979 memset(gcm_ctx, 0, sizeof(sl_se_gcm_multipart_context_t));
1980
1981 gcm_ctx->mode = mode;
1982 gcm_ctx->len = 0;
1983 gcm_ctx->add_len = add_len;
1984
1985 // The start context requires some data, either additional data or input data.
1986 // Case add_len > 0: Run start command with additonal data to create ctx_out.
1987 // Case add_len = 0: Store iv in gcm_ctx and run start function with input data
1988 // in sl_se_gcm_multipart_update. In the case of zero input data or
1989 // input data < 16 run sl_se_gcm_auth_decrypt()/sl_se_gcm_crypt_and_tag() in
1990 // sl_se_gcm_multipart_finish.
1991 if ( add_len > 0 ) {
1992 // Encrypt: Compute tag and store it in context and output tag in finish.
1993 // Decrypt: Compute tag and store it in context and compare it to the
1994 // input tag in finish to verify it.
1995
1996 // Explanation:The end-context in finish is currently not supporting 0 input data
1997 // for this config. For add_len = 0 and input_length = 0 we can run
1998 // sl_se_gcm_auth_decrypt()/sl_se_gcm_crypt_and_tag() in finish, so this is only
1999 // an issue for 0 input data and add_len != 0.
2000 SE_Command_t *se_cmd = &cmd_ctx->command;
2001 SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(iv, iv_len);
2002 SE_DataTransfer_t add_in = SE_DATATRANSFER_DEFAULT(add, add_len);
2003 SE_DataTransfer_t tag_out = SE_DATATRANSFER_DEFAULT(gcm_ctx->tagbuf,
2004 sizeof(gcm_ctx->tagbuf));
2005 sli_se_command_init(cmd_ctx,
2006 SLI_SE_COMMAND_AES_GCM_ENCRYPT
2007 | SLI_SE_COMMAND_OPTION_CONTEXT_WHOLE);
2008
2009 sli_add_key_parameters(cmd_ctx, key, status);
2010 SE_addParameter(se_cmd, add_len);
2011 SE_addParameter(se_cmd, 0);
2012
2013 sli_add_key_metadata(cmd_ctx, key, status);
2014 sli_add_key_input(cmd_ctx, key, status);
2015
2016 SE_addDataInput(se_cmd, &iv_in);
2017 SE_addDataInput(se_cmd, &add_in);
2018 SE_addDataOutput(se_cmd, &tag_out);
2019
2020 status = sli_se_execute_and_wait(cmd_ctx);
2021 if (status != SL_STATUS_OK) {
2022 memset(gcm_ctx->tagbuf, 0, sizeof(gcm_ctx->tagbuf));
2023 return status;
2024 }
2025
2026 SE_DataTransfer_t ctx_out =
2027 SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx, sizeof(gcm_ctx->se_ctx));
2028
2029 // Reuse the values of the command context object from the previous
2030 // operation, and only update the command word and the output data pointer.
2031 cmd_ctx->command.command =
2032 (gcm_ctx->mode == SL_SE_DECRYPT ? SLI_SE_COMMAND_AES_GCM_DECRYPT
2033 : SLI_SE_COMMAND_AES_GCM_ENCRYPT)
2034 | SLI_SE_COMMAND_OPTION_CONTEXT_START;
2035
2036 cmd_ctx->command.data_out = &ctx_out;
2037
2038 status = sli_se_execute_and_wait(cmd_ctx);
2039 if (status != SL_STATUS_OK) {
2040 memset(gcm_ctx->se_ctx, 0, sizeof(gcm_ctx->se_ctx));
2041 return status;
2042 }
2043 gcm_ctx->first_operation = false;
2044 } else {
2045 memcpy(gcm_ctx->se_ctx, iv, iv_len);
2046 gcm_ctx->first_operation = true;
2047 }
2048 return SL_STATUS_OK;
2049 }
2050 #endif
2051
2052 #if defined(SLI_SE_MAJOR_VERSION_TWO)
2053 /***************************************************************************//**
2054 * GCM multipart encryption/decryption, update stage.
2055 ******************************************************************************/
sl_se_gcm_multipart_update(sl_se_gcm_multipart_context_t * gcm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,size_t length,const uint8_t * input,uint8_t * output,size_t * output_length)2056 sl_status_t sl_se_gcm_multipart_update(sl_se_gcm_multipart_context_t *gcm_ctx,
2057 sl_se_command_context_t *cmd_ctx,
2058 const sl_se_key_descriptor_t *key,
2059 size_t length,
2060 const uint8_t *input,
2061 uint8_t *output,
2062 size_t *output_length)
2063 {
2064 sl_status_t status = SL_STATUS_OK;
2065 uint8_t stored_res_length = 0;
2066
2067 // Check input parameters.
2068 if (cmd_ctx == NULL || key == NULL || gcm_ctx == NULL) {
2069 return SL_STATUS_INVALID_PARAMETER;
2070 }
2071 if (length == 0) {
2072 return SL_STATUS_OK;
2073 }
2074 if (length > 0 && (input == NULL || output == NULL || output_length == NULL)) {
2075 return SL_STATUS_INVALID_PARAMETER;
2076 }
2077
2078 *output_length = 0;
2079
2080 // Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes.
2081 // Also check for possible overflow.
2082 if (gcm_ctx->len + length < gcm_ctx->len
2083 || (uint64_t)gcm_ctx->len + length > 0xFFFFFFFE0ULL) {
2084 return SL_STATUS_INVALID_PARAMETER;
2085 }
2086 SE_Command_t *se_cmd = &cmd_ctx->command;
2087
2088 // The update context only support an input length as a multiple of 16. Hence, there
2089 // there is a few cases that can happen.
2090
2091 // Always:
2092 // Case length = 0: Return SL_STATUS_OK
2093
2094 // If there is no data in gcm_ctx->final_data:
2095 // Case length < 16: Store data in gcm_ctx->final_data and return SL_STATUS_OK
2096 // Case length == 16: Run update as normal
2097 // Case length > 16 and length is a multiple of 16: Run update as normal
2098 // Case length > 16 and length is not a multiple of 16: Run update as normal on the largest multiple
2099 // and save the residue bytes in gcm_ctx->final_data.
2100
2101 // If there is data in gcm_ctx->final_data:
2102 // Case final_data_length + length < 16: Store input data in gcm_ctx and return SL_STATUS_OKAY
2103 // Case final_data_length + length > 16: Add data to fill up the gcm_ctx->final_data-buffer, run update
2104 // on the gcm_ctx->final_data-buffer and finally run update as explained above on the rest of the data.
2105
2106 if (gcm_ctx->final_data_length) {
2107 if ((gcm_ctx->final_data_length + length) < 16) {
2108 memcpy(gcm_ctx->final_data + gcm_ctx->final_data_length, input, length);
2109 gcm_ctx->final_data_length += length;
2110 *output_length = 0;
2111 return SL_STATUS_OK;
2112 }
2113 stored_res_length = 16 - gcm_ctx->final_data_length;
2114 memcpy(gcm_ctx->final_data + gcm_ctx->final_data_length, input, stored_res_length);
2115
2116 //The gcm_ctx->se_ctx buffer contain iv data with length 12 if gcm_ctx->first_operation = true
2117 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2118 gcm_ctx->first_operation ? 12 : sizeof(gcm_ctx->se_ctx));
2119
2120 SE_DataTransfer_t data_in =
2121 SE_DATATRANSFER_DEFAULT(gcm_ctx->final_data, 16);
2122
2123 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, 16);
2124 SE_DataTransfer_t ctx_out = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2125 sizeof(gcm_ctx->se_ctx));
2126
2127 sli_se_command_init(cmd_ctx,
2128 (gcm_ctx->mode == SL_SE_DECRYPT ? SLI_SE_COMMAND_AES_GCM_DECRYPT
2129 : SLI_SE_COMMAND_AES_GCM_ENCRYPT)
2130 | (gcm_ctx->first_operation ? SLI_SE_COMMAND_OPTION_CONTEXT_START : SLI_SE_COMMAND_OPTION_CONTEXT_ADD));
2131
2132 sli_add_key_parameters(cmd_ctx, key, status);
2133 SE_addParameter(se_cmd, 0);
2134 SE_addParameter(se_cmd, 16);
2135
2136 sli_add_key_metadata(cmd_ctx, key, status);
2137 sli_add_key_input(cmd_ctx, key, status);
2138
2139 SE_addDataInput(se_cmd, &iv_ctx_in);
2140 SE_addDataInput(se_cmd, &data_in);
2141
2142 SE_addDataOutput(se_cmd, &data_out);
2143
2144 SE_addDataOutput(se_cmd, &ctx_out);
2145
2146 status = sli_se_execute_and_wait(cmd_ctx);
2147
2148 if (status != SL_STATUS_OK) {
2149 memset(gcm_ctx->se_ctx, 0, sizeof(gcm_ctx->se_ctx));
2150 return status;
2151 }
2152 gcm_ctx->first_operation = false;
2153 gcm_ctx->len += 16;
2154 output += 16;
2155
2156 if ((length - stored_res_length) < 16) {
2157 memcpy(gcm_ctx->final_data, input + stored_res_length, length - stored_res_length);
2158 gcm_ctx->final_data_length = length - stored_res_length;
2159 *output_length = 16;
2160 return SL_STATUS_OK;
2161 }
2162
2163 length -= stored_res_length;
2164 gcm_ctx->final_data_length = 0;
2165 *output_length += 16;
2166 }
2167 if (length % 16 != 0) {
2168 if (length > 16) {
2169 // Input length is larger than, and a non multiple of, 16
2170 memcpy(gcm_ctx->final_data, input + stored_res_length + (length - (length % 16)), length % 16);
2171 gcm_ctx->final_data_length = length % 16;
2172 length -= length % 16;
2173 } else {
2174 // Input length is not a multiple of 16
2175 memcpy(gcm_ctx->final_data, input + stored_res_length, length);
2176 gcm_ctx->final_data_length = length;
2177 *output_length = 0;
2178 return SL_STATUS_OK;
2179 }
2180 }
2181 gcm_ctx->len += length;
2182
2183 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2184 gcm_ctx->first_operation ? 12 : sizeof(gcm_ctx->se_ctx));
2185
2186 SE_DataTransfer_t data_in =
2187 SE_DATATRANSFER_DEFAULT(input + stored_res_length, length);
2188
2189 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, length);
2190 SE_DataTransfer_t ctx_out = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2191 sizeof(gcm_ctx->se_ctx));
2192
2193 sli_se_command_init(cmd_ctx,
2194 (gcm_ctx->mode == SL_SE_DECRYPT ? SLI_SE_COMMAND_AES_GCM_DECRYPT
2195 : SLI_SE_COMMAND_AES_GCM_ENCRYPT)
2196 | (gcm_ctx->first_operation ? SLI_SE_COMMAND_OPTION_CONTEXT_START : SLI_SE_COMMAND_OPTION_CONTEXT_ADD));
2197
2198 sli_add_key_parameters(cmd_ctx, key, status);
2199 SE_addParameter(se_cmd, 0);
2200 SE_addParameter(se_cmd, length);
2201
2202 sli_add_key_metadata(cmd_ctx, key, status);
2203 sli_add_key_input(cmd_ctx, key, status);
2204
2205 SE_addDataInput(se_cmd, &iv_ctx_in);
2206 SE_addDataInput(se_cmd, &data_in);
2207
2208 SE_addDataOutput(se_cmd, &data_out);
2209
2210 SE_addDataOutput(se_cmd, &ctx_out);
2211
2212 status = sli_se_execute_and_wait(cmd_ctx);
2213
2214 if (status != SL_STATUS_OK) {
2215 memset(gcm_ctx->se_ctx, 0, sizeof(gcm_ctx->se_ctx));
2216 return status;
2217 }
2218 *output_length += length;
2219 gcm_ctx->first_operation = false;
2220 return SL_STATUS_OK;
2221 }
2222
2223 #else // SLI_SE_MAJOR_VERSION_ONE
2224 /***************************************************************************//**
2225 * GCM multipart encryption/decryption, update stage.
2226 ******************************************************************************/
sl_se_gcm_multipart_update(sl_se_gcm_multipart_context_t * gcm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,size_t length,const uint8_t * input,uint8_t * output,size_t * output_length)2227 sl_status_t sl_se_gcm_multipart_update(sl_se_gcm_multipart_context_t *gcm_ctx,
2228 sl_se_command_context_t *cmd_ctx,
2229 const sl_se_key_descriptor_t *key,
2230 size_t length,
2231 const uint8_t *input,
2232 uint8_t *output,
2233 size_t *output_length)
2234 {
2235 sl_status_t status = SL_STATUS_OK;
2236 uint8_t stored_res_length = 0;
2237
2238 // Check input parameters.
2239 if (cmd_ctx == NULL || key == NULL || gcm_ctx == NULL) {
2240 return SL_STATUS_INVALID_PARAMETER;
2241 }
2242 if (length == 0) {
2243 return SL_STATUS_OK;
2244 }
2245 if (length > 0 && (input == NULL || output == NULL || output_length == NULL)) {
2246 return SL_STATUS_INVALID_PARAMETER;
2247 }
2248
2249 *output_length = 0;
2250
2251 // Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes.
2252 // Also check for possible overflow.
2253 if (gcm_ctx->len + length < gcm_ctx->len
2254 || (uint64_t)gcm_ctx->len + length > 0xFFFFFFFE0ULL) {
2255 return SL_STATUS_INVALID_PARAMETER;
2256 }
2257 SE_Command_t *se_cmd = &cmd_ctx->command;
2258
2259 // The finish command will return the wrong tag or INVALID SIGNATURE if there is no
2260 // input data. There is no way to know when sl_se_gcm_multipart_update is called for the last time, so there must
2261 // always be data stored.
2262 // The update context only support an input length as a multiple of 16. Hence, there
2263 // there is a few cases that can happen.
2264
2265 // Always:
2266 // Case length = 0: Return SL_STATUS_OK
2267
2268 // If there is no data in gcm_ctx->final_data
2269 // Case length < 16: Store data in gcm_ctx->final_data and return SL_STATUS_OK
2270 // Case length > 16 and length is not a multiple of 16: Run update as normal on the largest multiple
2271 // and save the residue bytes in gcm_ctx->final_data.
2272 // Case length == 16: store the current se_ctx in gcm_ctx->previous_se_ctx and store input data in final_data,
2273 // then run update as normal on the input data.
2274 // Case length > 16 and length is a multible of 16: run update twice, one with all input data and one with
2275 // all input data except the last 16 bytes. The out_ctx from each run are stored in gcm_ctx->se_ctx and
2276 // gcm_ctx->previous_se_ctx respectively. The last 16 bytes are then stored in final_data.
2277 // NOTE:output_length will include all encrypted/decrypted data.
2278
2279 // If there is data in gcm_ctx->final_data
2280 // Case final_data_length + length < 16: Store input data in gcm_ctx and return SL_STATUS_OKAY
2281 // Case final_data_length + length > 16: Add data to fill up the gcm_ctx->final_data-buffer, run update
2282 // on the gcm_ctx->final_data-buffer and finally run update as explained above on the rest of the data.
2283
2284 // Our drivers only support full or no overlap between input and output
2285 // buffers. So in the case of partial overlap, copy the input buffer into
2286 // the output buffer and process it in place as if the buffers fully
2287 // overlapped.
2288 if ((output > input) && (output < (input + length))) {
2289 memmove(output, input, length);
2290 input = output;
2291 }
2292
2293 // Check for data in final_data_length.
2294 if (gcm_ctx->final_data_length && gcm_ctx->final_data_length != 16) {
2295 if ((gcm_ctx->final_data_length + length) < 16) {
2296 memcpy(gcm_ctx->final_data + gcm_ctx->final_data_length, input, length);
2297 gcm_ctx->final_data_length += length;
2298 *output_length = 0;
2299 return SL_STATUS_OK;
2300 }
2301
2302 if ((gcm_ctx->final_data_length + length) == 16) {
2303 memcpy(gcm_ctx->previous_se_ctx, gcm_ctx->se_ctx, sizeof(gcm_ctx->se_ctx));
2304 }
2305 stored_res_length = 16 - gcm_ctx->final_data_length;
2306 memcpy(gcm_ctx->final_data + gcm_ctx->final_data_length, input, stored_res_length);
2307
2308 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2309 gcm_ctx->first_operation ? 12 : sizeof(gcm_ctx->se_ctx));
2310
2311 SE_DataTransfer_t data_in =
2312 SE_DATATRANSFER_DEFAULT(gcm_ctx->final_data, 16);
2313
2314 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, 16);
2315 SE_DataTransfer_t ctx_out = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2316 sizeof(gcm_ctx->se_ctx));
2317
2318 sli_se_command_init(cmd_ctx,
2319 (gcm_ctx->mode == SL_SE_DECRYPT ? SLI_SE_COMMAND_AES_GCM_DECRYPT
2320 : SLI_SE_COMMAND_AES_GCM_ENCRYPT)
2321 | (gcm_ctx->first_operation ? SLI_SE_COMMAND_OPTION_CONTEXT_START : SLI_SE_COMMAND_OPTION_CONTEXT_ADD));
2322
2323 sli_add_key_parameters(cmd_ctx, key, status);
2324 SE_addParameter(se_cmd, 0);
2325 SE_addParameter(se_cmd, 16);
2326
2327 sli_add_key_metadata(cmd_ctx, key, status);
2328 sli_add_key_input(cmd_ctx, key, status);
2329
2330 SE_addDataInput(se_cmd, &iv_ctx_in);
2331 SE_addDataInput(se_cmd, &data_in);
2332
2333 SE_addDataOutput(se_cmd, &data_out);
2334
2335 SE_addDataOutput(se_cmd, &ctx_out);
2336
2337 status = sli_se_execute_and_wait(cmd_ctx);
2338
2339 if (status != SL_STATUS_OK) {
2340 memset(gcm_ctx->se_ctx, 0, sizeof(gcm_ctx->se_ctx));
2341 return status;
2342 }
2343 gcm_ctx->first_operation = false;
2344 gcm_ctx->len += 16;
2345 output += 16;
2346
2347 if ((gcm_ctx->final_data_length + length) == 16) {
2348 gcm_ctx->final_data_length = 16;
2349 *output_length = 16;
2350 return SL_STATUS_OK;
2351 }
2352
2353 if ((length - stored_res_length) < 16) {
2354 memcpy(gcm_ctx->final_data, input + stored_res_length, length - stored_res_length);
2355 gcm_ctx->final_data_length = length - stored_res_length;
2356 *output_length = 16;
2357 return SL_STATUS_OK;
2358 }
2359
2360 length -= stored_res_length;
2361 gcm_ctx->final_data_length = 0;
2362 *output_length += 16;
2363 }
2364 if (length % 16 != 0) {
2365 if (length > 16) {
2366 //Input length is larger than, and a non multiple of, 16
2367 memcpy(gcm_ctx->final_data, input + stored_res_length + (length - (length % 16)), length % 16);
2368 gcm_ctx->final_data_length = length % 16;
2369 length -= length % 16;
2370 } else {
2371 //Input length is not a multiple of 16
2372 memcpy(gcm_ctx->final_data, input + stored_res_length, length);
2373 gcm_ctx->final_data_length = length;
2374 *output_length = 0;
2375 return SL_STATUS_OK;
2376 }
2377 } else {
2378 if (length > 16) {
2379 //If length is larger than, and a multiple of, 16, we must compute a context without the last 16 bytes
2380 //and store it as the previous context in case there is no more data.
2381 memcpy(gcm_ctx->final_data, input + stored_res_length + (length - 16), 16);
2382 gcm_ctx->final_data_length = 16;
2383
2384 //The gcm_ctx->se_ctx buffer contain iv data with length 12 if gcm_ctx->first_operation = true
2385 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2386 gcm_ctx->first_operation ? 12 : sizeof(gcm_ctx->se_ctx));
2387
2388 SE_DataTransfer_t data_in =
2389 SE_DATATRANSFER_DEFAULT(input + stored_res_length, length - 16);
2390
2391 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, length - 16);
2392 SE_DataTransfer_t ctx_out = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2393 sizeof(gcm_ctx->se_ctx));
2394
2395 sli_se_command_init(cmd_ctx,
2396 (gcm_ctx->mode == SL_SE_DECRYPT ? SLI_SE_COMMAND_AES_GCM_DECRYPT
2397 : SLI_SE_COMMAND_AES_GCM_ENCRYPT)
2398 | (gcm_ctx->first_operation ? SLI_SE_COMMAND_OPTION_CONTEXT_START : SLI_SE_COMMAND_OPTION_CONTEXT_ADD));
2399
2400 sli_add_key_parameters(cmd_ctx, key, status);
2401 SE_addParameter(se_cmd, 0);
2402 SE_addParameter(se_cmd, length - 16);
2403
2404 sli_add_key_metadata(cmd_ctx, key, status);
2405 sli_add_key_input(cmd_ctx, key, status);
2406
2407 SE_addDataInput(se_cmd, &iv_ctx_in);
2408 SE_addDataInput(se_cmd, &data_in);
2409
2410 SE_addDataOutput(se_cmd, &data_out);
2411
2412 SE_addDataOutput(se_cmd, &ctx_out);
2413
2414 status = sli_se_execute_and_wait(cmd_ctx);
2415
2416 if (status != SL_STATUS_OK) {
2417 memset(gcm_ctx->se_ctx, 0, sizeof(gcm_ctx->se_ctx));
2418 return status;
2419 }
2420
2421 // Only process the last 16 bytes in the last operation.
2422 output += (length - 16);
2423 input += (length - 16);
2424 gcm_ctx->first_operation = false;
2425 gcm_ctx->len += (length - 16);
2426 *output_length += (length - 16);
2427
2428 length = 16;
2429
2430 memcpy(gcm_ctx->previous_se_ctx, gcm_ctx->se_ctx, sizeof(gcm_ctx->se_ctx));
2431 } else {
2432 memcpy(gcm_ctx->previous_se_ctx, gcm_ctx->se_ctx, sizeof(gcm_ctx->se_ctx));
2433 memcpy(gcm_ctx->final_data, input + stored_res_length, length);
2434 gcm_ctx->final_data_length = length;
2435 }
2436 }
2437 gcm_ctx->len += length;
2438
2439 // The gcm_ctx->se_ctx buffer contain iv data with length 12 if gcm_ctx->first_operation = true
2440 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2441 gcm_ctx->first_operation ? 12 : sizeof(gcm_ctx->se_ctx));
2442
2443 SE_DataTransfer_t data_in =
2444 SE_DATATRANSFER_DEFAULT(input + stored_res_length, length);
2445
2446 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, length);
2447 SE_DataTransfer_t ctx_out = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx,
2448 sizeof(gcm_ctx->se_ctx));
2449
2450 sli_se_command_init(cmd_ctx,
2451 (gcm_ctx->mode == SL_SE_DECRYPT ? SLI_SE_COMMAND_AES_GCM_DECRYPT
2452 : SLI_SE_COMMAND_AES_GCM_ENCRYPT)
2453 | (gcm_ctx->first_operation ? SLI_SE_COMMAND_OPTION_CONTEXT_START : SLI_SE_COMMAND_OPTION_CONTEXT_ADD));
2454
2455 sli_add_key_parameters(cmd_ctx, key, status);
2456 SE_addParameter(se_cmd, 0);
2457 SE_addParameter(se_cmd, length);
2458
2459 sli_add_key_metadata(cmd_ctx, key, status);
2460 sli_add_key_input(cmd_ctx, key, status);
2461
2462 SE_addDataInput(se_cmd, &iv_ctx_in);
2463 SE_addDataInput(se_cmd, &data_in);
2464
2465 SE_addDataOutput(se_cmd, &data_out);
2466
2467 SE_addDataOutput(se_cmd, &ctx_out);
2468
2469 status = sli_se_execute_and_wait(cmd_ctx);
2470
2471 if (status != SL_STATUS_OK) {
2472 memset(gcm_ctx->se_ctx, 0, sizeof(gcm_ctx->se_ctx));
2473 return status;
2474 }
2475 *output_length += length;
2476 gcm_ctx->first_operation = false;
2477 return SL_STATUS_OK;
2478 }
2479 #endif
2480
2481 /***************************************************************************//**
2482 * GCM multipart encryption/decryption, finish stage.
2483 ******************************************************************************/
sl_se_gcm_multipart_finish(sl_se_gcm_multipart_context_t * gcm_ctx,sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key,uint8_t * tag,uint8_t tag_length,uint8_t * output,uint8_t output_size,uint8_t * output_length)2484 sl_status_t sl_se_gcm_multipart_finish(sl_se_gcm_multipart_context_t *gcm_ctx,
2485 sl_se_command_context_t *cmd_ctx,
2486 const sl_se_key_descriptor_t *key,
2487 uint8_t *tag,
2488 uint8_t tag_length,
2489 uint8_t *output,
2490 uint8_t output_size,
2491 uint8_t *output_length)
2492 {
2493 sl_status_t status = SL_STATUS_OK;
2494 uint32_t tmpbuf[4];
2495 uint8_t length;
2496 if (cmd_ctx == NULL || key == NULL || gcm_ctx == NULL || tag == NULL || tag_length < 4 || tag_length > 16) {
2497 return SL_STATUS_INVALID_PARAMETER;
2498 }
2499
2500 if ((gcm_ctx->final_data_length != 16)
2501 && (output_size < gcm_ctx->final_data_length)) {
2502 return SL_STATUS_INVALID_PARAMETER;
2503 }
2504
2505 SE_Command_t *se_cmd = &cmd_ctx->command;
2506 length = gcm_ctx->final_data_length;
2507 gcm_ctx->len += ((length % 16 != 0) ? length : 0);
2508
2509 #if defined(SLI_SE_MAJOR_VERSION_ONE)
2510 if ((gcm_ctx->add_len > 0) && (gcm_ctx->len == 0)) {
2511 if (gcm_ctx->mode == SL_SE_DECRYPT) {
2512 if (memcmp_time_cst(tag, gcm_ctx->tagbuf, tag_length)) {
2513 memset(tag, 0, tag_length);
2514 return SL_STATUS_INVALID_SIGNATURE;
2515 }
2516 } else {
2517 memcpy(tag, gcm_ctx->tagbuf, tag_length);
2518 }
2519 return SL_STATUS_OK;
2520 }
2521 #endif
2522
2523 #if defined(SLI_SE_MAJOR_VERSION_ONE)
2524 // For xG21 devices, since the multipart finish command cannot handle cases without
2525 // more data being passed as part of the finish call, there are two cases for which
2526 // a finish call can condense into a one-shot operation:
2527 // 1. The 'first operation' flag is set, meaning no multipart context has been started
2528 // 2. There was no AAD input and the total input length equals 16 bytes. In such a case,
2529 // all information needed for a one-shot operation is still present in the context,
2530 // being the 16 bytes of input in the lookback buffer. In such a case, be careful to
2531 // not return ciphertext/plaintext to the user a second time, since it has already
2532 // been returned as part of the initial call to `_update`.
2533 if (gcm_ctx->first_operation || (gcm_ctx->add_len == 0 && gcm_ctx->len == 16)) {
2534 #else
2535 // Devices xG23 or newer support a finish call without data, so the only case for
2536 // condensing a multipart finish operation into a one-shot operation is when the
2537 // 'first operation' flag is set, meaning no multipart context has been started
2538 if (gcm_ctx->first_operation) {
2539 #endif
2540 if (gcm_ctx->mode == SL_SE_ENCRYPT) {
2541 status = sl_se_gcm_crypt_and_tag(cmd_ctx,
2542 key,
2543 gcm_ctx->mode,
2544 length,
2545 gcm_ctx->se_ctx, //iv
2546 12, //iv_len
2547 NULL,
2548 0,
2549 gcm_ctx->final_data,
2550 (length < 16 ? output : (unsigned char*)tmpbuf),
2551 tag_length,
2552 tag);
2553 } else {
2554 status = sl_se_gcm_auth_decrypt(cmd_ctx,
2555 key,
2556 length,
2557 gcm_ctx->se_ctx, //iv
2558 12, //iv_len
2559 NULL,
2560 0,
2561 gcm_ctx->final_data,
2562 (length < 16 ? output : (unsigned char*)tmpbuf),
2563 tag_length,
2564 tag);
2565 }
2566 if (status != SL_STATUS_OK) {
2567 *output_length = 0;
2568 memset(tag, 0, tag_length);
2569 return status;
2570 }
2571 if (length < 16) {
2572 *output_length = length;
2573 } else {
2574 *output_length = 0;
2575 }
2576 return SL_STATUS_OK;
2577 }
2578
2579 // Construct GCM LenA || LenC block into temporary buffer
2580 tmpbuf[0] = __REV(gcm_ctx->add_len >> 29);
2581 tmpbuf[1] = __REV((gcm_ctx->add_len << 3) & 0xFFFFFFFFUL);
2582 tmpbuf[2] = __REV(gcm_ctx->len >> 29);
2583 tmpbuf[3] = __REV((gcm_ctx->len << 3) & 0xFFFFFFFFUL);
2584
2585 SE_DataTransfer_t data_in =
2586 SE_DATATRANSFER_DEFAULT(gcm_ctx->final_data, length);
2587
2588 #if defined(SLI_SE_MAJOR_VERSION_ONE)
2589 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT((length % 16 != 0 || length == 0) ? gcm_ctx->se_ctx : gcm_ctx->previous_se_ctx, sizeof(gcm_ctx->previous_se_ctx));
2590 #else
2591 SE_DataTransfer_t iv_ctx_in = SE_DATATRANSFER_DEFAULT(gcm_ctx->se_ctx, sizeof(gcm_ctx->se_ctx));
2592 #endif
2593
2594 SE_DataTransfer_t lenalenc_in = SE_DATATRANSFER_DEFAULT(&tmpbuf[0],
2595 sizeof(tmpbuf));
2596
2597 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, length);
2598 if (length == 16) {
2599 data_out.data = NULL;
2600 data_out.length |= SE_DATATRANSFER_DISCARD;
2601 }
2602
2603 SE_DataTransfer_t gcm_tag = SE_DATATRANSFER_DEFAULT(tag, tag_length);
2604
2605 sli_se_command_init(cmd_ctx,
2606 (gcm_ctx->mode == SL_SE_DECRYPT ? SLI_SE_COMMAND_AES_GCM_DECRYPT
2607 : SLI_SE_COMMAND_AES_GCM_ENCRYPT)
2608 | tag_length << 8 | SLI_SE_COMMAND_OPTION_CONTEXT_END);
2609
2610 sli_add_key_parameters(cmd_ctx, key, status);
2611 SE_addParameter(se_cmd, 0);
2612 SE_addParameter(se_cmd, length);
2613
2614 sli_add_key_metadata(cmd_ctx, key, status);
2615 sli_add_key_input(cmd_ctx, key, status);
2616
2617 SE_addDataInput(se_cmd, &iv_ctx_in);
2618 SE_addDataInput(se_cmd, &data_in);
2619 SE_addDataInput(se_cmd, &lenalenc_in);
2620
2621 if (gcm_ctx->mode == SL_SE_DECRYPT) {
2622 SE_addDataInput(se_cmd, &gcm_tag);
2623 }
2624
2625 SE_addDataOutput(se_cmd, &data_out);
2626
2627 if (gcm_ctx->mode == SL_SE_ENCRYPT) {
2628 SE_addDataOutput(se_cmd, &gcm_tag);
2629 }
2630
2631 status = sli_se_execute_and_wait(cmd_ctx);
2632
2633 if (status != SL_STATUS_OK) {
2634 if (gcm_ctx->mode == SL_SE_ENCRYPT) {
2635 memset(tag, 0, tag_length);
2636 }
2637 *output_length = 0;
2638 return status;
2639 }
2640
2641 if (length < 16) {
2642 *output_length = length;
2643 } else {
2644 *output_length = 0;
2645 }
2646
2647 return SL_STATUS_OK;
2648 }
2649
2650 #if (defined(_SILICON_LABS_SECURITY_FEATURE) \
2651 && (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT))
2652 /***************************************************************************//**
2653 * ChaCha20 buffer encryption/decryption, as defined by RFC8439 section 2.4.
2654 ******************************************************************************/
2655 sl_status_t sl_se_chacha20_crypt(sl_se_command_context_t *cmd_ctx,
2656 sl_se_cipher_operation_t mode,
2657 const sl_se_key_descriptor_t *key,
2658 size_t length,
2659 const unsigned char initial_counter[4],
2660 const unsigned char nonce[12],
2661 const unsigned char *input,
2662 unsigned char *output)
2663 {
2664 if (cmd_ctx == NULL || key == NULL || initial_counter == NULL || nonce == NULL
2665 || input == NULL || output == NULL) {
2666 return SL_STATUS_INVALID_PARAMETER;
2667 }
2668
2669 if (key->type != SL_SE_KEY_TYPE_CHACHA20) {
2670 return SL_STATUS_INVALID_PARAMETER;
2671 }
2672
2673 SE_Command_t *se_cmd = &cmd_ctx->command;
2674 sl_status_t status;
2675
2676 sli_se_command_init(cmd_ctx,
2677 (mode == SL_SE_ENCRYPT
2678 ? SLI_SE_COMMAND_CHACHA20_ENCRYPT
2679 : SLI_SE_COMMAND_CHACHA20_DECRYPT)
2680 | SLI_SE_COMMAND_OPTION_CONTEXT_WHOLE);
2681
2682 // Add key parameters to command
2683 sli_add_key_parameters(cmd_ctx, key, status);
2684 // Message size (number of bytes)
2685 SE_addParameter(se_cmd, length);
2686
2687 // Add key metadata block to command
2688 sli_add_key_metadata(cmd_ctx, key, status);
2689 // Add key input block to command
2690 sli_add_key_input(cmd_ctx, key, status);
2691
2692 // Add initial counter to command
2693 SE_DataTransfer_t counter = SE_DATATRANSFER_DEFAULT(initial_counter, 4);
2694 SE_addDataInput(se_cmd, &counter);
2695
2696 // Add nonce/IV to command
2697 SE_DataTransfer_t iv = SE_DATATRANSFER_DEFAULT(nonce, 12);
2698 SE_addDataInput(se_cmd, &iv);
2699
2700 // Add input data to command
2701 SE_DataTransfer_t in = SE_DATATRANSFER_DEFAULT(input, length);
2702 SE_addDataInput(se_cmd, &in);
2703
2704 // Request output data from command
2705 SE_DataTransfer_t out = SE_DATATRANSFER_DEFAULT(output, length);
2706 SE_addDataOutput(se_cmd, &out);
2707
2708 return sli_se_execute_and_wait(cmd_ctx);
2709 }
2710
2711 /***************************************************************************//**
2712 * ChaCha20-Poly1305 authenticated encryption with additional data, as defined
2713 * by RFC8439 section 2.8.
2714 ******************************************************************************/
2715 sl_status_t sl_se_chacha20_poly1305_encrypt_and_tag(sl_se_command_context_t *cmd_ctx,
2716 const sl_se_key_descriptor_t *key,
2717 size_t length,
2718 const unsigned char nonce[12],
2719 const unsigned char *add, size_t add_len,
2720 const unsigned char *input,
2721 unsigned char *output,
2722 unsigned char *tag)
2723 {
2724 // Check input parameters.
2725 if (cmd_ctx == NULL || key == NULL || nonce == NULL
2726 || ((add_len > 0) && (add == NULL))
2727 || ((length > 0) && (input == NULL))) {
2728 return SL_STATUS_INVALID_PARAMETER;
2729 }
2730
2731 SE_Command_t *se_cmd = &cmd_ctx->command;
2732 sl_status_t status;
2733
2734 if (key->type != SL_SE_KEY_TYPE_CHACHA20) {
2735 return SL_STATUS_INVALID_PARAMETER;
2736 }
2737
2738 sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_CHACHAPOLY_ENCRYPT);
2739
2740 sli_add_key_parameters(cmd_ctx, key, status);
2741 SE_addParameter(se_cmd, add_len);
2742 SE_addParameter(se_cmd, length);
2743
2744 sli_add_key_metadata(cmd_ctx, key, status);
2745 sli_add_key_input(cmd_ctx, key, status);
2746
2747 SE_DataTransfer_t nonce_in = SE_DATATRANSFER_DEFAULT(nonce, 12);
2748 SE_addDataInput(se_cmd, &nonce_in);
2749
2750 SE_DataTransfer_t aad_in = SE_DATATRANSFER_DEFAULT(add, add_len);
2751 SE_addDataInput(se_cmd, &aad_in);
2752
2753 SE_DataTransfer_t data_in = SE_DATATRANSFER_DEFAULT(input, length);
2754 SE_addDataInput(se_cmd, &data_in);
2755
2756 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, length);
2757 if (output == NULL) {
2758 data_out.length |= SE_DATATRANSFER_DISCARD;
2759 }
2760 SE_addDataOutput(se_cmd, &data_out);
2761
2762 SE_DataTransfer_t mac_out = SE_DATATRANSFER_DEFAULT(tag, 16);
2763 if (tag == NULL) {
2764 mac_out.length |= SE_DATATRANSFER_DISCARD;
2765 }
2766 SE_addDataOutput(se_cmd, &mac_out);
2767
2768 // Execute AEAD operation.
2769 return sli_se_execute_and_wait(cmd_ctx);
2770 }
2771
2772 /***************************************************************************//**
2773 * ChaCha20-Poly1305 authenticated decryption with additional data, as defined
2774 * by RFC8439 section 2.8.
2775 ******************************************************************************/
2776 sl_status_t sl_se_chacha20_poly1305_auth_decrypt(sl_se_command_context_t *cmd_ctx,
2777 const sl_se_key_descriptor_t *key,
2778 size_t length,
2779 const unsigned char nonce[12],
2780 const unsigned char *add, size_t add_len,
2781 const unsigned char *input,
2782 unsigned char *output,
2783 const unsigned char tag[16])
2784 {
2785 // Check input parameters.
2786 if (cmd_ctx == NULL || key == NULL || nonce == NULL || tag == NULL
2787 || ((add_len > 0) && (add == NULL))
2788 || ((length > 0) && (input == NULL))) {
2789 return SL_STATUS_INVALID_PARAMETER;
2790 }
2791
2792 SE_Command_t *se_cmd = &cmd_ctx->command;
2793 sl_status_t status;
2794
2795 if (key->type != SL_SE_KEY_TYPE_CHACHA20) {
2796 return SL_STATUS_INVALID_PARAMETER;
2797 }
2798
2799 sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_CHACHAPOLY_DECRYPT);
2800
2801 sli_add_key_parameters(cmd_ctx, key, status);
2802 SE_addParameter(se_cmd, add_len);
2803 SE_addParameter(se_cmd, length);
2804
2805 sli_add_key_metadata(cmd_ctx, key, status);
2806 sli_add_key_input(cmd_ctx, key, status);
2807
2808 SE_DataTransfer_t nonce_in = SE_DATATRANSFER_DEFAULT(nonce, 12);
2809 SE_addDataInput(se_cmd, &nonce_in);
2810
2811 SE_DataTransfer_t aad_in = SE_DATATRANSFER_DEFAULT(add, add_len);
2812 SE_addDataInput(se_cmd, &aad_in);
2813
2814 SE_DataTransfer_t data_in = SE_DATATRANSFER_DEFAULT(input, length);
2815 SE_addDataInput(se_cmd, &data_in);
2816
2817 SE_DataTransfer_t mac_in = SE_DATATRANSFER_DEFAULT(tag, 16);
2818 SE_addDataInput(se_cmd, &mac_in);
2819
2820 SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(output, length);
2821 if (output == NULL) {
2822 data_out.length |= SE_DATATRANSFER_DISCARD;
2823 }
2824 SE_addDataOutput(se_cmd, &data_out);
2825
2826 // Execute AEAD operation.
2827 return sli_se_execute_and_wait(cmd_ctx);
2828 }
2829
2830 /***************************************************************************//**
2831 * Generate a MAC (message authentication code) for a given message, according
2832 * to RFC8439 section 2.8 but bypassing the encryption step.
2833 ******************************************************************************/
2834 sl_status_t sl_se_poly1305_genkey_tag(sl_se_command_context_t *cmd_ctx,
2835 const sl_se_key_descriptor_t *key,
2836 size_t length,
2837 const unsigned char nonce[12],
2838 const unsigned char *input,
2839 unsigned char *tag)
2840 {
2841 if (cmd_ctx == NULL || key == NULL || nonce == NULL || tag == NULL
2842 || ((length > 0) && (input == NULL))) {
2843 return SL_STATUS_INVALID_PARAMETER;
2844 }
2845
2846 if (key->type != SL_SE_KEY_TYPE_CHACHA20) {
2847 return SL_STATUS_INVALID_PARAMETER;
2848 }
2849
2850 SE_Command_t *se_cmd = &cmd_ctx->command;
2851 sl_status_t status;
2852
2853 sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_POLY1305_KEY_MAC);
2854
2855 // Add key parameters to command
2856 sli_add_key_parameters(cmd_ctx, key, status);
2857 // Message size (number of bytes)
2858 SE_addParameter(se_cmd, length);
2859
2860 // Add key metadata block to command
2861 sli_add_key_metadata(cmd_ctx, key, status);
2862 // Add key input block to command
2863 sli_add_key_input(cmd_ctx, key, status);
2864
2865 // Add nonce/IV to command
2866 SE_DataTransfer_t iv = SE_DATATRANSFER_DEFAULT(nonce, 12);
2867 SE_addDataInput(se_cmd, &iv);
2868
2869 // Add input data to command
2870 SE_DataTransfer_t in = SE_DATATRANSFER_DEFAULT(input, length);
2871 SE_addDataInput(se_cmd, &in);
2872
2873 // Request tag from command
2874 SE_DataTransfer_t out = SE_DATATRANSFER_DEFAULT(tag, 16);
2875 SE_addDataOutput(se_cmd, &out);
2876
2877 return sli_se_execute_and_wait(cmd_ctx);
2878 }
2879 #endif
2880
2881 /** @} (end addtogroup sl_se) */
2882
2883 #endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
2884