~ubuntu-branches/ubuntu/karmic/linux-ports/karmic

« back to all changes in this revision

Viewing changes to drivers/mxc/security/sahara2/fsl_shw_wrap.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich, Luke Yelavich, Michael Casadevall, Tim Gardner, Upstream Kernel Changes
  • Date: 2009-05-06 18:18:55 UTC
  • Revision ID: james.westby@ubuntu.com-20090506181855-t00baeevpnvd9o7a
Tags: 2.6.30-1.1
[ Luke Yelavich ]
* initial release for karmic
* SAUCE: rebase-ports - adjust for the karmic ports kernel
* SAUCE: rebase-ports - also remove abi dirs/files on rebase
* Update configs after rebase against mainline Jaunty tree
* [Config] Disable CONFIG_BLK_DEV_UB and CONFIG_USB_LIBUSUAL as per
  mainline jaunty
* forward-port patch to drbd for powerpc compilation
* [Config] disable CONFIG_LENOVO_SL_LAPTOP for i386 due to FTBFS
* add .o files found in arch/powerpc/lib to all powerpc kernel header
  packages
* [Config] enable CONFIG_DRM_I915_KMS for i386 as per karmic mainline

[ Michael Casadevall ]

* Disable kgdb on sparc64
* [sparc] [Config] Disable GPIO LEDS
* [ia64] Rename -ia64-generic to -ia64 in line with other architectures
* Correct kernel image path for sparc builds
* [hppa] Fix HPPA config files to build modules for all udebian

Rebase on top of karmic mainline 2.6.30-1.1

[ Tim Gardner ]

* [Config] armel: disable staging drivers, fixes FTBS
* [Config] armel imx51: Disable CONFIG_MTD_NAND_MXC, fixes FTBS

[ Upstream Kernel Changes ]

* mpt2sas: Change reset_type enum to avoid namespace collision.
  Submitted upstream.

* Initial release after rebasing against v2.6.30-rc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
3
 
 */
4
 
 
5
 
/*
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:
9
 
 *
10
 
 * http://www.opensource.org/licenses/gpl-license.html
11
 
 * http://www.gnu.org/copyleft/gpl.html
12
 
 */
13
 
 
14
 
/*!
15
 
 * @file fsl_shw_wrap.c
16
 
 *
17
 
 * This file implements Key-Wrap (Black Key) functions of the FSL SHW API for
18
 
 * Sahara.
19
 
 *
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
23
 
 *    size of SCC1 RAM.
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.
30
 
 * - T is a Nonce
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
35
 
<table>
36
 
<tr><TD align="right">BLACK_KEY <TD width="3">=<TD>ICV | T' | LEN | ALG |
37
 
     KEY'</td></tr>
38
 
<tr><td>&nbsp;</td></tr>
39
 
 
40
 
<tr><th>To Wrap</th></tr>
41
 
<tr><TD align="right">T</td> <TD width="3">=</td> <TD>RND()<sub>16</sub>
42
 
    </td></tr>
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>
51
 
 
52
 
<tr><td>&nbsp;</td></tr>
53
 
 
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>
63
 
</table>
64
 
 
65
 
 */
66
 
 
67
 
#include "sahara.h"
68
 
#include "fsl_platform.h"
69
 
#include "fsl_shw_keystore.h"
70
 
 
71
 
#include "sf_util.h"
72
 
#include "adaptor.h"
73
 
 
74
 
#if defined(DIAG_SECURITY_FUNC)
75
 
#include <diagnostic.h>
76
 
#endif
77
 
 
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
82
 
#else
83
 
#define LENGTH_PATCH  4
84
 
#define LENGTH_PATCH_MASK  3
85
 
#endif
86
 
 
87
 
#if LENGTH_PATCH
88
 
#define ROUND_LENGTH(len)                                                  \
89
 
({                                                                         \
90
 
    uint32_t orig_len = len;                                               \
91
 
    uint32_t new_len;                                                      \
92
 
                                                                           \
93
 
   if ((orig_len & LENGTH_PATCH_MASK) != 0) {                              \
94
 
       new_len = (orig_len + LENGTH_PATCH                                  \
95
 
            - (orig_len & LENGTH_PATCH_MASK));                             \
96
 
   }                                                                       \
97
 
   else {                                                                  \
98
 
       new_len = orig_len;                                                 \
99
 
   }                                                                       \
100
 
       new_len;                                                            \
101
 
})
102
 
#else
103
 
