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
8  *
9  */
10 
11 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 
16 #include "trousers/tss.h"
17 #include "trousers_types.h"
18 #include "tcs_tsp.h"
19 #include "tcs_utils.h"
20 #include "tcs_int_literals.h"
21 #include "capabilities.h"
22 #include "tcslog.h"
23 #include "tcsps.h"
24 
25 TSS_RESULT
TCS_RegisterKey_Internal(TCS_CONTEXT_HANDLE hContext,TSS_UUID * WrappingKeyUUID,TSS_UUID * KeyUUID,UINT32 cKeySize,BYTE * rgbKey,UINT32 cVendorData,BYTE * gbVendorData)26 TCS_RegisterKey_Internal(TCS_CONTEXT_HANDLE hContext,	/* in */
27 			 TSS_UUID *WrappingKeyUUID,	/* in */
28 			 TSS_UUID *KeyUUID,		/* in */
29 			 UINT32 cKeySize,		/* in */
30 			 BYTE * rgbKey,			/* in */
31 			 UINT32 cVendorData,		/* in */
32 			 BYTE * gbVendorData)		/* in */
33 {
34 	TSS_RESULT result;
35 	TSS_BOOL is_reg;
36 
37 	if ((result = ctx_verify_context(hContext)))
38 		return result;
39 
40 	/* Check if key is already regisitered */
41 	if (isUUIDRegistered(KeyUUID, &is_reg) != TSS_SUCCESS) {
42 		LogError("Failed checking if UUID is registered.");
43 		return TCSERR(TSS_E_INTERNAL_ERROR);
44 	}
45 
46 	if (is_reg == TRUE || TSS_UUID_IS_OWNEREVICT(KeyUUID)) {
47 		LogDebug("UUID is already registered");
48 		return TCSERR(TSS_E_KEY_ALREADY_REGISTERED);
49 	}
50 
51 	LogDebugUnrollKey(rgbKey);
52 
53 	/* Go ahead and store it in system persistant storage */
54 	if ((result = ps_write_key(KeyUUID, WrappingKeyUUID, gbVendorData, cVendorData, rgbKey,
55 				   cKeySize))) {
56 		LogError("Error writing key to file");
57 		return result;
58 	}
59 
60 	return TSS_SUCCESS;
61 }
62 
63 TSS_RESULT
TCS_UnregisterKey_Internal(TCS_CONTEXT_HANDLE hContext,TSS_UUID KeyUUID)64 TCS_UnregisterKey_Internal(TCS_CONTEXT_HANDLE hContext,	/* in */
65 			   TSS_UUID KeyUUID)		/* in */
66 {
67 	TSS_RESULT result;
68 
69 	if ((result = ctx_verify_context(hContext)))
70 		return result;
71 
72 	return ps_remove_key(&KeyUUID);
73 }
74 
75 TSS_RESULT
TCS_EnumRegisteredKeys_Internal(TCS_CONTEXT_HANDLE hContext,TSS_UUID * pKeyUUID,UINT32 * pcKeyHierarchySize,TSS_KM_KEYINFO ** ppKeyHierarchy)76 TCS_EnumRegisteredKeys_Internal(TCS_CONTEXT_HANDLE hContext,		/* in */
77 				TSS_UUID * pKeyUUID,			/* in */
78 				UINT32 * pcKeyHierarchySize,		/* out */
79 				TSS_KM_KEYINFO ** ppKeyHierarchy)	/* out */
80 {
81 	TSS_RESULT result = TSS_SUCCESS;
82 	UINT32 count = 0, i;
83 	TSS_KM_KEYINFO *ret = NULL;
84 	TSS_UUID tmp_uuid;
85 	struct key_disk_cache *disk_ptr, *tmp_ptrs[MAX_KEY_CHILDREN];
86 	struct key_mem_cache *mem_ptr;
87 	TSS_BOOL is_reg = FALSE;
88 
89 	LogDebug("Enum Reg Keys");
90 
91 	if (pcKeyHierarchySize == NULL || ppKeyHierarchy == NULL)
92 		return TCSERR(TSS_E_BAD_PARAMETER);
93 
94 	if ((result = ctx_verify_context(hContext)))
95 		return result;
96 
97 	if (pKeyUUID != NULL) {
98 		/* First have to verify the key is registered */
99 		if ((result = isUUIDRegistered(pKeyUUID, &is_reg)))
100 			return result;
101 
102 		if (is_reg == FALSE) {
103 			/* This return code is not listed as possible in the TSS 1.1 spec,
104 			 * but it makes more sense than just TCS_SUCCESS or TSS_E_FAIL */
105 			return TCSERR(TSS_E_PS_KEY_NOTFOUND);
106 		}
107 	}
108 
109 	/* this entire operation needs to be atomic wrt registered keys. We must
110 	 * lock the mem cache as well to test if a given key is loaded. */
111 	MUTEX_LOCK(disk_cache_lock);
112 	MUTEX_LOCK(mem_cache_lock);
113 
114 	/* return an array of all registered keys if pKeyUUID == NULL */
115 	if (pKeyUUID == NULL) {
116 		/*  determine the number of registered keys */
117 		for (disk_ptr = key_disk_cache_head; disk_ptr; disk_ptr = disk_ptr->next) {
118 			if (disk_ptr->flags & CACHE_FLAG_VALID)
119 				count++;
120 		}
121 
122 		/* malloc a structure for each of them */
123 		if (count != 0) {
124 			ret = calloc(count, sizeof(TSS_KM_KEYINFO));
125 			if (ret == NULL) {
126 				LogError("malloc of %zd bytes failed.",
127 						(count * sizeof(TSS_KM_KEYINFO)));
128 				count = 0;
129 				result = TCSERR(TSS_E_OUTOFMEMORY);
130 				goto done;
131 			}
132 		} else {
133 			goto done;
134 		}
135 
136 		/* fill out the structure for each key */
137 		i = 0;
138 		for (disk_ptr = key_disk_cache_head; disk_ptr; disk_ptr = disk_ptr->next) {
139 			if (disk_ptr->flags & CACHE_FLAG_VALID) {
140 				/* look for a mem cache entry to check if its loaded */
141 				for (mem_ptr = key_mem_cache_head; mem_ptr; mem_ptr = mem_ptr->next) {
142 					if (!memcmp(&mem_ptr->uuid, &disk_ptr->uuid, sizeof(TSS_UUID))) {
143 						if ((result = fill_key_info(disk_ptr, mem_ptr, &ret[i]))) {
144 							free(ret);
145 							ret = NULL;
146 							count = 0;
147 							goto done;
148 						}
149 						break;
150 					}
151 				}
152 				/* if there is no mem cache entry for this key, go ahead and call
153 				 * fill_key_info(), it will pull everything from disk */
154 				if (mem_ptr == NULL) {
155 					if ((result = fill_key_info(disk_ptr, NULL, &ret[i]))) {
156 						free(ret);
157 						ret = NULL;
158 						count = 0;
159 						goto done;
160 					}
161 				}
162 				i++;
163 			}
164 		}
165 	} else {
166 		/* return a chain of a key and its parents up to the SRK */
167 		/*  determine the number of keys in the chain */
168 		memcpy(&tmp_uuid, pKeyUUID, sizeof(TSS_UUID));
169 		disk_ptr = key_disk_cache_head;
170 		while (disk_ptr != NULL && count < MAX_KEY_CHILDREN)
171 		{
172 			if (disk_ptr->flags & CACHE_FLAG_VALID &&
173 				!memcmp(&disk_ptr->uuid, &tmp_uuid, sizeof(TSS_UUID)))
174 			{
175 				/* increment count, then search for the parent */
176 				count++;
177 				/* save a pointer to this cache entry */
178 				tmp_ptrs[count - 1] = disk_ptr;
179 				/* if the parent of this key is NULL, we're at the root of the tree */
180 				if (!memcmp(&disk_ptr->parent_uuid, &NULL_UUID, sizeof(TSS_UUID)))
181 					break;
182 				/* overwrite tmp_uuid with the parent, which we will now search for */
183 				memcpy(&tmp_uuid, &disk_ptr->parent_uuid, sizeof(TSS_UUID));
184 				disk_ptr = key_disk_cache_head;
185 				continue;
186 			}
187 			disk_ptr = disk_ptr->next;
188 		}
189 		/* when we reach this point, we have an array of TSS_UUID's that leads from the
190 		 * requested key up to the SRK*/
191 
192 		/* malloc a structure for each of them */
193 		if (count != 0) {
194 			ret = calloc(count, sizeof(TSS_KM_KEYINFO));
195 			if (ret == NULL) {
196 				LogError("malloc of %zd bytes failed.",
197 						(count * sizeof(TSS_KM_KEYINFO)));
198 				count = 0;
199 				result = TCSERR(TSS_E_OUTOFMEMORY);
200 				goto done;
201 			}
202 		} else {
203 			goto done;
204 		}
205 
206 		for (i = 0; i < count; i++) {
207 			/* look for a mem cache entry to check if its loaded */
208 			for (mem_ptr = key_mem_cache_head; mem_ptr; mem_ptr = mem_ptr->next) {
209 				if (!memcmp(&mem_ptr->uuid, &tmp_ptrs[i]->uuid, sizeof(TSS_UUID))) {
210 					if ((result = fill_key_info(tmp_ptrs[i], mem_ptr, &ret[i]))) {
211 						free(ret);
212 						ret = NULL;
213 						count = 0;
214 						goto done;
215 					}
216 					break;
217 				}
218 			}
219 			/* if there is no mem cache entry for this key, go ahead and call
220 			 * fill_key_info(), it will pull everything from disk */
221 			if (mem_ptr == NULL) {
222 				if ((result = fill_key_info(tmp_ptrs[i], NULL, &ret[i]))) {
223 					free(ret);
224 					ret = NULL;
225 					count = 0;
226 					goto done;
227 				}
228 			}
229 		}
230 	}
231 done:
232 
233 	MUTEX_UNLOCK(disk_cache_lock);
234 	MUTEX_UNLOCK(mem_cache_lock);
235 
236 	*ppKeyHierarchy = ret;
237 	*pcKeyHierarchySize = count;
238 
239 	return result;
240 }
241 
242 TSS_RESULT
TCS_EnumRegisteredKeys_Internal2(TCS_CONTEXT_HANDLE hContext,TSS_UUID * pKeyUUID,UINT32 * pcKeyHierarchySize,TSS_KM_KEYINFO2 ** ppKeyHierarchy)243 TCS_EnumRegisteredKeys_Internal2(TCS_CONTEXT_HANDLE hContext,		/* in */
244 				TSS_UUID * pKeyUUID,			/* in */
245 				UINT32 * pcKeyHierarchySize,		/* out */
246 				TSS_KM_KEYINFO2 ** ppKeyHierarchy)	/* out */
247 {
248 	TSS_RESULT result = TSS_SUCCESS;
249 	UINT32 count = 0, i;
250 	TSS_KM_KEYINFO2 *ret = NULL;
251 	TSS_UUID tmp_uuid;
252 	struct key_disk_cache *disk_ptr, *tmp_ptrs[MAX_KEY_CHILDREN];
253 	struct key_mem_cache *mem_ptr;
254 	TSS_BOOL is_reg = FALSE;
255 
256 	LogDebug("Enum Reg Keys2");
257 
258 	if (pcKeyHierarchySize == NULL || ppKeyHierarchy == NULL)
259 		return TCSERR(TSS_E_BAD_PARAMETER);
260 
261 	if ((result = ctx_verify_context(hContext)))
262 		return result;
263 
264 	if (pKeyUUID != NULL) {
265 		/* First have to verify the key is registered */
266 		if ((result = isUUIDRegistered(pKeyUUID, &is_reg)))
267 			return result;
268 
269 		if (is_reg == FALSE) {
270 			/* This return code is not listed as possible in the TSS 1.1 spec,
271 			 * but it makes more sense than just TCS_SUCCESS or TSS_E_FAIL */
272 			return TCSERR(TSS_E_PS_KEY_NOTFOUND);
273 		}
274 	}
275 
276 	/* this entire operation needs to be atomic wrt registered keys. We must
277 	 * lock the mem cache as well to test if a given key is loaded. */
278 	MUTEX_LOCK(disk_cache_lock);
279 	MUTEX_LOCK(mem_cache_lock);
280 
281 	/* return an array of all registered keys if pKeyUUID == NULL */
282 	if (pKeyUUID == NULL) {
283 		/*  determine the number of registered keys */
284 		for (disk_ptr = key_disk_cache_head; disk_ptr; disk_ptr = disk_ptr->next) {
285 			if (disk_ptr->flags & CACHE_FLAG_VALID)
286 				count++;
287 		}
288 
289 		/* malloc a structure for each of them */
290 		if (count != 0) {
291 			ret = calloc(count, sizeof(TSS_KM_KEYINFO2));
292 			if (ret == NULL) {
293 				LogError("malloc of %zd bytes failed.",
294 						(count * sizeof(TSS_KM_KEYINFO2)));
295 				count = 0;
296 				result = TCSERR(TSS_E_OUTOFMEMORY);
297 				goto done;
298 			}
299 		} else {
300 			goto done;
301 		}
302 
303 		/* fill out the structure for each key */
304 		i = 0;
305 		for (disk_ptr = key_disk_cache_head; disk_ptr; disk_ptr = disk_ptr->next) {
306 			if (disk_ptr->flags & CACHE_FLAG_VALID) {
307 				/* look for a mem cache entry to check if its loaded */
308 				for (mem_ptr = key_mem_cache_head; mem_ptr; mem_ptr = mem_ptr->next) {
309 					if (!memcmp(&mem_ptr->uuid, &disk_ptr->uuid, sizeof(TSS_UUID))) {
310 						if ((result = fill_key_info2(disk_ptr, mem_ptr, &ret[i]))) {
311 							free(ret);
312 							ret = NULL;
313 							count = 0;
314 							goto done;
315 						}
316 						break;
317 					}
318 				}
319 				/* if there is no mem cache entry for this key, go ahead and call
320 				 * fill_key_info2(), it will pull everything from disk */
321 				if (mem_ptr == NULL) {
322 					if ((result = fill_key_info2(disk_ptr, NULL, &ret[i]))) {
323 						free(ret);
324 						ret = NULL;
325 						count = 0;
326 						goto done;
327 					}
328 				}
329 				i++;
330 			}
331 		}
332 	} else {
333 		/* return a chain of a key and its parents up to the SRK */
334 		/*  determine the number of keys in the chain */
335 		memcpy(&tmp_uuid, pKeyUUID, sizeof(TSS_UUID));
336 		disk_ptr = key_disk_cache_head;
337 		while (disk_ptr != NULL && count < MAX_KEY_CHILDREN)
338 		{
339 			if (disk_ptr->flags & CACHE_FLAG_VALID &&
340 				!memcmp(&disk_ptr->uuid, &tmp_uuid, sizeof(TSS_UUID)))
341 			{
342 				/* increment count, then search for the parent */
343 				count++;
344 				/* save a pointer to this cache entry */
345 				tmp_ptrs[count - 1] = disk_ptr;
346 				/* if the parent of this key is NULL, we're at the root of the tree */
347 				if (!memcmp(&disk_ptr->parent_uuid, &NULL_UUID, sizeof(TSS_UUID)))
348 					break;
349 				/* overwrite tmp_uuid with the parent, which we will now search for */
350 				memcpy(&tmp_uuid, &disk_ptr->parent_uuid, sizeof(TSS_UUID));
351 				disk_ptr = key_disk_cache_head;
352 				continue;
353 			}
354 			disk_ptr = disk_ptr->next;
355 		}
356 		/* when we reach this point, we have an array of TSS_UUID's that leads from the
357 		 * requested key up to the SRK*/
358 
359 		/* malloc a structure for each of them */
360 		if (count != 0) {
361 			ret = calloc(count, sizeof(TSS_KM_KEYINFO2));
362 			if (ret == NULL) {
363 				LogError("malloc of %zd bytes failed.",
364 						(count * sizeof(TSS_KM_KEYINFO2)));
365 				count = 0;
366 				result = TCSERR(TSS_E_OUTOFMEMORY);
367 				goto done;
368 			}
369 		} else {
370 			goto done;
371 		}
372 
373 		for (i = 0; i < count; i++) {
374 			/* look for a mem cache entry to check if its loaded */
375 			for (mem_ptr = key_mem_cache_head; mem_ptr; mem_ptr = mem_ptr->next) {
376 				if (!memcmp(&mem_ptr->uuid, &tmp_ptrs[i]->uuid, sizeof(TSS_UUID))) {
377 					if ((result = fill_key_info2(tmp_ptrs[i], mem_ptr, &ret[i]))) {
378 						free(ret);
379 						ret = NULL;
380 						count = 0;
381 						goto done;
382 					}
383 					break;
384 				}
385 			}
386 			/* if there is no mem cache entry for this key, go ahead and call
387 			 * fill_key_info(), it will pull everything from disk */
388 			if (mem_ptr == NULL) {
389 				if ((result = fill_key_info2(tmp_ptrs[i], NULL, &ret[i]))) {
390 					free(ret);
391 					ret = NULL;
392 					count = 0;
393 					goto done;
394 				}
395 			}
396 		}
397 	}
398 done:
399 
400 	MUTEX_UNLOCK(disk_cache_lock);
401 	MUTEX_UNLOCK(mem_cache_lock);
402 
403 	*ppKeyHierarchy = ret;
404 	*pcKeyHierarchySize = count;
405 
406 	return result;
407 }
408 
409 TSS_RESULT
TCS_GetRegisteredKey_Internal(TCS_CONTEXT_HANDLE hContext,TSS_UUID * KeyUUID,TSS_KM_KEYINFO ** ppKeyInfo)410 TCS_GetRegisteredKey_Internal(TCS_CONTEXT_HANDLE hContext,	/* in */
411 			      TSS_UUID *KeyUUID,		/* in */
412 			      TSS_KM_KEYINFO ** ppKeyInfo)	/* out */
413 {
414 	TSS_RESULT result;
415 	UINT64 offset;
416 	BYTE tcpaKeyBlob[1024];
417 	TSS_KEY tcpaKey;
418 	UINT16 keySize = sizeof (tcpaKeyBlob);
419 	TSS_UUID parentUUID;
420 
421 	/* This should be set in case we return before the malloc */
422 	*ppKeyInfo = NULL;
423 
424 	if ((result = ctx_verify_context(hContext)))
425 		return result;
426 
427 	if ((result = ps_get_key_by_uuid(KeyUUID, tcpaKeyBlob, &keySize))) {
428 		return TCSERR(TSS_E_PS_KEY_NOTFOUND);
429 	}
430 
431 	if ((result = getParentUUIDByUUID(KeyUUID, &parentUUID)))
432 		return TCSERR(TSS_E_FAIL);
433 
434 	*ppKeyInfo = malloc(sizeof(TSS_KM_KEYINFO));
435 	if (*ppKeyInfo == NULL) {
436 		LogError("malloc of %zd bytes failed.", sizeof(TSS_KM_KEYINFO));
437 		return TCSERR(TSS_E_OUTOFMEMORY);
438 	}
439 
440 	offset = 0;
441 	UnloadBlob_TSS_KEY(&offset, tcpaKeyBlob, &tcpaKey);
442 
443 	(*ppKeyInfo)->bAuthDataUsage = tcpaKey.authDataUsage;
444 
445 	(*ppKeyInfo)->fIsLoaded = FALSE;
446 
447 	if (tcpaKey.hdr.key12.tag == TPM_TAG_KEY12) {
448 		(*ppKeyInfo)->versionInfo.bMajor = TSS_SPEC_MAJOR;
449 		(*ppKeyInfo)->versionInfo.bMinor = TSS_SPEC_MINOR;
450 		(*ppKeyInfo)->versionInfo.bRevMajor = 0;
451 		(*ppKeyInfo)->versionInfo.bRevMinor = 0;
452 	} else {
453 		(*ppKeyInfo)->versionInfo.bMajor = tcpaKey.hdr.key11.ver.major;
454 		(*ppKeyInfo)->versionInfo.bMinor = tcpaKey.hdr.key11.ver.minor;
455 		(*ppKeyInfo)->versionInfo.bRevMajor = tcpaKey.hdr.key11.ver.revMajor;
456 		(*ppKeyInfo)->versionInfo.bRevMinor = tcpaKey.hdr.key11.ver.revMinor;
457 	}
458 
459 	memcpy(&((*ppKeyInfo)->keyUUID), KeyUUID, sizeof(TSS_UUID));
460 
461 	(*ppKeyInfo)->ulVendorDataLength = 0;
462 	(*ppKeyInfo)->rgbVendorData = 0;
463 
464 	memcpy(&((*ppKeyInfo)->parentKeyUUID), &parentUUID, sizeof(TSS_UUID));
465 	return TSS_SUCCESS;
466 }
467 
468 TSS_RESULT
TCS_GetRegisteredKeyBlob_Internal(TCS_CONTEXT_HANDLE hContext,TSS_UUID * KeyUUID,UINT32 * pcKeySize,BYTE ** prgbKey)469 TCS_GetRegisteredKeyBlob_Internal(TCS_CONTEXT_HANDLE hContext,	/* in */
470 				  TSS_UUID *KeyUUID,		/* in */
471 				  UINT32 * pcKeySize,		/* out */
472 				  BYTE ** prgbKey)		/* out */
473 {
474 	UINT16 keySize;
475 	BYTE buffer[4096];
476 	TSS_RESULT result;
477 
478 	if ((result = ctx_verify_context(hContext)))
479 		return result;
480 
481 	keySize = sizeof(buffer);
482 	if ((result = ps_get_key_by_uuid(KeyUUID, buffer, &keySize)))
483 		return TCSERR(TSS_E_PS_KEY_NOTFOUND);
484 
485 	*prgbKey = calloc(1, keySize);
486 	if (*prgbKey == NULL) {
487 		LogError("malloc of %d bytes failed.", keySize);
488 		return TCSERR(TSS_E_OUTOFMEMORY);
489 	} else {
490 		memcpy(*prgbKey, buffer, keySize);
491 	}
492 	*pcKeySize = keySize;
493 
494 	return TSS_SUCCESS;
495 }
496 
497 TSS_RESULT
TCSP_LoadKeyByUUID_Internal(TCS_CONTEXT_HANDLE hContext,TSS_UUID * KeyUUID,TCS_LOADKEY_INFO * pLoadKeyInfo,TCS_KEY_HANDLE * phKeyTCSI)498 TCSP_LoadKeyByUUID_Internal(TCS_CONTEXT_HANDLE hContext,	/* in */
499 			    TSS_UUID *KeyUUID,			/* in */
500 			    TCS_LOADKEY_INFO * pLoadKeyInfo,	/* in, out */
501 			    TCS_KEY_HANDLE * phKeyTCSI)		/* out */
502 {
503 	UINT32 keyslot = 0, keySize;
504 	UINT32 ordinal;
505 	TSS_RESULT result;
506 	TSS_UUID parentUuid;
507 	BYTE keyBlob[0x1000];
508 	UINT16 blobSize = sizeof(keyBlob);
509 	UINT64 offset;
510 	TCS_KEY_HANDLE parentTCSKeyHandle;
511 
512 	if (TPM_VERSION_IS(1,2))
513 		ordinal = TPM_ORD_LoadKey2;
514 	else
515 		ordinal = TPM_ORD_LoadKey;
516 
517 	LogDebugFn("Enter: uuid: 0x%lx auth? 0x%x ***********", (unsigned long)KeyUUID,
518 		  pLoadKeyInfo == NULL ? 0xdeadbeef : pLoadKeyInfo->authData.AuthHandle);
519 
520 	if ((result = ctx_verify_context(hContext)))
521 		return result;
522 
523 	memset(&parentUuid, 0, sizeof(TSS_UUID));
524 
525 	if (pLoadKeyInfo &&
526 	    memcmp(&pLoadKeyInfo->parentKeyUUID, &parentUuid, sizeof(TSS_UUID))) {
527 		if (ps_get_key_by_uuid(&pLoadKeyInfo->keyUUID, keyBlob, &blobSize))
528 			return TCSERR(TSS_E_PS_KEY_NOTFOUND);
529 
530 		if (mc_get_handles_by_uuid(&pLoadKeyInfo->parentKeyUUID, &parentTCSKeyHandle,
531 					   &keyslot))
532 			return TCSERR(TCS_E_KM_LOADFAILED);
533 
534 		return LoadKeyByBlob_Internal(ordinal, hContext, parentTCSKeyHandle,
535 					      blobSize, keyBlob,
536 					      &pLoadKeyInfo->authData,
537 					      phKeyTCSI, &keyslot);
538 	}
539 
540 	/* if KeyUUID is already loaded, increment the ref count and return */
541 	if (mc_get_handles_by_uuid(KeyUUID, phKeyTCSI, &keyslot) == TSS_SUCCESS) {
542 		if (keyslot) {
543 			if (ctx_mark_key_loaded(hContext, *phKeyTCSI)) {
544 				LogError("Error marking key as loaded");
545 				return TCSERR(TSS_E_INTERNAL_ERROR);
546 			}
547 			return TSS_SUCCESS;
548 		}
549 	}
550 	/*********************************************************************
551 	 *	The first thing to do in this func is setup all the info and make sure
552 	 *		that we get it all from either the keyfile or the keyCache
553 	 *		also, it's important to return if the key is already loaded
554 	 ***********************************************************************/
555 	LogDebugFn("calling ps_get_key_by_uuid");
556 	if (ps_get_key_by_uuid(KeyUUID, keyBlob, &blobSize))
557 		return TCSERR(TSS_E_PS_KEY_NOTFOUND);
558 	/* convert UINT16 to UIN32 */
559 	keySize = blobSize;
560 
561 	LogDebugFn("calling getParentUUIDByUUID");
562 	/*---	Get my parent's UUID.  Since My key is registered, my parent should be as well. */
563 	if ((result = getParentUUIDByUUID(KeyUUID, &parentUuid)))
564 		return TCSERR(TCS_E_KM_LOADFAILED);
565 
566 	if ((result = TCSP_LoadKeyByUUID_Internal(hContext, &parentUuid,
567 						  pLoadKeyInfo, &parentTCSKeyHandle)))
568 		return result;
569 
570 	LogDebugFn("calling LoadKeyByBlob_Internal");
571 	/*******************************************************
572 	 * If no errors have happend up till now, then the parent is loaded and ready for use.
573 	 * The parent's TCS Handle should be in parentTCSKeyHandle.
574 	 ******************************************************/
575 	if ((result = LoadKeyByBlob_Internal(ordinal, hContext, parentTCSKeyHandle,
576 					     keySize, keyBlob,
577 					     NULL,
578 					     phKeyTCSI, &keyslot))) {
579 		LogDebugFn("LoadKeyByBlob_Internal returned 0x%x", result);
580 		if (result == TCPA_E_AUTHFAIL && pLoadKeyInfo) {
581 			BYTE blob[1000];
582 
583 			/* set up a load key info struct */
584 			memcpy(&pLoadKeyInfo->parentKeyUUID, &parentUuid, sizeof(TSS_UUID));
585 			memcpy(&pLoadKeyInfo->keyUUID, KeyUUID, sizeof(TSS_UUID));
586 
587 			/* calculate the paramDigest */
588 			offset = 0;
589 			LoadBlob_UINT32(&offset, ordinal, blob);
590 			LoadBlob(&offset, keySize, blob, keyBlob);
591 			if (Hash(TSS_HASH_SHA1, offset, blob,
592 				 (BYTE *)&pLoadKeyInfo->paramDigest.digest))
593 				result = TCSERR(TSS_E_INTERNAL_ERROR);
594 
595 			result = TCSERR(TCS_E_KM_LOADFAILED);
596 		}
597 	}
598 
599 	return result;
600 }
601 
602 TSS_RESULT
TCSP_GetRegisteredKeyByPublicInfo_Internal(TCS_CONTEXT_HANDLE tcsContext,TCPA_ALGORITHM_ID algID,UINT32 ulPublicInfoLength,BYTE * rgbPublicInfo,UINT32 * keySize,BYTE ** keyBlob)603 TCSP_GetRegisteredKeyByPublicInfo_Internal(TCS_CONTEXT_HANDLE tcsContext,	/* in */
604 					   TCPA_ALGORITHM_ID algID,		/* in */
605 					   UINT32 ulPublicInfoLength,		/* in */
606 					   BYTE * rgbPublicInfo,		/* in */
607 					   UINT32 * keySize,			/* out */
608 					   BYTE ** keyBlob)			/* out */
609 {
610 	TCPA_STORE_PUBKEY pubKey;
611 	TSS_RESULT result = TCSERR(TSS_E_FAIL);
612 
613 	pubKey.key = NULL;
614 
615 	if ((result = ctx_verify_context(tcsContext)))
616 		return result;
617 
618 	if (algID == TCPA_ALG_RSA) {
619 		/*---	Convert Public info to a structure */
620 		pubKey.keyLength = ulPublicInfoLength;
621 		pubKey.key = malloc(pubKey.keyLength);
622 		if (pubKey.key == NULL) {
623 			LogError("malloc of %d bytes failed.", pubKey.keyLength);
624 			return TCSERR(TSS_E_OUTOFMEMORY);
625 		}
626 
627 		memcpy(pubKey.key, rgbPublicInfo, pubKey.keyLength);
628 
629 		if ((result = ps_get_key_by_pub(&pubKey, keySize, keyBlob))) {
630 			LogDebug("Public key data not found in PS");
631 			free(pubKey.key);
632 			return TCSERR(TSS_E_PS_KEY_NOTFOUND);
633 		}
634 	}
635 	free(pubKey.key);
636 
637 	return result;
638 }
639