~ubuntu-branches/ubuntu/jaunty/trousers/jaunty

« back to all changes in this revision

Viewing changes to src/tcs/tcs_key_mem_cache.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2008-01-23 22:03:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080123220300-fhtqja3c0oq0gp6z
Tags: 0.3.1-4
* Added patch from Aaron M. Ucko <ucko@debian.org> to allow trousers to
  build successfully on amd64, and presumably also other 64-bit
  architectures (Closes: #457400).
* Including udev rule for /dev/tpm from William Lima
  <wlima.amadeus@gmail.com> as suggested by David Smith <dds@google.com>
  (Closes: #459682).
* Added lintian overrides.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * Licensed Materials - Property of IBM
 
4
 *
 
5
 * trousers - An open source TCG Software Stack
 
6
 *
 
7
 * (C) Copyright International Business Machines Corp. 2004-2006
 
8
 *
 
9
 */
 
10
 
 
11
 
 
12
#include <stdlib.h>
 
13
#include <stdio.h>
 
14
#include <string.h>
 
15
#include <unistd.h>
 
16
#include <errno.h>
 
17
 
 
18
#include "trousers/tss.h"
 
19
#include "trousers_types.h"
 
20
#include "trousers_types.h"
 
21
#include "tcs_tsp.h"
 
22
#include "tcs_utils.h"
 
23
#include "tcs_int_literals.h"
 
24
#include "capabilities.h"
 
25
#include "tcslog.h"
 
26
#include "tcsps.h"
 
27
#include "req_mgr.h"
 
28
 
 
29
#include "tcs_key_ps.h"
 
30
 
 
31
/*
 
32
 * mem_cache_lock will be responsible for protecting the key_mem_cache_head list. This is a
 
33
 * TCSD global linked list of all keys which have been loaded into the TPM at some time.
 
34
 */
 
35
MUTEX_DECLARE_INIT(mem_cache_lock);
 
36
 
 
37
/*
 
38
 * tcs_keyhandle_lock is only used to make TCS keyhandle generation atomic for all TCSD
 
39
 * threads.
 
40
 */
 
41
static MUTEX_DECLARE_INIT(tcs_keyhandle_lock);
 
42
 
 
43
/*
 
44
 * timestamp_lock is only used to make TCS key timestamp generation atomic for all TCSD
 
45
 * threads.
 
46
 */
 
47
static MUTEX_DECLARE_INIT(timestamp_lock);
 
48
 
 
49
TCS_KEY_HANDLE
 
50
getNextTcsKeyHandle()
 
51
{
 
52
        static TCS_KEY_HANDLE NextTcsKeyHandle = 0x22330000;
 
53
        TCS_KEY_HANDLE ret;
 
54
 
 
55
        MUTEX_LOCK(tcs_keyhandle_lock);
 
56
 
 
57
        do {
 
58
                ret = NextTcsKeyHandle++;
 
59
        } while (NextTcsKeyHandle == SRK_TPM_HANDLE || NextTcsKeyHandle == NULL_TCS_HANDLE);
 
60
 
 
61
        MUTEX_UNLOCK(tcs_keyhandle_lock);
 
62
 
 
63
        return ret;
 
64
}
 
65
 
 
66
UINT32
 
67
getNextTimeStamp()
 
68
{
 
69
        static UINT32 time_stamp = 1;
 
70
        UINT32 ret;
 
71
 
 
72
        MUTEX_LOCK(timestamp_lock);
 
73
        ret = time_stamp++;
 
74
        MUTEX_UNLOCK(timestamp_lock);
 
75
 
 
76
        return ret;
 
77
}
 
78
 
 
79
/* only called from load key paths, so no locking */
 
80
TCPA_STORE_PUBKEY *
 
81
mc_get_pub_by_slot(TCPA_KEY_HANDLE tpm_handle)
 
82
{
 
83
        struct key_mem_cache *tmp;
 
84
        TCPA_STORE_PUBKEY *ret;
 
85
 
 
86
        if (tpm_handle == NULL_TPM_HANDLE)
 
87
                return NULL;
 
88
 
 
89
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
90
                LogDebugFn("TCSD mem_cached handle: 0x%x",
 
91
                           tmp->tcs_handle);
 
92
                if (tmp->tpm_handle == tpm_handle) {
 
93
                        ret = tmp->blob ? &tmp->blob->pubKey : NULL;
 
94
                        return ret;
 
95
                }
 
96
        }
 
97
        LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
 
98
        return NULL;
 
99
}
 
100
 
 
101
/* only called from load key paths, so no locking */
 
102
TCPA_STORE_PUBKEY *
 
103
mc_get_pub_by_handle(TCS_KEY_HANDLE tcs_handle)
 
104
{
 
105
        struct key_mem_cache *tmp;
 
106
        TCPA_STORE_PUBKEY *ret;
 
107
 
 
108
        LogDebugFn("looking for 0x%x", tcs_handle);
 
109
 
 
110
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
111
                LogDebugFn("TCSD mem_cached handle: 0x%x",
 
112
                         tmp->tcs_handle);
 
113
                if (tmp->tcs_handle == tcs_handle) {
 
114
                        ret = tmp->blob ? &tmp->blob->pubKey : NULL;
 
115
                        return ret;
 
116
                }
 
117
        }
 
118
 
 
119
        LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
 
120
        return NULL;
 
121
}
 
122
 
 
123
/* only called from load key paths, so no locking */
 
124
TSS_RESULT
 
125
mc_set_parent_by_handle(TCS_KEY_HANDLE tcs_handle, TCS_KEY_HANDLE p_tcs_handle)
 
126
{
 
127
        struct key_mem_cache *tmp, *parent;
 
128
 
 
129
        /* find parent */
 
130
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
131
                LogDebug("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
132
                if (tmp->tcs_handle == p_tcs_handle) {
 
133
                        parent = tmp;
 
134
                        break;
 
135
                }
 
136
        }
 
137
 
 
138
        /* didn't find parent */
 
139
        if (tmp == NULL)
 
140
                goto done;
 
141
 
 
142
        /* set parent blob in child */
 
143
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
144
                if (tmp->tcs_handle == tcs_handle) {
 
145
                        tmp->parent = parent;
 
146
                        return TSS_SUCCESS;
 
147
                }
 
148
        }
 
149
done:
 
150
        return TCSERR(TSS_E_FAIL);
 
151
}
 
152
 
 
153
TCPA_RESULT
 
154
ensureKeyIsLoaded(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE keyHandle, TCPA_KEY_HANDLE * keySlot)
 
