Home | History | Annotate | Line # | Download | only in tspi
      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 
     16 #include "trousers/tss.h"
     17 #include "trousers/trousers.h"
     18 #include "trousers_types.h"
     19 #include "trousers_types.h"
     20 #include "spi_utils.h"
     21 #include "capabilities.h"
     22 #include "tsplog.h"
     23 #include "tcs_tsp.h"
     24 #include "tspps.h"
     25 #include "hosttable.h"
     26 #include "tcsd_wrap.h"
     27 #include "tcsd.h"
     28 #include "obj.h"
     29 
     30 TSS_UUID owner_evict_uuid = {0, 0, 0, 0, 0, {0, 0, 0, 0, 1, 0}};
     31 
     32 TSS_RESULT
     33 Tspi_Context_LoadKeyByUUID(TSS_HCONTEXT tspContext,		/* in */
     34 			   TSS_FLAG persistentStorageType,	/* in */
     35 			   TSS_UUID uuidData,			/* in */
     36 			   TSS_HKEY * phKey)			/* out */
     37 {
     38 	TSS_RESULT result;
     39 	TSS_UUID parentUUID;
     40 	UINT32 keyBlobSize, parentPSType;
     41 	BYTE *keyBlob = NULL;
     42 	TCS_KEY_HANDLE tcsKeyHandle;
     43 	TSS_HKEY parentTspHandle;
     44 	TCS_LOADKEY_INFO info;
     45 	UINT32		ulPubKeyLength;
     46 	BYTE		*rgbPubKey;
     47 	TPM_COMMAND_CODE ordinal;
     48 
     49 	if (phKey == NULL)
     50 		return TSPERR(TSS_E_BAD_PARAMETER);
     51 
     52 	if ((!obj_is_context(tspContext)))
     53 		return TSPERR(TSS_E_INVALID_HANDLE);
     54 
     55 	if ((result = obj_context_get_loadkey_ordinal(tspContext, &ordinal)))
     56 		return result;
     57 
     58 	/* This key is in the System Persistant storage */
     59 	if (persistentStorageType == TSS_PS_TYPE_SYSTEM) {
     60 #if 1
     61 		__tspi_memset(&info, 0, sizeof(TCS_LOADKEY_INFO));
     62 
     63 		result = RPC_LoadKeyByUUID(tspContext, uuidData, &info, &tcsKeyHandle);
     64 
     65 		if (TSS_ERROR_CODE(result) == TCS_E_KM_LOADFAILED) {
     66 			TSS_HKEY keyHandle;
     67 			TSS_HPOLICY hPolicy;
     68 
     69 			/* load failed, due to some key in the chain needing auth
     70 			 * which doesn't yet exist at the TCS level. However, the
     71 			 * auth may already be set in policies at the TSP level.
     72 			 * To find out, get the key handle of the key requiring
     73 			 * auth. First, look at the list of keys in memory. */
     74 			if ((obj_rsakey_get_by_uuid(&info.parentKeyUUID, &keyHandle))) {
     75 				/* If that failed, look on disk, in User PS. */
     76 				if (ps_get_key_by_uuid(tspContext, &info.parentKeyUUID,
     77 						       &keyHandle))
     78 					return result;
     79 			}
     80 
     81 			if (obj_rsakey_get_policy(keyHandle, TSS_POLICY_USAGE,
     82 						  &hPolicy, NULL))
     83 				return result;
     84 
     85 			if (secret_PerformAuth_OIAP(keyHandle, ordinal, hPolicy, FALSE,
     86 						    &info.paramDigest, &info.authData))
     87 				return result;
     88 
     89 			if ((result = RPC_LoadKeyByUUID(tspContext, uuidData, &info,
     90 							&tcsKeyHandle)))
     91 				return result;
     92 		} else if (result)
     93 			return result;
     94 
     95 		/*check if provided UUID has an owner evict key UUID prefix */
     96 		if (!memcmp(&uuidData, &owner_evict_uuid, sizeof(TSS_UUID)-1)) {
     97 			if ((result = obj_rsakey_add(tspContext, TSS_RSAKEY_FLAG_OWNEREVICT,
     98 						      phKey)))
     99 				return result;
    100 			if ((result = obj_rsakey_set_tcs_handle(*phKey, tcsKeyHandle)))
    101 				return result;
    102 
    103 			//The cached public key portion of the owner evict key is used
    104 			//further by TPM_KEY_CONTROLOWNER command for sanity check
    105 			if ((result = Tspi_Key_GetPubKey(*phKey, &ulPubKeyLength, &rgbPubKey)))
    106 				return result;
    107 
    108 			result = obj_rsakey_set_pubkey(*phKey, FALSE, rgbPubKey);
    109 
    110 			free_tspi(tspContext,rgbPubKey);
    111 			if (result != TSS_SUCCESS)
    112 				return result;
    113 		} else {
    114 			if ((result = RPC_GetRegisteredKeyBlob(tspContext, uuidData, &keyBlobSize,
    115 							       &keyBlob)))
    116 				return result;
    117 
    118 			if ((result = obj_rsakey_add_by_key(tspContext, &uuidData, keyBlob,
    119 							    TSS_OBJ_FLAG_SYSTEM_PS, phKey))) {
    120 				free (keyBlob);
    121 				return result;
    122 			}
    123 
    124 			result = obj_rsakey_set_tcs_handle(*phKey, tcsKeyHandle);
    125 
    126 			free (keyBlob);
    127 		}
    128 #else
    129 		if ((result = load_from_system_ps(tspContext, &uuidData, phKey)))
    130 			return result;
    131 #endif
    132 	} else if (persistentStorageType == TSS_PS_TYPE_USER) {
    133 		if ((result = ps_get_parent_uuid_by_uuid(&uuidData, &parentUUID)))
    134 			return result;
    135 
    136 		/* If the parent is not in memory, recursively call ourselves on it */
    137 		if (obj_rsakey_get_by_uuid(&parentUUID, &parentTspHandle) != TSS_SUCCESS) {
    138 			if ((result = ps_get_parent_ps_type_by_uuid(&uuidData, &parentPSType)))
    139 				return result;
    140 
    141 			if ((result = Tspi_Context_LoadKeyByUUID(tspContext, parentPSType,
    142 								 parentUUID, &parentTspHandle)))
    143 				return result;
    144 		}
    145 
    146 		if ((result = ps_get_key_by_uuid(tspContext, &uuidData, phKey)))
    147 			return result;
    148 
    149 		/* The parent is loaded and we have the parent key handle, so call the TCS to
    150 		 * actually load the child. */
    151 		return Tspi_Key_LoadKey(*phKey, parentTspHandle);
    152 	} else {
    153 		return TSPERR(TSS_E_BAD_PARAMETER);
    154 	}
    155 
    156 	return TSS_SUCCESS;
    157 }
    158 
    159 TSS_RESULT
    160 Tspi_Context_RegisterKey(TSS_HCONTEXT tspContext,		/* in */
    161 			 TSS_HKEY hKey,				/* in */
    162 			 TSS_FLAG persistentStorageType,	/* in */
    163 			 TSS_UUID uuidKey,			/* in */
    164 			 TSS_FLAG persistentStorageTypeParent,	/* in */
    165 			 TSS_UUID uuidParentKey)		/* in */
    166 {
    167 	BYTE *keyBlob;
    168 	UINT32 keyBlobSize;
    169 	TSS_RESULT result;
    170 	TSS_BOOL answer;
    171 
    172 	if (!obj_is_context(tspContext) || !obj_is_rsakey(hKey))
    173 		return TSPERR(TSS_E_INVALID_HANDLE);
    174 
    175 	if (persistentStorageType == TSS_PS_TYPE_SYSTEM) {
    176 		if (persistentStorageTypeParent == TSS_PS_TYPE_USER) {
    177 			return TSPERR(TSS_E_NOTIMPL);
    178 		} else if (persistentStorageTypeParent == TSS_PS_TYPE_SYSTEM) {
    179 			if ((result = obj_rsakey_get_blob(hKey, &keyBlobSize,
    180 							  &keyBlob)))
    181 				return result;
    182 
    183 			if ((result = RPC_RegisterKey(tspContext, uuidParentKey, uuidKey,
    184 						      keyBlobSize, keyBlob,
    185 						      strlen(PACKAGE_STRING) + 1,
    186 						      (BYTE *)PACKAGE_STRING)))
    187 				return result;
    188 		} else {
    189 			return TSPERR(TSS_E_BAD_PARAMETER);
    190 		}
    191 	} else if (persistentStorageType == TSS_PS_TYPE_USER) {
    192 		if ((result = ps_is_key_registered(&uuidKey, &answer)))
    193 			return result;
    194 
    195 		if (answer == TRUE)
    196 			return TSPERR(TSS_E_KEY_ALREADY_REGISTERED);
    197 
    198 		if ((result = obj_rsakey_get_blob (hKey, &keyBlobSize, &keyBlob)))
    199 			return result;
    200 
    201 		if ((result = ps_write_key(&uuidKey, &uuidParentKey,
    202 					   persistentStorageTypeParent,
    203 					   keyBlobSize, keyBlob)))
    204 			return result;
    205 	} else {
    206 		return TSPERR(TSS_E_BAD_PARAMETER);
    207 	}
    208 
    209 	if ((result = obj_rsakey_set_uuid(hKey, persistentStorageType, &uuidKey)))
    210 		return result;
    211 
    212 	return TSS_SUCCESS;
    213 }
    214 
    215 TSS_RESULT
    216 Tspi_Context_UnregisterKey(TSS_HCONTEXT tspContext,		/* in */
    217 			   TSS_FLAG persistentStorageType,	/* in */
    218 			   TSS_UUID uuidKey,			/* in */
    219 			   TSS_HKEY *phKey)			/* out */
    220 {
    221 	BYTE *keyBlob = NULL;
    222 	UINT32 keyBlobSize;
    223 	TSS_RESULT result;
    224 
    225 	if (phKey == NULL)
    226 		return TSPERR(TSS_E_BAD_PARAMETER);
    227 
    228 	if ((!obj_is_context(tspContext)))
    229 		return TSPERR(TSS_E_INVALID_HANDLE);
    230 
    231 	if (persistentStorageType == TSS_PS_TYPE_SYSTEM) {
    232 		/* get the key first, so it doesn't disappear when we
    233 		 * unregister it */
    234 		if ((result = RPC_GetRegisteredKeyBlob(tspContext, uuidKey, &keyBlobSize,
    235 						       &keyBlob)))
    236 			return result;
    237 
    238 		if ((obj_rsakey_add_by_key(tspContext, &uuidKey, keyBlob, TSS_OBJ_FLAG_SYSTEM_PS,
    239 					   phKey))) {
    240 			free(keyBlob);
    241 			return result;
    242 		}
    243 
    244 		free(keyBlob);
    245 
    246 		/* now unregister it */
    247 		if ((result = RPC_UnregisterKey(tspContext, uuidKey)))
    248 			return result;
    249 	} else if (persistentStorageType == TSS_PS_TYPE_USER) {
    250 		/* get the key first, so it doesn't disappear when we
    251 		 * unregister it */
    252 		if ((result = ps_get_key_by_uuid(tspContext, &uuidKey, phKey)))
    253 			return result;
    254 
    255 		/* now unregister it */
    256 		if ((result = ps_remove_key(&uuidKey)))
    257 			return result;
    258 	} else {
    259 		return TSPERR(TSS_E_BAD_PARAMETER);
    260 	}
    261 
    262 	return TSS_SUCCESS;
    263 }
    264 
    265 TSS_RESULT
    266 Tspi_Context_GetKeyByUUID(TSS_HCONTEXT tspContext,		/* in */
    267 			  TSS_FLAG persistentStorageType,	/* in */
    268 			  TSS_UUID uuidData,			/* in */
    269 			  TSS_HKEY * phKey)			/* out */
    270 {
    271 	TCPA_RESULT result;
    272 	UINT32 keyBlobSize = 0;
    273 	BYTE *keyBlob = NULL;
    274 
    275 	if (phKey == NULL)
    276 		return TSPERR(TSS_E_BAD_PARAMETER);
    277 
    278 	if ((!obj_is_context(tspContext)))
    279 		return TSPERR(TSS_E_INVALID_HANDLE);
    280 
    281 	if (persistentStorageType == TSS_PS_TYPE_SYSTEM) {
    282 		if ((result = RPC_GetRegisteredKeyBlob(tspContext, uuidData, &keyBlobSize,
    283 						       &keyBlob)))
    284 			return result;
    285 
    286 		if ((obj_rsakey_add_by_key(tspContext, &uuidData, keyBlob, TSS_OBJ_FLAG_SYSTEM_PS,
    287 					   phKey))) {
    288 			free(keyBlob);
    289 			return result;
    290 		}
    291 
    292 		free(keyBlob);
    293 	} else if (persistentStorageType == TSS_PS_TYPE_USER) {
    294 		if (!obj_is_context(tspContext))
    295 			return TSPERR(TSS_E_INVALID_HANDLE);
    296 
    297 		if ((result = ps_get_key_by_uuid(tspContext, &uuidData, phKey)))
    298 			return result;
    299 	} else
    300 		return TSPERR(TSS_E_BAD_PARAMETER);
    301 
    302 	return TSS_SUCCESS;
    303 }
    304 
    305 TSS_RESULT
    306 Tspi_Context_GetKeyByPublicInfo(TSS_HCONTEXT tspContext,	/* in */
    307 				TSS_FLAG persistentStorageType,	/* in */
    308 				TSS_ALGORITHM_ID algID,		/* in */
    309 				UINT32 ulPublicInfoLength,	/* in */
    310 				BYTE * rgbPublicInfo,		/* in */
    311 				TSS_HKEY * phKey)		/* out */
    312 {
    313 	TCPA_ALGORITHM_ID tcsAlgID;
    314 	UINT32 keyBlobSize;
    315 	BYTE *keyBlob;
    316 	TSS_RESULT result;
    317 	TSS_HKEY keyOutHandle;
    318 	UINT32 flag = 0;
    319 	TSS_KEY keyContainer;
    320 	UINT64 offset;
    321 
    322 	if (phKey == NULL)
    323 		return TSPERR(TSS_E_BAD_PARAMETER);
    324 
    325 	if (!obj_is_context(tspContext))
    326 		return TSPERR(TSS_E_INVALID_HANDLE);
    327 
    328 	switch (algID) {
    329 		case TSS_ALG_RSA:
    330 			tcsAlgID = TCPA_ALG_RSA;
    331 			break;
    332 		default:
    333 			LogError("Algorithm ID was not type RSA.");
    334 			return TSPERR(TSS_E_BAD_PARAMETER);
    335 	}
    336 
    337 	if (persistentStorageType == TSS_PS_TYPE_SYSTEM) {
    338 		if ((result = RPC_GetRegisteredKeyByPublicInfo(tspContext, tcsAlgID,
    339 							       ulPublicInfoLength, rgbPublicInfo,
    340 							       &keyBlobSize, &keyBlob)))
    341 			return result;
    342 
    343 	} else if (persistentStorageType == TSS_PS_TYPE_USER) {
    344 		return ps_get_key_by_pub(tspContext, ulPublicInfoLength, rgbPublicInfo,
    345 					 phKey);
    346 	} else
    347 		return TSPERR(TSS_E_BAD_PARAMETER);
    348 
    349 	/* need to setup the init flags of the create object based on
    350 	 * the size of the blob's pubkey */
    351 	offset = 0;
    352 	if ((result = UnloadBlob_TSS_KEY(&offset, keyBlob, &keyContainer))) {
    353 		free(keyBlob);
    354 		return result;
    355 	}
    356 
    357 	/* begin setting up the key object */
    358 	switch (keyContainer.pubKey.keyLength) {
    359 		case 16384/8:
    360 			flag |= TSS_KEY_SIZE_16384;
    361 			break;
    362 		case 8192/8:
    363 			flag |= TSS_KEY_SIZE_8192;
    364 			break;
    365 		case 4096/8:
    366 			flag |= TSS_KEY_SIZE_4096;
    367 			break;
    368 		case 2048/8:
    369 			flag |= TSS_KEY_SIZE_2048;
    370 			break;
    371 		case 1024/8:
    372 			flag |= TSS_KEY_SIZE_1024;
    373 			break;
    374 		case 512/8:
    375 			flag |= TSS_KEY_SIZE_512;
    376 			break;
    377 		default:
    378 			LogError("Key was not a known keylength.");
    379 			free(keyBlob);
    380 			free_key_refs(&keyContainer);
    381 			return TSPERR(TSS_E_INTERNAL_ERROR);
    382 	}
    383 
    384 	if (keyContainer.keyUsage == TPM_KEY_SIGNING)
    385 		flag |= TSS_KEY_TYPE_SIGNING;
    386 	else if (keyContainer.keyUsage == TPM_KEY_STORAGE)
    387 		flag |= TSS_KEY_TYPE_STORAGE;
    388 	else if (keyContainer.keyUsage == TPM_KEY_IDENTITY)
    389 		flag |= TSS_KEY_TYPE_IDENTITY;
    390 	else if (keyContainer.keyUsage == TPM_KEY_AUTHCHANGE)
    391 		flag |= TSS_KEY_TYPE_AUTHCHANGE;
    392 	else if (keyContainer.keyUsage == TPM_KEY_BIND)
    393 		flag |= TSS_KEY_TYPE_BIND;
    394 	else if (keyContainer.keyUsage == TPM_KEY_LEGACY)
    395 		flag |= TSS_KEY_TYPE_LEGACY;
    396 
    397 	if (keyContainer.authDataUsage == TPM_AUTH_NEVER)
    398 		flag |= TSS_KEY_NO_AUTHORIZATION;
    399 	else
    400 		flag |= TSS_KEY_AUTHORIZATION;
    401 
    402 	if (keyContainer.keyFlags & TPM_MIGRATABLE)
    403 		flag |= TSS_KEY_MIGRATABLE;
    404 	else
    405 		flag |= TSS_KEY_NOT_MIGRATABLE;
    406 
    407 	if (keyContainer.keyFlags & TPM_VOLATILE)
    408 		flag |= TSS_KEY_VOLATILE;
    409 	else
    410 		flag |= TSS_KEY_NON_VOLATILE;
    411 
    412 #ifdef TSS_BUILD_CMK
    413 	if (keyContainer.keyFlags & TPM_MIGRATEAUTHORITY)
    414 		flag |= TSS_KEY_CERTIFIED_MIGRATABLE;
    415 	else
    416 		flag |= TSS_KEY_NOT_CERTIFIED_MIGRATABLE;
    417 #endif
    418 
    419 	/* Create a new Key Object */
    420 	if ((result = obj_rsakey_add(tspContext, flag, &keyOutHandle))) {
    421 		free(keyBlob);
    422 		free_key_refs(&keyContainer);
    423 		return result;
    424 	}
    425 	/* Stick the info into this net KeyObject */
    426 	if ((result = obj_rsakey_set_tcpakey(keyOutHandle, keyBlobSize, keyBlob))) {
    427 		free(keyBlob);
    428 		free_key_refs(&keyContainer);
    429 		return result;
    430 	}
    431 
    432 	free(keyBlob);
    433 	free_key_refs(&keyContainer);
    434 	*phKey = keyOutHandle;
    435 
    436 	return TSS_SUCCESS;
    437 }
    438 
    439 TSS_RESULT
    440 Tspi_Context_GetRegisteredKeysByUUID(TSS_HCONTEXT tspContext,		/* in */
    441 				     TSS_FLAG persistentStorageType,	/* in */
    442 				     TSS_UUID * pUuidData,		/* in */
    443 				     UINT32 * pulKeyHierarchySize,	/* out */
    444 				     TSS_KM_KEYINFO ** ppKeyHierarchy)	/* out */
    445 {
    446 	TSS_RESULT result;
    447 	TSS_KM_KEYINFO *tcsHier, *tspHier;
    448 	UINT32 tcsHierSize, tspHierSize;
    449 	TSS_UUID tcs_uuid;
    450 
    451 	if (pulKeyHierarchySize == NULL || ppKeyHierarchy == NULL)
    452 		return TSPERR(TSS_E_BAD_PARAMETER);
    453 
    454 	if (!obj_is_context(tspContext))
    455 		return TSPERR(TSS_E_INVALID_HANDLE);
    456 
    457 	if (pUuidData) {
    458 		if (persistentStorageType == TSS_PS_TYPE_SYSTEM) {
    459 			if ((result = RPC_EnumRegisteredKeys(tspContext, pUuidData,
    460 							     pulKeyHierarchySize,
    461 							     ppKeyHierarchy)))
    462 				return result;
    463 		} else if (persistentStorageType == TSS_PS_TYPE_USER) {
    464 			if ((result = ps_get_registered_keys(pUuidData, &tcs_uuid,
    465 							     &tspHierSize, &tspHier)))
    466 				return result;
    467 
    468 			if ((result = RPC_EnumRegisteredKeys(tspContext, &tcs_uuid, &tcsHierSize,
    469 							     &tcsHier))) {
    470 				free(tspHier);
    471 				return result;
    472 			}
    473 
    474 			result = merge_key_hierarchies(tspContext, tspHierSize, tspHier,
    475 						       tcsHierSize, tcsHier, pulKeyHierarchySize,
    476 						       ppKeyHierarchy);
    477 			free(tcsHier);
    478 			free(tspHier);
    479 		} else
    480 			return TSPERR(TSS_E_BAD_PARAMETER);
    481 	} else {
    482 		if ((result = RPC_EnumRegisteredKeys(tspContext, pUuidData, &tcsHierSize,
    483 						     &tcsHier)))
    484 			return result;
    485 
    486 		if ((result = ps_get_registered_keys(pUuidData, NULL, &tspHierSize, &tspHier))) {
    487 			free(tcsHier);
    488 			return result;
    489 		}
    490 
    491 		result = merge_key_hierarchies(tspContext, tspHierSize, tspHier, tcsHierSize,
    492 					       tcsHier, pulKeyHierarchySize, ppKeyHierarchy);
    493 		free(tcsHier);
    494 		free(tspHier);
    495 	}
    496 
    497 	if ((result = __tspi_add_mem_entry(tspContext, *ppKeyHierarchy))) {
    498 		free(*ppKeyHierarchy);
    499 		*ppKeyHierarchy = NULL;
    500 		*pulKeyHierarchySize = 0;
    501 	}
    502 
    503 	return result;
    504 }
    505 
    506 TSS_RESULT
    507 Tspi_Context_GetRegisteredKeysByUUID2(TSS_HCONTEXT tspContext,		/* in */
    508 				     TSS_FLAG persistentStorageType,	/* in */
    509 				     TSS_UUID * pUuidData,		/* in */
    510 				     UINT32 * pulKeyHierarchySize,	/* out */
    511 				     TSS_KM_KEYINFO2 ** ppKeyHierarchy)	/* out */
    512 {
    513 	TSS_RESULT result;
    514 	TSS_KM_KEYINFO2 *tcsHier, *tspHier;
    515 	UINT32 tcsHierSize, tspHierSize;
    516 	TSS_UUID tcs_uuid;
    517 
    518 	/* If out parameters are NULL, return error */
    519 	if (pulKeyHierarchySize == NULL || ppKeyHierarchy == NULL)
    520 			return TSPERR(TSS_E_BAD_PARAMETER);
    521 
    522 	if (!obj_is_context(tspContext))
    523 			return TSPERR(TSS_E_INVALID_HANDLE);
    524 
    525 	if (pUuidData) {
    526 		/* TSS 1.2 Spec: If a certain key UUID is provided, the returned array of
    527 		 * TSS_KM_KEYINFO2 structures only contains data reflecting the path of the key
    528 		 * hierarchy regarding that key. The first array entry is the key addressed by the
    529 		 * given UUID followed by its parent key up to and including the root key. */
    530 		if (persistentStorageType == TSS_PS_TYPE_SYSTEM) {
    531 			if ((result = RPC_EnumRegisteredKeys2(tspContext, pUuidData,
    532 							      pulKeyHierarchySize, ppKeyHierarchy)))
    533 				return result;
    534 		} else if (persistentStorageType == TSS_PS_TYPE_USER) {
    535 			if ((result = ps_get_registered_keys2(pUuidData, &tcs_uuid, &tspHierSize,
    536 							      &tspHier)))
    537 				return result;
    538 			/* The tcs_uuid returned by ps_get_registered_key2 will always be a parent
    539 			 * of some key into the system ps of a user key into the user ps. This key
    540 			 * needs to be searched for in the system ps to be merged */
    541 			if ((result = RPC_EnumRegisteredKeys2(tspContext, &tcs_uuid, &tcsHierSize,
    542 							      &tcsHier))) {
    543 				free(tspHier);
    544 				return result;
    545 			}
    546 
    547 			result = merge_key_hierarchies2(tspContext, tspHierSize, tspHier,
    548 							tcsHierSize, tcsHier, pulKeyHierarchySize,
    549 							ppKeyHierarchy);
    550 			free(tcsHier);
    551 			free(tspHier);
    552 		} else
    553 			return TSPERR(TSS_E_BAD_PARAMETER);
    554 	} else {
    555 		/* If this field is set to NULL, the returned array of TSS_KM_KEYINFO2 structures
    556 		 * contains data reflecting the entire key hierarchy starting with root key. The
    557 		 * array will include keys from both the user and the system TSS key store. The
    558 		 * persistentStorageType field will be ignored. */
    559 		if ((result = RPC_EnumRegisteredKeys2(tspContext, pUuidData, &tcsHierSize,
    560 						      &tcsHier)))
    561 			return result;
    562 
    563 		if ((result = ps_get_registered_keys2(pUuidData, NULL, &tspHierSize, &tspHier))) {
    564 			free(tcsHier);
    565 			return result;
    566 		}
    567 
    568 		result = merge_key_hierarchies2(tspContext, tspHierSize, tspHier, tcsHierSize,
    569 						tcsHier, pulKeyHierarchySize, ppKeyHierarchy);
    570 		free(tcsHier);
    571 		free(tspHier);
    572 	}
    573 
    574 	if ((result = __tspi_add_mem_entry(tspContext, *ppKeyHierarchy))) {
    575 		free(*ppKeyHierarchy);
    576 		*ppKeyHierarchy = NULL;
    577 		*pulKeyHierarchySize = 0;
    578 	}
    579 
    580 	return result;
    581 }
    582