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 <string.h>
13 
14 #include "trousers/tss.h"
15 #include "trousers_types.h"
16 #include "req_mgr.h"
17 #include "tcs_tsp.h"
18 #include "tcslog.h"
19 #include "tcs_utils.h"
20 #include "tcs_int_literals.h"
21 
22 struct key_mem_cache *key_mem_cache_head = NULL;
23 
24 TSS_UUID NULL_UUID = { 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0 } };
25 
26 
27 TSS_RESULT
add_cache_entry(TCS_CONTEXT_HANDLE hContext,BYTE * blob,TCS_KEY_HANDLE hParent,TPM_KEY_HANDLE hSlot,TCS_KEY_HANDLE * new)28 add_cache_entry(TCS_CONTEXT_HANDLE hContext,
29 		BYTE*              blob,
30 		TCS_KEY_HANDLE     hParent,
31 		TPM_KEY_HANDLE     hSlot,
32 		TCS_KEY_HANDLE*    new)
33 {
34 	UINT64 offset;
35 	TSS_RESULT result;
36 	TCS_KEY_HANDLE tcsHandle;
37 	TSS_KEY key, *pKey;
38 
39 	if (!blob) {
40 		pKey = NULL;
41 	} else {
42 		offset = 0;
43 		if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key)))
44 			return result;
45 
46 		if ((tcsHandle = mc_get_handle_by_pub(&key.pubKey, hParent)) == NULL_TCS_HANDLE) {
47 			pKey = &key;
48 		} else {
49 			mc_set_slot_by_handle(tcsHandle, hSlot);
50 			*new = tcsHandle;
51 			goto done;
52 		}
53 	}
54 
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);
59 
60 	if ((result = mc_add_entry(tcsHandle, hSlot, pKey)))
61 		goto done;
62 
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);
67 		goto done;
68 	}
69 
70 	if ((result = mc_set_parent_by_handle(tcsHandle, hParent))) {
71 		LogError("mc_set_parent_by_handle failed.");
72 		goto done;
73 	}
74 
75 	*new = tcsHandle;
76 done:
77 	if (blob)
78 		destroy_key_refs(&key);
79 	return result;
80 }
81 
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 */
84 TSS_RESULT
get_slot_lite(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE hKey,TPM_KEY_HANDLE * out)85 get_slot_lite(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey, TPM_KEY_HANDLE *out)
86 {
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);
90 
91 		return TSS_SUCCESS;
92 	}
93 
94 	return TCSERR(TCS_E_INVALID_KEY);
95 }
96 
97 /* XXX Can get_slot be merged with ensureKeyIsLoaded? */
98 
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. */
102 TSS_RESULT
get_slot(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE hKey,TPM_KEY_HANDLE * out)103 get_slot(TCS_CONTEXT_HANDLE hContext, TCS_KEY_HANDLE hKey, TPM_KEY_HANDLE *out)
104 {
105 	TSS_RESULT result = TSS_SUCCESS;
106 	TPM_STORE_PUBKEY *pub = NULL;
107 	TPM_KEY_HANDLE slot;
108 
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);
114 
115                 LogDebugFn("calling LoadKeyShim");
116                 /* Otherwise, try to load it using the shim */
117                 result = LoadKeyShim(hContext, pub, NULL, &slot);
118         }
119 
120 	if (!result)
121 		*out = slot;
122 
123 	return result;
124 }
125 
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.
128  *
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
131  *    another thread)
132  * B) Its in a transport session (the key blob is encrypted)
133  *
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
136  * the TPM.
137  */
138 TSS_RESULT
load_key_init(TPM_COMMAND_CODE ord,TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE parent_handle,UINT32 blob_size,BYTE * blob,TSS_BOOL encrypted,TPM_AUTH * auth,TSS_BOOL * load_key,UINT64 * out_len,BYTE * out,TCS_KEY_HANDLE * handle,TPM_KEY_HANDLE * slot)139 load_key_init(TPM_COMMAND_CODE   ord,
140 	      TCS_CONTEXT_HANDLE hContext,
141 	      TCS_KEY_HANDLE     parent_handle,
142 	      UINT32             blob_size,
143 	      BYTE*              blob,
144 	      TSS_BOOL           encrypted,
145 	      TPM_AUTH*          auth,
146 	      TSS_BOOL*          load_key,
147 	      UINT64*            out_len,
148 	      BYTE*              out,
149 	      TCS_KEY_HANDLE*    handle,
150 	      TPM_KEY_HANDLE*    slot)
151 {
152 	TSS_RESULT result = TSS_SUCCESS;
153 	TSS_KEY key;
154 	UINT64 offset;
155 	TPM_KEY_HANDLE tpm_slot;
156 	TCS_KEY_HANDLE tcs_handle;
157 	TSS_BOOL canLoad;
158 
159 
160 	if (!encrypted) {
161 		offset = 0;
162 		memset(&key, 0, sizeof(TSS_KEY));
163 		if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key)))
164 			return result;
165 	}
166 
167 	if (!auth && !encrypted) {
168 		LogDebugFn("Checking if LoadKeyByBlob can be avoided by using existing key");
169 
170 		if ((tcs_handle = mc_get_handle_by_pub(&key.pubKey, parent_handle))) {
171 			LogDebugFn("tcs key handle exists");
172 
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;
177 				*slot = tpm_slot;
178 				*load_key = FALSE;
179 				goto done;
180 			}
181 		}
182 	}
183 	*load_key = TRUE;
184 
185 	LogDebugFn("calling canILoadThisKey");
186 	if (!encrypted) {
187 		if ((result = canILoadThisKey(&(key.algorithmParms), &canLoad)))
188 			goto error;
189 
190 		if (canLoad == FALSE) {
191 			LogDebugFn("calling evictFirstKey");
192 			/* Evict a key that isn't the parent */
193 			if ((result = evictFirstKey(parent_handle)))
194 				goto error;
195 		}
196 	}
197 
198 error:
199 	if (!encrypted)
200 		destroy_key_refs(&key);
201 done:
202 	return result;
203 }
204 
205 TSS_RESULT
load_key_final(TCS_CONTEXT_HANDLE hContext,TCS_KEY_HANDLE parent_handle,TCS_KEY_HANDLE * tcs_handle,BYTE * blob,TPM_KEY_HANDLE slot)206 load_key_final(TCS_CONTEXT_HANDLE hContext,
207 	       TCS_KEY_HANDLE     parent_handle,
208 	       TCS_KEY_HANDLE*    tcs_handle,
209 	       BYTE*              blob,
210 	       TPM_KEY_HANDLE     slot)
211 {
212 	if (*tcs_handle == NULL_TCS_HANDLE)
213 		return add_cache_entry(hContext, blob, parent_handle, slot, tcs_handle);
214 	else
215 		return mc_set_slot_by_handle(*tcs_handle, slot);
216 }
217 
218 TSS_RESULT
canILoadThisKey(TCPA_KEY_PARMS * parms,TSS_BOOL * b)219 canILoadThisKey(TCPA_KEY_PARMS *parms, TSS_BOOL *b)
220 {
221 	UINT16 subCapLength;
222 	UINT64 offset;
223 	BYTE subCap[100];
224 	TCPA_RESULT result;
225 	UINT32 respDataLength;
226 	BYTE *respData;
227 
228 	offset = 0;
229 	LoadBlob_KEY_PARMS(&offset, subCap, parms);
230 	subCapLength = offset;
231 
232 	if ((result = TCSP_GetCapability_Internal(InternalContext, TCPA_CAP_CHECK_LOADED,
233 						  subCapLength, subCap, &respDataLength,
234 						  &respData))) {
235 		*b = FALSE;
236 		LogDebugFn("NO");
237 		return result;
238 	}
239 
240 	*b = respData[0];
241 	free(respData);
242 	LogDebugFn("%s", *b ? "YES" : "NO");
243 
244 	return TSS_SUCCESS;
245 }
246 
247 TCPA_RESULT
internal_EvictByKeySlot(TCPA_KEY_HANDLE slot)248 internal_EvictByKeySlot(TCPA_KEY_HANDLE slot)
249 {
250 	TCPA_RESULT result;
251 	UINT32 paramSize;
252 	UINT64 offset;
253 	BYTE txBlob[TSS_TPM_TXBLOB_SIZE];
254 
255 	LogDebug("Entering Evict Key");
256 
257 #ifdef TSS_BUILD_TSS12
258 	if (TPM_VERSION_IS(1,2)) {
259 		LogDebugFn("Evicting key using FlushSpecific for TPM 1.2");
260 
261 		return TCSP_FlushSpecific_Common(slot, TPM_RT_KEY);
262 	}
263 #endif
264 
265 	offset = 10;
266 	LoadBlob_UINT32(&offset, slot, txBlob);
267 	LoadBlob_Header(TPM_TAG_RQU_COMMAND, offset, TPM_ORD_EvictKey, txBlob);
268 
269 	if ((result = req_mgr_submit_req(txBlob)))
270 		return result;
271 
272 	result = UnloadBlob_Header(txBlob, &paramSize);
273 
274 	LogResult("Evict Key", result);
275 	return result;
276 }
277 
278 TSS_RESULT
clearUnknownKeys(TCS_CONTEXT_HANDLE hContext,UINT32 * cleared)279 clearUnknownKeys(TCS_CONTEXT_HANDLE hContext, UINT32 *cleared)
280 {
281 	TSS_RESULT result = TSS_SUCCESS;
282 	TCPA_KEY_HANDLE_LIST keyList = { 0, NULL };
283 	int i;
284 	BYTE *respData = NULL;
285 	UINT32 respDataSize = 0, count = 0;
286 	TCPA_CAPABILITY_AREA capArea = -1;
287 	UINT64 offset = 0;
288 	TSS_BOOL found = FALSE;
289 	struct key_mem_cache *tmp;
290 
291 	capArea = TCPA_CAP_KEY_HANDLE;
292 
293 	if ((result = TCSP_GetCapability_Internal(hContext, capArea, 0, NULL, &respDataSize,
294 						  &respData)))
295 		return result;
296 
297 	if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList)))
298 		goto done;
299 
300 #ifdef TSS_DEBUG
301 	LogDebug("Loaded TPM key handles:");
302 	for (i = 0; i < keyList.loaded; i++) {
303 		LogDebugFn("%d: %x", i, keyList.handle[i]);
304 	}
305 
306 	LogDebug("Loaded TCSD key handles:");
307 	i=0;
308 	for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
309 		LogDebugFn("%d: 0x%x -> 0x%x", i++, tmp->tpm_handle,
310 			    tmp->tcs_handle);
311 	}
312 #endif
313 
314 	for (i = 0; i < keyList.loaded; i++) {
315 		/* as long as we're only called from evictFirstKey(), we don't
316 		 * need to lock here */
317 		for (tmp = key_mem_cache_head; tmp; tmp = tmp->next) {
318 			if (tmp->tpm_handle == keyList.handle[i]) {
319 				found = TRUE;
320 				break;
321 			}
322 		}
323 		if (found)
324 			found = FALSE;
325 		else {
326 			if ((result = internal_EvictByKeySlot(keyList.handle[i])))
327 				goto done;
328 			else
329 				count++;
330 		}
331 	}
332 
333 	*cleared = count;
334 done:
335 	free(keyList.handle);
336 	free(respData);
337 
338 	return TSS_SUCCESS;
339 }
340 
341 #if 0
342 TCPA_RESULT
343 clearKeysFromChip(TCS_CONTEXT_HANDLE hContext)
344 {
345 	TCPA_RESULT result;
346 	TCPA_KEY_HANDLE_LIST keyList;
347 	UINT32 i;
348 	BYTE *respData = 0;
349 	UINT32 respDataSize = 0;
350 	TCPA_CAPABILITY_AREA capArea = -1;
351 	UINT64 offset = 0;
352 
353 	capArea = TCPA_CAP_KEY_HANDLE;
354 
355 	if ((result = TCSP_GetCapability_Internal(hContext, capArea, 0, NULL,
356 					&respDataSize, &respData)))
357 		return result;
358 
359 	if ((result = UnloadBlob_KEY_HANDLE_LIST(&offset, respData, &keyList)))
360 		return result;
361 	for (i = 0; i < keyList.loaded; i++) {
362 		if (keyList.handle[i] == SRK_TPM_HANDLE ||	/*can't evict SRK */
363 		    keyList.handle[i] == EK_TPM_HANDLE)	/*can't evict EK */
364 			continue;
365 		if ((result = internal_EvictByKeySlot(keyList.handle[i])))
366 			return result;
367 	}
368 	return TSS_SUCCESS;
369 }
370 #endif
371 
372 void
LoadBlob_KEY_PARMS(UINT64 * offset,BYTE * blob,TCPA_KEY_PARMS * keyInfo)373 LoadBlob_KEY_PARMS(UINT64 *offset, BYTE *blob, TCPA_KEY_PARMS *keyInfo)
374 {
375 	LoadBlob_UINT32(offset, keyInfo->algorithmID, blob);
376 	LoadBlob_UINT16(offset, keyInfo->encScheme, blob);
377 	LoadBlob_UINT16(offset, keyInfo->sigScheme, blob);
378 	LoadBlob_UINT32(offset, keyInfo->parmSize, blob);
379 	LoadBlob(offset, keyInfo->parmSize, blob, keyInfo->parms);
380 }
381 
382 TSS_RESULT
UnloadBlob_STORE_PUBKEY(UINT64 * offset,BYTE * blob,TCPA_STORE_PUBKEY * store)383 UnloadBlob_STORE_PUBKEY(UINT64 *offset, BYTE *blob, TCPA_STORE_PUBKEY *store)
384 {
385 	if (!store) {
386 		UINT32 keyLength;
387 
388 		UnloadBlob_UINT32(offset, &keyLength, blob);
389 
390 		if (keyLength > 0)
391 			UnloadBlob(offset, keyLength, blob, NULL);
392 
393 		return TSS_SUCCESS;
394 	}
395 
396 	UnloadBlob_UINT32(offset, &store->keyLength, blob);
397 
398 	if (store->keyLength == 0) {
399 		store->key = NULL;
400 		LogWarn("Unloading a public key of size 0!");
401 	} else {
402 		store->key = (BYTE *)malloc(store->keyLength);
403 		if (store->key == NULL) {
404 			LogError("malloc of %u bytes failed.", store->keyLength);
405 			store->keyLength = 0;
406 			return TCSERR(TSS_E_OUTOFMEMORY);
407 		}
408 
409 		UnloadBlob(offset, store->keyLength, blob, store->key);
410 	}
411 
412 	return TSS_SUCCESS;
413 }
414 
415 void
LoadBlob_STORE_PUBKEY(UINT64 * offset,BYTE * blob,TCPA_STORE_PUBKEY * store)416 LoadBlob_STORE_PUBKEY(UINT64 *offset, BYTE * blob, TCPA_STORE_PUBKEY * store)
417 {
418 	LoadBlob_UINT32(offset, store->keyLength, blob);
419 	LoadBlob(offset, store->keyLength, blob, store->key);
420 }
421 
422 TSS_RESULT
UnloadBlob_TSS_KEY(UINT64 * offset,BYTE * blob,TSS_KEY * key)423 UnloadBlob_TSS_KEY(UINT64 *offset, BYTE *blob, TSS_KEY *key)
424 {
425 	TSS_RESULT rc;
426 
427 	if (!key) {
428 		UINT32 size;
429 
430 		/* TPM_KEY's ver and TPM_KEY12's tag/file are
431 		   the same size, so... */
432 		UnloadBlob_VERSION(offset, blob, NULL);
433 		UnloadBlob_UINT16(offset, NULL, blob);
434 		UnloadBlob_KEY_FLAGS(offset, blob, NULL);
435 		UnloadBlob_BOOL(offset, NULL, blob);
436 		if ((rc = UnloadBlob_KEY_PARMS(offset, blob, NULL)))
437 			return rc;
438 		UnloadBlob_UINT32(offset, &size, blob);
439 
440 		if (size > 0)
441 			UnloadBlob(offset, size, blob, NULL);
442 
443 		if ((rc = UnloadBlob_STORE_PUBKEY(offset, blob, NULL)))
444 			return rc;
445 
446 		UnloadBlob_UINT32(offset, &size, blob);
447 
448 		if (size > 0)
449 			UnloadBlob(offset, size, blob, NULL);
450 
451 		return TSS_SUCCESS;
452 	}
453 
454 	if (key->hdr.key12.tag == TPM_TAG_KEY12) {
455 		UnloadBlob_UINT16(offset, &key->hdr.key12.tag, blob);
456 		UnloadBlob_UINT16(offset, &key->hdr.key12.fill, blob);
457 	} else
458 		UnloadBlob_TCPA_VERSION(offset, blob, &key->hdr.key11.ver);
459 	UnloadBlob_UINT16(offset, &key->keyUsage, blob);
460 	UnloadBlob_KEY_FLAGS(offset, blob, &key->keyFlags);
461 	UnloadBlob_BOOL(offset, (TSS_BOOL *)&key->authDataUsage, blob);
462 	if ((rc = UnloadBlob_KEY_PARMS(offset, blob, &key->algorithmParms)))
463 		return rc;
464 	UnloadBlob_UINT32(offset, &key->PCRInfoSize, blob);
465 
466 	if (key->PCRInfoSize == 0)
467 		key->PCRInfo = NULL;
468 	else {
469 		key->PCRInfo = malloc(key->PCRInfoSize);
470 		if (key->PCRInfo == NULL) {
471 			LogError("malloc of %u bytes failed.", key->PCRInfoSize);
472 			key->PCRInfoSize = 0;
473 			free(key->algorithmParms.parms);
474 			key->algorithmParms.parms = NULL;
475 			key->algorithmParms.parmSize = 0;
476 			return TCSERR(TSS_E_OUTOFMEMORY);
477 		}
478 		UnloadBlob(offset, key->PCRInfoSize, blob, key->PCRInfo);
479 	}
480 
481 	if ((rc = UnloadBlob_STORE_PUBKEY(offset, blob, &key->pubKey))) {
482 		free(key->PCRInfo);
483 		key->PCRInfo = NULL;
484 		key->PCRInfoSize = 0;
485 		free(key->algorithmParms.parms);
486 		key->algorithmParms.parms = NULL;
487 		key->algorithmParms.parmSize = 0;
488 		return rc;
489 	}
490 	UnloadBlob_UINT32(offset, &key->encSize, blob);
491 
492 	if (key->encSize == 0)
493 		key->encData = NULL;
494 	else {
495 		key->encData = (BYTE *)malloc(key->encSize);
496 		if (key->encData == NULL) {
497 			LogError("malloc of %d bytes failed.", key->encSize);
498 			key->encSize = 0;
499 			free(key->algorithmParms.parms);
500 			key->algorithmParms.parms = NULL;
501 			key->algorithmParms.parmSize = 0;
502 			free(key->PCRInfo);
503 			key->PCRInfo = NULL;
504 			key->PCRInfoSize = 0;
505 			free(key->pubKey.key);
506 			key->pubKey.key = NULL;
507 			key->pubKey.keyLength = 0;
508 			return TCSERR(TSS_E_OUTOFMEMORY);
509 		}
510 		UnloadBlob(offset, key->encSize, blob, key->encData);
511 	}
512 
513 	return TSS_SUCCESS;
514 }
515 
516 void
LoadBlob_TSS_KEY(UINT64 * offset,BYTE * blob,TSS_KEY * key)517 LoadBlob_TSS_KEY(UINT64 *offset, BYTE * blob, TSS_KEY * key)
518 {
519 	if (key->hdr.key12.tag == TPM_TAG_KEY12) {
520 		LoadBlob_UINT16(offset, key->hdr.key12.tag, blob);
521 		LoadBlob_UINT16(offset, key->hdr.key12.fill, blob);
522 	} else
523 		LoadBlob_TCPA_VERSION(offset, blob, &key->hdr.key11.ver);
524 	LoadBlob_UINT16(offset, key->keyUsage, blob);
525 	LoadBlob_KEY_FLAGS(offset, blob, &key->keyFlags);
526 	LoadBlob_BOOL(offset, key->authDataUsage, blob);
527 	LoadBlob_KEY_PARMS(offset, blob, &key->algorithmParms);
528 	LoadBlob_UINT32(offset, key->PCRInfoSize, blob);
529 	LoadBlob(offset, key->PCRInfoSize, blob, key->PCRInfo);
530 	LoadBlob_STORE_PUBKEY(offset, blob, &key->pubKey);
531 	LoadBlob_UINT32(offset, key->encSize, blob);
532 	LoadBlob(offset, key->encSize, blob, key->encData);
533 }
534 
535 void
LoadBlob_PUBKEY(UINT64 * offset,BYTE * blob,TCPA_PUBKEY * key)536 LoadBlob_PUBKEY(UINT64 *offset, BYTE * blob, TCPA_PUBKEY * key)
537 {
538 	LoadBlob_KEY_PARMS(offset, blob, &(key->algorithmParms));
539 	LoadBlob_STORE_PUBKEY(offset, blob, &(key->pubKey));
540 }
541 
542 TSS_RESULT
UnloadBlob_PUBKEY(UINT64 * offset,BYTE * blob,TCPA_PUBKEY * key)543 UnloadBlob_PUBKEY(UINT64 *offset, BYTE *blob, TCPA_PUBKEY *key)
544 {
545 	TSS_RESULT rc;
546 
547 	if (!key) {
548 		if ((rc = UnloadBlob_KEY_PARMS(offset, blob, NULL)))
549 			return rc;
550 		return UnloadBlob_STORE_PUBKEY(offset, blob, NULL);
551 	}
552 
553 	if ((rc = UnloadBlob_KEY_PARMS(offset, blob, &key->algorithmParms)))
554 		return rc;
555 	if ((rc = UnloadBlob_STORE_PUBKEY(offset, blob, &key->pubKey))) {
556 		free(key->algorithmParms.parms);
557 		key->algorithmParms.parms = NULL;
558 		key->algorithmParms.parmSize = 0;
559 	}
560 
561 	return rc;
562 }
563 
564 void
LoadBlob_KEY_FLAGS(UINT64 * offset,BYTE * blob,TCPA_KEY_FLAGS * flags)565 LoadBlob_KEY_FLAGS(UINT64 *offset, BYTE * blob, TCPA_KEY_FLAGS * flags)
566 {
567 	LoadBlob_UINT32(offset, *flags, blob);
568 }
569 
570 void
destroy_key_refs(TSS_KEY * key)571 destroy_key_refs(TSS_KEY *key)
572 {
573 	free(key->algorithmParms.parms);
574 	key->algorithmParms.parms = NULL;
575 	key->algorithmParms.parmSize = 0;
576 
577 	free(key->pubKey.key);
578 	key->pubKey.key = NULL;
579 	key->pubKey.keyLength = 0;
580 
581 	free(key->encData);
582 	key->encData = NULL;
583 	key->encSize = 0;
584 
585 	free(key->PCRInfo);
586 	key->PCRInfo = NULL;
587 	key->PCRInfoSize = 0;
588 }
589