3
* Licensed Materials - Property of IBM
5
* trousers - An open source TCG Software Stack
7
* (C) Copyright International Business Machines Corp. 2004-2006
14
#include "trousers/tss.h"
15
#include "trousers_types.h"
19
#include "tcs_utils.h"
20
#include "tcs_int_literals.h"
22
struct key_mem_cache *key_mem_cache_head = NULL;
24
TSS_UUID NULL_UUID = { 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0 } };
28
add_cache_entry(TCS_CONTEXT_HANDLE hContext,
30
TCS_KEY_HANDLE hParent,
36
TCS_KEY_HANDLE tcsHandle;
43
if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key)))
46
if ((tcsHandle = mc_get_handle_by_pub(&key.pubKey, hParent)) == NULL_TCS_HANDLE) {
49
mc_set_slot_by_handle(tcsHandle, hSlot);
55
LogDebugFn("No existing key handle for this key, creating new one...");
56
/* Get a new TCS Key Handle */
57
tcsHandle = getNextTcsKeyHandle();
58
LogDebugFn("calling mc_add_entry, TCS handle: 0x%x, TPM handle 0x%x", tcsHandle, hSlot);
60
if ((result = mc_add_entry(tcsHandle, hSlot, pKey)))
63
LogDebugFn("ctx_mark_key_loaded");
64
if (ctx_mark_key_loaded(hContext, tcsHandle)) {
65
LogError("Error marking key as loaded");
66
result = TCSERR(TSS_E_INTERNAL_ERROR);
70
if ((result = mc_set_parent_by_handle(tcsHandle, hParent))) {
71
LogError("mc_set_parent_by_handle failed.");
78
destroy_key_refs(&key);
82
/* Check that the context has this key loaded and return the associated slot. Do not search PS if
83
* the key is not found */
85
get_slot_lite(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey, TPM_KEY_HANDLE *out)
87
if (ctx_has_key_loaded(hContext, hKey)) {
88
if ((*out = mc_get_slot_by_handle(hKey)) == NULL_TPM_HANDLE)
89
return TCSERR(TCS_E_INVALID_KEY);
94
return TCSERR(TCS_E_INVALID_KEY);
97
/* XXX Can get_slot be merged with ensureKeyIsLoaded? */
99
/* Given a handle, get_slot searches the mem cache for a mapping to a TPM handle. If there is no
100
* mapping, it looks up the pub key of the handle and attempts to load it by finding its pub key
101
* in the persistent store. If that's not found, return error. */
103
get_slot(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey, TPM_KEY_HANDLE *out)
105
TSS_RESULT result = TSS_SUCCESS;
106
TPM_STORE_PUBKEY *pub = NULL;
109
LogDebugFn("calling mc_get_slot_by_handle");
110
if ((slot = mc_get_slot_by_handle(hKey)) == NULL_TPM_HANDLE) {
111
LogDebugFn("calling mc_get_pub_by_slot");
112
if ((pub = mc_get_pub_by_slot(hKey)) == NULL)
113
return TCSERR(TCS_E_KM_LOADFAILED);
115
LogDebugFn("calling LoadKeyShim");
116
/* Otherwise, try to load it using the shim */
117
result = LoadKeyShim(hContext, pub, NULL, &slot);
126
/* load_key_init is the common entry point for all load key requests to the TCSD. These can come in
127
* as straight load or load2 requests, or through a transport session.
129
* We'll always attempt to load the key if
130
* A) It requires auth (load should fail if auth is bad, even when its already been loaded by
132
* B) Its in a transport session (the key blob is encrypted)
134
* Otherwise if the key is already loaded by another thread and it doesn't require auth, then we
135
* will just set *load_key to FALSE, telling the caller that there's no need to send anything to
139
load_key_init(TPM_COMMAND_CODE ord,
140
TCS_CONTEXT_HANDLE hContext,
141
TCS_KEY_HANDLE parent_handle,
149
TCS_KEY_HANDLE* handle,
150
TPM_KEY_HANDLE* slot)
152
TSS_RESULT result = TSS_SUCCESS;
155
TPM_KEY_HANDLE tpm_slot;
156
TCS_KEY_HANDLE tcs_handle;
162
memset(&key, 0, sizeof(TSS_KEY));
163
if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key)))
167
if (!auth && !encrypted) {
168
LogDebugFn("Checking if LoadKeyByBlob can be avoided by using existing key");
170
if ((tcs_handle = mc_get_handle_by_pub(&key.pubKey, parent_handle))) {
171
LogDebugFn("tcs key handle exists");
173
tpm_slot = mc_get_slot_by_handle(tcs_handle);
174
if (tpm_slot && (isKeyLoaded(tpm_slot) == TRUE)) {
175
LogDebugFn("Don't need to reload this key.");
176
*handle = tcs_handle;
185
LogDebugFn("calling canILoadThisKey");
187
if ((result = canILoadThisKey(&(key.algorithmParms), &canLoad)))
190
if (canLoad == FALSE) {
191
LogDebugFn("calling evictFirstKey");
192
/* Evict a key that isn't the parent */
193
if ((result = evictFirstKey(parent_handle)))
200
destroy_key_refs(&key);
206
load_key_final(TCS_CONTEXT_HANDLE hContext,
207
TCS_KEY_HANDLE parent_handle,
208
TCS_KEY_HANDLE* tcs_handle,
212
if (*tcs_handle == NULL_TCS_HANDLE)
213
return add_cache_entry(hContext, blob, parent_handle, slot, tcs_handle);
215
return mc_set_slot_by_handle(*tcs_handle, slot);
219
canILoadThisKey(TCPA_KEY_PARMS *parms, TSS_BOOL *b)
225
UINT32 respDataLength;
229
LoadBlob_KEY_PARMS(&offset, subCap, parms);
230
subCapLength = offset;
232
if ((result = TCSP_GetCapability_Internal(InternalContext, TCPA_CAP_CHECK_LOADED,
233
subCapLength, subCap, &respDataLength,
242
LogDebugFn("%s", *b ? "YES" : "NO");
248
internal_EvictByKeySlot(TCPA_KEY_HANDLE slot)
253
BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
255
LogDebug("Entering Evict Key");
257
if (TPM_VERSION_IS(1,2)) {
258
LogDebugFn("Evicting key using FlushSpecific for TPM 1.2");
260
return TCSP_FlushSpecific_Common(slot, TPM_RT_KEY);
264
LoadBlob_UINT32(&offset, slot, txBlob);
265
LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_EvictKey, txBlob);
267
if ((result = req_mgr_submit_req(txBlob)))
270
result = UnloadBlob_Header(txBlob, ¶mSize);
272
LogResult("Evict Key", result);
277
clearUnknownKeys(TCS_CONTEXT_HANDLE hContext, UINT32 *cleared)
279
TSS_RESULT result = TSS_SUCCESS;
280
TCPA_KEY_HANDLE_LIST keyList = { 0, NULL };
282
BYTE *respData = NULL;
283
UINT32 respDataSize = 0, count = 0;
284
TCPA_CAPABILITY_AREA capArea = -1;
286
TSS_BOOL found = FALSE;
287
struct key_mem_cache *tmp;
289
capArea = TCPA_CAP_KEY_HANDLE;
291
if ((result = TCSP_GetCapability_Internal(hContext, capArea, 0, NULL, &respDataSize,
295
if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList)))
299
LogDebug("Loaded TPM key handles:");
300
for (i = 0; i < keyList.loaded; i++) {
301
LogDebugFn("%d: %x", i, keyList.handle[i]);
304
LogDebug("Loaded TCSD key handles:");
306
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
307
LogDebugFn("%d: 0x%x -> 0x%x", i++, tmp->tpm_handle,
312
for (i = 0; i < keyList.loaded; i++) {
313
/* as long as we're only called from evictFirstKey(), we don't
314
* need to lock here */
315
for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
316
if (tmp->tpm_handle == keyList.handle[i]) {
324
if ((result = internal_EvictByKeySlot(keyList.handle[i])))
333
free(keyList.handle);
341
clearKeysFromChip(TCS_CONTEXT_HANDLE hContext)
344
TCPA_KEY_HANDLE_LIST keyList;
347
UINT32 respDataSize = 0;
348
TCPA_CAPABILITY_AREA capArea = -1;
351
capArea = TCPA_CAP_KEY_HANDLE;
353
if ((result = TCSP_GetCapability_Internal(hContext, capArea, 0, NULL,
354
&respDataSize, &respData)))
357
if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList)))
359
for (i = 0; i < keyList.loaded; i++) {
360
if (keyList.handle[i] == SRK_TPM_HANDLE || /*can't evict SRK */
361
keyList.handle[i] == EK_TPM_HANDLE) /*can't evict EK */
363
if ((result = internal_EvictByKeySlot(keyList.handle[i])))
371
LoadBlob_KEY_PARMS(UINT64 *offset, BYTE *blob, TCPA_KEY_PARMS *keyInfo)
373
LoadBlob_UINT32(offset, keyInfo->algorithmID, blob);
374
LoadBlob_UINT16(offset, keyInfo->encScheme, blob);
375
LoadBlob_UINT16(offset, keyInfo->sigScheme, blob);
376
LoadBlob_UINT32(offset, keyInfo->parmSize, blob);
377
LoadBlob(offset, keyInfo->parmSize, blob, keyInfo->parms);
381
UnloadBlob_STORE_PUBKEY(UINT64 *offset, BYTE *blob, TCPA_STORE_PUBKEY *store)
386
UnloadBlob_UINT32(offset, &keyLength, blob);
389
UnloadBlob(offset, keyLength, blob, NULL);
394
UnloadBlob_UINT32(offset, &store->keyLength, blob);
396
if (store->keyLength == 0) {
398
LogWarn("Unloading a public key of size 0!");
400
store->key = (BYTE *)malloc(store->keyLength);
401
if (store->key == NULL) {
402
LogError("malloc of %u bytes failed.", store->keyLength);
403
store->keyLength = 0;
404
return TCSERR(TSS_E_OUTOFMEMORY);
407
UnloadBlob(offset, store->keyLength, blob, store->key);
414
LoadBlob_STORE_PUBKEY(UINT64 *offset, BYTE * blob, TCPA_STORE_PUBKEY * store)
416
LoadBlob_UINT32(offset, store->keyLength, blob);
417
LoadBlob(offset, store->keyLength, blob, store->key);
421
UnloadBlob_TSS_KEY(UINT64 *offset, BYTE *blob, TSS_KEY *key)
428
/* TPM_KEY's ver and TPM_KEY12's tag/file are
429
the same size, so... */
430
UnloadBlob_VERSION(offset, blob, NULL);
431
UnloadBlob_UINT16(offset, NULL, blob);
432
UnloadBlob_KEY_FLAGS(offset, blob, NULL);
433
UnloadBlob_BOOL(offset, NULL, blob);
434
if ((rc = UnloadBlob_KEY_PARMS(offset, blob, NULL)))
436
UnloadBlob_UINT32(offset, &size, blob);
439
UnloadBlob(offset, size, blob, NULL);
441
if ((rc = UnloadBlob_STORE_PUBKEY(offset, blob, NULL)))
444
UnloadBlob_UINT32(offset, &size, blob);
447
UnloadBlob(offset, size, blob, NULL);
452
if (key->hdr.key12.tag == TPM_TAG_KEY12) {
453
UnloadBlob_UINT16(offset, &key->hdr.key12.tag, blob);
454
UnloadBlob_UINT16(offset, &key->hdr.key12.fill, blob);
456
UnloadBlob_TCPA_VERSION(offset, blob, &key->hdr.key11.ver);
457
UnloadBlob_UINT16(offset, &key->keyUsage, blob);
458
UnloadBlob_KEY_FLAGS(offset, blob, &key->keyFlags);
459
UnloadBlob_BOOL(offset, (TSS_BOOL *)&key->authDataUsage, blob);
460
if ((rc = UnloadBlob_KEY_PARMS(offset, blob, &key->algorithmParms)))
462
UnloadBlob_UINT32(offset, &key->PCRInfoSize, blob);
464
if (key->PCRInfoSize == 0)
467
key->PCRInfo = malloc(key->PCRInfoSize);
468
if (key->PCRInfo == NULL) {
469
LogError("malloc of %u bytes failed.", key->PCRInfoSize);
470
key->PCRInfoSize = 0;
471
free(key->algorithmParms.parms);
472
key->algorithmParms.parms = NULL;
473
key->algorithmParms.parmSize = 0;
474
return TCSERR(TSS_E_OUTOFMEMORY);
476
UnloadBlob(offset, key->PCRInfoSize, blob, key->PCRInfo);
479
if ((rc = UnloadBlob_STORE_PUBKEY(offset, blob, &key->pubKey))) {
482
key->PCRInfoSize = 0;
483
free(key->algorithmParms.parms);
484
key->algorithmParms.parms = NULL;
485
key->algorithmParms.parmSize = 0;
488
UnloadBlob_UINT32(offset, &key->encSize, blob);
490
if (key->encSize == 0)
493
key->encData = (BYTE *)malloc(key->encSize);
494
if (key->encData == NULL) {
495
LogError("malloc of %d bytes failed.", key->encSize);
497
free(key->algorithmParms.parms);
498
key->algorithmParms.parms = NULL;
499
key->algorithmParms.parmSize = 0;
502
key->PCRInfoSize = 0;
503
free(key->pubKey.key);
504
key->pubKey.key = NULL;
505
key->pubKey.keyLength = 0;
506
return TCSERR(TSS_E_OUTOFMEMORY);
508
UnloadBlob(offset, key->encSize, blob, key->encData);
515
LoadBlob_TSS_KEY(UINT64 *offset, BYTE * blob, TSS_KEY * key)
517
if (key->hdr.key12.tag == TPM_TAG_KEY12) {
518
LoadBlob_UINT16(offset, key->hdr.key12.tag, blob);
519
LoadBlob_UINT16(offset, key->hdr.key12.fill, blob);
521
LoadBlob_TCPA_VERSION(offset, blob, &key->hdr.key11.ver);
522
LoadBlob_UINT16(offset, key->keyUsage, blob);
523
LoadBlob_KEY_FLAGS(offset, blob, &key->keyFlags);
524
LoadBlob_BOOL(offset, key->authDataUsage, blob);
525
LoadBlob_KEY_PARMS(offset, blob, &key->algorithmParms);
526
LoadBlob_UINT32(offset, key->PCRInfoSize, blob);
527
LoadBlob(offset, key->PCRInfoSize, blob, key->PCRInfo);
528
LoadBlob_STORE_PUBKEY(offset, blob, &key->pubKey);
529
LoadBlob_UINT32(offset, key->encSize, blob);
530
LoadBlob(offset, key->encSize, blob, key->encData);
534
LoadBlob_PUBKEY(UINT64 *offset, BYTE * blob, TCPA_PUBKEY * key)
536
LoadBlob_KEY_PARMS(offset, blob, &(key->algorithmParms));
537
LoadBlob_STORE_PUBKEY(offset, blob, &(key->pubKey));
541
UnloadBlob_PUBKEY(UINT64 *offset, BYTE *blob, TCPA_PUBKEY *key)
546
if ((rc = UnloadBlob_KEY_PARMS(offset, blob, NULL)))
548
return UnloadBlob_STORE_PUBKEY(offset, blob, NULL);
551
if ((rc = UnloadBlob_KEY_PARMS(offset, blob, &key->algorithmParms)))
553
if ((rc = UnloadBlob_STORE_PUBKEY(offset, blob, &key->pubKey))) {
554
free(key->algorithmParms.parms);
555
key->algorithmParms.parms = NULL;
556
key->algorithmParms.parmSize = 0;
563
LoadBlob_KEY_FLAGS(UINT64 *offset, BYTE * blob, TCPA_KEY_FLAGS * flags)
565
LoadBlob_UINT32(offset, *flags, blob);
569
destroy_key_refs(TSS_KEY *key)
571
free(key->algorithmParms.parms);
572
key->algorithmParms.parms = NULL;
573
key->algorithmParms.parmSize = 0;
575
free(key->pubKey.key);
576
key->pubKey.key = NULL;
577
key->pubKey.keyLength = 0;
585
key->PCRInfoSize = 0;