155
{
 
156
        TCPA_RESULT result = TSS_SUCCESS;
 
157
        TCPA_STORE_PUBKEY *myPub;
 
158
 
 
159
        LogDebugFn("0x%x", keyHandle);
 
160
 
 
161
        if (!ctx_has_key_loaded(hContext, keyHandle))
 
162
                return TCSERR(TCS_E_INVALID_KEY);
 
163
 
 
164
        MUTEX_LOCK(mem_cache_lock);
 
165
 
 
166
        *keySlot = mc_get_slot_by_handle(keyHandle);
 
167
        LogDebug("keySlot is %08X", *keySlot);
 
168
        if (*keySlot == NULL_TPM_HANDLE || isKeyLoaded(*keySlot) == FALSE) {
 
169
                LogDebug("calling mc_get_pub_by_handle");
 
170
                if ((myPub = mc_get_pub_by_handle(keyHandle)) == NULL) {
 
171
                        LogDebug("Failed to find pub by handle");
 
172
                        result = TCSERR(TCS_E_KM_LOADFAILED);
 
173
                        goto done;
 
174
                }
 
175
 
 
176
                LogDebugFn("calling LoadKeyShim");
 
177
                if ((result = LoadKeyShim(hContext, myPub, NULL, keySlot))) {
 
178
                        LogDebug("Failed shim");
 
179
                        goto done;
 
180
                }
 
181
 
 
182
                if (*keySlot == NULL_TPM_HANDLE) {
 
183
                        LogDebug("Key slot is still invalid after ensureKeyIsLoaded");
 
184
                        result = TCSERR(TCS_E_KM_LOADFAILED);
 
185
                        goto done;
 
186
                }
 
187
        }
 
188
        mc_update_time_stamp(*keySlot);
 
189
 
 
190
done:
 
191
        MUTEX_UNLOCK(mem_cache_lock);
 
192
        LogDebugFn("Exit");
 
193
        return result;
 
194
}
 
195
 
 
196
 
 
197
/* only called from load key paths, so no locking */
 
198
TSS_UUID *
 
199
mc_get_uuid_by_pub(TCPA_STORE_PUBKEY *pub)
 
200
{
 
201
        TSS_UUID *ret;
 
202
        struct key_mem_cache *tmp;
 
203
 
 
204
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
205
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
206
                if (tmp->blob &&
 
207
                    tmp->blob->pubKey.keyLength == pub->keyLength &&
 
208
                    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
 
209
                        ret = &tmp->uuid;
 
210
                        return ret;
 
211
                }
 
212
        }
 
213
 
 
214
        return NULL;
 
215
}
 
216
 
 
217
TSS_RESULT
 
218
mc_get_handles_by_uuid(TSS_UUID *uuid, TCS_KEY_HANDLE *tcsHandle, TCPA_KEY_HANDLE *slot)
 
219
{
 
220
        struct key_mem_cache *tmp;
 
221
 
 
222
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
223
                if (!memcmp(&tmp->uuid, uuid, sizeof(TSS_UUID))) {
 
224
                        *tcsHandle = tmp->tcs_handle;
 
225
                        *slot = tmp->tpm_handle;
 
226
                        return TSS_SUCCESS;
 
227
                }
 
228
        }
 
229
 
 
230
        return TCSERR(TSS_E_FAIL);
 
231
}
 
232
 
 
233
TCS_KEY_HANDLE
 
234
mc_get_handle_by_encdata(BYTE *encData)
 
235
{
 
236
        struct key_mem_cache *tmp;
 
237
        TCS_KEY_HANDLE ret;
 
238
 
 
239
        MUTEX_LOCK(mem_cache_lock);
 
240
 
 
241
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
242
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
243
                if (!tmp->blob || tmp->blob->encSize == 0)
 
244
                        continue;
 
245
                if (!memcmp(tmp->blob->encData, encData, tmp->blob->encSize)) {
 
246
                        ret = tmp->tcs_handle;
 
247
                        MUTEX_UNLOCK(mem_cache_lock);
 
248
                        return ret;
 
249
                }
 
250
        }
 
251
        MUTEX_UNLOCK(mem_cache_lock);
 
252
        return 0;
 
253
}
 
254
 
 
255
TSS_RESULT
 
256
mc_update_encdata(BYTE *encData, BYTE *newEncData)
 
257
{
 
258
        struct key_mem_cache *tmp;
 
259
        BYTE *tmp_enc_data;
 
260
 
 
261
        MUTEX_LOCK(mem_cache_lock);
 
262
 
 
263
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
264
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
265
                if (!tmp->blob || tmp->blob->encSize == 0)
 
266
                        continue;
 
267
                if (!memcmp(tmp->blob->encData, encData, tmp->blob->encSize)) {
 
268
                        tmp_enc_data = (BYTE *)malloc(tmp->blob->encSize);
 
269
                        if (tmp_enc_data == NULL) {
 
270
                                LogError("malloc of %u bytes failed.", tmp->blob->encSize);
 
271
                                MUTEX_UNLOCK(mem_cache_lock);
 
272
                                return TCSERR(TSS_E_OUTOFMEMORY);
 
273
                        }
 
274
 
 
275
                        memcpy(tmp_enc_data, newEncData, tmp->blob->encSize);
 
276
                        free(tmp->blob->encData);
 
277
                        tmp->blob->encData = tmp_enc_data;
 
278
                        MUTEX_UNLOCK(mem_cache_lock);
 
279
                        return TSS_SUCCESS;
 
280
                }
 
281
        }
 
282
        MUTEX_UNLOCK(mem_cache_lock);
 
283
        LogError("Couldn't find requested encdata in mem cache");
 
284
        return TCSERR(TSS_E_INTERNAL_ERROR);
 
285
}
 
286
 
 
287
/*
 
288
 * only called from load key paths and the init (single thread time) path,
 
289
 * so no locking
 
290
 */
 
291
TSS_RESULT
 
292
mc_add_entry(TCS_KEY_HANDLE tcs_handle,
 
293
             TCPA_KEY_HANDLE tpm_handle,
 
294
             TSS_KEY *key_blob)
 
295
{
 
296
        struct key_mem_cache *entry, *tmp;
 
297
 
 
298
        /* Make sure the cache doesn't already have an entry for this key */
 
299
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
300
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
301
                if (tcs_handle == tmp->tcs_handle) {
 
302
                        return TSS_SUCCESS;
 
303
                }
 
304
        }
 
305
 
 
306
        /* Not found - we need to create a new entry */
 
307
        entry = (struct key_mem_cache *)calloc(1, sizeof(struct key_mem_cache));
 