#define ROUND_LENGTH(len) (len)
104
 
#endif
105
 
 
106
 
#ifdef __KERNEL__
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);
111
 
#endif
112
 
 
113
 
#define ICV_LENGTH 16
114
 
#define T_LENGTH 16
115
 
#define KEK_LENGTH 16
116
 
#define LENGTH_LENGTH 1
117
 
#define ALGORITHM_LENGTH 1
118
 
#define FLAGS_LENGTH 1
119
 
 
120
 
/* ICV | T' | LEN | ALG | KEY' */
121
 
#define ICV_OFFSET       0
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
128
 
 
129
 
/*
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).
134
 
 *
135
 
 * Normally, a random sequence is used.
136
 
 */
137
 
#ifdef DO_REPEATABLE_WRAP
138
 
/*!
139
 
 * Block of zeroes which is maximum Symmetric block size, used for
140
 
 * initializing context register, etc.
141
 
 */
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
145
 
};
146
 
#endif
147
 
 
148
 
/*!
149
 
 * Insert descriptors to calculate ICV = HMAC(key=T, data=LEN|ALG|KEY')
150
 
 *
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.
158
 
 *
159
 
 * @return    A return code of type #fsl_shw_return_t.
160
 
 */
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,
165
 
                                               uint32_t key_length,
166
 
                                               uint8_t * hmac)
167
 
{
168
 
        fsl_shw_return_t sah_code;
169
 
        uint32_t header;
170
 
        sah_Link *link1 = NULL;
171
 
        sah_Link *link2 = NULL;
172
 
 
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) {
181
 
                goto out;
182
 
        }
183
 
 
184
 
        /* Previous step loaded key; Now set up to hash the data */
185
 
        header = SAH_HDR_MDHA_HASH;     /* #10 */
186
 
 
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),
191
 
                                   SAH_USES_LINK_DATA);
192
 
        if (sah_code != FSL_RETURN_OK_S) {
193
 
                goto out;
194
 
        }
195
 
 
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,
199
 
                                   (LENGTH_LENGTH
200
 
                                    + ALGORITHM_LENGTH
201
 
                                    + key_length), SAH_USES_LINK_DATA);
202
 
 
203
 
        if (sah_code != FSL_RETURN_OK_S) {
204
 
                goto out;
205
 
        }
206
 
        /* Output - computed ICV/HMAC */
207
 
        sah_code = sah_Create_Link(user_ctx->mem_util, &link2,
208
 
                                   hmac, ICV_LENGTH,
209
 
                                   SAH_USES_LINK_DATA | SAH_OUTPUT_LINK);
210
 
        if (sah_code != FSL_RETURN_OK_S) {
211
 
                goto out;
212
 
        }
213
 
 
214
 
        sah_code = sah_Append_Desc(user_ctx->mem_util, desc_chain,
215
 
                                   header, link1, link2);
216
 
 
217
 
      out:
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);
221
 
        }
222
 
 
223
 
        return sah_code;
224
 
}                               /* create_icv_calc */
225
 
 
226
 
/*!
227
 
 * Perform unwrapping of a black key into a RED slot
228
 
 *
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
233
 
 *
234
 
 * @return    A return code of type #fsl_shw_return_t.
235
 
 */
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)
239
 
{
240
 
        SAH_SF_DCLS;
241
 
        uint8_t *hmac = NULL;
242
 
        fsl_shw_sko_t t_key_info;
243
 
        sah_Link *link1 = NULL;
244
 
        sah_Link *link2 = NULL;
245
 
        unsigned i;
246
 
        unsigned rounded_key_length;
247
 
        unsigned original_key_length = key_info->key_length;
248
 
 
249
 
        hmac = DESC_TEMP_ALLOC(ICV_LENGTH);
250
 
 
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;
258
 
 
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;
263
 
                goto out;
264
 
        }
265
 
 
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,
270
 
                                        key_info->userid,
271
 
                                    t_key_info.handle,
272
 
                                    T_LENGTH, 
273
 
                                    black_key + T_PRIME_OFFSET);
274
 
        
275
 
        } else {
276
 
                        /* Key goes in user keystore */
277
 
                        ret = keystore_slot_decrypt(user_ctx,
278
 
                                                        key_info->keystore,
279
 
                                                        key_info->userid,
280
 
                                                        t_key_info.handle,
281
 
                                                        T_LENGTH,
282
 
                                                    black_key + T_PRIME_OFFSET);
283
 
        }
