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 #include <limits.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <inttypes.h>
16 #include <limits.h>
17 
18 #include "trousers/tss.h"
19 #include "trousers/trousers.h"
20 #include "trousers_types.h"
21 #include "spi_utils.h"
22 #include "capabilities.h"
23 #include "tsplog.h"
24 #include "obj.h"
25 #include "authsess.h"
26 
27 
28 TSS_RESULT
Tspi_TPM_CollateIdentityRequest(TSS_HTPM hTPM,TSS_HKEY hKeySRK,TSS_HKEY hCAPubKey,UINT32 ulIdentityLabelLength,BYTE * rgbIdentityLabelData,TSS_HKEY hIdentityKey,TSS_ALGORITHM_ID algID,UINT32 * pulTcpaIdentityReqLength,BYTE ** prgbTcpaIdentityReq)29 Tspi_TPM_CollateIdentityRequest(TSS_HTPM hTPM,				/* in */
30 				TSS_HKEY hKeySRK,			/* in */
31 				TSS_HKEY hCAPubKey,			/* in */
32 				UINT32 ulIdentityLabelLength,		/* in */
33 				BYTE * rgbIdentityLabelData,		/* in */
34 				TSS_HKEY hIdentityKey,			/* in */
35 				TSS_ALGORITHM_ID algID,			/* in */
36 				UINT32 * pulTcpaIdentityReqLength,	/* out */
37 				BYTE ** prgbTcpaIdentityReq)		/* out */
38 {
39 #ifdef TSS_BUILD_TRANSPORT
40 	UINT32 transport;
41 #endif
42 	TPM_AUTH srkAuth;
43 	TCPA_RESULT result;
44 	UINT64 offset;
45 	BYTE hashblob[USHRT_MAX], idReqBlob[USHRT_MAX], testblob[USHRT_MAX];
46 	TCPA_DIGEST digest;
47 	TSS_HPOLICY hSRKPolicy, hIDPolicy, hCAPolicy;
48 	UINT32 caKeyBlobSize, idKeySize, idPubSize;
49 	BYTE *caKeyBlob, *idKey, *newIdKey, *idPub;
50 	TSS_KEY caKey;
51 	TCPA_CHOSENID_HASH chosenIDHash = { { 0, } };
52 	UINT32 pcIdentityBindingSize;
53 	BYTE *prgbIdentityBinding = NULL;
54 	UINT32 pcEndorsementCredentialSize;
55 	BYTE *prgbEndorsementCredential = NULL;
56 	UINT32 pcPlatformCredentialSize;
57 	BYTE *prgbPlatformCredential = NULL;
58 	UINT32 pcConformanceCredentialSize;
59 	BYTE *prgbConformanceCredential = NULL;
60 #define CHOSENID_BLOB_SIZE 2048
61 	BYTE chosenIDBlob[CHOSENID_BLOB_SIZE];
62 	TSS_HCONTEXT tspContext;
63 	UINT32 encSymKeySize = 256, tmp;
64 	BYTE encSymKey[256], *cb_var;
65 	TSS_BOOL usesAuth;
66 	TPM_AUTH *pSrkAuth = &srkAuth;
67 	TCPA_IDENTITY_REQ rgbTcpaIdentityReq;
68 	TCPA_KEY_PARMS symParms, asymParms;
69 	TCPA_SYMMETRIC_KEY symKey;
70 	int padding;
71 	TSS_CALLBACK *cb;
72 	Trspi_HashCtx hashCtx;
73 	UINT32 tempCredSize;
74 	BYTE *tempCred = NULL;
75 	struct authsess *xsap = NULL;
76 
77 	if (pulTcpaIdentityReqLength == NULL || prgbTcpaIdentityReq == NULL)
78 		return TSPERR(TSS_E_BAD_PARAMETER);
79 
80 	if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
81 		return result;
82 
83 	if ((result = obj_tpm_get_cb12(hTPM, TSS_TSPATTRIB_TPM_CALLBACK_COLLATEIDENTITY, &tmp,
84 				       &cb_var)))
85 		return result;
86 
87 	cb = (TSS_CALLBACK *)cb_var;
88 	if (cb->callback == NULL) {
89 		free_tspi(tspContext, cb);
90 		cb = NULL;
91 	}
92 
93 	/* Get Policies */
94 	if ((result = obj_rsakey_get_policy(hKeySRK, TSS_POLICY_USAGE, &hSRKPolicy, &usesAuth)))
95 		return result;
96 
97 	if ((result = obj_rsakey_get_policy(hCAPubKey, TSS_POLICY_USAGE,
98 					    &hCAPolicy, NULL)))
99 		return result;
100 
101 	if ((result = obj_rsakey_get_policy(hIdentityKey, TSS_POLICY_USAGE,
102 					   &hIDPolicy, NULL)))
103 		return result;
104 
105 	/* setup the symmetric key's parms. */
106 	__tspi_memset(&symParms, 0, sizeof(TCPA_KEY_PARMS));
107 	switch (algID) {
108 		case TSS_ALG_AES:
109 			symParms.algorithmID = TCPA_ALG_AES;
110 			symKey.algId = TCPA_ALG_AES;
111 			symKey.size = 128/8;
112 			break;
113 		case TSS_ALG_DES:
114 			symParms.algorithmID = TCPA_ALG_DES;
115 			symKey.algId = TCPA_ALG_DES;
116 			symKey.size = 64/8;
117 			break;
118 		case TSS_ALG_3DES:
119 			symParms.algorithmID = TCPA_ALG_3DES;
120 			symKey.algId = TCPA_ALG_3DES;
121 			symKey.size = 192/8;
122 			break;
123 		default:
124 			result = TSPERR(TSS_E_BAD_PARAMETER);
125 			goto error;
126 			break;
127 	}
128 
129 	/* No symmetric key encryption schemes existed in the 1.1 time frame */
130 	symParms.encScheme = TCPA_ES_NONE;
131 
132 	/* get the CA Pubkey's encryption scheme */
133 	if ((result = obj_rsakey_get_es(hCAPubKey, &tmp)))
134 		return TSPERR(TSS_E_BAD_PARAMETER);
135 
136 	switch (tmp) {
137 		case TSS_ES_RSAESPKCSV15:
138 			padding = TR_RSA_PKCS1_PADDING;
139 			break;
140 		case TSS_ES_RSAESOAEP_SHA1_MGF1:
141 			padding = TR_RSA_PKCS1_OAEP_PADDING;
142 			break;
143 		case TSS_ES_NONE:
144 			/* fall through */
145 		default:
146 			padding = TR_RSA_NO_PADDING;
147 			break;
148 	}
149 
150 	/* Get Key blobs */
151 	if ((result = obj_rsakey_get_blob(hIdentityKey, &idKeySize, &idKey)))
152 		return result;
153 
154 	if ((result = obj_rsakey_get_blob(hCAPubKey, &caKeyBlobSize, &caKeyBlob)))
155 		return result;
156 
157 	offset = 0;
158 	__tspi_memset(&caKey, 0, sizeof(TSS_KEY));
159 	if ((result = UnloadBlob_TSS_KEY(&offset, caKeyBlob, &caKey)))
160 		return result;
161 
162 	/* ChosenID hash =  SHA1(label || TCPA_PUBKEY(CApub)) */
163 	offset = 0;
164 	Trspi_LoadBlob(&offset, ulIdentityLabelLength, chosenIDBlob, rgbIdentityLabelData);
165 	Trspi_LoadBlob_KEY_PARMS(&offset, chosenIDBlob, &caKey.algorithmParms);
166 	Trspi_LoadBlob_STORE_PUBKEY(&offset, chosenIDBlob, &caKey.pubKey);
167 
168 	if (offset > CHOSENID_BLOB_SIZE)
169 		return TSPERR(TSS_E_INTERNAL_ERROR);
170 
171 	if ((result = Trspi_Hash(TSS_HASH_SHA1, offset, chosenIDBlob, chosenIDHash.digest))) {
172 		free_key_refs(&caKey);
173 		return result;
174 	}
175 
176 	/* use chosenIDBlob temporarily */
177 	offset = 0;
178 	Trspi_LoadBlob_KEY_PARMS(&offset, chosenIDBlob, &caKey.algorithmParms);
179 
180 	offset = 0;
181 	if ((result = Trspi_UnloadBlob_KEY_PARMS(&offset, chosenIDBlob, &asymParms)))
182 		return result;
183 
184 	if ((result = authsess_xsap_init(tspContext, hTPM, hIdentityKey, TSS_AUTH_POLICY_REQUIRED,
185 					 TPM_ORD_MakeIdentity, TPM_ET_OWNER, &xsap))){
186 		free(asymParms.parms);
187 		return result;
188 	}
189 
190 	/* Hash the Auth data */
191 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
192 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_MakeIdentity);
193 	result |= Trspi_Hash_ENCAUTH(&hashCtx, xsap->encAuthUse.authdata);
194 	result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN, chosenIDHash.digest);
195 	result |= Trspi_HashUpdate(&hashCtx, idKeySize, idKey);
196 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
197 		goto error;
198 
199 	/* Do the Auth's */
200 	if (usesAuth) {
201 		if ((result = secret_PerformAuth_OIAP(hKeySRK, TPM_ORD_MakeIdentity, hSRKPolicy,
202 						      FALSE, &digest, &srkAuth)))
203 			goto error;
204 		pSrkAuth = &srkAuth;
205 	} else {
206 		pSrkAuth = NULL;
207 	}
208 
209 	if ((result = authsess_xsap_hmac(xsap, &digest)))
210 		goto error;
211 
212 #ifdef TSS_BUILD_TRANSPORT
213 	if ((result = obj_context_transport_get_control(tspContext, TSS_TSPATTRIB_ENABLE_TRANSPORT,
214 							&transport)))
215 		goto error;
216 
217 	if (transport) {
218 		if ((result = Transport_MakeIdentity2(tspContext, xsap->encAuthUse, chosenIDHash,
219 						      idKeySize, idKey, pSrkAuth, xsap->pAuth,
220 						      &idKeySize, &newIdKey, &pcIdentityBindingSize,
221 						      &prgbIdentityBinding)))
222 			goto error;
223 	} else {
224 #endif
225 		if ((result = RPC_MakeIdentity(tspContext, xsap->encAuthUse, chosenIDHash,
226 					       idKeySize, idKey, pSrkAuth, xsap->pAuth, &idKeySize,
227 					       &newIdKey, &pcIdentityBindingSize,
228 					       &prgbIdentityBinding, &pcEndorsementCredentialSize,
229 					       &prgbEndorsementCredential,
230 					       &pcPlatformCredentialSize, &prgbPlatformCredential,
231 					       &pcConformanceCredentialSize,
232 					       &prgbConformanceCredential)))
233 			goto error;
234 #ifdef TSS_BUILD_TRANSPORT
235 	}
236 #endif
237 
238 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
239 	result |= Trspi_Hash_UINT32(&hashCtx, result);
240 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_MakeIdentity);
241 	result |= Trspi_HashUpdate(&hashCtx, idKeySize, newIdKey);
242 	result |= Trspi_Hash_UINT32(&hashCtx, pcIdentityBindingSize);
243 	result |= Trspi_HashUpdate(&hashCtx, pcIdentityBindingSize, prgbIdentityBinding);
244 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) {
245 		free(newIdKey);
246 		goto error;
247 	}
248 
249 	if ((result = authsess_xsap_verify(xsap, &digest))) {
250 		free(newIdKey);
251 		goto error;
252 	}
253 
254 	if (usesAuth == TRUE) {
255 		if ((result = obj_policy_validate_auth_oiap(hSRKPolicy, &digest, &srkAuth))) {
256 			free(newIdKey);
257 			goto error;
258 		}
259 	}
260 
261 	if ((result = obj_rsakey_set_tcpakey(hIdentityKey, idKeySize, newIdKey))) {
262 		free(newIdKey);
263 		goto error;
264 	}
265 	free(newIdKey);
266 	if ((result = obj_rsakey_set_tcs_handle(hIdentityKey, 0)))
267 		goto error;
268 
269 	if ((result = obj_rsakey_get_pub_blob(hIdentityKey, &idPubSize, &idPub)))
270 		goto error;
271 
272 	if ((result = obj_tpm_get_cred(hTPM, TSS_TPMATTRIB_EKCERT, &tempCredSize, &tempCred)))
273 		goto error;
274 
275 	if (tempCred != NULL) {
276 		free(prgbEndorsementCredential);
277 		prgbEndorsementCredential = tempCred;
278 		pcEndorsementCredentialSize = tempCredSize;
279 	}
280 
281 	if ((result = obj_tpm_get_cred(hTPM, TSS_TPMATTRIB_TPM_CC, &tempCredSize, &tempCred)))
282 		goto error;
283 
284 	if (tempCred != NULL) {
285 		free(prgbConformanceCredential);
286 		prgbConformanceCredential = tempCred;
287 		pcConformanceCredentialSize = tempCredSize;
288 	}
289 
290 	if ((result = obj_tpm_get_cred(hTPM, TSS_TPMATTRIB_PLATFORMCERT, &tempCredSize, &tempCred)))
291 		goto error;
292 
293 	if (tempCred != NULL) {
294 		free(prgbPlatformCredential);
295 		prgbPlatformCredential = tempCred;
296 		pcPlatformCredentialSize = tempCredSize;
297 	}
298 
299 	/* set up the TCPA_IDENTITY_PROOF structure */
300 	/* XXX This should be DER encoded first. TPM1.1b section 9.4 */
301 	/* XXX hash this incrementally using a Trspi_HashCtx */
302 	offset = 0;
303 	Trspi_LoadBlob_TSS_VERSION(&offset, hashblob, VERSION_1_1);
304 	Trspi_LoadBlob_UINT32(&offset, ulIdentityLabelLength, hashblob);
305 	Trspi_LoadBlob_UINT32(&offset, pcIdentityBindingSize, hashblob);
306 	Trspi_LoadBlob_UINT32(&offset, pcEndorsementCredentialSize, hashblob);
307 	Trspi_LoadBlob_UINT32(&offset, pcPlatformCredentialSize, hashblob);
308 	Trspi_LoadBlob_UINT32(&offset, pcConformanceCredentialSize, hashblob);
309 	Trspi_LoadBlob(&offset, idPubSize, hashblob, idPub);
310 	free_tspi(tspContext, idPub);
311 	Trspi_LoadBlob(&offset, ulIdentityLabelLength, hashblob, rgbIdentityLabelData);
312 	Trspi_LoadBlob(&offset, pcIdentityBindingSize, hashblob, prgbIdentityBinding);
313 	Trspi_LoadBlob(&offset, pcEndorsementCredentialSize, hashblob, prgbEndorsementCredential);
314 	Trspi_LoadBlob(&offset, pcPlatformCredentialSize, hashblob, prgbPlatformCredential);
315 	Trspi_LoadBlob(&offset, pcConformanceCredentialSize, hashblob, prgbConformanceCredential);
316 
317 	if (cb && cb->callback) {
318 		/* Alloc the space for the callback to copy into. The additional 32 bytes will
319 		 * attempt to account for padding that the symmetric encryption will do. */
320 		rgbTcpaIdentityReq.asymBlob = calloc(1, (int)offset + 32);
321 		rgbTcpaIdentityReq.symBlob = calloc(1, (int)offset + 32);
322 		if (rgbTcpaIdentityReq.asymBlob == NULL ||
323 		    rgbTcpaIdentityReq.symBlob == NULL) {
324 			free(rgbTcpaIdentityReq.asymBlob);
325 			free(rgbTcpaIdentityReq.symBlob);
326 			LogError("malloc of %" PRIu64 " bytes failed", offset);
327 			free_tspi(tspContext, cb);
328 			result = TSPERR(TSS_E_OUTOFMEMORY);
329 			goto error;
330 		}
331 		rgbTcpaIdentityReq.asymSize = (UINT32)offset + 32;
332 		rgbTcpaIdentityReq.symSize = (UINT32)offset + 32;
333 
334 		if ((result = ((TSS_RESULT (*)(PVOID, UINT32, BYTE *, UINT32, UINT32 *, BYTE *,
335 			       UINT32 *, BYTE *))cb->callback)(cb->appData, (UINT32)offset,
336 							       hashblob, algID,
337 							       &rgbTcpaIdentityReq.asymSize,
338 							       rgbTcpaIdentityReq.asymBlob,
339 							       &rgbTcpaIdentityReq.symSize,
340 							       rgbTcpaIdentityReq.symBlob))) {
341 			LogDebug("CollateIdentityRequest callback returned error 0x%x", result);
342 			free_tspi(tspContext, cb);
343 			goto error;
344 		}
345 	} else {
346 		/* generate the symmetric key. */
347 		if ((result = get_local_random(tspContext, TRUE, symKey.size, &symKey.data)))
348 			goto error;
349 
350 		/* No symmetric key encryption schemes existed in the 1.1 time frame */
351 		symKey.encScheme = TCPA_ES_NONE;
352 
353 		/* encrypt the proof */
354 		rgbTcpaIdentityReq.symSize = sizeof(testblob);
355 		if ((result = Trspi_SymEncrypt(algID, TR_SYM_MODE_CBC, symKey.data, NULL, hashblob,
356 					       offset, testblob, &rgbTcpaIdentityReq.symSize)))
357 			goto error;
358 
359 		rgbTcpaIdentityReq.symBlob = testblob;
360 
361 		/* XXX This should be DER encoded first. TPM1.1b section 9.4 */
362 		offset = 0;
363 		Trspi_LoadBlob_SYMMETRIC_KEY(&offset, hashblob, &symKey);
364 
365 		if ((result = Trspi_RSA_Public_Encrypt(hashblob, offset, encSymKey, &encSymKeySize,
366 						       caKey.pubKey.key, caKey.pubKey.keyLength,
367 						       65537, padding)))
368 			goto error;
369 
370 		rgbTcpaIdentityReq.asymSize = encSymKeySize;
371 		rgbTcpaIdentityReq.asymBlob = encSymKey;
372 	}
373 
374 	rgbTcpaIdentityReq.asymAlgorithm = asymParms;
375 	rgbTcpaIdentityReq.symAlgorithm = symParms;
376 
377 	/* XXX This should be DER encoded first. TPM1.1b section 9.4 */
378 	offset = 0;
379 	Trspi_LoadBlob_IDENTITY_REQ(&offset, idReqBlob, &rgbTcpaIdentityReq);
380 
381 	if (cb && cb->callback) {
382 		free(rgbTcpaIdentityReq.symBlob);
383 		free(rgbTcpaIdentityReq.asymBlob);
384 		free_tspi(tspContext, cb);
385 	}
386 
387 	if ((*prgbTcpaIdentityReq = calloc_tspi(tspContext, offset)) == NULL) {
388 		result = TSPERR(TSS_E_OUTOFMEMORY);
389 		goto error;
390 	}
391 
392 	memcpy(*prgbTcpaIdentityReq, idReqBlob, offset);
393 	*pulTcpaIdentityReqLength = offset;
394 error:
395 	authsess_free(xsap);
396 	free_key_refs(&caKey);
397 	free(asymParms.parms);
398 	free(prgbIdentityBinding);
399 	free(prgbEndorsementCredential);
400 	free(prgbPlatformCredential);
401 	free(prgbConformanceCredential);
402 
403 	return result;
404 }
405 
406 TSS_RESULT
Tspi_TPM_ActivateIdentity(TSS_HTPM hTPM,TSS_HKEY hIdentKey,UINT32 ulAsymCAContentsBlobLength,BYTE * rgbAsymCAContentsBlob,UINT32 ulSymCAAttestationBlobLength,BYTE * rgbSymCAAttestationBlob,UINT32 * pulCredentialLength,BYTE ** prgbCredential)407 Tspi_TPM_ActivateIdentity(TSS_HTPM hTPM,			/* in */
408 			  TSS_HKEY hIdentKey,			/* in */
409 			  UINT32 ulAsymCAContentsBlobLength,	/* in */
410 			  BYTE * rgbAsymCAContentsBlob,		/* in */
411 			  UINT32 ulSymCAAttestationBlobLength,	/* in */
412 			  BYTE * rgbSymCAAttestationBlob,	/* in */
413 			  UINT32 * pulCredentialLength,		/* out */
414 			  BYTE ** prgbCredential)		/* out */
415 {
416 	TPM_AUTH idKeyAuth;
417 	TPM_AUTH ownerAuth;
418 	TSS_HCONTEXT tspContext;
419 	TSS_HPOLICY hIDPolicy, hTPMPolicy;
420 	UINT64 offset;
421 	BYTE credBlob[0x1000];
422 	TCPA_DIGEST digest;
423 	TSS_RESULT result;
424 	TCS_KEY_HANDLE tcsKeyHandle;
425 	TSS_BOOL usesAuth;
426 	TPM_AUTH *pIDKeyAuth;
427 	BYTE *symKeyBlob, *credCallback, *cb_var;
428 	UINT32 symKeyBlobLen, credLen, tmp;
429 	TCPA_SYMMETRIC_KEY symKey;
430 	TSS_CALLBACK *cb;
431 	Trspi_HashCtx hashCtx;
432 	TPM_SYM_CA_ATTESTATION symCAAttestation;
433 
434 	if (pulCredentialLength == NULL || prgbCredential == NULL)
435 		return TSPERR(TSS_E_BAD_PARAMETER);
436 
437 	if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
438 		return result;
439 
440 	if ((result = obj_tpm_get_cb12(hTPM, TSS_TSPATTRIB_TPM_CALLBACK_ACTIVATEIDENTITY, &tmp,
441 				       &cb_var)))
442 		return result;
443 
444 	cb = (TSS_CALLBACK *)cb_var;
445 	if (cb->callback == NULL) {
446 		free_tspi(tspContext, cb);
447 		cb = NULL;
448 	}
449 
450 	if ((result = obj_rsakey_get_tcs_handle(hIdentKey, &tcsKeyHandle)))
451 		return result;
452 
453 	if ((result = obj_rsakey_get_policy(hIdentKey, TSS_POLICY_USAGE,
454 					    &hIDPolicy, &usesAuth)))
455 		return result;
456 
457 	if ((result = obj_tpm_get_policy(hTPM, TSS_POLICY_USAGE, &hTPMPolicy)))
458 		return result;
459 
460 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
461 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ActivateIdentity);
462 	result |= Trspi_Hash_UINT32(&hashCtx, ulAsymCAContentsBlobLength);
463 	result |= Trspi_HashUpdate(&hashCtx, ulAsymCAContentsBlobLength, rgbAsymCAContentsBlob);
464 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
465 		return result;
466 
467 	if (usesAuth) {
468 		if ((result = secret_PerformAuth_OIAP(hIDPolicy, TPM_ORD_ActivateIdentity,
469 						      hIDPolicy, FALSE, &digest, &idKeyAuth)))
470 			return result;
471 		pIDKeyAuth = &idKeyAuth;
472 	} else {
473 		pIDKeyAuth = NULL;
474 	}
475 
476 	if ((result = secret_PerformAuth_OIAP(hTPM, TPM_ORD_ActivateIdentity, hTPMPolicy, FALSE,
477 					      &digest, &ownerAuth)))
478 		return result;
479 
480 	if ((result = TCS_API(tspContext)->ActivateTPMIdentity(tspContext, tcsKeyHandle,
481 							       ulAsymCAContentsBlobLength,
482 							       rgbAsymCAContentsBlob, pIDKeyAuth,
483 							       &ownerAuth, &symKeyBlobLen,
484 							       &symKeyBlob)))
485 		return result;
486 
487 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
488 	result |= Trspi_Hash_UINT32(&hashCtx, result);
489 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ActivateIdentity);
490 	result |= Trspi_HashUpdate(&hashCtx, symKeyBlobLen, symKeyBlob);
491 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
492 		return result;
493 
494 	if (usesAuth) {
495 		if ((result = obj_policy_validate_auth_oiap(hIDPolicy, &digest,
496 							    &idKeyAuth))) {
497 			LogDebugFn("Identity key auth validation of the symmetric key failed.");
498 			return result;
499 		}
500 	}
501 
502 	if ((result = obj_policy_validate_auth_oiap(hTPMPolicy, &digest,
503 						    &ownerAuth))) {
504 		LogDebugFn("Owner auth validation of the symmetric key failed.");
505 		return result;
506 	}
507 
508 	offset = 0;
509 	if ((result = Trspi_UnloadBlob_SYM_CA_ATTESTATION(&offset, rgbSymCAAttestationBlob,
510 							  &symCAAttestation))) {
511 		LogDebugFn("Error unloading CA's attestation blob.");
512 		return result;
513 	}
514 
515 	if (cb && cb->callback) {
516 		/* alloc the space for the callback to copy into */
517 		credCallback = calloc(1, ulSymCAAttestationBlobLength);
518 		if (credCallback == NULL) {
519 			LogDebug("malloc of %u bytes failed", ulSymCAAttestationBlobLength);
520 			free(symKeyBlob);
521 			free_tspi(tspContext, cb);
522 			return TSPERR(TSS_E_INTERNAL_ERROR);
523 		}
524 		credLen = ulSymCAAttestationBlobLength;
525 
526 		if ((result = ((TSS_RESULT (*)(PVOID, UINT32, BYTE *, UINT32, BYTE *, UINT32 *,
527 			       BYTE *))cb->callback)(cb->appData, symKeyBlobLen, symKeyBlob,
528 						     symCAAttestation.credSize,
529 						     symCAAttestation.credential,
530 						     &credLen, credCallback))) {
531 			LogDebug("ActivateIdentity callback returned error 0x%x", result);
532 			free(symCAAttestation.credential);
533 			free(symKeyBlob);
534 			free_tspi(tspContext, cb);
535 			free(credCallback);
536 			return TSPERR(TSS_E_INTERNAL_ERROR);
537 		}
538 		free(symCAAttestation.credential);
539 		free_tspi(tspContext, cb);
540 		free(symKeyBlob);
541 
542 		if ((*prgbCredential = calloc_tspi(tspContext, credLen)) == NULL) {
543 			free(credCallback);
544 			return TSPERR(TSS_E_OUTOFMEMORY);
545 		}
546 
547 		memcpy(*prgbCredential, credCallback, credLen);
548 		*pulCredentialLength = credLen;
549 		free(credCallback);
550 
551 		return TSS_SUCCESS;
552 	}
553 
554 	/* decrypt the symmetric blob using the recovered symmetric key */
555 	offset = 0;
556 	if ((result = Trspi_UnloadBlob_SYMMETRIC_KEY(&offset, symKeyBlob, &symKey))) {
557 		free(symCAAttestation.credential);
558 		free(symKeyBlob);
559 		return result;
560 	}
561 	free(symKeyBlob);
562 
563 	if ((result = Trspi_SymDecrypt(symKey.algId, symKey.encScheme, symKey.data, NULL,
564 				       symCAAttestation.credential, symCAAttestation.credSize,
565 				       credBlob, &credLen))) {
566 		free(symCAAttestation.credential);
567 		free(symKey.data);
568 		return result;
569 	}
570 	free(symCAAttestation.credential);
571 
572 	if ((*prgbCredential = calloc_tspi(tspContext, credLen)) == NULL) {
573 		free(symKey.data);
574 		return TSPERR(TSS_E_OUTOFMEMORY);
575 	}
576 
577 	free(symKey.data);
578 	memcpy(*prgbCredential, credBlob, credLen);
579 	*pulCredentialLength = credLen;
580 
581 	return TSS_SUCCESS;
582 }
583