tcsi_ps.c revision 1.1.1.1
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
25TSS_RESULT
26TCS_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
63TSS_RESULT
64TCS_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
75TSS_RESULT
76TCS_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	}
231done:
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
242TSS_RESULT
243TCS_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	}
398done:
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
409TSS_RESULT
410TCS_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
468TSS_RESULT
469TCS_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
497TSS_RESULT
498TCSP_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	TSS_RESULT result;
505	TSS_UUID parentUuid;
506	BYTE keyBlob[0x1000];
507	UINT16 blobSize = sizeof(keyBlob);
508	UINT64 offset;
509	TCS_KEY_HANDLE parentTCSKeyHandle;
510
511	LogDebugFn("Enter: uuid: 0x%lx auth? 0x%x ***********", (unsigned long)KeyUUID,
512		  pLoadKeyInfo == NULL ? 0xdeadbeef : pLoadKeyInfo->authData.AuthHandle);
513
514	if ((result = ctx_verify_context(hContext)))
515		return result;
516
517	memset(&parentUuid, 0, sizeof(TSS_UUID));
518
519	if (pLoadKeyInfo &&
520	    memcmp(&pLoadKeyInfo->parentKeyUUID, &parentUuid, sizeof(TSS_UUID))) {
521		if (ps_get_key_by_uuid(&pLoadKeyInfo->keyUUID, keyBlob, &blobSize))
522			return TCSERR(TSS_E_PS_KEY_NOTFOUND);
523
524		if (mc_get_handles_by_uuid(&pLoadKeyInfo->parentKeyUUID, &parentTCSKeyHandle,
525					   &keyslot))
526			return TCSERR(TCS_E_KM_LOADFAILED);
527
528		return TCSP_LoadKeyByBlob_Internal(hContext, parentTCSKeyHandle,
529						   blobSize, keyBlob,
530						   &pLoadKeyInfo->authData,
531						   phKeyTCSI, &keyslot);
532	}
533
534	/* if KeyUUID is already loaded, increment the ref count and return */
535	if (mc_get_handles_by_uuid(KeyUUID, phKeyTCSI, &keyslot) == TSS_SUCCESS) {
536		if (keyslot) {
537			if (ctx_mark_key_loaded(hContext, *phKeyTCSI)) {
538				LogError("Error marking key as loaded");
539				return TCSERR(TSS_E_INTERNAL_ERROR);
540			}
541			return TSS_SUCCESS;
542		}
543	}
544	/*********************************************************************
545	 *	The first thing to do in this func is setup all the info and make sure
546	 *		that we get it all from either the keyfile or the keyCache
547	 *		also, it's important to return if the key is already loaded
548	 ***********************************************************************/
549	LogDebugFn("calling ps_get_key_by_uuid");
550	if (ps_get_key_by_uuid(KeyUUID, keyBlob, &blobSize))
551		return TCSERR(TSS_E_PS_KEY_NOTFOUND);
552	/* convert UINT16 to UIN32 */
553	keySize = blobSize;
554
555	LogDebugFn("calling getParentUUIDByUUID");
556	/*---	Get my parent's UUID.  Since My key is registered, my parent should be as well. */
557	if ((result = getParentUUIDByUUID(KeyUUID, &parentUuid)))
558		return TCSERR(TCS_E_KM_LOADFAILED);
559
560	if ((result = TCSP_LoadKeyByUUID_Internal(hContext, &parentUuid,
561						  pLoadKeyInfo, &parentTCSKeyHandle)))
562		return result;
563
564	LogDebugFn("calling TCSP_LoadKeyByBlob_Internal");
565	/*******************************************************
566	 * If no errors have happend up till now, then the parent is loaded and ready for use.
567	 * The parent's TCS Handle should be in parentTCSKeyHandle.
568	 ******************************************************/
569	if ((result = TCSP_LoadKeyByBlob_Internal(hContext, parentTCSKeyHandle,
570						  keySize, keyBlob,
571						  NULL,
572						  phKeyTCSI, &keyslot))) {
573		LogDebugFn("TCSP_LoadKeyByBlob_Internal returned 0x%x", result);
574		if (result == TCPA_E_AUTHFAIL && pLoadKeyInfo) {
575			BYTE blob[1000];
576
577			/* set up a load key info struct */
578			memcpy(&pLoadKeyInfo->parentKeyUUID, &parentUuid, sizeof(TSS_UUID));
579			memcpy(&pLoadKeyInfo->keyUUID, KeyUUID, sizeof(TSS_UUID));
580
581			/* calculate the paramDigest */
582			offset = 0;
583			LoadBlob_UINT32(&offset, TPM_ORD_LoadKey, blob);
584			LoadBlob(&offset, keySize, blob, keyBlob);
585			if (Hash(TSS_HASH_SHA1, offset, blob,
586				 (BYTE *)&pLoadKeyInfo->paramDigest.digest))
587				result = TCSERR(TSS_E_INTERNAL_ERROR);
588
589			result = TCSERR(TCS_E_KM_LOADFAILED);
590		}
591	}
592
593	return result;
594}
595
596TSS_RESULT
597TCSP_GetRegisteredKeyByPublicInfo_Internal(TCS_CONTEXT_HANDLE tcsContext,	/* in */
598					   TCPA_ALGORITHM_ID algID,		/* in */
599					   UINT32 ulPublicInfoLength,		/* in */
600					   BYTE * rgbPublicInfo,		/* in */
601					   UINT32 * keySize,			/* out */
602					   BYTE ** keyBlob)			/* out */
603{
604	TCPA_STORE_PUBKEY pubKey;
605	TSS_RESULT result = TCSERR(TSS_E_FAIL);
606
607	if ((result = ctx_verify_context(tcsContext)))
608		return result;
609
610	if (algID == TCPA_ALG_RSA) {
611		/*---	Convert Public info to a structure */
612		pubKey.keyLength = ulPublicInfoLength;
613		pubKey.key = malloc(pubKey.keyLength);
614		if (pubKey.key == NULL) {
615			LogError("malloc of %d bytes failed.", pubKey.keyLength);
616			return TCSERR(TSS_E_OUTOFMEMORY);
617		}
618
619		memcpy(pubKey.key, rgbPublicInfo, pubKey.keyLength);
620
621		if ((result = ps_get_key_by_pub(&pubKey, keySize, keyBlob))) {
622			LogDebug("Public key data not found in PS");
623			free(pubKey.key);
624			return TCSERR(TSS_E_PS_KEY_NOTFOUND);
625		}
626	}
627	free(pubKey.key);
628
629	return result;
630}
631