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