xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tspi/tspi_ps.c (revision 1023804e3833a0bd94414f2545512128f6502c74)
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
Tspi_Context_LoadKeyByUUID(TSS_HCONTEXT tspContext,TSS_FLAG persistentStorageType,TSS_UUID uuidData,TSS_HKEY * phKey)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
Tspi_Context_RegisterKey(TSS_HCONTEXT tspContext,TSS_HKEY hKey,TSS_FLAG persistentStorageType,TSS_UUID uuidKey,TSS_FLAG persistentStorageTypeParent,TSS_UUID uuidParentKey)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
Tspi_Context_UnregisterKey(TSS_HCONTEXT tspContext,TSS_FLAG persistentStorageType,TSS_UUID uuidKey,TSS_HKEY * phKey)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
Tspi_Context_GetKeyByUUID(TSS_HCONTEXT tspContext,TSS_FLAG persistentStorageType,TSS_UUID uuidData,TSS_HKEY * phKey)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
Tspi_Context_GetKeyByPublicInfo(TSS_HCONTEXT tspContext,TSS_FLAG persistentStorageType,TSS_ALGORITHM_ID algID,UINT32 ulPublicInfoLength,BYTE * rgbPublicInfo,TSS_HKEY * phKey)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
Tspi_Context_GetRegisteredKeysByUUID(TSS_HCONTEXT tspContext,TSS_FLAG persistentStorageType,TSS_UUID * pUuidData,UINT32 * pulKeyHierarchySize,TSS_KM_KEYINFO ** ppKeyHierarchy)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
Tspi_Context_GetRegisteredKeysByUUID2(TSS_HCONTEXT tspContext,TSS_FLAG persistentStorageType,TSS_UUID * pUuidData,UINT32 * pulKeyHierarchySize,TSS_KM_KEYINFO2 ** ppKeyHierarchy)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