308
        if (entry == NULL) {
 
309
                LogError("malloc of %zd bytes failed.", sizeof(struct key_mem_cache));
 
310
                return TCSERR(TSS_E_OUTOFMEMORY);
 
311
        }
 
312
 
 
313
        entry->tcs_handle = tcs_handle;
 
314
        if (tpm_handle != NULL_TPM_HANDLE)
 
315
                entry->time_stamp = getNextTimeStamp();
 
316
 
 
317
        entry->tpm_handle = tpm_handle;
 
318
 
 
319
        if (!key_blob)
 
320
                goto add;
 
321
 
 
322
        /* allocate space for the blob */
 
323
        entry->blob = calloc(1, sizeof(TSS_KEY));
 
324
        if (entry->blob == NULL) {
 
325
                LogError("malloc of %zd bytes failed.", sizeof(TSS_KEY));
 
326
                free(entry);
 
327
                return TCSERR(TSS_E_OUTOFMEMORY);
 
328
        }
 
329
        memcpy(entry->blob, key_blob, sizeof(TSS_KEY));
 
330
 
 
331
        /* allocate space for the key parameters if necessary */
 
332
        if (key_blob->algorithmParms.parmSize) {
 
333
                BYTE *tmp_parms = (BYTE *)malloc(key_blob->algorithmParms.parmSize);
 
334
                if (tmp_parms == NULL) {
 
335
                        LogError("malloc of %u bytes failed.", key_blob->algorithmParms.parmSize);
 
336
                        free(entry->blob);
 
337
                        free(entry);
 
338
                        return TCSERR(TSS_E_OUTOFMEMORY);
 
339
                }
 
340
                memcpy(tmp_parms, key_blob->algorithmParms.parms, key_blob->algorithmParms.parmSize);
 
341
                entry->blob->algorithmParms.parms = tmp_parms;
 
342
        }
 
343
        entry->blob->algorithmParms.parmSize = key_blob->algorithmParms.parmSize;
 
344
 
 
345
        /* allocate space for the public key */
 
346
        if (key_blob->pubKey.keyLength > 0) {
 
347
                entry->blob->pubKey.key = (BYTE *)malloc(key_blob->pubKey.keyLength);
 
348
                if (entry->blob->pubKey.key == NULL) {
 
349
                        LogError("malloc of %u bytes failed.", key_blob->pubKey.keyLength);
 
350
                        free(entry->blob->algorithmParms.parms);
 
351
                        free(entry->blob);
 
352
                        free(entry);
 
353
                        return TCSERR(TSS_E_OUTOFMEMORY);
 
354
                }
 
355
                memcpy(entry->blob->pubKey.key, key_blob->pubKey.key, key_blob->pubKey.keyLength);
 
356
        }
 
357
        entry->blob->pubKey.keyLength = key_blob->pubKey.keyLength;
 
358
 
 
359
        /* allocate space for the PCR info */
 
360
        if (key_blob->PCRInfoSize > 0) {
 
361
                entry->blob->PCRInfo = (BYTE *)malloc(key_blob->PCRInfoSize);
 
362
                if (entry->blob->PCRInfo == NULL) {
 
363
                        LogError("malloc of %u bytes failed.", key_blob->PCRInfoSize);
 
364
                        free(entry->blob->pubKey.key);
 
365
                        free(entry->blob->algorithmParms.parms);
 
366
                        free(entry->blob);
 
367
                        free(entry);
 
368
                        return TCSERR(TSS_E_OUTOFMEMORY);
 
369
                }
 
370
                memcpy(entry->blob->PCRInfo, key_blob->PCRInfo, key_blob->PCRInfoSize);
 
371
        }
 
372
        entry->blob->PCRInfoSize = key_blob->PCRInfoSize;
 
373
 
 
374
        /* allocate space for the encData if necessary */
 
375
        if (key_blob->encSize > 0) {
 
376
                entry->blob->encData = (BYTE *)malloc(key_blob->encSize);
 
377
                if (entry->blob->encData == NULL) {
 
378
                        LogError("malloc of %u bytes failed.", key_blob->encSize);
 
379
                        free(entry->blob->PCRInfo);
 
380
                        free(entry->blob->pubKey.key);
 
381
                        free(entry->blob->algorithmParms.parms);
 
382
                        free(entry->blob);
 
383
                        free(entry);
 
384
                        return TCSERR(TSS_E_OUTOFMEMORY);
 
385
                }
 
386
                memcpy(entry->blob->encData, key_blob->encData, key_blob->encSize);
 
387
        }
 
388
        entry->blob->encSize = key_blob->encSize;
 
389
add:
 
390
        /* add to the front of the list */
 
391
        entry->next = key_mem_cache_head;
 
392
        if (key_mem_cache_head) {
 
393
                /* set the reference count to 0 initially for all keys not being the SRK. Up
 
394
                 * the call chain, a reference to this mem cache entry will be set in the
 
395
                 * context object of the calling context and this reference count will be
 
396
                 * incremented there. */
 
397
                entry->ref_cnt = 0;
 
398
 
 
399
                key_mem_cache_head->prev = entry;
 
400
        } else {
 
401
                /* if we are the SRK, initially set the reference count to 1, so that it is
 
402
                 * always seen as loaded in the TPM. */
 
403
                entry->ref_cnt = 1;
 
404
        }
 
405
        key_mem_cache_head = entry;
 
406
 
 
407
        return TSS_SUCCESS;
 
408
}
 
409
 
 
410
/* caller must lock the mem cache before calling! */
 
411
TSS_RESULT
 
412
mc_remove_entry(TCS_KEY_HANDLE tcs_handle)
 
413
{
 
414
        struct key_mem_cache *cur;
 
415
 
 
416
        for (cur = key_mem_cache_head; cur; cur = cur->next) {
 
417
                if (cur->tcs_handle == tcs_handle) {
 
418
                        if (cur->blob) {
 
419
                                destroy_key_refs(cur->blob);
 
420
                                free(cur->blob);
 
421
                        }
 
422
 
 
423
                        if (cur->prev != NULL)
 
424
                                cur->prev->next = cur->next;
 
425
                        if (cur->next != NULL)
 
426
                                cur->next->prev = cur->prev;
 
427
 
 
428
                        if (cur == key_mem_cache_head)
 
429
                                key_mem_cache_head = cur->next;
 
430
                        free(cur);
 
431
 
 
432
                        return TSS_SUCCESS;
 
433
                }
 
434
        }
 
435
 
 
436
        return TCSERR(TSS_E_FAIL);
 
437
}
 
