1 /***************************************************************************//**
2  * @file
3  * @brief Silicon Labs Secure Engine Manager key handling.
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 <string.h>
32 #include "sl_se_manager.h"
33 
34 #if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
35 
36 #include "sli_se_manager_internal.h"
37 #include "sl_se_manager_key_handling.h"
38 
39 /***************************************************************************//**
40  * \addtogroup sl_se_key SE key handling API
41  * @{
42  ******************************************************************************/
43 
44 // -----------------------------------------------------------------------------
45 // Defines
46 
47 #define KEYSPEC_TYPE_MASK                   0xf0000000
48 #define KEYSPEC_TYPE_OFFSET                 28
49 #define KEYSPEC_TYPE_RAW                    (uint32_t)(0x0UL << KEYSPEC_TYPE_OFFSET)
50 
51 #define KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME  (uint32_t)(0x8UL << KEYSPEC_TYPE_OFFSET)
52 
53 #define KEYSPEC_MODE_MASK                   0x0c000000
54 #define KEYSPEC_MODE_OFFSET                 26
55 #define KEYSPEC_MODE_UNPROTECTED            (0UL << KEYSPEC_MODE_OFFSET)
56 #define KEYSPEC_MODE_VOLATILE               (1UL << KEYSPEC_MODE_OFFSET)
57 
58 #define KEYSPEC_RESTRICTION_MASK            0x03000000U
59 #define KEYSPEC_RESTRICTION_OFFSET          24U
60 
61 #define KEYSPEC_RESTRICTION_UNLOCKED        (0U << KEYSPEC_RESTRICTION_OFFSET)
62 
63 #define KEYSPEC_INDEX_MASK                  0x00ff0000U
64 #define KEYSPEC_INDEX_OFFSET                16U
65 
66 #define KEYSPEC_TRANSFER_MODE_MASK          0x00000300U
67 #define KEYSPEC_TRANSFER_MODE_OFFSET        8U
68 #define KEYSPEC_TRANSFER_INDEX_MASK         0x000000ffU
69 #define KEYSPEC_TRANSFER_INDEX_OFFSET       0U
70 #define KEYSPEC_TRANSFER_PROT_BIT_MASK      0xffe00000U
71 #define KEYSPEC_TRANSFER_PROT_BIT_OFFSET    21U
72 
73 #define KEYSPEC_NOPROT_MASK                 0x00008000U
74 #define KEYSPEC_NOPROT_OFFSET               15U
75 
76 #define KEYSPEC_ATTRIBUTES_MASK             0x00007fffU
77 #define KEYSPEC_ATTRIBUTES_OFFSET           0U
78 
79 #define KEYSPEC_ATTRIBUTES_ECC_PRIVATE_MASK (1U << 14)
80 #define KEYSPEC_ATTRIBUTES_ECC_PUBLIC_MASK  (1U << 13)
81 #define KEYSPEC_ATTRIBUTES_ECC_DOMAIN       (1U << 12)
82 #define KEYSPEC_ATTRIBUTES_ECC_SIGN         (1U << 10)
83 #define KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK    0x0000007fU
84 
85 #define KEYSPEC_TYPE_ECC_EDWARDS    ((uint32_t)(0xaUL << KEYSPEC_TYPE_OFFSET))
86 #define KEYSPEC_TYPE_ECC_MONTGOMERY ((uint32_t)(0xbUL << KEYSPEC_TYPE_OFFSET))
87 #define KEYSPEC_TYPE_ECC_EDDSA      ((uint32_t)(0xcUL << KEYSPEC_TYPE_OFFSET))
88 
89 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
90 
91   #define KEYSPEC_MODE_WRAPPED \
92   (2UL << KEYSPEC_MODE_OFFSET)
93 
94   #define KEYSPEC_ECC_WEIERSTRASS_PRIME_A_IS_ZERO \
95   (1U << 9)
96   #define KEYSPEC_ECC_WEIERSTRASS_PRIME_A_IS_MINUS_THREE \
97   (1U << 8)
98 
99 #endif
100 
101 #define KEYSPEC_RESTRICTION_LOCKED          (1UL << KEYSPEC_RESTRICTION_OFFSET)
102 #define KEYSPEC_RESTRICTION_INTERNAL        (2UL << KEYSPEC_RESTRICTION_OFFSET)
103 #define KEYSPEC_RESTRICTION_RESTRICTED      (3UL << KEYSPEC_RESTRICTION_OFFSET)
104 
105 // -----------------------------------------------------------------------------
106 // Local Functions
107 
sli_key_get_storage_size(const sl_se_key_descriptor_t * key,uint32_t * storage_size)108 sl_status_t sli_key_get_storage_size(const sl_se_key_descriptor_t* key,
109                                      uint32_t *storage_size)
110 {
111   if (key == NULL || storage_size == NULL) {
112     return SL_STATUS_INVALID_PARAMETER;
113   }
114 
115   uint32_t key_size = 0;
116   sl_status_t status = sli_key_get_size(key, &key_size);
117   if (status != SL_STATUS_OK) {
118     return status;
119   }
120 
121   uint32_t key_type = (key->type & KEYSPEC_TYPE_MASK);
122 
123   #if defined(SLI_SE_KEY_PADDING_REQUIRED)
124   // Round up to word length
125   key_size = (key_size + 3U) & ~0x03U;
126   #endif
127 
128   if (key_type == KEYSPEC_TYPE_RAW) {
129     *storage_size = key_size;
130     return SL_STATUS_OK;
131   }
132 
133   bool has_private_key =
134     ((key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY) != 0);
135   bool has_public_key =
136     ((key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY) != 0);
137 
138   #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
139   bool has_custom_curve =
140     ((key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_USES_CUSTOM_DOMAIN) != 0);
141   #else
142   bool has_custom_curve = false;
143   #endif
144 
145   if ((key_type == KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME)) {
146     *storage_size = key_size * (1 * has_private_key + 2 * has_public_key + 6 * has_custom_curve);
147   } else if (key_type == KEYSPEC_TYPE_ECC_EDWARDS) {
148     *storage_size = key_size * (has_private_key + has_public_key + 5 * has_custom_curve);
149   } else if ((key_type == KEYSPEC_TYPE_ECC_MONTGOMERY)
150              || (key_type == KEYSPEC_TYPE_ECC_EDDSA)) {
151     *storage_size = key_size * (has_private_key + has_public_key);
152   } else {
153     return SL_STATUS_INVALID_PARAMETER;
154   }
155 
156   return SL_STATUS_OK;
157 }
158 
159 #if defined(SLI_SE_KEY_PADDING_REQUIRED)
160 /***************************************************************************//**
161  * @brief
162  *   Clear the additional bytes of a key that is not word-aligned.
163  *   Does nothing for aligned or asymmetric keys, or non-plaintext keys.
164  *
165  * @param key
166  *   Key descriptor for the key.
167  *
168  * @returns
169  *   Status code, @ref sl_status.h.
170  ******************************************************************************/
clear_padding(const sl_se_key_descriptor_t * key)171 static sl_status_t clear_padding(const sl_se_key_descriptor_t *key)
172 {
173   if (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT
174       && (key->type & KEYSPEC_TYPE_MASK) == KEYSPEC_TYPE_RAW) {
175     uint32_t key_size = 0;
176     if (sli_key_get_size(key, &key_size) != SL_STATUS_OK) {
177       return SL_STATUS_INVALID_PARAMETER;
178     }
179     if (key_size & 0x03) {
180       if (key_size > key->storage.location.buffer.size) {
181         return SL_STATUS_WOULD_OVERFLOW;
182       }
183       uint8_t *padding_ptr = key->storage.location.buffer.pointer + key_size;
184       uint32_t padding_size = (key->storage.location.buffer.size - key_size) & 0x3;
185       memset(padding_ptr, 0, padding_size);
186     }
187   }
188   return SL_STATUS_OK;
189 }
190 #endif
191 
192 // -----------------------------------------------------------------------------
193 // Global Functions
194 
sli_key_get_size(const sl_se_key_descriptor_t * key,uint32_t * size)195 sl_status_t sli_key_get_size(const sl_se_key_descriptor_t *key, uint32_t *size)
196 {
197   if (key == NULL || size == NULL) {
198     return SL_STATUS_INVALID_PARAMETER;
199   }
200 
201   // Find size from key_type
202   uint32_t key_type = (key->type & KEYSPEC_TYPE_MASK);
203   if (key_type == KEYSPEC_TYPE_RAW) {
204     *size = (key->type & KEYSPEC_ATTRIBUTES_MASK);
205   } else if ((key_type == KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME)
206              || (key_type == KEYSPEC_TYPE_ECC_EDWARDS)
207              || (key_type == KEYSPEC_TYPE_ECC_MONTGOMERY)
208              || (key_type == KEYSPEC_TYPE_ECC_EDDSA)) {
209 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
210     bool has_custom_curve =
211       ((key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_USES_CUSTOM_DOMAIN) != 0);
212 #endif
213 
214 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
215     if (has_custom_curve) {
216       if (key->domain == NULL) {
217         return SL_STATUS_INVALID_PARAMETER;
218       }
219       if (key->type & SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM) {
220         sl_se_custom_weierstrass_prime_domain_t *domain = (sl_se_custom_weierstrass_prime_domain_t*)key->domain;
221         *size = domain->size;
222       } else {
223         return SL_STATUS_NOT_SUPPORTED;
224       }
225     } else
226 #endif
227     {
228       *size = (key->type & KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK);
229     }
230   } else {
231     return SL_STATUS_INVALID_PARAMETER;
232   }
233 
234 // If the key type didn't contain a size, use the one in the dedicated size
235 // field
236   if (*size == 0) {
237     if (key->size == 0) {
238       return SL_STATUS_INVALID_PARAMETER;
239     }
240     *size = key->size;
241   }
242 
243   return SL_STATUS_OK;
244 }
245 
sli_key_check_equivalent(const sl_se_key_descriptor_t * key_1,const sl_se_key_descriptor_t * key_2,bool check_key_flag,bool public_export)246 sl_status_t sli_key_check_equivalent(const sl_se_key_descriptor_t *key_1,
247                                      const sl_se_key_descriptor_t *key_2,
248                                      bool check_key_flag,
249                                      bool public_export)
250 {
251   sl_status_t status;
252 
253   if (key_1 == NULL || key_2 == NULL) {
254     return SL_STATUS_INVALID_PARAMETER;
255   }
256 
257   if (key_1->type != key_2->type) {
258     // The type fields are different, but this may be due to one of the keys
259     // not containing the size in the type, but rather in the size field.
260     if (((key_1->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
261          == SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM)
262         || ((key_1->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
263             == SL_SE_KEY_TYPE_ECC_EDDSA)) {
264       if ((key_1->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
265           == (key_2->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)) {
266         // Assume that the sizes are equal for now (this will be checked later)
267         uint32_t key_size = 0;
268         if (sli_key_get_size(key_1, &key_size) == SL_STATUS_OK) {
269           // Add the key sizes to both key types, and check for equality then
270           sl_se_key_type_t type_1 = key_1->type | (SL_SE_KEY_TYPE_ATTRIBUTES_MASK & key_size);
271           sl_se_key_type_t type_2 = key_2->type | (SL_SE_KEY_TYPE_ATTRIBUTES_MASK & key_size);
272           if (type_1 != type_2) {
273             return SL_STATUS_INVALID_PARAMETER;
274           }
275         } else {
276           return SL_STATUS_INVALID_PARAMETER;
277         }
278       }
279     } else {
280       return SL_STATUS_INVALID_PARAMETER;
281     }
282   }
283 
284   // Verify asymmetry flags
285   if ((key_1->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
286       >= KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME) {
287     uint32_t consistent_flags =
288       (public_export) ? SL_SE_KEY_FLAG_ASYMMETRIC_USES_CUSTOM_DOMAIN
289       : (SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY
290          | SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY
291          | SL_SE_KEY_FLAG_ASYMMETRIC_USES_CUSTOM_DOMAIN);
292     if (check_key_flag && (key_1->flags & consistent_flags) ^ (key_2->flags & consistent_flags)) {
293       return SL_STATUS_INVALID_PARAMETER;
294     }
295 
296     if (public_export
297         && (!(key_2->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY))) {
298       return SL_STATUS_INVALID_PARAMETER;
299     }
300   }
301 
302   // Verify key sizes
303   uint32_t key_1_size = 0;
304   status = sli_key_get_size(key_1, &key_1_size);
305   if (status != SL_STATUS_OK) {
306     return status;
307   }
308   uint32_t key_2_size = 0;
309   status = sli_key_get_size(key_2, &key_2_size);
310   if (status != SL_STATUS_OK) {
311     return status;
312   }
313 
314   if (key_1_size != key_2_size) {
315     return SL_STATUS_INVALID_PARAMETER;
316   }
317 
318   return SL_STATUS_OK;
319 }
320 
321 /***************************************************************************//**
322  * @brief
323  *   Convert key descriptor struct to a 32-bit keyspec value to pass into an SE
324  *   command.
325  *
326  * @return
327  *   Status code, @ref sl_status.h.
328  ******************************************************************************/
sli_se_key_to_keyspec(const sl_se_key_descriptor_t * key,uint32_t * keyspec)329 sl_status_t sli_se_key_to_keyspec(const sl_se_key_descriptor_t *key,
330                                   uint32_t *keyspec)
331 {
332   if (key == NULL || keyspec == NULL) {
333     return SL_STATUS_INVALID_PARAMETER;
334   }
335 
336   // Clear output
337   *keyspec = 0;
338 
339   // ---------------------
340   // Key type [31-28]
341 
342   *keyspec = (key->type & KEYSPEC_TYPE_MASK);
343 
344   // ---------------------
345   // Key mode [27-26]
346 
347   switch (key->storage.method) {
348     case SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT:
349       *keyspec |= KEYSPEC_MODE_UNPROTECTED;
350       break;
351 
352 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
353     case SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED:
354       *keyspec |= KEYSPEC_MODE_WRAPPED;
355       break;
356 
357     case SL_SE_KEY_STORAGE_INTERNAL_VOLATILE:
358       *keyspec |= KEYSPEC_MODE_VOLATILE;
359       break;
360 #endif
361 
362     case SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE:
363       *keyspec |= KEYSPEC_MODE_VOLATILE;
364       break;
365 
366     default:
367       return SL_STATUS_INVALID_PARAMETER;
368   }
369 
370   // ---------------------
371   // Key restriction [25-24]
372 
373   uint32_t keyspec_restriction = 0;
374   if (key->flags & SL_SE_KEY_FLAG_NON_EXPORTABLE) {
375     keyspec_restriction = KEYSPEC_RESTRICTION_LOCKED;
376   }
377   if (key->flags & SL_SE_KEY_FLAG_IS_DEVICE_GENERATED) {
378     keyspec_restriction = KEYSPEC_RESTRICTION_INTERNAL;
379   }
380   if ((key->flags & SL_SE_KEY_FLAG_IS_RESTRICTED) == SL_SE_KEY_FLAG_IS_RESTRICTED) {
381     keyspec_restriction = KEYSPEC_RESTRICTION_RESTRICTED;
382   }
383   // Key restrictions are only applicable to volatile and wrapped keys
384   if (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT) {
385     if (keyspec_restriction != 0) {
386       return SL_STATUS_INVALID_PARAMETER;
387     }
388   }
389 
390   *keyspec = (*keyspec & ~KEYSPEC_RESTRICTION_MASK)
391              | (keyspec_restriction & KEYSPEC_RESTRICTION_MASK);
392 
393   // ---------------------
394   // Key index [23-16]
395 
396 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
397   if (key->storage.method == SL_SE_KEY_STORAGE_INTERNAL_VOLATILE) {
398     if (key->storage.location.slot > SL_SE_KEY_SLOT_VOLATILE_3) {
399       return SL_STATUS_INVALID_PARAMETER;
400     }
401     *keyspec = (*keyspec & ~KEYSPEC_INDEX_MASK)
402                | ((key->storage.location.slot << KEYSPEC_INDEX_OFFSET)
403                   & KEYSPEC_INDEX_MASK);
404   }
405 #endif
406 
407   if (key->storage.method == SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE) {
408     if (key->storage.location.slot
409         < SL_SE_KEY_SLOT_INTERNAL_MIN) {
410       return SL_STATUS_INVALID_PARAMETER;
411     }
412     *keyspec = (*keyspec & ~KEYSPEC_INDEX_MASK)
413                | ((key->storage.location.slot << KEYSPEC_INDEX_OFFSET)
414                   & KEYSPEC_INDEX_MASK);
415   }
416 
417   // ---------------------
418   // Key NoProt [15]
419 
420   if (key->flags & SL_SE_KEY_FLAG_ALLOW_ANY_ACCESS) {
421     *keyspec = (*keyspec & ~KEYSPEC_NOPROT_MASK) | (1 << KEYSPEC_NOPROT_OFFSET);
422   }
423 
424   // ---------------------
425   // Key attributes [14-0]
426 
427   // Set general properties from key->type
428   if (key->storage.method != SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE) {
429     *keyspec = (*keyspec & ~KEYSPEC_ATTRIBUTES_MASK)
430                | (key->type & KEYSPEC_ATTRIBUTES_MASK);
431   }
432 
433   // Set public/private flags
434   bool has_private_key =
435     ((key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY) != 0);
436   bool has_public_key =
437     ((key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY) != 0);
438 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
439   bool has_custom_curve =
440     ((key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_USES_CUSTOM_DOMAIN) != 0);
441 #endif
442   bool signing_only =
443     ((key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY) != 0);
444 
445   if ((key->type & KEYSPEC_TYPE_MASK) >= KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME) {
446     if (has_private_key) {
447       *keyspec |= KEYSPEC_ATTRIBUTES_ECC_PRIVATE_MASK;
448     }
449     if (has_public_key) {
450       *keyspec |= KEYSPEC_ATTRIBUTES_ECC_PUBLIC_MASK;
451     }
452   #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
453     if (has_custom_curve) {
454       *keyspec |= KEYSPEC_ATTRIBUTES_ECC_DOMAIN;
455     }
456   #endif
457     if (!(has_private_key || has_public_key)) {
458       return SL_STATUS_INVALID_PARAMETER;
459     }
460   }
461 
462   if ((key->type & KEYSPEC_TYPE_MASK) >= KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME
463       && (key->type & KEYSPEC_TYPE_MASK) < KEYSPEC_TYPE_ECC_EDDSA) {
464     if (signing_only) {
465       *keyspec |= KEYSPEC_ATTRIBUTES_ECC_SIGN;
466     }
467   }
468 
469   // Ensure that symmetric keys don't have asymmetric flags
470   if ((key->type & KEYSPEC_TYPE_MASK) < KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME) {
471     if (has_private_key || has_public_key || signing_only) {
472       return SL_STATUS_INVALID_PARAMETER;
473     }
474   }
475 
476   // Set or adjust the key attributes for different key types
477   uint32_t size = 0;
478   sl_status_t status;
479   status = sli_key_get_size(key, &size);
480   if (status != SL_STATUS_OK) {
481     return status;
482   }
483 
484   // Symmetric and raw keys
485   uint32_t key_type = (key->type & KEYSPEC_TYPE_MASK);
486   if (key_type == KEYSPEC_TYPE_RAW) {
487     *keyspec = (*keyspec & ~KEYSPEC_ATTRIBUTES_MASK)
488                | (size & KEYSPEC_ATTRIBUTES_MASK);
489   } else if ((key_type == KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME)
490              || (key_type == KEYSPEC_TYPE_ECC_EDWARDS)
491              || (key_type == KEYSPEC_TYPE_ECC_MONTGOMERY)
492              || (key_type == KEYSPEC_TYPE_ECC_EDDSA)) {
493     *keyspec = (*keyspec & ~KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK)
494                | ((size - 1) & KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK);
495   } else {
496     return SL_STATUS_INVALID_PARAMETER;
497   }
498 
499   // Custom domain
500 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
501   if (has_custom_curve) {
502     if (key->domain == NULL) {
503       return SL_STATUS_INVALID_PARAMETER;
504     }
505     if (key_type == SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM) {
506       sl_se_custom_weierstrass_prime_domain_t *domain = (sl_se_custom_weierstrass_prime_domain_t*)key->domain;
507       if (domain->a_is_zero && signing_only) {
508         *keyspec |= KEYSPEC_ECC_WEIERSTRASS_PRIME_A_IS_ZERO;
509       }
510       if (domain->a_is_minus_three && signing_only) {
511         *keyspec |= KEYSPEC_ECC_WEIERSTRASS_PRIME_A_IS_MINUS_THREE;
512       }
513     } else {
514       return SL_STATUS_NOT_SUPPORTED;
515     }
516   }
517 #endif
518 
519   return SL_STATUS_OK;
520 }
521 
522 /***************************************************************************//**
523  * @brief
524  *   Convert a 32-bit SE compatible keyspec value to a key descriptor struct.
525  ******************************************************************************/
sli_se_keyspec_to_key(const uint32_t keyspec,sl_se_key_descriptor_t * key)526 sl_status_t sli_se_keyspec_to_key(const uint32_t keyspec,
527                                   sl_se_key_descriptor_t* key)
528 {
529   if (key == NULL) {
530     return SL_STATUS_INVALID_PARAMETER;
531   }
532 
533   // Clear output
534   key->type = 0;
535   key->storage.method = 0;
536   key->storage.location.slot = 0;
537   key->size = 0;
538   key->flags = 0;
539 
540   // ---------------------
541   // Key type [31-28]
542   key->type = keyspec & KEYSPEC_TYPE_MASK;
543 
544   // ---------------------
545   // Key mode [27-26] and key index [23-16]
546 
547   if ((keyspec & KEYSPEC_MODE_MASK) == KEYSPEC_MODE_UNPROTECTED) {
548     key->storage.method = SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT;
549   }
550 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
551   else if ((keyspec & KEYSPEC_MODE_MASK) == KEYSPEC_MODE_WRAPPED) {
552     key->storage.method = SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED;
553   }
554 #endif
555   else if ((keyspec & KEYSPEC_MODE_MASK) == KEYSPEC_MODE_VOLATILE) {
556     // Volatile can mean either internal-volatile or internal-immutable
557     // Check which is which based on key index
558     uint32_t key_index = (keyspec & KEYSPEC_INDEX_MASK) >> KEYSPEC_INDEX_OFFSET;
559 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
560     if (key_index <= SL_SE_KEY_SLOT_VOLATILE_3) {
561       key->storage.method = SL_SE_KEY_STORAGE_INTERNAL_VOLATILE;
562     } else
563 #endif
564     if ((key_index <= SL_SE_KEY_SLOT_APPLICATION_ATTESTATION_KEY)
565         && (key_index >= SL_SE_KEY_SLOT_INTERNAL_MIN)) {
566       key->storage.method = SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE;
567     } else {
568       return SL_STATUS_INVALID_PARAMETER;
569     }
570     key->storage.location.slot = key_index;
571   } else {
572     return SL_STATUS_INVALID_PARAMETER;
573   }
574 
575   // ---------------------
576   // Key restriction [25-24]
577 
578   uint32_t keyspec_restriction = (keyspec & KEYSPEC_RESTRICTION_MASK);
579   if (keyspec_restriction == KEYSPEC_RESTRICTION_LOCKED) {
580     key->flags |= SL_SE_KEY_FLAG_NON_EXPORTABLE;
581   } else if (keyspec_restriction == KEYSPEC_RESTRICTION_UNLOCKED) {
582     // no-op
583   }
584 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
585   else if (keyspec_restriction == KEYSPEC_RESTRICTION_INTERNAL) {
586     key->flags |= SL_SE_KEY_FLAG_IS_DEVICE_GENERATED;
587   } else if (keyspec_restriction == KEYSPEC_RESTRICTION_RESTRICTED) {
588     key->flags |= SL_SE_KEY_FLAG_IS_RESTRICTED;
589   }
590 #endif
591   else {
592     return SL_STATUS_INVALID_PARAMETER;
593   }
594 
595   // Key restrictions are only applicable to volatile and wrapped keys
596   if (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT) {
597     if (keyspec_restriction != 0) {
598       return SL_STATUS_INVALID_PARAMETER;
599     }
600   }
601 
602   // ---------------------
603   // Key NoProt [15]
604 
605   if ((keyspec & KEYSPEC_NOPROT_MASK) == (1 << KEYSPEC_NOPROT_OFFSET)) {
606     key->flags |= SL_SE_KEY_FLAG_ALLOW_ANY_ACCESS;
607   }
608 
609   // ---------------------
610   // Key attributes [14-0]
611 
612   // Set public/private flags
613   bool has_private_key = ((keyspec & KEYSPEC_ATTRIBUTES_ECC_PRIVATE_MASK) != 0);
614   bool has_public_key = ((keyspec & KEYSPEC_ATTRIBUTES_ECC_PUBLIC_MASK) != 0);
615 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
616   bool has_custom_curve = ((keyspec & KEYSPEC_ATTRIBUTES_ECC_DOMAIN) != 0);
617 #endif
618   bool signing_only = ((keyspec & KEYSPEC_ATTRIBUTES_ECC_SIGN) != 0);
619 
620   if ((keyspec & KEYSPEC_TYPE_MASK) >= KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME) {
621     if (has_private_key) {
622       key->flags |= SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY;
623     }
624     if (has_public_key) {
625       key->flags |= SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY;
626     }
627 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
628     if (has_custom_curve) {
629       key->flags |= SL_SE_KEY_FLAG_ASYMMETRIC_USES_CUSTOM_DOMAIN;
630 
631       // TODO: custom curve parameter injection?
632       return SL_STATUS_NOT_SUPPORTED;
633     }
634 #endif
635     if (!(has_private_key || has_public_key)) {
636       return SL_STATUS_INVALID_PARAMETER;
637     }
638 
639     // For ECC keys, their length is encoded in the type
640     key->type = (key->type & ~SL_SE_KEY_TYPE_ATTRIBUTES_MASK) | ((keyspec & KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK) + 1);
641   }
642 
643   if ((keyspec & KEYSPEC_TYPE_MASK) >= KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME
644       && (keyspec & KEYSPEC_TYPE_MASK) < KEYSPEC_TYPE_ECC_EDDSA) {
645     if (signing_only) {
646       key->flags |= SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY;
647     }
648   }
649 
650   // Ensure that symmetric keys don't have asymmetric flags
651   if ((keyspec & KEYSPEC_TYPE_MASK) < KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME) {
652     if (has_private_key || has_public_key || signing_only) {
653       return SL_STATUS_INVALID_PARAMETER;
654     }
655 
656     key->size = keyspec & KEYSPEC_ATTRIBUTES_MASK;
657 
658     switch ((keyspec & KEYSPEC_ATTRIBUTES_MASK)) {
659       case SL_SE_KEY_TYPE_AES_128:
660       case SL_SE_KEY_TYPE_AES_192:
661       case SL_SE_KEY_TYPE_AES_256:
662         key->type = keyspec & (KEYSPEC_TYPE_MASK | KEYSPEC_ATTRIBUTES_MASK);
663         break;
664       default:
665         break;
666     }
667   }
668 
669   return SL_STATUS_OK;
670 }
671 
672 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
673 static const uint32_t default_auth_data[2] = { 0 };
674 #endif
675 
sli_se_get_auth_buffer(const sl_se_key_descriptor_t * key,sli_se_datatransfer_t * auth_buffer)676 sl_status_t sli_se_get_auth_buffer(const sl_se_key_descriptor_t *key,
677                                    sli_se_datatransfer_t *auth_buffer)
678 {
679   if (key == NULL || auth_buffer == NULL) {
680     return SL_STATUS_INVALID_PARAMETER;
681   }
682 
683   auth_buffer->next = (void*)SLI_SE_DATATRANSFER_STOP;
684 
685 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
686   if ((key->storage.method == SL_SE_KEY_STORAGE_INTERNAL_VOLATILE)
687       || (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED)) {
688     if (key->password) {
689       auth_buffer->data = key->password;
690       auth_buffer->length = sizeof(default_auth_data) | SLI_SE_DATATRANSFER_REALIGN;
691     } else {
692       auth_buffer->data = (void*)default_auth_data;
693       auth_buffer->length = sizeof(default_auth_data) | SLI_SE_DATATRANSFER_REALIGN;
694     }
695   } else {
696     auth_buffer->length = 0 | SLI_SE_DATATRANSFER_REALIGN;
697   }
698 #else
699   (void)key;
700   auth_buffer->length = 0 | SLI_SE_DATATRANSFER_REALIGN;
701 #endif
702 
703   return SL_STATUS_OK;
704 }
705 
sli_se_get_key_input_output(const sl_se_key_descriptor_t * key,sli_se_datatransfer_t * buffer)706 sl_status_t sli_se_get_key_input_output(const sl_se_key_descriptor_t *key,
707                                         sli_se_datatransfer_t *buffer)
708 {
709   if (key == NULL || buffer == NULL) {
710     return SL_STATUS_INVALID_PARAMETER;
711   }
712 
713   buffer->next = (void*)SLI_SE_DATATRANSFER_STOP;
714 
715   if ((key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT)
716 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
717       || (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED)
718 #endif
719       ) {
720     // Set or adjust the key attributes for different key types
721     uint32_t storage_size = 0;
722     sl_status_t status = sli_key_get_storage_size(key, &storage_size);
723     if (status != SL_STATUS_OK) {
724       return status;
725     }
726 
727     uint32_t total_storage_size = 0;
728     if (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT) {
729       total_storage_size = storage_size;
730     }
731 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
732     else if (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED) {
733       total_storage_size = storage_size + SLI_SE_WRAPPED_KEY_OVERHEAD;
734     }
735 #endif
736 
737     if (total_storage_size > key->storage.location.buffer.size) {
738       return SL_STATUS_WOULD_OVERFLOW;
739     }
740 
741     buffer->data = key->storage.location.buffer.pointer;
742     buffer->length = total_storage_size | SLI_SE_DATATRANSFER_REALIGN;
743   } else if ((key->storage.method == SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE)
744 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
745              || (key->storage.method == SL_SE_KEY_STORAGE_INTERNAL_VOLATILE)
746 #endif
747              ) {
748     buffer->length = 0;
749   } else {
750     return SL_STATUS_INVALID_PARAMETER;
751   }
752 
753   return SL_STATUS_OK;
754 }
755 
756 /***************************************************************************//**
757  * Validate key descriptor.
758  ******************************************************************************/
sl_se_validate_key(const sl_se_key_descriptor_t * key)759 sl_status_t sl_se_validate_key(const sl_se_key_descriptor_t *key)
760 {
761   sl_status_t status = SL_STATUS_OK;
762   uint32_t keyspec = 0;
763 
764   if (key == NULL) {
765     return SL_STATUS_INVALID_PARAMETER;
766   }
767 
768   status = sli_se_key_to_keyspec(key, &keyspec);
769   if (status != SL_STATUS_OK) {
770     return status;
771   }
772 
773   sli_se_datatransfer_t auth_buffer;
774   status = sli_se_get_auth_buffer(key, &auth_buffer);
775   if (status != SL_STATUS_OK) {
776     return status;
777   }
778 
779   sli_se_datatransfer_t key_buffer;
780   status = sli_se_get_key_input_output(key, &key_buffer);
781   if (status != SL_STATUS_OK) {
782     return status;
783   }
784 
785   return status;
786 }
787 
788 /***************************************************************************//**
789  * Generate a random key adhering to the given key descriptor
790  ******************************************************************************/
sl_se_generate_key(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key_out)791 sl_status_t sl_se_generate_key(sl_se_command_context_t *cmd_ctx,
792                                const sl_se_key_descriptor_t *key_out)
793 {
794   sl_status_t status;
795 
796   if (cmd_ctx == NULL || key_out == NULL) {
797     return SL_STATUS_INVALID_PARAMETER;
798   }
799 
800   // Initialize command
801   sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_CREATE_KEY);
802 
803   // Add key parameters to command
804   sli_add_key_parameters(cmd_ctx, key_out, status);
805 
806 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
807   sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
808   // Custom curve domain
809   sli_se_datatransfer_t domain_p_buffer;
810   sli_se_datatransfer_t domain_N_buffer;
811   sli_se_datatransfer_t domain_Gx_buffer;
812   sli_se_datatransfer_t domain_Gy_buffer;
813   sli_se_datatransfer_t domain_a_buffer;
814   sli_se_datatransfer_t domain_b_buffer;
815 
816   if (key_out->flags & SL_SE_KEY_FLAG_ASYMMETRIC_USES_CUSTOM_DOMAIN) {
817     if (key_out->type & SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM) {
818       sl_se_custom_weierstrass_prime_domain_t *domain = (sl_se_custom_weierstrass_prime_domain_t*)key_out->domain;
819       uint32_t domain_size = domain->size;
820 
821       domain_p_buffer.next = (void*)SLI_SE_DATATRANSFER_STOP;
822       domain_p_buffer.data = (void*)domain->p;
823       domain_p_buffer.length = domain_size;
824       sli_se_mailbox_command_add_input(se_cmd, (sli_se_datatransfer_t*)&domain_p_buffer);
825 
826       domain_N_buffer.next = (void*)SLI_SE_DATATRANSFER_STOP;
827       domain_N_buffer.data = (void*)domain->N;
828       domain_N_buffer.length = domain_size;
829       sli_se_mailbox_command_add_input(se_cmd, (sli_se_datatransfer_t*)&domain_N_buffer);
830 
831       domain_Gx_buffer.next = (void*)SLI_SE_DATATRANSFER_STOP;
832       domain_Gx_buffer.data = (void*)domain->Gx;
833       domain_Gx_buffer.length = domain_size;
834       sli_se_mailbox_command_add_input(se_cmd, (sli_se_datatransfer_t*)&domain_Gx_buffer);
835 
836       domain_Gy_buffer.next = (void*)SLI_SE_DATATRANSFER_STOP;
837       domain_Gy_buffer.data = (void*)domain->Gy;
838       domain_Gy_buffer.length = domain_size;
839       sli_se_mailbox_command_add_input(se_cmd, (sli_se_datatransfer_t*)&domain_Gy_buffer);
840 
841       domain_a_buffer.next = (void*)SLI_SE_DATATRANSFER_STOP;
842       domain_a_buffer.data = (void*)domain->a;
843       domain_a_buffer.length = domain_size;
844       sli_se_mailbox_command_add_input(se_cmd, (sli_se_datatransfer_t*)&domain_a_buffer);
845 
846       domain_b_buffer.next = (void*)SLI_SE_DATATRANSFER_STOP;
847       domain_b_buffer.data = (void*)domain->b;
848       domain_b_buffer.length = domain_size;
849       sli_se_mailbox_command_add_input(se_cmd, (sli_se_datatransfer_t*)&domain_b_buffer);
850     } else {
851       return SL_STATUS_NOT_SUPPORTED;
852     }
853   }
854 #endif
855 
856   // Add key metadata block to command
857   sli_add_key_metadata(cmd_ctx, key_out, status);
858   // Add key output block to command
859   sli_add_key_output(cmd_ctx, key_out, status);
860 
861   // Execute command
862   status = sli_se_execute_and_wait(cmd_ctx);
863 
864   #if defined(SLI_SE_KEY_PADDING_REQUIRED)
865   // Clear padding for plaintext keys upon success
866   if (status == SL_STATUS_OK) {
867     status = clear_padding(key_out);
868   }
869   #endif
870 
871   return status;
872 }
873 
874 /***************************************************************************//**
875  * Export the public key of an ECC keypair
876  ******************************************************************************/
sl_se_export_public_key(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key_in,const sl_se_key_descriptor_t * key_out)877 sl_status_t sl_se_export_public_key(sl_se_command_context_t *cmd_ctx,
878                                     const sl_se_key_descriptor_t *key_in,
879                                     const sl_se_key_descriptor_t *key_out)
880 {
881   if (cmd_ctx == NULL || key_in == NULL || key_out == NULL) {
882     return SL_STATUS_INVALID_PARAMETER;
883   }
884 
885   sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
886   sl_status_t status;
887 
888   // Check input/output key type and size relationship
889   status = sli_key_check_equivalent(key_in, key_out, true, true);
890   if (status != SL_STATUS_OK) {
891     return status;
892   }
893 
894   // Check that the input key has a private or public key
895   if (!(key_in->flags & (SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY
896                          | SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY))) {
897     return SL_STATUS_INVALID_PARAMETER;
898   }
899   if (!(key_out->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY)
900       || (key_out->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY)) {
901     return SL_STATUS_INVALID_PARAMETER;
902   }
903 
904   // Initialize command
905   sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_READPUB_KEY);
906 
907   // Add key parameters to command
908   sli_add_key_parameters(cmd_ctx, key_in, status);
909   // Add key metadata block to command
910   sli_add_key_metadata(cmd_ctx, key_in, status);
911   // Add key input block to command
912   sli_add_key_input(cmd_ctx, key_in, status);
913 
914   // Pubkey buffer
915   // Check for correct storage and flags
916   if ((key_out->storage.method != SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT)
917       || (key_out->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY)
918       || !(key_out->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY)) {
919     return SL_STATUS_INVALID_PARAMETER;
920   }
921 
922   uint32_t required_storage_size;
923   status = sli_key_get_storage_size(key_out, &required_storage_size);
924   if (status != SL_STATUS_OK) {
925     return status;
926   }
927 
928   if (required_storage_size > key_out->storage.location.buffer.size) {
929     return SL_STATUS_WOULD_OVERFLOW;
930   }
931 
932   sli_se_datatransfer_t pubkey_buffer = SLI_SE_DATATRANSFER_DEFAULT(
933     key_out->storage.location.buffer.pointer, required_storage_size);
934   sli_se_mailbox_command_add_output(se_cmd, &pubkey_buffer);
935 
936   // Execute command.
937   // The retries are necessary in order to reduce the risk of random failures
938   // in the accelerated point multiplication. This mainly affects very small or
939   // large scalars, which in this case would be the private key.
940   for (size_t i = 0; i < SLI_SE_MAX_POINT_MULT_RETRIES; ++i) {
941     status = sli_se_execute_and_wait(cmd_ctx);
942     if (status != SL_STATUS_FAIL) {
943       break;
944     }
945   }
946   return status;
947 }
948 
949 /***************************************************************************//**
950  * Returns the required storage size for the given key
951  ******************************************************************************/
sl_se_get_storage_size(const sl_se_key_descriptor_t * key,uint32_t * storage_size)952 sl_status_t sl_se_get_storage_size(const sl_se_key_descriptor_t *key, uint32_t *storage_size)
953 {
954   if (key == NULL || storage_size == NULL) {
955     return SL_STATUS_INVALID_PARAMETER;
956   }
957 
958   if ((key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT)
959 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
960       || (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED)
961 #endif
962       ) {
963     // Set or adjust the key attributes for different key types
964     sl_status_t status = sli_key_get_storage_size(key, storage_size);
965     if (status != SL_STATUS_OK) {
966       return status;
967     }
968 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
969     if (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED) {
970       *storage_size = *storage_size + SLI_SE_WRAPPED_KEY_OVERHEAD;
971     }
972 #endif
973   } else if ((key->storage.method == SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE)
974 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
975              || (key->storage.method == SL_SE_KEY_STORAGE_INTERNAL_VOLATILE)
976 #endif
977              ) {
978     *storage_size = 0;
979   } else {
980     return SL_STATUS_INVALID_PARAMETER;
981   }
982 
983   return SL_STATUS_OK;
984 }
985 
986 #if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
987 /***************************************************************************//**
988  * Protect a plaintext key using the SE
989  ******************************************************************************/
sl_se_import_key(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key_in,const sl_se_key_descriptor_t * key_out)990 sl_status_t sl_se_import_key(sl_se_command_context_t *cmd_ctx,
991                              const sl_se_key_descriptor_t *key_in,
992                              const sl_se_key_descriptor_t *key_out)
993 {
994   sl_status_t status;
995 
996   if (cmd_ctx == NULL || key_in == NULL || key_out == NULL) {
997     return SL_STATUS_INVALID_PARAMETER;
998   }
999 
1000   // Check input/output key type and size relationship
1001   status = sli_key_check_equivalent(key_in, key_out, true, false);
1002   if (status != SL_STATUS_OK) {
1003     return status;
1004   }
1005 
1006   if ((key_in->storage.method != SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT)
1007       || ((key_out->storage.method != SL_SE_KEY_STORAGE_INTERNAL_VOLATILE)
1008           && (key_out->storage.method != SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED))) {
1009     return SL_STATUS_INVALID_PARAMETER;
1010   }
1011 
1012   // Initialize command
1013   sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_WRAP_KEY);
1014 
1015   // Add key parameters to command
1016   sli_add_key_parameters(cmd_ctx, key_out, status);
1017 
1018   // Add key input block to command
1019   sli_add_key_input(cmd_ctx, key_in, status);
1020 
1021   // Add key metadata block to command
1022   sli_add_key_metadata(cmd_ctx, key_out, status);
1023 
1024   // Add key output block to command
1025   sli_add_key_output(cmd_ctx, key_out, status);
1026 
1027   status = sli_se_execute_and_wait(cmd_ctx);
1028   return status;
1029 }
1030 
1031 /***************************************************************************//**
1032  * Export a volatile or wrapped key back to plaintext if allowed
1033  ******************************************************************************/
sl_se_export_key(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key_in,const sl_se_key_descriptor_t * key_out)1034 sl_status_t sl_se_export_key(sl_se_command_context_t *cmd_ctx,
1035                              const sl_se_key_descriptor_t *key_in,
1036                              const sl_se_key_descriptor_t *key_out)
1037 {
1038   sl_status_t status;
1039 
1040   if (cmd_ctx == NULL || key_in == NULL || key_out == NULL) {
1041     return SL_STATUS_INVALID_PARAMETER;
1042   }
1043 
1044   // Check input/output key type and size relationship
1045   status = sli_key_check_equivalent(key_in, key_out, true, false);
1046   if (status != SL_STATUS_OK) {
1047     return status;
1048   }
1049 
1050   if ((key_out->storage.method != SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT)
1051       || ((key_in->storage.method != SL_SE_KEY_STORAGE_INTERNAL_VOLATILE)
1052           && (key_in->storage.method != SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED))) {
1053     return SL_STATUS_INVALID_PARAMETER;
1054   }
1055 
1056   // Initialize command
1057   sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_UNWRAP_KEY);
1058 
1059   // Add key parameters to command
1060   sli_add_key_parameters(cmd_ctx, key_in, status);
1061 
1062   // Add key metadata block to command
1063   sli_add_key_metadata(cmd_ctx, key_in, status);
1064 
1065   // Add key input block to command
1066   sli_add_key_input(cmd_ctx, key_in, status);
1067 
1068   // Add key output block to command
1069   sli_add_key_output(cmd_ctx, key_out, status);
1070 
1071   status = sli_se_execute_and_wait(cmd_ctx);
1072 
1073   #if defined(SLI_SE_KEY_PADDING_REQUIRED)
1074   // The SE will only output word-aligned data. Clear the extra padding before
1075   // returning
1076   if (status == SL_STATUS_OK) {
1077     status = clear_padding(key_out);
1078   }
1079   #endif
1080 
1081   return status;
1082 }
1083 
1084 /***************************************************************************//**
1085  * Transfer a protected (volatile/wrapped) key
1086  ******************************************************************************/
sl_se_transfer_key(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key_in,const sl_se_key_descriptor_t * key_out)1087 sl_status_t sl_se_transfer_key(sl_se_command_context_t *cmd_ctx,
1088                                const sl_se_key_descriptor_t *key_in,
1089                                const sl_se_key_descriptor_t *key_out)
1090 {
1091   if (cmd_ctx == NULL || key_in == NULL || key_out == NULL) {
1092     return SL_STATUS_INVALID_PARAMETER;
1093   }
1094 
1095   sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
1096   sl_status_t status;
1097   sli_se_datatransfer_t auth_buffer_out;
1098   uint32_t key_update_index;
1099   uint32_t key_update_mode;
1100 
1101   // Check input/output key type and size relationship
1102   status = sli_key_check_equivalent(key_in, key_out, true, false);
1103   if (status != SL_STATUS_OK) {
1104     return status;
1105   }
1106 
1107   if ((key_in->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT)
1108       || (key_in->storage.method == SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE)
1109       || (key_out->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT)
1110       || (key_out->storage.method == SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE)) {
1111     return SL_STATUS_INVALID_PARAMETER;
1112   }
1113 
1114   // Create command
1115   sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_TRANSFER_KEY);
1116 
1117   // Add key input parameters to command
1118   sli_add_key_parameters(cmd_ctx, key_in, status);
1119 
1120   // Add key update parameters to command
1121   uint32_t keyspec_out;
1122   status = sli_se_key_to_keyspec(key_out, &keyspec_out);
1123   if (status != SL_STATUS_OK) {
1124     return status;
1125   }
1126   key_update_index = ((keyspec_out & KEYSPEC_INDEX_MASK) >> KEYSPEC_INDEX_OFFSET);
1127   key_update_mode = ((keyspec_out & KEYSPEC_MODE_MASK) >> KEYSPEC_MODE_OFFSET);
1128   keyspec_out = (keyspec_out & ~KEYSPEC_TRANSFER_INDEX_MASK)
1129                 | ((key_update_index << KEYSPEC_TRANSFER_INDEX_OFFSET)
1130                    & KEYSPEC_TRANSFER_INDEX_MASK);
1131   keyspec_out = (keyspec_out & ~KEYSPEC_TRANSFER_MODE_MASK)
1132                 | ((key_update_mode << KEYSPEC_TRANSFER_MODE_OFFSET)
1133                    & KEYSPEC_TRANSFER_MODE_MASK);
1134   keyspec_out = (keyspec_out & ~KEYSPEC_TRANSFER_PROT_BIT_MASK);
1135   sli_se_mailbox_command_add_parameter(se_cmd, keyspec_out);
1136 
1137   // Add key input metadata block to command
1138   sli_add_key_metadata(cmd_ctx, key_in, status);
1139   // Add key input block to command
1140   sli_add_key_input(cmd_ctx, key_in, status);
1141 
1142   // Add key output metadata block to command
1143   status = sli_se_get_auth_buffer(key_out, &auth_buffer_out);
1144   if (status != SL_STATUS_OK) {
1145     return status;
1146   }
1147   sli_se_mailbox_command_add_input(se_cmd, &auth_buffer_out);
1148 
1149   // Add key output block to command
1150   sli_add_key_output(cmd_ctx, key_out, status);
1151 
1152   status = sli_se_execute_and_wait(cmd_ctx);
1153 
1154   #if defined(SLI_SE_KEY_PADDING_REQUIRED)
1155   // Clear padding bytes for plaintext keys upon success
1156   if (status == SL_STATUS_OK) {
1157     status = clear_padding(key_out);
1158   }
1159   #endif
1160 
1161   return status;
1162 }
1163 
1164 /***************************************************************************//**
1165  * Delete a key a volatile SE storage slot
1166  ******************************************************************************/
sl_se_delete_key(sl_se_command_context_t * cmd_ctx,const sl_se_key_descriptor_t * key)1167 sl_status_t sl_se_delete_key(sl_se_command_context_t *cmd_ctx,
1168                              const sl_se_key_descriptor_t *key)
1169 {
1170   sl_status_t status;
1171 
1172   if (cmd_ctx == NULL || key == NULL) {
1173     return SL_STATUS_INVALID_PARAMETER;
1174   }
1175 
1176   // Initialize command
1177   sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_DELETE_KEY);
1178 
1179   // Add key parameters to command
1180   sli_add_key_parameters(cmd_ctx, key, status);
1181   // Add key metadata block to command
1182   sli_add_key_metadata(cmd_ctx, key, status);
1183 
1184   // Execute command
1185   status = sli_se_execute_and_wait(cmd_ctx);
1186   return status;
1187 }
1188 #endif
1189 
1190 /** @} (end addtogroup sl_se_key) */
1191 
1192 #endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
1193