284
 
        if (ret != FSL_RETURN_OK_S) {
285
 
                goto out;
286
 
        }
287
 
 
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"
294
 
                         " flag!\n");
295
 
#endif                          /*DIAG_SECURITY_FUNC */
296
 
                goto out;
297
 
        }
298
 
#ifdef DIAG_SECURITY_FUNC
299
 
        LOG_DIAG("Validating MAC of wrapped key");
300
 
#endif
301
 
        SAH_SF_EXECUTE();
302
 
        if (ret != FSL_RETURN_OK_S) {
303
 
                goto out;
304
 
        }
305
 
        SAH_SF_DESC_CLEAN();
306
 
 
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);
312
 
 
313
 
                        {
314
 
                                char buff[300];
315
 
                                int a;
316
 
                                for (a = 0; a < ICV_LENGTH; a++)
317
 
                                        sprintf(&(buff[a * 2]), "%02x",
318
 
                                                black_key[ICV_OFFSET + a]);
319
 
                                buff[a * 2 + 1] = 0;
320
 
                                LOG_DIAG_ARGS("black key: %s", buff);
321
 
 
322
 
                                for (a = 0; a < ICV_LENGTH; a++)
323
 
                                        sprintf(&(buff[a * 2]), "%02x",
324
 
                                                hmac[a]);
325
 
                                buff[a * 2 + 1] = 0;
326
 
                                LOG_DIAG_ARGS("hmac:      %s", buff);
327
 
                        }
328
 
#endif
329
 
                        ret = FSL_RETURN_AUTH_FAILED_S;
330
 
                        goto out;
331
 
                }
332
 
        }
333
 
 
334
 
        /* This is no longer needed. */
335
 
        DESC_TEMP_FREE(hmac);
336
 
 
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);
341
 
 
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) {
345
 
                goto out;
346
 
        }
347
 
 
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) {
353
 
                goto out;
354
 
        }
355
 
 
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) {
359
 
                goto out;
360
 
        }
361
 
 
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) {
366
 
                goto out;
367
 
        }
368
 
 
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);
376
 
 
377
 
        rounded_key_length = ROUND_LENGTH(original_key_length);
378
 
        key_info->key_length = rounded_key_length;
379
 
 
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,
383
 
                    key_info);
384
 
 
385
 
        /* Perform the operation */
386
 
#ifdef DIAG_SECURITY_FUNC
387
 
        LOG_DIAG("Decrypting key with KEK");
388
 
#endif
389
 
        SAH_SF_EXECUTE();
390
 
 
391
 
      out:
392
 
        key_info->key_length = original_key_length;
393
 
        SAH_SF_DESC_CLEAN();
394
 
 
395
 
        DESC_TEMP_FREE(hmac);
396
 
 
397
 
        /* Erase tracks */
398
 
        t_key_info.userid = 0xdeadbeef;
399
 
        t_key_info.handle = 0xdeadbeef;
400
 
 
401
 
        return ret;
402
 
}                               /* unwrap */
403
 
 
404
 
/*!
405
 
 * Perform wrapping of a black key from a RED slot
406
 
 *
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
411
 
 *
412
 
 * @return    A return code of type #fsl_shw_return_t.
413
 
 */
414
 
static fsl_shw_return_t wrap(fsl_shw_uco_t * user_ctx,
415
 
                             fsl_shw_sko_t * key_info, uint8_t * black_key)
416
 
{
417
 
        SAH_SF_DCLS;
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;
423
 
        sah_Link *link1;
424
 
        sah_Link *link2;
425
 
 
426
 
        black_key[LENGTH_OFFSET] = key_info->key_length;
427
 
        black_key[ALGORITHM_OFFSET] = key_info->algorithm;
428
 
 
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;
432
 
 
433
 
        memcpy(&KEK_key_info, &T_key_info, sizeof(KEK_key_info));
434
 
        KEK_key_info.algorithm = FSL_KEY_ALG_AES;
435
 
 
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,
440
 
                            &T_key_info.handle);
441
 
        
442
 
        } else {
443
 
                /* Key goes in user keystore */
444
 
                ret = keystore_slot_alloc(key_info->keystore,
445
 
                                  T_LENGTH,
446
 
                                  key_info->userid, &T_key_info.handle);
447
 
        }
448
 
        if (ret != FSL_RETURN_OK_S) {
449
 
                goto out;
450
 
        }
451
 
 
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);
457
 
                
458
 
        } else {
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);
463
 
        }