438
 
 
439
TSS_RESULT
 
440
mc_add_entry_init(TCS_KEY_HANDLE tcs_handle,
 
441
                  TCPA_KEY_HANDLE tpm_handle,
 
442
                  TSS_KEY *key_blob,
 
443
                  TSS_UUID *uuid)
 
444
{
 
445
        struct key_mem_cache *entry, *tmp;
 
446
 
 
447
        /* Make sure the cache doesn't already have an entry for this key */
 
448
        MUTEX_LOCK(mem_cache_lock);
 
449
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
450
                if (tcs_handle == tmp->tcs_handle) {
 
451
                        mc_remove_entry(tcs_handle);
 
452
                }
 
453
        }
 
454
        MUTEX_UNLOCK(mem_cache_lock);
 
455
 
 
456
        /* Not found - we need to create a new entry */
 
457
        entry = (struct key_mem_cache *)calloc(1, sizeof(struct key_mem_cache));
 
458
        if (entry == NULL) {
 
459
                LogError("malloc of %zd bytes failed.", sizeof(struct key_mem_cache));
 
460
                return TCSERR(TSS_E_OUTOFMEMORY);
 
461
        }
 
462
 
 
463
        entry->tcs_handle = tcs_handle;
 
464
        if (tpm_handle != NULL_TPM_HANDLE)
 
465
                entry->time_stamp = getNextTimeStamp();
 
466
 
 
467
        entry->tpm_handle = tpm_handle;
 
468
 
 
469
        if (key_blob) {
 
470
                /* allocate space for the blob */
 
471
                entry->blob = malloc(sizeof(TSS_KEY));
 
472
                if (entry->blob == NULL) {
 
473
                        LogError("malloc of %zd bytes failed.", sizeof(TSS_KEY));
 
474
                        free(entry);
 
475
                        return TCSERR(TSS_E_OUTOFMEMORY);
 
476
                }
 
477
 
 
478
                memcpy(entry->blob, key_blob, sizeof(TSS_KEY));
 
479
 
 
480
                /* allocate space for the key parameters if necessary */
 
481
                if (key_blob->algorithmParms.parmSize) {
 
482
                        BYTE *tmp_parms = (BYTE *)malloc(key_blob->algorithmParms.parmSize);
 
483
                        if (tmp_parms == NULL) {
 
484
                                LogError("malloc of %u bytes failed.",
 
485
                                         key_blob->algorithmParms.parmSize);
 
486
                                free(entry->blob);
 
487
                                free(entry);
 
488
                                return TCSERR(TSS_E_OUTOFMEMORY);
 
489
                        }
 
490
                        memcpy(tmp_parms, key_blob->algorithmParms.parms,
 
491
                               key_blob->algorithmParms.parmSize);
 
492
                        entry->blob->algorithmParms.parms = tmp_parms;
 
493
                }
 
494
 
 
495
                /* allocate space for the public key */
 
496
                entry->blob->pubKey.key = (BYTE *)malloc(key_blob->pubKey.keyLength);
 
497
                if (entry->blob->pubKey.key == NULL) {
 
498
                        LogError("malloc of %u bytes failed.", key_blob->pubKey.keyLength);
 
499
                        free(entry->blob);
 
500
                        free(entry);
 
501
                        return TCSERR(TSS_E_OUTOFMEMORY);
 
502
                }
 
503
                memcpy(entry->blob->pubKey.key, key_blob->pubKey.key, key_blob->pubKey.keyLength);
 
504
 
 
505
                /* allocate space for the encData if necessary */
 
506
                if (key_blob->encSize != 0) {
 
507
                        entry->blob->encData = (BYTE *)malloc(key_blob->encSize);
 
508
                        if (entry->blob->encData == NULL) {
 
509
                                LogError("malloc of %u bytes failed.", key_blob->encSize);
 
510
                                free(entry->blob->pubKey.key);
 
511
                                free(entry->blob);
 
512
                                free(entry);
 
513
                                return TCSERR(TSS_E_OUTOFMEMORY);
 
514
                        }
 
515
                        memcpy(entry->blob->encData, key_blob->encData, key_blob->encSize);
 
516
                }
 
517
                entry->blob->encSize = key_blob->encSize;
 
518
        }
 
519
 
 
520
        memcpy(&entry->uuid, uuid, sizeof(TSS_UUID));
 
521
 
 
522
        MUTEX_LOCK(mem_cache_lock);
 
523
 
 
524
        entry->next = key_mem_cache_head;
 
525
        if (key_mem_cache_head)
 
526
                key_mem_cache_head->prev = entry;
 
527
 
 
528
        entry->ref_cnt = 1;
 
529
        key_mem_cache_head = entry;
 
530
        MUTEX_UNLOCK(mem_cache_lock);
 
531
 
 
532
        return TSS_SUCCESS;
 
533
}
 
534
 
 
535
/* only called from evict key paths, so no locking */
 
536
TSS_RESULT
 
537
mc_set_slot_by_slot(TCPA_KEY_HANDLE old_handle, TCPA_KEY_HANDLE new_handle)
 
538
{
 
539
        struct key_mem_cache *tmp;
 
540
 
 
541
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
542
                if (tmp->tpm_handle == old_handle) {
 
543
                        LogDebugFn("Set TCS key 0x%x, old TPM handle: 0x%x "
 
544
                                   "new TPM handle: 0x%x", tmp->tcs_handle,
 
545
                                   old_handle, new_handle);
 
546
                        if (new_handle == NULL_TPM_HANDLE)
 
547
                                tmp->time_stamp = 0;
 
548
                        else
 
549
                                tmp->time_stamp = getNextTimeStamp();
 
550
                        tmp->tpm_handle = new_handle;
 
551
                        return TSS_SUCCESS;
 
552
                }
 
553
        }
 
554
 
 
555
        return TCSERR(TSS_E_FAIL);
 
556
}
 
557
 
 
558
/* only called from load key paths, so no locking */
 
559
TSS_RESULT
 
560
mc_set_slot_by_handle(TCS_KEY_HANDLE tcs_handle, TCPA_KEY_HANDLE tpm_handle)
 
561
{
 
562
        struct key_mem_cache *tmp;
 
563
 
 
564
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
565
                LogDebug("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
566
                if (tmp->tcs_handle == tcs_handle) {
 
567
                        if (tpm_handle == NULL_TPM_HANDLE)
 
568
                                tmp->time_stamp = 0;
 
569
                        else
 
570
                                tmp->time_stamp = getNextTimeStamp();
 
571
                        tmp->tpm_handle = tpm_handle;
 
572
                        return TSS_SUCCESS;
 
573
                }
 
574
        }
 
575
 
 
576
        return TCSERR(TSS_E_FAIL);
 
577
}
 
