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 #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
     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
    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