464
 
 
465
 
        if (ret != FSL_RETURN_OK_S) {
466
 
#ifdef DIAG_SECURITY_FUNC
467
 
                LOG_DIAG("do_scc_slot_alloc() failed");
468
 
#endif
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);
473
 
        
474
 
                } else {
475
 
                        /* Key goes in user keystore */
476
 
                        (void)keystore_slot_dealloc(key_info->keystore,
477
 
                                        key_info->userid, T_key_info.handle);
478
 
                }
479
 
        } else {
480
 
                slots_allocated = 1;
481
 
        }
482
 
 
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);
488
 
#else
489
 
        if (key_info->keystore == NULL) {
490
 
                /* Key goes in system keystore */
491
 
                ret = do_system_keystore_slot_load(user_ctx,
492
 
                           T_key_info.userid,
493
 
                           T_key_info.handle, T_block,
494
 
                           T_key_info.key_length);
495
 
        } else {
496
 
                /* Key goes in user keystore */
497
 
                ret = keystore_slot_load(key_info->keystore,
498
 
                                 T_key_info.userid,
499
 
                                 T_key_info.handle,
500
 
                                 T_block, T_key_info.key_length);
501
 
        }
502
 
 
503
 
        if (ret != FSL_RETURN_OK_S) {
504
 
                goto out;
505
 
        }
506
 
#endif
507
 
 
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) {
516
 
                goto out;
517
 
        }
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) {
523
 
                goto out;
524
 
        }
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) {
528
 
                goto out;
529
 
        }
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) {
534
 
                goto out;
535
 
        }
536
 
#if defined(NEED_CTR_WORKAROUND)
537
 
        rounded_key_length = ROUND_LENGTH(original_key_length);
538
 
        key_info->key_length = rounded_key_length;
539
 
#else
540
 
        rounded_key_length = original_key_length;
541
 
#endif
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);
552
 
 
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;
557
 
        }
558
 
 
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"
566
 
                         " flag!\n");
567
 
#endif                          /*DIAG_SECURITY_FUNC */
568
 
                goto out;
569
 
        }
570
 
 
571
 
        /* Now get Sahara to do the work. */
572
 
#ifdef DIAG_SECURITY_FUNC
573
 
        LOG_DIAG("Encrypting key with KEK");
574
 
#endif
575
 
        SAH_SF_EXECUTE();
576
 
        if (ret != FSL_RETURN_OK_S) {
577
 
#ifdef DIAG_SECURITY_FUNC
578
 
                LOG_DIAG("sah_Descriptor_Chain_Execute() failed");
579
 
#endif
580
 
                goto out;
581
 
        }
582
 
 
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);
589
 
        } else {
590
 
                /* Key goes in user keystore */
591
 
                ret = keystore_slot_encrypt(user_ctx,
592
 
                                            key_info->keystore,
593
 
                                            T_key_info.userid,
594
 
                                            T_key_info.handle,
595
 
                                            T_LENGTH,
596
 
                                            black_key + T_PRIME_OFFSET);
597
 
        }
598
 
 
599
 
        if (ret != FSL_RETURN_OK_S) {
600
 
#ifdef DIAG_SECURITY_FUNC
601
 
                LOG_DIAG("do_scc_slot_encrypt() failed");
602
 
#endif
603
 
                goto out;
604
 
        }
605
 
 
606
 
      out:
607
 
        key_info->key_length = original_key_length;
608
 
 
609
 
        SAH_SF_DESC_CLEAN();
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,
614
 
                                                              key_info->userid,
615
 
                                                              T_key_info.
616
 
                                                              handle);
617
 
                        (void)do_system_keystore_slot_dealloc(user_ctx,
618
 
                                                              key_info->userid,
619
 
                                                              KEK_key_info.
620
 
                                                              handle);
621
 
                } else {
622
 
                        /* Key goes in user keystore */
623
 
                        (void)keystore_slot_dealloc(key_info->keystore,
624
 
                                                    key_info->userid,
625
 
                                    T_key_info.handle);
626
 
                        (void)keystore_slot_dealloc(key_info->keystore,
627
 
                                    key_info->userid,
628
 
                                    KEK_key_info.handle);
629
 
            }
630
 
        }       
631
 
 
632
 
        return ret;
633
 
}                               /* wrap */
634
 
 
635
 