578
 
 
579
/* the beginnings of a key manager start here ;-) */
 
580
 
 
581
TSS_RESULT
 
582
key_mgr_evict(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey)
 
583
{
 
584
        TSS_RESULT result = TCS_SUCCESS;
 
585
 
 
586
        if ((result = ctx_remove_key_loaded(hContext, hKey)))
 
587
                return result;
 
588
 
 
589
        if ((result = key_mgr_dec_ref_count(hKey)))
 
590
                return result;
 
591
 
 
592
        key_mgr_ref_count();
 
593
 
 
594
        return result;
 
595
}
 
596
 
 
597
TSS_RESULT
 
598
key_mgr_load_by_blob(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hUnwrappingKey,
 
599
                     UINT32 cWrappedKeyBlob, BYTE *rgbWrappedKeyBlob,
 
600
                     TPM_AUTH *pAuth, TCS_KEY_HANDLE *phKeyTCSI, TCS_KEY_HANDLE *phKeyHMAC)
 
601
{
 
602
        TSS_RESULT result;
 
603
 
 
604
        MUTEX_LOCK(mem_cache_lock);
 
605
 
 
606
        if (TPM_VERSION_IS(1,2)) {
 
607
                result = TCSP_LoadKey2ByBlob_Internal(hContext, hUnwrappingKey, cWrappedKeyBlob,
 
608
                                                      rgbWrappedKeyBlob, pAuth, phKeyTCSI);
 
609
        } else {
 
610
                result = TCSP_LoadKeyByBlob_Internal(hContext, hUnwrappingKey, cWrappedKeyBlob,
 
611
                                                     rgbWrappedKeyBlob, pAuth, phKeyTCSI,
 
612
                                                     phKeyHMAC);
 
613
        }
 
614
 
 
615
        MUTEX_UNLOCK(mem_cache_lock);
 
616
 
 
617
        return result;
 
618
}
 
619
 
 
620
/* create a reference to one key. This is called from the key_mgr_load_*
 
621
 * functions only, so no locking is done.
 
622
 */
 
623
TSS_RESULT
 
624
key_mgr_inc_ref_count(TCS_KEY_HANDLE key_handle)
 
625
{
 
626
        struct key_mem_cache *cur;
 
627
 
 
628
        for (cur = key_mem_cache_head; cur; cur = cur->next) {
 
629
                LogDebugFn("TCSD mem_cached handle: 0x%x", cur->tcs_handle);
 
630
                if (cur->tcs_handle == key_handle) {
 
631
                        cur->ref_cnt++;
 
632
                        return TSS_SUCCESS;
 
633
                }
 
634
        }
 
635
 
 
636
        return TCSERR(TSS_E_FAIL);
 
637
}
 
638
 
 
639
/* de-reference one key.  This is called by the context routines, so
 
640
 * locking is necessary.
 
641
 */
 
642
TSS_RESULT
 
643
key_mgr_dec_ref_count(TCS_KEY_HANDLE key_handle)
 
644
{
 
645
        struct key_mem_cache *cur;
 
646
 
 
647
        MUTEX_LOCK(mem_cache_lock);
 
648
 
 
649
        for (cur = key_mem_cache_head; cur; cur = cur->next) {
 
650
                if (cur->tcs_handle == key_handle) {
 
651
                        cur->ref_cnt--;
 
652
                        LogDebugFn("decrementing ref cnt for key 0x%x",
 
653
                                   key_handle);
 
654
                        MUTEX_UNLOCK(mem_cache_lock);
 
655
                        return TSS_SUCCESS;
 
656
                }
 
657
        }
 
658
 
 
659
        MUTEX_UNLOCK(mem_cache_lock);
 
660
        return TCSERR(TSS_E_FAIL);
 
661
}
 
662
 
 
663
/* run through the global list and free any keys with reference counts of 0 */
 
664
void
 
665
key_mgr_ref_count()
 
666
{
 
667
        struct key_mem_cache *tmp, *cur;
 
668
 
 
669
        MUTEX_LOCK(mem_cache_lock);
 
670
 
 
671
        for (cur = key_mem_cache_head; cur;) {
 
672
                if (cur->ref_cnt == 0) {
 
673
                        if (cur->tpm_handle != NULL_TPM_HANDLE) {
 
674
                                LogDebugFn("Key 0x%x being freed from TPM", cur->tpm_handle);
 
675
                                internal_EvictByKeySlot(cur->tpm_handle);
 
676
                        }
 
677
                        LogDebugFn("Key 0x%x being freed", cur->tcs_handle);
 
678
                        if (cur->blob) {
 
679
                                destroy_key_refs(cur->blob);
 
680
                                free(cur->blob);
 
681
                        }
 
682
                        if (cur->prev != NULL)
 
683
                                cur->prev->next = cur->next;
 
684
                        if (cur->next != NULL)
 
685
                                cur->next->prev = cur->prev;
 
686
 
 
687
                        tmp = cur;
 
688
                        if (cur == key_mem_cache_head)
 
689
                                key_mem_cache_head = cur->next;
 
690
                        cur = cur->next;
 
691
                        free(tmp);
 
692
                } else {
 
693
                        cur = cur->next;
 
694
                }
 
695
        }
 
696
 
 
697
        MUTEX_UNLOCK(mem_cache_lock);
 
698
}
 
699
 
 
700
/* only called from load key paths, so no locking */
 
701
TCPA_KEY_HANDLE
 
702
mc_get_slot_by_handle(TCS_KEY_HANDLE tcs_handle)
 
703
{
 
704
        struct key_mem_cache *tmp;
 
705
        TCS_KEY_HANDLE ret;
 
706
 
 
707
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
708
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
709
                if (tmp->tcs_handle == tcs_handle) {
 
710
                        ret = tmp->tpm_handle;
 
711
                        return ret;
 
712
                }
 
713
        }
 
714
 
 
715
        LogDebugFn("returning NULL_TPM_HANDLE");
 
716
        return NULL_TPM_HANDLE;
 
717
}
 
718
 
 
719
/* called from functions outside the load key path */
 
720
TCPA_KEY_HANDLE
 
721
mc_get_slot_by_handle_lock(TCS_KEY_HANDLE tcs_handle)
 
