Home | History | Annotate | Line # | Download | only in tcs
      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
     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
     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
     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
    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
    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
    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
    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
    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