/*!
636
 
 * Place a key into a protected location for use only by cryptographic
637
 
 * algorithms.
638
 
 *
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.
643
 
 *
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()
649
 
 *
650
 
 * The protected key will not be available for use until this operation
651
 
 * successfully completes.
652
 
 *
653
 
 * This feature is not available for all platforms, nor for all algorithms and
654
 
 * modes.
655
 
 *
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
661
 
 *                              key for use.
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.
668
 
 *
669
 
 * @return    A return code of type #fsl_shw_return_t.
670
 
 */
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,
674
 
                                       const uint8_t * key)
675
 
{
676
 
        SAH_SF_DCLS;
677
 
        unsigned original_key_length = key_info->key_length;
678
 
        unsigned rounded_key_length;
679
 
        unsigned slot_allocated = 0;
680
 
        uint32_t old_flags;
681
 
 
682
 
        header = SAH_HDR_RNG_GENERATE;  /* Desc. #18 for rand */
683
 
 
684
 
        /* TODO: THIS STILL NEEDS TO BE REFACTORED */
685
 
 
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);
692
 
        } else {
693
 
                rounded_key_length = original_key_length;
694
 
        }
695
 
 
696
 
        SAH_SF_USER_CHECK();
697
 
        
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");
702
 
#endif
703
 
        }
704
 
 
705
 
 
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,
710
 
                                                    key_info->userid,
711
 
                                                    &(key_info->handle));
712
 
#ifdef DIAG_SECURITY_FUNC
713
 
                LOG_DIAG_ARGS
714
 
                    ("key length: %i, handle: %i, rounded key length: %i",
715
 
                     key_info->key_length, key_info->handle,
716
 
                     rounded_key_length);
717
 
#endif
718
 
 
719
 
        } else {
720
 
                /* Key goes in user keystore */
721
 
                ret = keystore_slot_alloc(key_info->keystore,
722
 
                                          key_info->key_length,
723
 
                                          key_info->userid,
724
 
                                          &(key_info->handle));
725
 
        }
726
 
        if (ret != FSL_RETURN_OK_S) {
727
 
#ifdef DIAG_SECURITY_FUNC
728
 
                LOG_DIAG("Slot allocation failed\n");
729
 
#endif
730
 
                goto out;
731
 
        }
732
 
        slot_allocated = 1;
733
 
 
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");
739
 
#endif
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;
746
 
 
747
 
                old_flags = user_ctx->flags;
748
 
                /* Now put random value into key */
749
 
                SAH_SF_EXECUTE();
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");
755
 
                } else {
756
 
                        LOG_DIAG("ret is not ok");
757
 
                }
758
 
#endif
759
 
                break;
760
 
 
761
 
        case FSL_KEY_WRAP_ACCEPT:
762
 
#ifdef DIAG_SECURITY_FUNC
763
 
                LOG_DIAG("Accepting plaintext key\n");
764
 
#endif
765
 
                if (key == NULL) {
766
 
#ifdef DIAG_SECURITY_FUNC
767
 
                        LOG_DIAG("ACCEPT:  Red Key is NULL");
768
 
#endif
769
 
                        ret = FSL_RETURN_ERROR_S;
770
 
                        goto out;
771
 
                }
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,
776
 
                                                   key_info->userid,
777
 
                                                   key_info->handle, key,
778
 
                                                   rounded_key_length);
779
 
                } else {
780
 
                        /* Key goes in user keystore */
781
 
                        ret = keystore_slot_load(key_info->keystore,
782
 
                                                                 key_info->userid,
783
 
                                                                 key_info->handle, key,
784
 
                                                                 key_info->key_length);
785
 
                }
786
 
                break;
787
 
 
788
 
        case FSL_KEY_WRAP_UNWRAP:
789
 
#ifdef DIAG_SECURITY_FUNC
790
 
                LOG_DIAG("Unwrapping wrapped key\n");
791
 
#endif
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;
797
 
                } else {
798
 
                        ret = unwrap(user_ctx, key_info, key);
799
 
                }
800
 
                break;
801
 
 
802
 
        default:
803
 
                ret = FSL_RETURN_BAD_FLAG_S;
804
 
                break;
805
 
        }                       /* switch */
806
 
 
807
 
      out:
808
 
        if (slot_allocated && (ret != FSL_RETURN_OK_S)) {
809
 
                fsl_shw_return_t scc_err;
810
 
                
811
 
                if (key_info->keystore == NULL) {
812
 
                        /* Key goes in system keystore */
813
 
                        scc_err = do_system_keystore_slot_dealloc(user_ctx,
814
 
                                                  key_info->userid,
815
 
                                                  key_info->handle);
816
 
                } else {
817
 
                        /* Key goes in user keystore */
818
 
                        scc_err = keystore_slot_dealloc(key_info->keystore,
819
 
                                                key_info->userid,  key_info->handle);
820
 
                }
821
 
                
822
 
                key_info->flags &= ~FSL_SKO_KEY_ESTABLISHED;
823
 
        }
