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