722
{
 
723
        struct key_mem_cache *tmp;
 
724
        TCS_KEY_HANDLE ret;
 
725
 
 
726
        MUTEX_LOCK(mem_cache_lock);
 
727
 
 
728
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
729
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
730
                if (tmp->tcs_handle == tcs_handle) {
 
731
                        ret = tmp->tpm_handle;
 
732
                        MUTEX_UNLOCK(mem_cache_lock);
 
733
                        return ret;
 
734
                }
 
735
        }
 
736
 
 
737
        MUTEX_UNLOCK(mem_cache_lock);
 
738
        LogDebugFn("returning NULL_TPM_HANDLE");
 
739
        return NULL_TPM_HANDLE;
 
740
}
 
741
 
 
742
/* only called from load key paths, so no locking */
 
743
TCPA_KEY_HANDLE
 
744
mc_get_slot_by_pub(TCPA_STORE_PUBKEY *pub)
 
745
{
 
746
        struct key_mem_cache *tmp;
 
747
        TCPA_KEY_HANDLE ret;
 
748
 
 
749
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
750
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
751
                if (tmp->blob &&
 
752
                    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
 
753
                        ret = tmp->tpm_handle;
 
754
                        return ret;
 
755
                }
 
756
        }
 
757
 
 
758
        LogDebugFn("returning NULL_TPM_HANDLE");
 
759
        return NULL_TPM_HANDLE;
 
760
}
 
761
 
 
762
/* Check the mem cache for a key with public key pub. If a parent TCS key handle
 
763
 * is passed in, make sure the parent of the key find matches it, else return
 
764
 * key not found */
 
765
/* only called from load key paths, so no locking */
 
766
TCS_KEY_HANDLE
 
767
mc_get_handle_by_pub(TCPA_STORE_PUBKEY *pub, TCS_KEY_HANDLE parent)
 
768
{
 
769
        struct key_mem_cache *tmp;
 
770
 
 
771
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
772
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
773
                if (tmp->blob &&
 
774
                    pub->keyLength == tmp->blob->pubKey.keyLength &&
 
775
                    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
 
776
                        if (parent) {
 
777
                                if (!tmp->parent)
 
778
                                        continue;
 
779
                                if (parent == tmp->parent->tcs_handle)
 
780
                                        return tmp->tcs_handle;
 
781
                        } else
 
782
                                return tmp->tcs_handle;
 
783
                }
 
784
        }
 
785
 
 
786
        LogDebugFn("returning NULL_TCS_HANDLE");
 
787
        return NULL_TCS_HANDLE;
 
788
}
 
789
 
 
790
/* only called from load key paths, so no locking */
 
791
TCPA_STORE_PUBKEY *
 
792
mc_get_parent_pub_by_pub(TCPA_STORE_PUBKEY *pub)
 
793
{
 
794
        struct key_mem_cache *tmp;
 
795
        TCPA_STORE_PUBKEY *ret = NULL;
 
796
 
 
797
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
798
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
799
                if (tmp->tcs_handle == TPM_KEYHND_SRK) {
 
800
                        LogDebugFn("skipping the SRK");
 
801
                        continue;
 
802
                }
 
803
                if (tmp->blob &&
 
804
                    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
 
805
                        if (tmp->parent && tmp->parent->blob) {
 
806
                                ret = &tmp->parent->blob->pubKey;
 
807
                                LogDebugFn("Success");
 
808
                        } else {
 
809
                                LogError("parent pointer not set in key mem cache object w/ TCS "
 
810
                                         "handle: 0x%x", tmp->tcs_handle);
 
811
                        }
 
812
                        return ret;
 
813
                }
 
814
        }
 
815
 
 
816
        LogDebugFn("returning NULL TCPA_STORE_PUBKEY");
 
817
        return NULL;
 
818
}
 
819
 
 
820
/* only called from load key paths, so no locking */
 
821
TSS_RESULT
 
822
mc_get_blob_by_pub(TCPA_STORE_PUBKEY *pub, TSS_KEY **ret_key)
 
823
{
 
824
        struct key_mem_cache *tmp;
 
825
 
 
826
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
827
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
828
                if (tmp->blob &&
 
829
                    !memcmp(tmp->blob->pubKey.key, pub->key, pub->keyLength)) {
 
830
                        *ret_key = tmp->blob;
 
831
                        return TSS_SUCCESS;
 
832
                }
 
833
        }
 
834
 
 
835
        LogDebugFn("returning TSS_E_FAIL");
 
836
        return TCSERR(TSS_E_FAIL);
 
837
}
 
838
 
 
839
/* only called from load key paths, so no locking */
 
840
TCS_KEY_HANDLE
 
841
mc_get_handle_by_slot(TCPA_KEY_HANDLE tpm_handle)
 
842
{
 
843
        struct key_mem_cache *tmp;
 
844
        TCS_KEY_HANDLE ret;
 
845
 
 
846
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
847
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
848
                if (tmp->tpm_handle == tpm_handle) {
 
849
                        ret = tmp->tcs_handle;
 
850
                        return ret;
 
851
                }
 
852
        }
 
853
 
 
854
        return NULL_TCS_HANDLE;
 
855
}
 
856
 
 
857
/* only called from load key paths, so no locking */
 
858
TSS_RESULT
 
859
mc_update_time_stamp(TCPA_KEY_HANDLE tpm_handle)
 
860
{
 
861
        struct key_mem_cache *tmp;
 
862
        TSS_RESULT ret = TCSERR(TSS_E_FAIL);
 
863
 
 
864
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
865
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
866
                if (tmp->tpm_handle == tpm_handle) {
 
867
                        tmp->time_stamp = getNextTimeStamp();
 
868
                        ret = TSS_SUCCESS;
 
869
                        break;
 
870
                }
 
871
        }
 
872
 
 
873
        return ret;
 
874
}
 
875
 
 
876
/* Right now this evicts the LRU key assuming it's not the parent */
 
877
TSS_RESULT
 
878
evictFirstKey(TCS_KEY_HANDLE parent_tcs_handle)
 
879
{
 
880
        struct key_mem_cache *tmp;
 
881
        TCS_KEY_HANDLE tpm_handle_to_evict = NULL_TPM_HANDLE;
 
882
        UINT32 smallestTimeStamp = ~(0U);       /* largest */
 
883
        TSS_RESULT result;
 
884
        UINT32 count;
 
885
 
 
886
        /* First, see if there are any known keys worth evicting */
 
887
        if ((result = clearUnknownKeys(InternalContext, &count)))
 
888
                return result;
 
889
 
 
890
        if (count > 0) {
 
891
                LogDebugFn("Evicted %u unknown keys", count);
 
892
                return TSS_SUCCESS;
 
893
        }
 
894
 
 
895
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
896
                if (tmp->tpm_handle != NULL_TPM_HANDLE &&       /* not already evicted */
 
897
                    tmp->tpm_handle != SRK_TPM_HANDLE &&        /* not the srk */
 
898
                    tmp->tcs_handle != parent_tcs_handle &&     /* not my parent */
 
899
                    tmp->time_stamp < smallestTimeStamp) {      /* is the smallest time
 
900
                                                                   stamp so far */
 
901
                        tpm_handle_to_evict = tmp->tpm_handle;
 
902
                        smallestTimeStamp = tmp->time_stamp;
 
903
                }
 
904
        }
 