824
 
 
825
 
        SAH_SF_DESC_CLEAN();
826
 
 
827
 
        return ret;
828
 
}                               /* fsl_shw_establish_key() */
829
 
 
830
 
/*!
831
 
 * Wrap a key and retrieve the wrapped value.
832
 
 *
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().
835
 
 *
836
 
 * This function will also release the key (see #fsl_shw_release_key()) so
837
 
 * that it must be re-established before reuse.
838
 
 *
839
 
 * This feature is not available for all platforms, nor for all algorithms and
840
 
 * modes.
841
 
 *
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
846
 
 *                              of 32 octets).
847
 
 *
848
 
 * @return    A return code of type #fsl_shw_return_t.
849
 
 */
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)
853
 
{
854
 
        SAH_SF_DCLS;
855
 
 
856
 
        SAH_SF_USER_CHECK();
857
 
 
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) {
863
 
                                goto out;
864
 
                        }
865
 
 
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;
869
 
                          goto out;*/
870
 
                        }
871
 
 
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);
877
 
                        } else {
878
 
                                /* Key goes in user keystore */
879
 
                                ret = keystore_slot_dealloc(key_info->keystore,
880
 
                                                key_info->userid, key_info->handle);
881
 
                        }       
882
 
                        /* Mark key not available in the flags */
883
 
                        key_info->flags &=
884
 
                            ~(FSL_SKO_KEY_ESTABLISHED | FSL_SKO_KEY_PRESENT);
885
 
                }
886
 
        }
887
 
 
888
 
out:
889
 
        SAH_SF_DESC_CLEAN();
890
 
 
891
 
        return ret;
892
 
}
893
 
 
894
 
/*!
895
 
 * De-establish a key so that it can no longer be accessed.
896
 
 *
897
 
 * The key will need to be re-established before it can again be used.
898
 
 *
899
 
 * This feature is not available for all platforms, nor for all algorithms and
900
 
 * modes.
901
 
 *
902
 
 * @param      user_ctx         A user context from #fsl_shw_register_user().
903
 
 * @param      key_info         The information about the key to be deleted.
904
 
 *
905
 
 * @return    A return code of type #fsl_shw_return_t.
906
 
 */
907
 
fsl_shw_return_t fsl_shw_release_key(fsl_shw_uco_t * user_ctx,
908
 
                                     fsl_shw_sko_t * key_info)
909
 
{
910
 
        SAH_SF_DCLS;
911
 
 
912
 
        SAH_SF_USER_CHECK();
913
 
 
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,
918
 
                                                        key_info->userid,
919
 
                                                        key_info->handle);
920
 
                } else {
921
 
                        /* Key goes in user keystore */
922
 
                        keystore_slot_dealloc(key_info->keystore,
923
 
                                                key_info->userid,
924
 
                                                key_info->handle);
925
 
                }       
926
 
                key_info->flags &= ~(FSL_SKO_KEY_ESTABLISHED |
927
 
                                     FSL_SKO_KEY_PRESENT);
928
 
        }
929
 
 
930
 
out:
931
 
        SAH_SF_DESC_CLEAN();
932
 
 
933
 
        return ret;
934
 
}
935
 
 
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)
938
 
{
939
 
        SAH_SF_DCLS;
940
 
 
941
 
        SAH_SF_USER_CHECK();
942
 
 
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;
946
 
                goto out;
947
 
        }
948
 
 
949
 
        if (key_info->keystore == NULL) {
950
 
                /* Key lives in system keystore */
951
 
                ret = do_system_keystore_slot_read(user_ctx,
952
 
                                                   key_info->userid,
953
 
                                                   key_info->handle,
954
 
                                                   key_info->key_length, key);
955
 
        } else {
956
 
                /* Key lives in user keystore */
957
 
                ret = keystore_slot_read(key_info->keystore,
958
 
                                         key_info->userid,
959
 
                                         key_info->handle,
960
 
                                         key_info->key_length, key);
961
 
        }
962
 
 
963
 
      out:
964
 
        SAH_SF_DESC_CLEAN();
965
 
 
966
 
        return ret;
967
 
}