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