905
 
 
906
        if (tpm_handle_to_evict != NULL_TCS_HANDLE) {
 
907
                if ((result = internal_EvictByKeySlot(tpm_handle_to_evict)))
 
908
                        return result;
 
909
 
 
910
                LogDebugFn("Evicted key w/ TPM handle 0x%x", tpm_handle_to_evict);
 
911
                result = mc_set_slot_by_slot(tpm_handle_to_evict, NULL_TPM_HANDLE);
 
912
        } else
 
913
                return TSS_SUCCESS;
 
914
 
 
915
        return result;
 
916
}
 
917
 
 
918
TSS_BOOL
 
919
isKeyLoaded(TCPA_KEY_HANDLE keySlot)
 
920
{
 
921
        UINT64 offset;
 
922
        UINT32 i;
 
923
        TCPA_KEY_HANDLE_LIST keyList;
 
924
        UINT32 respSize;
 
925
        BYTE *resp;
 
926
        TSS_RESULT result;
 
927
 
 
928
        if (keySlot == SRK_TPM_HANDLE) {
 
929
                return TRUE;
 
930
        }
 
931
 
 
932
        if ((result = TCSP_GetCapability_Internal(InternalContext, TCPA_CAP_KEY_HANDLE, 0, NULL,
 
933
                                                  &respSize, &resp)))
 
934
                goto not_loaded;
 
935
 
 
936
        offset = 0;
 
937
        UnloadBlob_KEY_HANDLE_LIST(&offset, resp, &keyList);
 
938
        free(resp);
 
939
        for (i = 0; i < keyList.loaded; i++) {
 
940
                LogDebugFn("loaded TPM key handle: 0x%x", keyList.handle[i]);
 
941
                if (keyList.handle[i] == keySlot) {
 
942
                        free(keyList.handle);
 
943
                        return TRUE;
 
944
                }
 
945
        }
 
946
 
 
947
        free(keyList.handle);
 
948
 
 
949
not_loaded:
 
950
        LogDebugFn("Key is not loaded, changing slot");
 
951
        mc_set_slot_by_slot(keySlot, NULL_TPM_HANDLE);
 
952
        return FALSE;
 
953
}
 
954
 
 
955
/* all calls to LoadKeyShim are inside locks */
 
956
TSS_RESULT
 
957
LoadKeyShim(TCS_CONTEXT_HANDLE hContext, TCPA_STORE_PUBKEY *pubKey,
 
958
            TSS_UUID *parentUuid, TCPA_KEY_HANDLE *slotOut)
 
959
{
 
960
 
 
961
        TCPA_STORE_PUBKEY *parentPub;
 
962
        UINT32 result;
 
963
        TCPA_KEY_HANDLE keySlot;
 
964
        TCPA_KEY_HANDLE parentSlot;
 
965
        TCS_KEY_HANDLE tcsKeyHandle;
 
966
        TSS_KEY *myKey;
 
967
        UINT64 offset;
 
968
        TCS_KEY_HANDLE parentHandle;
 
969
        BYTE keyBlob[1024];
 
970
 
 
971
        LogDebugFn("calling mc_get_slot_by_pub");
 
972
 
 
973
        /* If I'm loaded, then no point being here.  Get the slot and return */
 
974
        keySlot = mc_get_slot_by_pub(pubKey);
 
975
        if (keySlot != NULL_TPM_HANDLE && isKeyLoaded(keySlot)) {
 
976
                *slotOut = keySlot;
 
977
                return TSS_SUCCESS;
 
978
        }
 
979
 
 
980
        /*
 
981
         * Before proceeding, the parent must be loaded.
 
982
         * If the parent is registered, then it can be loaded by UUID.
 
983
         * If not, then the shim will be called to load it's parent and then try
 
984
         * to load it based on the persistent store.
 
985
         */
 
986
 
 
987
        LogDebugFn("calling mc_get_parent_pub_by_pub");
 
988
        /* Check if the Key is in the memory cache */
 
989
        if ((parentPub = mc_get_parent_pub_by_pub(pubKey)) == NULL) {
 
990
#if 0
 
991
                LogDebugFn("parentPub is NULL");
 
992
                /* If parentUUID is not handed in, then this key was never loaded and isn't reg'd */
 
993
                if (parentUuid == NULL)
 
994
                        return TCSERR(TCS_E_KM_LOADFAILED);
 
995
 
 
996
                LogDebugFn("calling TCSP_LoadKeyByUUID_Internal");
 
997
                /* This will try to load my parent by UUID */
 
998
                if ((result = TCSP_LoadKeyByUUID_Internal(hContext, parentUuid, NULL, &parentSlot)))
 
999
                        return result;
 
1000
#else
 
1001
                return TCSERR(TCS_E_KM_LOADFAILED);
 
1002
#endif
 
1003
        } else {
 
1004
                LogDebugFn("calling LoadKeyShim");
 
1005
                if ((result = LoadKeyShim(hContext, parentPub, NULL, &parentSlot)))
 
1006
                        return result;
 
1007
        }
 
1008
 
 
1009
        /*
 
1010
         * Now that the parent is loaded, I can load myself.
 
1011
         * If I'm registered, that's by UUID.  If I'm not,
 
1012
         * that's by blob.  If there is no persistent storage data, then I cannot be
 
1013
         * loaded by blob. The user must have some point loaded this key manually.
 
1014
         */
 
1015
 
 
1016
        /* check the mem cache */
 
1017
        if (mc_get_blob_by_pub(pubKey, &myKey) == TSS_SUCCESS) {
 
1018
                parentHandle = mc_get_handle_by_slot(parentSlot);
 
1019
                if (parentHandle == 0)
 
1020
                        return TCSERR(TCS_E_KM_LOADFAILED);
 
1021
 
 
1022
                offset = 0;
 
1023
                LoadBlob_TSS_KEY(&offset, keyBlob, myKey);
 
1024
                if ((result = TCSP_LoadKeyByBlob_Internal(hContext, parentHandle, offset, keyBlob,
 
1025
                                                          NULL, &tcsKeyHandle, slotOut)))
 
1026
                        return result;
 
1027
 
 
1028
                return ctx_mark_key_loaded(hContext, tcsKeyHandle);
 
1029
#if TSS_BUILD_PS
 
1030
        } else {
 
1031
                TSS_UUID *uuid;
 
1032
 
 
1033
                /* check registered */
 
1034
                if (ps_is_pub_registered(pubKey) == FALSE)
 
1035
                        return TCSERR(TCS_E_KM_LOADFAILED);
 
1036
                //uuid = mc_get_uuid_by_pub(pubKey); // XXX pub is not in MC
 
1037
                if ((result = ps_get_uuid_by_pub(pubKey, &uuid)))
 
1038
                        return result;
 
1039
 
 
1040
                if ((result = TCSP_LoadKeyByUUID_Internal(hContext, uuid, NULL, &tcsKeyHandle))) {
 
1041
                        free(uuid);
 
1042
                        return result;
 
1043
                }
 
1044
                free(uuid);
 
1045
                *slotOut = mc_get_slot_by_handle(tcsKeyHandle);
 
1046
 
 
1047
                return ctx_mark_key_loaded(hContext, tcsKeyHandle);
 
1048
#endif
 
1049
        }
 
1050
 
 
1051
        return TCSERR(TCS_E_KM_LOADFAILED);
 
1052
}
 
