2
* Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
6
* The code contained herein is licensed under the GNU General Public
7
* License. You may obtain a copy of the GNU General Public License
8
* Version 2 or later at the following locations:
10
* http://www.opensource.org/licenses/gpl-license.html
11
* http://www.gnu.org/copyleft/gpl.html
15
* @file fsl_shw_wrap.c
17
* This file implements Key-Wrap (Black Key) functions of the FSL SHW API for
20
* - Ownerid is an 8-byte, user-supplied, value to keep KEY confidential.
21
* - KEY is a 1-32 byte value which starts in SCC RED RAM before
22
* wrapping, and ends up there on unwrap. Length is limited because of
24
* - KEY' is the encrypted KEY
25
* - LEN is a 1-byte (for now) byte-length of KEY
26
* - ALG is a 1-byte value for the algorithm which which the key is
27
* associated. Values are defined by the FSL SHW API
28
* - Ownerid, LEN, and ALG come from the user's "key_info" object, as does the
29
* slot number where KEY already is/will be.
31
* - T' is the encrypted T
32
* - KEK is a Key-Encryption Key for the user's Key
33
* - ICV is the "Integrity Check Value" for the wrapped key
34
* - Black Key is the string of bytes returned as the wrapped key
36
<tr><TD align="right">BLACK_KEY <TD width="3">=<TD>ICV | T' | LEN | ALG |
38
<tr><td> </td></tr>
40
<tr><th>To Wrap</th></tr>
41
<tr><TD align="right">T</td> <TD width="3">=</td> <TD>RND()<sub>16</sub>
43
<tr><TD align="right">KEK</td><TD width="3">=</td><TD>HASH<sub>sha256</sub>(T |
44
Ownerid)<sub>16</sub></td></tr>
45
<tr><TD align="right">KEY'<TD width="3">=</td><TD>
46
AES<sub>ctr-enc</sub>(Key=KEK, CTR=0, Data=KEY)</td></tr>
47
<tr><TD align="right">ICV</td><TD width="3">=</td><td>HMAC<sub>sha256</sub>
48
(Key=T, Data=Ownerid | LEN | ALG | KEY')<sub>16</sub></td></tr>
49
<tr><TD align="right">T'</td><TD width="3">=</td><TD>TDES<sub>cbc-enc</sub>
50
(Key=SLID, IV=Ownerid, Data=T)</td></tr>
52
<tr><td> </td></tr>
54
<tr><th>To Unwrap</th></tr>
55
<tr><TD align="right">T</td><TD width="3">=</td><TD>TDES<sub>ecb-dec</sub>
56
(Key=SLID, IV=Ownerid, Data=T')</sub></td></tr>
57
<tr><TD align="right">ICV</td><TD width="3">=</td><td>HMAC<sub>sha256</sub>
58
(Key=T, Data=Ownerid | LEN | ALG | KEY')<sub>16</sub></td></tr>
59
<tr><TD align="right">KEK</td><TD width="3">=</td><td>HASH<sub>sha256</sub>
60
(T | Ownerid)<sub>16</sub></td></tr>
61
<tr><TD align="right">KEY<TD width="3">=</td><TD>AES<sub>ctr-dec</sub>
62
(Key=KEK, CTR=0, Data=KEY')</td></tr>
68
#include "fsl_platform.h"
69
#include "fsl_shw_keystore.h"
74
#if defined(DIAG_SECURITY_FUNC)
75
#include <diagnostic.h>
78
#if defined(NEED_CTR_WORKAROUND)
79
/* CTR mode needs block-multiple data in/out */
80
#define LENGTH_PATCH 16
81
#define LENGTH_PATCH_MASK 0xF
83
#define LENGTH_PATCH 4
84
#define LENGTH_PATCH_MASK 3
88
#define ROUND_LENGTH(len) \
90
uint32_t orig_len = len; \
93
if ((orig_len & LENGTH_PATCH_MASK) != 0) { \
94
new_len = (orig_len + LENGTH_PATCH \
95
- (orig_len & LENGTH_PATCH_MASK)); \
103
#define ROUND_LENGTH(len) (len)
107
EXPORT_SYMBOL(fsl_shw_establish_key);
108
EXPORT_SYMBOL(fsl_shw_extract_key);
109
EXPORT_SYMBOL(fsl_shw_release_key);
110
EXPORT_SYMBOL(fsl_shw_read_key);
113
#define ICV_LENGTH 16
115
#define KEK_LENGTH 16
116
#define LENGTH_LENGTH 1
117
#define ALGORITHM_LENGTH 1
118
#define FLAGS_LENGTH 1
120
/* ICV | T' | LEN | ALG | KEY' */
122
#define T_PRIME_OFFSET (ICV_OFFSET + ICV_LENGTH)
123
#define LENGTH_OFFSET (T_PRIME_OFFSET + T_LENGTH)
124
#define ALGORITHM_OFFSET (LENGTH_OFFSET + LENGTH_LENGTH)
125
#define FLAGS_OFFSET (ALGORITHM_OFFSET + ALGORITHM_LENGTH)
126
#define KEY_PRIME_OFFSET (FLAGS_OFFSET + FLAGS_LENGTH)
127
#define FLAGS_SW_KEY 0x01
130
* For testing of the algorithm implementation,, the DO_REPEATABLE_WRAP flag
131
* causes the T_block to go into the T field during a wrap operation. This
132
* will make the black key value repeatable (for a given SCC secret key, or
133
* always if the default key is in use).
135
* Normally, a random sequence is used.
137
#ifdef DO_REPEATABLE_WRAP
139
* Block of zeroes which is maximum Symmetric block size, used for
140
* initializing context register, etc.
142
static uint8_t T_block_[16] = {
143
0x42, 0, 0, 0x42, 0x42, 0, 0, 0x42,
144
0x42, 0, 0, 0x42, 0x42, 0, 0, 0x42
149
* Insert descriptors to calculate ICV = HMAC(key=T, data=LEN|ALG|KEY')
151
* @param user_ctx User's context for this operation
152
* @param desc_chain Descriptor chain to append to
153
* @param t_key_info T's key object
154
* @param black_key Beginning of Black Key region
155
* @param key_length Number of bytes of key' there are in @c black_key
156
* @param[out] hmac Location to store ICV. Will be tagged "USES" so
157
* sf routines will not try to free it.
159
* @return A return code of type #fsl_shw_return_t.
161
static inline fsl_shw_return_t create_icv_calc(fsl_shw_uco_t * user_ctx,
162
sah_Head_Desc ** desc_chain,
163
fsl_shw_sko_t * t_key_info,
164
const uint8_t * black_key,
168
fsl_shw_return_t sah_code;
170
sah_Link *link1 = NULL;
171
sah_Link *link2 = NULL;
173
/* Load up T as key for the HMAC */
174
header = (SAH_HDR_MDHA_SET_MODE_MD_KEY /* #6 */
175
^ sah_insert_mdha_algorithm_sha256
176
^ sah_insert_mdha_init ^ sah_insert_mdha_hmac ^
177
sah_insert_mdha_pdata ^ sah_insert_mdha_mac_full);
178
sah_code = sah_add_in_key_desc(header, NULL, 0, t_key_info, /* Reference T in RED */
179
user_ctx->mem_util, desc_chain);
180
if (sah_code != FSL_RETURN_OK_S) {
184
/* Previous step loaded key; Now set up to hash the data */
185
header = SAH_HDR_MDHA_HASH; /* #10 */
187
/* Input - start with ownerid */
188
sah_code = sah_Create_Link(user_ctx->mem_util, &link1,
189
(void *)&t_key_info->userid,
190
sizeof(t_key_info->userid),
192
if (sah_code != FSL_RETURN_OK_S) {
196
/* Still input - Append black-key fields len, alg, key' */
197
sah_code = sah_Append_Link(user_ctx->mem_util, link1,
198
(void *)black_key + LENGTH_OFFSET,
201
+ key_length), SAH_USES_LINK_DATA);
203
if (sah_code != FSL_RETURN_OK_S) {
206
/* Output - computed ICV/HMAC */
207
sah_code = sah_Create_Link(user_ctx->mem_util, &link2,
209
SAH_USES_LINK_DATA | SAH_OUTPUT_LINK);
210
if (sah_code != FSL_RETURN_OK_S) {
214
sah_code = sah_Append_Desc(user_ctx->mem_util, desc_chain,
215
header, link1, link2);
218
if (sah_code != FSL_RETURN_OK_S) {
219
(void)sah_Destroy_Link(user_ctx->mem_util, link1);
220
(void)sah_Destroy_Link(user_ctx->mem_util, link2);
224
} /* create_icv_calc */
227
* Perform unwrapping of a black key into a RED slot
229
* @param user_ctx A user context from #fsl_shw_register_user().
230
* @param[in,out] key_info The information about the key to be which will
231
* be unwrapped... key length, slot info, etc.
232
* @param black_key Encrypted key
234
* @return A return code of type #fsl_shw_return_t.
236
static fsl_shw_return_t unwrap(fsl_shw_uco_t * user_ctx,
237
fsl_shw_sko_t * key_info,
238
const uint8_t * black_key)
241
uint8_t *hmac = NULL;
242
fsl_shw_sko_t t_key_info;
243
sah_Link *link1 = NULL;
244
sah_Link *link2 = NULL;
246
unsigned rounded_key_length;
247
unsigned original_key_length = key_info->key_length;
249
hmac = DESC_TEMP_ALLOC(ICV_LENGTH);
251
/* Set up key_info for "T" - use same slot as eventual key */
252
fsl_shw_sko_init(&t_key_info, FSL_KEY_ALG_AES);
253
t_key_info.userid = key_info->userid;
254
t_key_info.handle = key_info->handle;
255
t_key_info.flags = key_info->flags;
256
t_key_info.key_length = T_LENGTH;
257
t_key_info.keystore = key_info->keystore;
259
/* Validate SW flags to prevent misuse */
260
if ((key_info->flags & FSL_SKO_KEY_SW_KEY)
261
&& !(black_key[FLAGS_OFFSET] & FLAGS_SW_KEY)) {
262
ret = FSL_RETURN_BAD_FLAG_S;
266
/* Compute T = SLID_decrypt(T'); leave in RED slot */
267
if (key_info->keystore == NULL) {
268
/* Key goes in system keystore */
269
ret = do_system_keystore_slot_decrypt(user_ctx,
273
black_key + T_PRIME_OFFSET);
276
/* Key goes in user keystore */
277
ret = keystore_slot_decrypt(user_ctx,
282
black_key + T_PRIME_OFFSET);
284
if (ret != FSL_RETURN_OK_S) {
288
/* Compute ICV = HMAC(T, ownerid | len | alg | key' */
289
ret = create_icv_calc(user_ctx, &desc_chain, &t_key_info,
290
black_key, original_key_length, hmac);
291
if (ret != FSL_RETURN_OK_S) {
292
#ifdef DIAG_SECURITY_FUNC
293
LOG_DIAG("Creation of sah_Key_Link failed due to bad key"
295
#endif /*DIAG_SECURITY_FUNC */
298
#ifdef DIAG_SECURITY_FUNC
299
LOG_DIAG("Validating MAC of wrapped key");
302
if (ret != FSL_RETURN_OK_S) {
307
/* Check computed ICV against value in Black Key */
308
for (i = 0; i < ICV_LENGTH; i++) {
309
if (black_key[ICV_OFFSET + i] != hmac[i]) {
310
#ifdef DIAG_SECURITY_FUNC
311
LOG_DIAG_ARGS("computed ICV fails at offset %i\n", i);
316
for (a = 0; a < ICV_LENGTH; a++)
317
sprintf(&(buff[a * 2]), "%02x",
318
black_key[ICV_OFFSET + a]);
320
LOG_DIAG_ARGS("black key: %s", buff);
322
for (a = 0; a < ICV_LENGTH; a++)
323
sprintf(&(buff[a * 2]), "%02x",
326
LOG_DIAG_ARGS("hmac: %s", buff);
329
ret = FSL_RETURN_AUTH_FAILED_S;
334
/* This is no longer needed. */
335
DESC_TEMP_FREE(hmac);
337
/* Compute KEK = SHA256(T | ownerid). Rewrite slot with value */
338
header = (SAH_HDR_MDHA_SET_MODE_HASH /* #8 */
339
^ sah_insert_mdha_init
340
^ sah_insert_mdha_algorithm_sha256 ^ sah_insert_mdha_pdata);
342
/* Input - Start with T */
343
ret = sah_Create_Key_Link(user_ctx->mem_util, &link1, &t_key_info);
344
if (ret != FSL_RETURN_OK_S) {
348
/* Still input - append ownerid */
349
ret = sah_Append_Link(user_ctx->mem_util, link1,
350
(void *)&key_info->userid,
351
sizeof(key_info->userid), SAH_USES_LINK_DATA);
352
if (ret != FSL_RETURN_OK_S) {
356
/* Output - KEK goes into RED slot */
357
ret = sah_Create_Key_Link(user_ctx->mem_util, &link2, &t_key_info);
358
if (ret != FSL_RETURN_OK_S) {
362
/* Put the Hash calculation into the chain. */
363
ret = sah_Append_Desc(user_ctx->mem_util, &desc_chain,
364
header, link1, link2);
365
if (ret != FSL_RETURN_OK_S) {
369
/* Compute KEY = AES-decrypt(KEK, KEY') */
370
header = (SAH_HDR_SKHA_SET_MODE_IV_KEY /* #1 */
371
^ sah_insert_skha_mode_ctr
372
^ sah_insert_skha_algorithm_aes
373
^ sah_insert_skha_modulus_128);
374
/* Load KEK in as the key to use */
375
DESC_IN_KEY(header, 0, NULL, &t_key_info);
377
rounded_key_length = ROUND_LENGTH(original_key_length);
378
key_info->key_length = rounded_key_length;
380
/* Now set up for computation. Result in RED */
381
header = SAH_HDR_SKHA_ENC_DEC; /* #4 */
382
DESC_IN_KEY(header, rounded_key_length, black_key + KEY_PRIME_OFFSET,
385
/* Perform the operation */
386
#ifdef DIAG_SECURITY_FUNC
387
LOG_DIAG("Decrypting key with KEK");
392
key_info->key_length = original_key_length;
395
DESC_TEMP_FREE(hmac);
398
t_key_info.userid = 0xdeadbeef;
399
t_key_info.handle = 0xdeadbeef;
405
* Perform wrapping of a black key from a RED slot
407
* @param user_ctx A user context from #fsl_shw_register_user().
408
* @param[in,out] key_info The information about the key to be which will
409
* be wrapped... key length, slot info, etc.
410
* @param black_key Place to store encrypted key
412
* @return A return code of type #fsl_shw_return_t.
414
static fsl_shw_return_t wrap(fsl_shw_uco_t * user_ctx,
415
fsl_shw_sko_t * key_info, uint8_t * black_key)
418
unsigned slots_allocated = 0; /* boolean */
419
fsl_shw_sko_t T_key_info; /* for holding T */
420
fsl_shw_sko_t KEK_key_info; /* for holding KEK */
421
unsigned original_key_length = key_info->key_length;
422
unsigned rounded_key_length;
426
black_key[LENGTH_OFFSET] = key_info->key_length;
427
black_key[ALGORITHM_OFFSET] = key_info->algorithm;
429
memcpy(&T_key_info, key_info, sizeof(T_key_info));
430
fsl_shw_sko_set_key_length(&T_key_info, T_LENGTH);
431
T_key_info.algorithm = FSL_KEY_ALG_HMAC;
433
memcpy(&KEK_key_info, &T_key_info, sizeof(KEK_key_info));
434
KEK_key_info.algorithm = FSL_KEY_ALG_AES;
436
if (key_info->keystore == NULL) {
437
/* Key goes in system keystore */
438
ret = do_system_keystore_slot_alloc(user_ctx,
439
T_LENGTH, key_info->userid,
443
/* Key goes in user keystore */
444
ret = keystore_slot_alloc(key_info->keystore,
446
key_info->userid, &T_key_info.handle);
448
if (ret != FSL_RETURN_OK_S) {
452
if (key_info->keystore == NULL) {
453
/* Key goes in system keystore */
454
ret = do_system_keystore_slot_alloc(user_ctx,
455
KEK_LENGTH, key_info->userid,
456
&KEK_key_info.handle);
459
/* Key goes in user keystore */
460
ret = keystore_slot_alloc(key_info->keystore,
461
KEK_LENGTH, key_info->userid,
462
&KEK_key_info.handle);
465
if (ret != FSL_RETURN_OK_S) {
466
#ifdef DIAG_SECURITY_FUNC
467
LOG_DIAG("do_scc_slot_alloc() failed");
469
if (key_info->keystore == NULL) {
470
/* Key goes in system keystore */
471
(void)do_system_keystore_slot_dealloc(user_ctx,
472
key_info->userid, T_key_info.handle);
475
/* Key goes in user keystore */
476
(void)keystore_slot_dealloc(key_info->keystore,
477
key_info->userid, T_key_info.handle);
483
/* Set up to compute everything except T' ... */
484
#ifndef DO_REPEATABLE_WRAP
485
/* Compute T = RND() */
486
header = SAH_HDR_RNG_GENERATE; /* Desc. #18 */
487
DESC_KEY_OUT(header, &T_key_info, 0, NULL);
489
if (key_info->keystore == NULL) {
490
/* Key goes in system keystore */
491
ret = do_system_keystore_slot_load(user_ctx,
493
T_key_info.handle, T_block,
494
T_key_info.key_length);
496
/* Key goes in user keystore */
497
ret = keystore_slot_load(key_info->keystore,
500
T_block, T_key_info.key_length);
503
if (ret != FSL_RETURN_OK_S) {
508
/* Compute KEK = SHA256(T | Ownerid) */
509
header = (SAH_HDR_MDHA_SET_MODE_HASH /* #8 */
510
^ sah_insert_mdha_init
511
^ sah_insert_mdha_algorithm[FSL_HASH_ALG_SHA256]
512
^ sah_insert_mdha_pdata);
513
/* Input - Start with T */
514
ret = sah_Create_Key_Link(user_ctx->mem_util, &link1, &T_key_info);
515
if (ret != FSL_RETURN_OK_S) {
518
/* Still input - append ownerid */
519
ret = sah_Append_Link(user_ctx->mem_util, link1,
520
(void *)&key_info->userid,
521
sizeof(key_info->userid), SAH_USES_LINK_DATA);
522
if (ret != FSL_RETURN_OK_S) {
525
/* Output - KEK goes into RED slot */
526
ret = sah_Create_Key_Link(user_ctx->mem_util, &link2, &KEK_key_info);
527
if (ret != FSL_RETURN_OK_S) {
530
/* Put the Hash calculation into the chain. */
531
ret = sah_Append_Desc(user_ctx->mem_util, &desc_chain,
532
header, link1, link2);
533
if (ret != FSL_RETURN_OK_S) {
536
#if defined(NEED_CTR_WORKAROUND)
537
rounded_key_length = ROUND_LENGTH(original_key_length);
538
key_info->key_length = rounded_key_length;
540
rounded_key_length = original_key_length;
542
/* Compute KEY' = AES-encrypt(KEK, KEY) */
543
header = (SAH_HDR_SKHA_SET_MODE_IV_KEY /* #1 */
544
^ sah_insert_skha_mode[FSL_SYM_MODE_CTR]
545
^ sah_insert_skha_algorithm[FSL_KEY_ALG_AES]
546
^ sah_insert_skha_modulus[FSL_CTR_MOD_128]);
547
/* Set up KEK as key to use */
548
DESC_IN_KEY(header, 0, NULL, &KEK_key_info);
549
header = SAH_HDR_SKHA_ENC_DEC;
550
DESC_KEY_OUT(header, key_info,
551
key_info->key_length, black_key + KEY_PRIME_OFFSET);
553
/* Set up flags info */
554
black_key[FLAGS_OFFSET] = 0;
555
if (key_info->flags & FSL_SKO_KEY_SW_KEY) {
556
black_key[FLAGS_OFFSET] |= FLAGS_SW_KEY;
559
/* Compute and store ICV into Black Key */
560
ret = create_icv_calc(user_ctx, &desc_chain, &T_key_info,
561
black_key, original_key_length,
562
black_key + ICV_OFFSET);
563
if (ret != FSL_RETURN_OK_S) {
564
#ifdef DIAG_SECURITY_FUNC
565
LOG_DIAG("Creation of sah_Key_Link failed due to bad key"
567
#endif /*DIAG_SECURITY_FUNC */
571
/* Now get Sahara to do the work. */
572
#ifdef DIAG_SECURITY_FUNC
573
LOG_DIAG("Encrypting key with KEK");
576
if (ret != FSL_RETURN_OK_S) {
577
#ifdef DIAG_SECURITY_FUNC
578
LOG_DIAG("sah_Descriptor_Chain_Execute() failed");
583
/* Compute T' = SLID_encrypt(T); Result goes to Black Key */
584
if (key_info->keystore == NULL) {
585
/* Key goes in system keystore */
586
ret = do_system_keystore_slot_encrypt(user_ctx,
587
T_key_info.userid, T_key_info.handle,
588
T_LENGTH, black_key + T_PRIME_OFFSET);
590
/* Key goes in user keystore */
591
ret = keystore_slot_encrypt(user_ctx,
596
black_key + T_PRIME_OFFSET);
599
if (ret != FSL_RETURN_OK_S) {
600
#ifdef DIAG_SECURITY_FUNC
601
LOG_DIAG("do_scc_slot_encrypt() failed");
607
key_info->key_length = original_key_length;
610
if (slots_allocated) {
611
if (key_info->keystore == NULL) {
612
/* Key goes in system keystore */
613
(void)do_system_keystore_slot_dealloc(user_ctx,
617
(void)do_system_keystore_slot_dealloc(user_ctx,
622
/* Key goes in user keystore */
623
(void)keystore_slot_dealloc(key_info->keystore,
626
(void)keystore_slot_dealloc(key_info->keystore,
628
KEK_key_info.handle);
636
* Place a key into a protected location for use only by cryptographic
639
* This only needs to be used to a) unwrap a key, or b) set up a key which
640
* could be wrapped with a later call to #fsl_shw_extract_key(). Normal
641
* cleartext keys can simply be placed into #fsl_shw_sko_t key objects with
642
* #fsl_shw_sko_set_key() and used directly.
644
* The maximum key size supported for wrapped/unwrapped keys is 32 octets.
645
* (This is the maximum reasonable key length on Sahara - 32 octets for an HMAC
646
* key based on SHA-256.) The key size is determined by the @a key_info. The
647
* expected length of @a key can be determined by
648
* #fsl_shw_sko_calculate_wrapped_size()
650
* The protected key will not be available for use until this operation
651
* successfully completes.
653
* This feature is not available for all platforms, nor for all algorithms and
656
* @param user_ctx A user context from #fsl_shw_register_user().
657
* @param[in,out] key_info The information about the key to be which will
658
* be established. In the create case, the key
659
* length must be set.
660
* @param establish_type How @a key will be interpreted to establish a
662
* @param key If @a establish_type is #FSL_KEY_WRAP_UNWRAP,
663
* this is the location of a wrapped key. If
664
* @a establish_type is #FSL_KEY_WRAP_CREATE, this
665
* parameter can be @a NULL. If @a establish_type
666
* is #FSL_KEY_WRAP_ACCEPT, this is the location
667
* of a plaintext key.
669
* @return A return code of type #fsl_shw_return_t.
671
fsl_shw_return_t fsl_shw_establish_key(fsl_shw_uco_t * user_ctx,
672
fsl_shw_sko_t * key_info,
673
fsl_shw_key_wrap_t establish_type,
677
unsigned original_key_length = key_info->key_length;
678
unsigned rounded_key_length;
679
unsigned slot_allocated = 0;
682
header = SAH_HDR_RNG_GENERATE; /* Desc. #18 for rand */
684
/* TODO: THIS STILL NEEDS TO BE REFACTORED */
686
/* Write operations into SCC memory require word-multiple number of
687
* bytes. For ACCEPT and CREATE functions, the key length may need
688
* to be rounded up. Calculate. */
689
if (LENGTH_PATCH && (original_key_length & LENGTH_PATCH_MASK) != 0) {
690
rounded_key_length = original_key_length + LENGTH_PATCH
691
- (original_key_length & LENGTH_PATCH_MASK);
693
rounded_key_length = original_key_length;
698
if (key_info->flags & FSL_SKO_KEY_ESTABLISHED) {
699
#ifdef DIAG_SECURITY_FUNC
700
ret = FSL_RETURN_BAD_FLAG_S;
701
LOG_DIAG("Key already established\n");
706
if (key_info->keystore == NULL) {
707
/* Key goes in system keystore */
708
ret = do_system_keystore_slot_alloc(user_ctx,
709
key_info->key_length,
711
&(key_info->handle));
712
#ifdef DIAG_SECURITY_FUNC
714
("key length: %i, handle: %i, rounded key length: %i",
715
key_info->key_length, key_info->handle,
720
/* Key goes in user keystore */
721
ret = keystore_slot_alloc(key_info->keystore,
722
key_info->key_length,
724
&(key_info->handle));
726
if (ret != FSL_RETURN_OK_S) {
727
#ifdef DIAG_SECURITY_FUNC
728
LOG_DIAG("Slot allocation failed\n");
734
key_info->flags |= FSL_SKO_KEY_ESTABLISHED;
735
switch (establish_type) {
736
case FSL_KEY_WRAP_CREATE:
737
#ifdef DIAG_SECURITY_FUNC
738
LOG_DIAG("Creating random key\n");
740
/* Use safe version of key length */
741
key_info->key_length = rounded_key_length;
742
/* Generate descriptor to put random value into */
743
DESC_KEY_OUT(header, key_info, 0, NULL);
744
/* Restore actual, desired key length */
745
key_info->key_length = original_key_length;
747
old_flags = user_ctx->flags;
748
/* Now put random value into key */
750
/* Restore user's old flag value */
751
user_ctx->flags = old_flags;
752
#ifdef DIAG_SECURITY_FUNC
753
if (ret == FSL_RETURN_OK_S) {
754
LOG_DIAG("ret is ok");
756
LOG_DIAG("ret is not ok");
761
case FSL_KEY_WRAP_ACCEPT:
762
#ifdef DIAG_SECURITY_FUNC
763
LOG_DIAG("Accepting plaintext key\n");
766
#ifdef DIAG_SECURITY_FUNC
767
LOG_DIAG("ACCEPT: Red Key is NULL");
769
ret = FSL_RETURN_ERROR_S;
772
/* Copy in safe number of bytes of Red key */
773
if (key_info->keystore == NULL) {
774
/* Key goes in system keystore */
775
ret = do_system_keystore_slot_load(user_ctx,
777
key_info->handle, key,
780
/* Key goes in user keystore */
781
ret = keystore_slot_load(key_info->keystore,
783
key_info->handle, key,
784
key_info->key_length);
788
case FSL_KEY_WRAP_UNWRAP:
789
#ifdef DIAG_SECURITY_FUNC
790
LOG_DIAG("Unwrapping wrapped key\n");
792
/* For now, disallow non-blocking calls. */
793
if (!(user_ctx->flags & FSL_UCO_BLOCKING_MODE)) {
794
ret = FSL_RETURN_BAD_FLAG_S;
795
} else if (key == NULL) {
796
ret = FSL_RETURN_ERROR_S;
798
ret = unwrap(user_ctx, key_info, key);
803
ret = FSL_RETURN_BAD_FLAG_S;
808
if (slot_allocated && (ret != FSL_RETURN_OK_S)) {
809
fsl_shw_return_t scc_err;
811
if (key_info->keystore == NULL) {
812
/* Key goes in system keystore */
813
scc_err = do_system_keystore_slot_dealloc(user_ctx,
817
/* Key goes in user keystore */
818
scc_err = keystore_slot_dealloc(key_info->keystore,
819
key_info->userid, key_info->handle);
822
key_info->flags &= ~FSL_SKO_KEY_ESTABLISHED;
828
} /* fsl_shw_establish_key() */
831
* Wrap a key and retrieve the wrapped value.
833
* A wrapped key is a key that has been cryptographically obscured. It is
834
* only able to be used with #fsl_shw_establish_key().
836
* This function will also release the key (see #fsl_shw_release_key()) so
837
* that it must be re-established before reuse.
839
* This feature is not available for all platforms, nor for all algorithms and
842
* @param user_ctx A user context from #fsl_shw_register_user().
843
* @param key_info The information about the key to be deleted.
844
* @param[out] covered_key The location to store the 48-octet wrapped key.
845
* (This size is based upon the maximum key size
848
* @return A return code of type #fsl_shw_return_t.
850
fsl_shw_return_t fsl_shw_extract_key(fsl_shw_uco_t * user_ctx,
851
fsl_shw_sko_t * key_info,
852
uint8_t * covered_key)
858
/* For now, only blocking mode calls are supported */
859
if (user_ctx->flags & FSL_UCO_BLOCKING_MODE) {
860
if (key_info->flags & FSL_SKO_KEY_ESTABLISHED) {
861
ret = wrap(user_ctx, key_info, covered_key);
862
if (ret != FSL_RETURN_OK_S) {
866
/* Verify that a SW key info really belongs to a SW key */
867
if (key_info->flags & FSL_SKO_KEY_SW_KEY) {
868
/* ret = FSL_RETURN_BAD_FLAG_S;
872
/* Need to deallocate on successful extraction */
873
if (key_info->keystore == NULL) {
874
/* Key goes in system keystore */
875
ret = do_system_keystore_slot_dealloc(user_ctx,
876
key_info->userid, key_info->handle);
878
/* Key goes in user keystore */
879
ret = keystore_slot_dealloc(key_info->keystore,
880
key_info->userid, key_info->handle);
882
/* Mark key not available in the flags */
884
~(FSL_SKO_KEY_ESTABLISHED | FSL_SKO_KEY_PRESENT);
895
* De-establish a key so that it can no longer be accessed.
897
* The key will need to be re-established before it can again be used.
899
* This feature is not available for all platforms, nor for all algorithms and
902
* @param user_ctx A user context from #fsl_shw_register_user().
903
* @param key_info The information about the key to be deleted.
905
* @return A return code of type #fsl_shw_return_t.
907
fsl_shw_return_t fsl_shw_release_key(fsl_shw_uco_t * user_ctx,
908
fsl_shw_sko_t * key_info)
914
if (key_info->flags & FSL_SKO_KEY_ESTABLISHED) {
915
if (key_info->keystore == NULL) {
916
/* Key goes in system keystore */
917
do_system_keystore_slot_dealloc(user_ctx,
921
/* Key goes in user keystore */
922
keystore_slot_dealloc(key_info->keystore,
926
key_info->flags &= ~(FSL_SKO_KEY_ESTABLISHED |
927
FSL_SKO_KEY_PRESENT);
936
fsl_shw_return_t fsl_shw_read_key(fsl_shw_uco_t * user_ctx,
937
fsl_shw_sko_t * key_info, uint8_t * key)
943
if (!(key_info->flags & FSL_SKO_KEY_ESTABLISHED)
944
|| !(key_info->flags & FSL_SKO_KEY_SW_KEY)) {
945
ret = FSL_RETURN_BAD_FLAG_S;
949
if (key_info->keystore == NULL) {
950
/* Key lives in system keystore */
951
ret = do_system_keystore_slot_read(user_ctx,
954
key_info->key_length, key);
956
/* Key lives in user keystore */
957
ret = keystore_slot_read(key_info->keystore,
960
key_info->key_length, key);