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