1053
 
 
1054
TSS_RESULT
 
1055
owner_evict_init()
 
1056
{
 
1057
        TSS_RESULT result = TSS_SUCCESS;
 
1058
        TCPA_KEY_HANDLE_LIST keyList = { 0, NULL };
 
1059
        BYTE *respData = NULL, ownerEvictCtr = 0;
 
1060
        UINT32 respDataSize = 0, i;
 
1061
        UINT64 offset = 0;
 
1062
 
 
1063
        /* If we're a 1.1 TPM, we can exit immediately since only 1.2+ supports owner evict */
 
1064
        if (TPM_VERSION_IS(1,1))
 
1065
                return TSS_SUCCESS;
 
1066
 
 
1067
        if ((result = TCSP_GetCapability_Internal(InternalContext, TPM_CAP_KEY_HANDLE, 0, NULL,
 
1068
                                                  &respDataSize, &respData)))
 
1069
                return result;
 
1070
 
 
1071
        if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList))) {
 
1072
                free(respData);
 
1073
                return result;
 
1074
        }
 
1075
 
 
1076
        free(respData);
 
1077
        for (i = 0; i < keyList.loaded; i++) {
 
1078
                UINT64 offset = 0;
 
1079
                UINT32 keyHandle;
 
1080
 
 
1081
                LoadBlob_UINT32(&offset, keyList.handle[i], (BYTE *)&keyHandle);
 
1082
                /* get the ownerEvict flag for this key handle */
 
1083
                if ((result = TCSP_GetCapability_Internal(InternalContext, TPM_CAP_KEY_STATUS,
 
1084
                                                          sizeof(UINT32), (BYTE *)&keyHandle,
 
1085
                                                          &respDataSize, &respData))) {
 
1086
                        free(keyList.handle);
 
1087
                        return result;
 
1088
                }
 
1089
 
 
1090
                if (*(TPM_BOOL *)respData == TRUE) {
 
1091
                        TSS_UUID uuid = TSS_UUID_OWNEREVICT(ownerEvictCtr);
 
1092
 
 
1093
                        LogDebugFn("Found an owner evict key, assigned uuid %hhu", ownerEvictCtr);
 
1094
                        if ((result = mc_add_entry_init(getNextTcsKeyHandle(), keyList.handle[i],
 
1095
                                                        NULL, &uuid))) {
 
1096
                                free(keyList.handle);
 
1097
                                return result;
 
1098
                        }
 
1099
                        ownerEvictCtr++;
 
1100
                }
 
1101
        }
 
1102
 
 
1103
        return result;
 
1104
}
 
1105
 
 
1106
/* find next lowest OWNEREVICT uuid */
 
1107
TSS_RESULT
 
1108
mc_find_next_ownerevict_uuid(TSS_UUID *uuid)
 
1109
{
 
1110
        TCS_KEY_HANDLE tmpKey;
 
1111
        TCPA_KEY_HANDLE tmpSlot;
 
1112
        UINT16 seed = 0;
 
1113
        TSS_RESULT result = TCSERR(TSS_E_FAIL);
 
1114
 
 
1115
        MUTEX_LOCK(mem_cache_lock);
 
1116
 
 
1117
        for (seed = 0; seed <= 255; seed++) {
 
1118
                TSS_UUID tmpUuid = TSS_UUID_OWNEREVICT(seed);
 
1119
 
 
1120
                /* if UUID is found, continue on, trying the next UUID */
 
1121
                if (!mc_get_handles_by_uuid(&tmpUuid, &tmpKey, &tmpSlot))
 
1122
                        continue;
 
1123
 
 
1124
                /* UUID is not found, so its the first one available */
 
1125
                memcpy(uuid, &tmpUuid, sizeof(TSS_UUID));
 
1126
                result = TSS_SUCCESS;
 
1127
                break;
 
1128
        }
 
1129
 
 
1130
        MUTEX_UNLOCK(mem_cache_lock);
 
1131
        return result;
 
1132
}
 
1133
 
 
1134
TSS_RESULT
 
1135
mc_set_uuid(TCS_KEY_HANDLE tcs_handle, TSS_UUID *uuid)
 
1136
{
 
1137
        struct key_mem_cache *tmp;
 
1138
        TSS_RESULT result = TCSERR(TSS_E_FAIL);
 
1139
 
 
1140
        MUTEX_LOCK(mem_cache_lock);
 
1141
 
 
1142
        LogDebugFn("looking for 0x%x", tcs_handle);
 
1143
 
 
1144
        for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
 
1145
                LogDebugFn("TCSD mem_cached handle: 0x%x", tmp->tcs_handle);
 
1146
                if (tmp->tcs_handle == tcs_handle) {
 
1147
                        LogDebugFn("Handle found, re-setting UUID");
 
1148
                        memcpy(&tmp->uuid, uuid, sizeof(TSS_UUID));
 
1149
                        result = TSS_SUCCESS;
 
1150
                        break;
 
1151
                }
 
1152
        }
 
1153
        MUTEX_UNLOCK(mem_cache_lock);
 
1154
 
 
1155
        return result;
 
1156
}