1723e4046Schristos 
2723e4046Schristos /*
3723e4046Schristos  * Licensed Materials - Property of IBM
4723e4046Schristos  *
5723e4046Schristos  * trousers - An open source TCG Software Stack
6723e4046Schristos  *
7723e4046Schristos  * (C) Copyright International Business Machines Corp. 2004-2006
8723e4046Schristos  *
9723e4046Schristos  */
10723e4046Schristos 
11723e4046Schristos #include <limits.h>
12723e4046Schristos #include <stdlib.h>
13723e4046Schristos #include <stdio.h>
14723e4046Schristos #include <string.h>
15723e4046Schristos #include <inttypes.h>
16723e4046Schristos #include <limits.h>
17723e4046Schristos 
18723e4046Schristos #include "trousers/tss.h"
19723e4046Schristos #include "trousers/trousers.h"
20723e4046Schristos #include "trousers_types.h"
21723e4046Schristos #include "spi_utils.h"
22723e4046Schristos #include "capabilities.h"
23723e4046Schristos #include "tsplog.h"
24723e4046Schristos #include "obj.h"
25723e4046Schristos #include "authsess.h"
26723e4046Schristos 
27723e4046Schristos 
28723e4046Schristos 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)29723e4046Schristos Tspi_TPM_CollateIdentityRequest(TSS_HTPM hTPM,				/* in */
30723e4046Schristos 				TSS_HKEY hKeySRK,			/* in */
31723e4046Schristos 				TSS_HKEY hCAPubKey,			/* in */
32723e4046Schristos 				UINT32 ulIdentityLabelLength,		/* in */
33723e4046Schristos 				BYTE * rgbIdentityLabelData,		/* in */
34723e4046Schristos 				TSS_HKEY hIdentityKey,			/* in */
35723e4046Schristos 				TSS_ALGORITHM_ID algID,			/* in */
36723e4046Schristos 				UINT32 * pulTcpaIdentityReqLength,	/* out */
37723e4046Schristos 				BYTE ** prgbTcpaIdentityReq)		/* out */
38723e4046Schristos {
39723e4046Schristos #ifdef TSS_BUILD_TRANSPORT
40723e4046Schristos 	UINT32 transport;
41723e4046Schristos #endif
42723e4046Schristos 	TPM_AUTH srkAuth;
43723e4046Schristos 	TCPA_RESULT result;
44723e4046Schristos 	UINT64 offset;
45723e4046Schristos 	BYTE hashblob[USHRT_MAX], idReqBlob[USHRT_MAX], testblob[USHRT_MAX];
46723e4046Schristos 	TCPA_DIGEST digest;
47723e4046Schristos 	TSS_HPOLICY hSRKPolicy, hIDPolicy, hCAPolicy;
48723e4046Schristos 	UINT32 caKeyBlobSize, idKeySize, idPubSize;
49723e4046Schristos 	BYTE *caKeyBlob, *idKey, *newIdKey, *idPub;
50723e4046Schristos 	TSS_KEY caKey;
51723e4046Schristos 	TCPA_CHOSENID_HASH chosenIDHash = { { 0, } };
52723e4046Schristos 	UINT32 pcIdentityBindingSize;
53723e4046Schristos 	BYTE *prgbIdentityBinding = NULL;
54723e4046Schristos 	UINT32 pcEndorsementCredentialSize;
55723e4046Schristos 	BYTE *prgbEndorsementCredential = NULL;
56723e4046Schristos 	UINT32 pcPlatformCredentialSize;
57723e4046Schristos 	BYTE *prgbPlatformCredential = NULL;
58723e4046Schristos 	UINT32 pcConformanceCredentialSize;
59723e4046Schristos 	BYTE *prgbConformanceCredential = NULL;
60723e4046Schristos #define CHOSENID_BLOB_SIZE 2048
61723e4046Schristos 	BYTE chosenIDBlob[CHOSENID_BLOB_SIZE];
62723e4046Schristos 	TSS_HCONTEXT tspContext;
63723e4046Schristos 	UINT32 encSymKeySize = 256, tmp;
64723e4046Schristos 	BYTE encSymKey[256], *cb_var;
65723e4046Schristos 	TSS_BOOL usesAuth;
66723e4046Schristos 	TPM_AUTH *pSrkAuth = &srkAuth;
67723e4046Schristos 	TCPA_IDENTITY_REQ rgbTcpaIdentityReq;
68723e4046Schristos 	TCPA_KEY_PARMS symParms, asymParms;
69723e4046Schristos 	TCPA_SYMMETRIC_KEY symKey;
70723e4046Schristos 	int padding;
71723e4046Schristos 	TSS_CALLBACK *cb;
72723e4046Schristos 	Trspi_HashCtx hashCtx;
73723e4046Schristos 	UINT32 tempCredSize;
74723e4046Schristos 	BYTE *tempCred = NULL;
75723e4046Schristos 	struct authsess *xsap = NULL;
76723e4046Schristos 
77723e4046Schristos 	if (pulTcpaIdentityReqLength == NULL || prgbTcpaIdentityReq == NULL)
78723e4046Schristos 		return TSPERR(TSS_E_BAD_PARAMETER);
79723e4046Schristos 
80723e4046Schristos 	if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
81723e4046Schristos 		return result;
82723e4046Schristos 
83723e4046Schristos 	if ((result = obj_tpm_get_cb12(hTPM, TSS_TSPATTRIB_TPM_CALLBACK_COLLATEIDENTITY, &tmp,
84723e4046Schristos 				       &cb_var)))
85723e4046Schristos 		return result;
86723e4046Schristos 
87723e4046Schristos 	cb = (TSS_CALLBACK *)cb_var;
88723e4046Schristos 	if (cb->callback == NULL) {
89723e4046Schristos 		free_tspi(tspContext, cb);
90723e4046Schristos 		cb = NULL;
91723e4046Schristos 	}
92723e4046Schristos 
93723e4046Schristos 	/* Get Policies */
94723e4046Schristos 	if ((result = obj_rsakey_get_policy(hKeySRK, TSS_POLICY_USAGE, &hSRKPolicy, &usesAuth)))
95723e4046Schristos 		return result;
96723e4046Schristos 
97723e4046Schristos 	if ((result = obj_rsakey_get_policy(hCAPubKey, TSS_POLICY_USAGE,
98723e4046Schristos 					    &hCAPolicy, NULL)))
99723e4046Schristos 		return result;
100723e4046Schristos 
101723e4046Schristos 	if ((result = obj_rsakey_get_policy(hIdentityKey, TSS_POLICY_USAGE,
102723e4046Schristos 					   &hIDPolicy, NULL)))
103723e4046Schristos 		return result;
104723e4046Schristos 
105723e4046Schristos 	/* setup the symmetric key's parms. */
106*0861b331Schristos 	__tspi_memset(&symParms, 0, sizeof(TCPA_KEY_PARMS));
107723e4046Schristos 	switch (algID) {
108723e4046Schristos 		case TSS_ALG_AES:
109723e4046Schristos 			symParms.algorithmID = TCPA_ALG_AES;
110723e4046Schristos 			symKey.algId = TCPA_ALG_AES;
111723e4046Schristos 			symKey.size = 128/8;
112723e4046Schristos 			break;
113723e4046Schristos 		case TSS_ALG_DES:
114723e4046Schristos 			symParms.algorithmID = TCPA_ALG_DES;
115723e4046Schristos 			symKey.algId = TCPA_ALG_DES;
116723e4046Schristos 			symKey.size = 64/8;
117723e4046Schristos 			break;
118723e4046Schristos 		case TSS_ALG_3DES:
119723e4046Schristos 			symParms.algorithmID = TCPA_ALG_3DES;
120723e4046Schristos 			symKey.algId = TCPA_ALG_3DES;
121723e4046Schristos 			symKey.size = 192/8;
122723e4046Schristos 			break;
123723e4046Schristos 		default:
124723e4046Schristos 			result = TSPERR(TSS_E_BAD_PARAMETER);
125723e4046Schristos 			goto error;
126723e4046Schristos 			break;
127723e4046Schristos 	}
128723e4046Schristos 
129723e4046Schristos 	/* No symmetric key encryption schemes existed in the 1.1 time frame */
130723e4046Schristos 	symParms.encScheme = TCPA_ES_NONE;
131723e4046Schristos 
132723e4046Schristos 	/* get the CA Pubkey's encryption scheme */
133723e4046Schristos 	if ((result = obj_rsakey_get_es(hCAPubKey, &tmp)))
134723e4046Schristos 		return TSPERR(TSS_E_BAD_PARAMETER);
135723e4046Schristos 
136723e4046Schristos 	switch (tmp) {
137723e4046Schristos 		case TSS_ES_RSAESPKCSV15:
138723e4046Schristos 			padding = TR_RSA_PKCS1_PADDING;
139723e4046Schristos 			break;
140723e4046Schristos 		case TSS_ES_RSAESOAEP_SHA1_MGF1:
141723e4046Schristos 			padding = TR_RSA_PKCS1_OAEP_PADDING;
142723e4046Schristos 			break;
143723e4046Schristos 		case TSS_ES_NONE:
144723e4046Schristos 			/* fall through */
145723e4046Schristos 		default:
146723e4046Schristos 			padding = TR_RSA_NO_PADDING;
147723e4046Schristos 			break;
148723e4046Schristos 	}
149723e4046Schristos 
150723e4046Schristos 	/* Get Key blobs */
151723e4046Schristos 	if ((result = obj_rsakey_get_blob(hIdentityKey, &idKeySize, &idKey)))
152723e4046Schristos 		return result;
153723e4046Schristos 
154723e4046Schristos 	if ((result = obj_rsakey_get_blob(hCAPubKey, &caKeyBlobSize, &caKeyBlob)))
155723e4046Schristos 		return result;
156723e4046Schristos 
157723e4046Schristos 	offset = 0;
158*0861b331Schristos 	__tspi_memset(&caKey, 0, sizeof(TSS_KEY));
159723e4046Schristos 	if ((result = UnloadBlob_TSS_KEY(&offset, caKeyBlob, &caKey)))
160723e4046Schristos 		return result;
161723e4046Schristos 
162723e4046Schristos 	/* ChosenID hash =  SHA1(label || TCPA_PUBKEY(CApub)) */
163723e4046Schristos 	offset = 0;
164723e4046Schristos 	Trspi_LoadBlob(&offset, ulIdentityLabelLength, chosenIDBlob, rgbIdentityLabelData);
165723e4046Schristos 	Trspi_LoadBlob_KEY_PARMS(&offset, chosenIDBlob, &caKey.algorithmParms);
166723e4046Schristos 	Trspi_LoadBlob_STORE_PUBKEY(&offset, chosenIDBlob, &caKey.pubKey);
167723e4046Schristos 
168723e4046Schristos 	if (offset > CHOSENID_BLOB_SIZE)
169723e4046Schristos 		return TSPERR(TSS_E_INTERNAL_ERROR);
170723e4046Schristos 
171723e4046Schristos 	if ((result = Trspi_Hash(TSS_HASH_SHA1, offset, chosenIDBlob, chosenIDHash.digest))) {
172723e4046Schristos 		free_key_refs(&caKey);
173723e4046Schristos 		return result;
174723e4046Schristos 	}
175723e4046Schristos 
176723e4046Schristos 	/* use chosenIDBlob temporarily */
177723e4046Schristos 	offset = 0;
178723e4046Schristos 	Trspi_LoadBlob_KEY_PARMS(&offset, chosenIDBlob, &caKey.algorithmParms);
179723e4046Schristos 
180723e4046Schristos 	offset = 0;
181723e4046Schristos 	if ((result = Trspi_UnloadBlob_KEY_PARMS(&offset, chosenIDBlob, &asymParms)))
182723e4046Schristos 		return result;
183723e4046Schristos 
184723e4046Schristos 	if ((result = authsess_xsap_init(tspContext, hTPM, hIdentityKey, TSS_AUTH_POLICY_REQUIRED,
185*0861b331Schristos 					 TPM_ORD_MakeIdentity, TPM_ET_OWNER, &xsap))){
186*0861b331Schristos 		free(asymParms.parms);
187723e4046Schristos 		return result;
188*0861b331Schristos 	}
189723e4046Schristos 
190723e4046Schristos 	/* Hash the Auth data */
191723e4046Schristos 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
192723e4046Schristos 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_MakeIdentity);
193723e4046Schristos 	result |= Trspi_Hash_ENCAUTH(&hashCtx, xsap->encAuthUse.authdata);
194723e4046Schristos 	result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN, chosenIDHash.digest);
195723e4046Schristos 	result |= Trspi_HashUpdate(&hashCtx, idKeySize, idKey);
196723e4046Schristos 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
197723e4046Schristos 		goto error;
198723e4046Schristos 
199723e4046Schristos 	/* Do the Auth's */
200723e4046Schristos 	if (usesAuth) {
201723e4046Schristos 		if ((result = secret_PerformAuth_OIAP(hKeySRK, TPM_ORD_MakeIdentity, hSRKPolicy,
202723e4046Schristos 						      FALSE, &digest, &srkAuth)))
203723e4046Schristos 			goto error;
204723e4046Schristos 		pSrkAuth = &srkAuth;
205723e4046Schristos 	} else {
206723e4046Schristos 		pSrkAuth = NULL;
207723e4046Schristos 	}
208723e4046Schristos 
209723e4046Schristos 	if ((result = authsess_xsap_hmac(xsap, &digest)))
210723e4046Schristos 		goto error;
211723e4046Schristos 
212723e4046Schristos #ifdef TSS_BUILD_TRANSPORT
213723e4046Schristos 	if ((result = obj_context_transport_get_control(tspContext, TSS_TSPATTRIB_ENABLE_TRANSPORT,
214723e4046Schristos 							&transport)))
215723e4046Schristos 		goto error;
216723e4046Schristos 
217723e4046Schristos 	if (transport) {
218723e4046Schristos 		if ((result = Transport_MakeIdentity2(tspContext, xsap->encAuthUse, chosenIDHash,
219723e4046Schristos 						      idKeySize, idKey, pSrkAuth, xsap->pAuth,
220723e4046Schristos 						      &idKeySize, &newIdKey, &pcIdentityBindingSize,
221723e4046Schristos 						      &prgbIdentityBinding)))
222723e4046Schristos 			goto error;
223723e4046Schristos 	} else {
224723e4046Schristos #endif
225723e4046Schristos 		if ((result = RPC_MakeIdentity(tspContext, xsap->encAuthUse, chosenIDHash,
226723e4046Schristos 					       idKeySize, idKey, pSrkAuth, xsap->pAuth, &idKeySize,
227723e4046Schristos 					       &newIdKey, &pcIdentityBindingSize,
228723e4046Schristos 					       &prgbIdentityBinding, &pcEndorsementCredentialSize,
229723e4046Schristos 					       &prgbEndorsementCredential,
230723e4046Schristos 					       &pcPlatformCredentialSize, &prgbPlatformCredential,
231723e4046Schristos 					       &pcConformanceCredentialSize,
232723e4046Schristos 					       &prgbConformanceCredential)))
233723e4046Schristos 			goto error;
234723e4046Schristos #ifdef TSS_BUILD_TRANSPORT
235723e4046Schristos 	}
236723e4046Schristos #endif
237723e4046Schristos 
238723e4046Schristos 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
239723e4046Schristos 	result |= Trspi_Hash_UINT32(&hashCtx, result);
240723e4046Schristos 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_MakeIdentity);
241723e4046Schristos 	result |= Trspi_HashUpdate(&hashCtx, idKeySize, newIdKey);
242723e4046Schristos 	result |= Trspi_Hash_UINT32(&hashCtx, pcIdentityBindingSize);
243723e4046Schristos 	result |= Trspi_HashUpdate(&hashCtx, pcIdentityBindingSize, prgbIdentityBinding);
244723e4046Schristos 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) {
245723e4046Schristos 		free(newIdKey);
246723e4046Schristos 		goto error;
247723e4046Schristos 	}
248723e4046Schristos 
249723e4046Schristos 	if ((result = authsess_xsap_verify(xsap, &digest))) {
250723e4046Schristos 		free(newIdKey);
251723e4046Schristos 		goto error;
252723e4046Schristos 	}
253723e4046Schristos 
254723e4046Schristos 	if (usesAuth == TRUE) {
255723e4046Schristos 		if ((result = obj_policy_validate_auth_oiap(hSRKPolicy, &digest, &srkAuth))) {
256723e4046Schristos 			free(newIdKey);
257723e4046Schristos 			goto error;
258723e4046Schristos 		}
259723e4046Schristos 	}
260723e4046Schristos 
261723e4046Schristos 	if ((result = obj_rsakey_set_tcpakey(hIdentityKey, idKeySize, newIdKey))) {
262723e4046Schristos 		free(newIdKey);
263723e4046Schristos 		goto error;
264723e4046Schristos 	}
265723e4046Schristos 	free(newIdKey);
266723e4046Schristos 	if ((result = obj_rsakey_set_tcs_handle(hIdentityKey, 0)))
267723e4046Schristos 		goto error;
268723e4046Schristos 
269723e4046Schristos 	if ((result = obj_rsakey_get_pub_blob(hIdentityKey, &idPubSize, &idPub)))
270723e4046Schristos 		goto error;
271723e4046Schristos 
272723e4046Schristos 	if ((result = obj_tpm_get_cred(hTPM, TSS_TPMATTRIB_EKCERT, &tempCredSize, &tempCred)))
273723e4046Schristos 		goto error;
274723e4046Schristos 
275723e4046Schristos 	if (tempCred != NULL) {
276723e4046Schristos 		free(prgbEndorsementCredential);
277723e4046Schristos 		prgbEndorsementCredential = tempCred;
278723e4046Schristos 		pcEndorsementCredentialSize = tempCredSize;
279723e4046Schristos 	}
280723e4046Schristos 
281723e4046Schristos 	if ((result = obj_tpm_get_cred(hTPM, TSS_TPMATTRIB_TPM_CC, &tempCredSize, &tempCred)))
282723e4046Schristos 		goto error;
283723e4046Schristos 
284723e4046Schristos 	if (tempCred != NULL) {
285723e4046Schristos 		free(prgbConformanceCredential);
286723e4046Schristos 		prgbConformanceCredential = tempCred;
287723e4046Schristos 		pcConformanceCredentialSize = tempCredSize;
288723e4046Schristos 	}
289723e4046Schristos 
290723e4046Schristos 	if ((result = obj_tpm_get_cred(hTPM, TSS_TPMATTRIB_PLATFORMCERT, &tempCredSize, &tempCred)))
291723e4046Schristos 		goto error;
292723e4046Schristos 
293723e4046Schristos 	if (tempCred != NULL) {
294723e4046Schristos 		free(prgbPlatformCredential);
295723e4046Schristos 		prgbPlatformCredential = tempCred;
296723e4046Schristos 		pcPlatformCredentialSize = tempCredSize;
297723e4046Schristos 	}
298723e4046Schristos 
299723e4046Schristos 	/* set up the TCPA_IDENTITY_PROOF structure */
300723e4046Schristos 	/* XXX This should be DER encoded first. TPM1.1b section 9.4 */
301723e4046Schristos 	/* XXX hash this incrementally using a Trspi_HashCtx */
302723e4046Schristos 	offset = 0;
303723e4046Schristos 	Trspi_LoadBlob_TSS_VERSION(&offset, hashblob, VERSION_1_1);
304723e4046Schristos 	Trspi_LoadBlob_UINT32(&offset, ulIdentityLabelLength, hashblob);
305723e4046Schristos 	Trspi_LoadBlob_UINT32(&offset, pcIdentityBindingSize, hashblob);
306723e4046Schristos 	Trspi_LoadBlob_UINT32(&offset, pcEndorsementCredentialSize, hashblob);
307723e4046Schristos 	Trspi_LoadBlob_UINT32(&offset, pcPlatformCredentialSize, hashblob);
308723e4046Schristos 	Trspi_LoadBlob_UINT32(&offset, pcConformanceCredentialSize, hashblob);
309723e4046Schristos 	Trspi_LoadBlob(&offset, idPubSize, hashblob, idPub);
310723e4046Schristos 	free_tspi(tspContext, idPub);
311723e4046Schristos 	Trspi_LoadBlob(&offset, ulIdentityLabelLength, hashblob, rgbIdentityLabelData);
312723e4046Schristos 	Trspi_LoadBlob(&offset, pcIdentityBindingSize, hashblob, prgbIdentityBinding);
313723e4046Schristos 	Trspi_LoadBlob(&offset, pcEndorsementCredentialSize, hashblob, prgbEndorsementCredential);
314723e4046Schristos 	Trspi_LoadBlob(&offset, pcPlatformCredentialSize, hashblob, prgbPlatformCredential);
315723e4046Schristos 	Trspi_LoadBlob(&offset, pcConformanceCredentialSize, hashblob, prgbConformanceCredential);
316723e4046Schristos 
317723e4046Schristos 	if (cb && cb->callback) {
318723e4046Schristos 		/* Alloc the space for the callback to copy into. The additional 32 bytes will
319723e4046Schristos 		 * attempt to account for padding that the symmetric encryption will do. */
320723e4046Schristos 		rgbTcpaIdentityReq.asymBlob = calloc(1, (int)offset + 32);
321723e4046Schristos 		rgbTcpaIdentityReq.symBlob = calloc(1, (int)offset + 32);
322723e4046Schristos 		if (rgbTcpaIdentityReq.asymBlob == NULL ||
323723e4046Schristos 		    rgbTcpaIdentityReq.symBlob == NULL) {
324723e4046Schristos 			free(rgbTcpaIdentityReq.asymBlob);
325723e4046Schristos 			free(rgbTcpaIdentityReq.symBlob);
326723e4046Schristos 			LogError("malloc of %" PRIu64 " bytes failed", offset);
327723e4046Schristos 			free_tspi(tspContext, cb);
328723e4046Schristos 			result = TSPERR(TSS_E_OUTOFMEMORY);
329723e4046Schristos 			goto error;
330723e4046Schristos 		}
331723e4046Schristos 		rgbTcpaIdentityReq.asymSize = (UINT32)offset + 32;
332723e4046Schristos 		rgbTcpaIdentityReq.symSize = (UINT32)offset + 32;
333723e4046Schristos 
334723e4046Schristos 		if ((result = ((TSS_RESULT (*)(PVOID, UINT32, BYTE *, UINT32, UINT32 *, BYTE *,
335723e4046Schristos 			       UINT32 *, BYTE *))cb->callback)(cb->appData, (UINT32)offset,
336723e4046Schristos 							       hashblob, algID,
337723e4046Schristos 							       &rgbTcpaIdentityReq.asymSize,
338723e4046Schristos 							       rgbTcpaIdentityReq.asymBlob,
339723e4046Schristos 							       &rgbTcpaIdentityReq.symSize,
340723e4046Schristos 							       rgbTcpaIdentityReq.symBlob))) {
341723e4046Schristos 			LogDebug("CollateIdentityRequest callback returned error 0x%x", result);
342723e4046Schristos 			free_tspi(tspContext, cb);
343723e4046Schristos 			goto error;
344723e4046Schristos 		}
345723e4046Schristos 	} else {
346723e4046Schristos 		/* generate the symmetric key. */
347723e4046Schristos 		if ((result = get_local_random(tspContext, TRUE, symKey.size, &symKey.data)))
348723e4046Schristos 			goto error;
349723e4046Schristos 
350723e4046Schristos 		/* No symmetric key encryption schemes existed in the 1.1 time frame */
351723e4046Schristos 		symKey.encScheme = TCPA_ES_NONE;
352723e4046Schristos 
353723e4046Schristos 		/* encrypt the proof */
354723e4046Schristos 		rgbTcpaIdentityReq.symSize = sizeof(testblob);
355723e4046Schristos 		if ((result = Trspi_SymEncrypt(algID, TR_SYM_MODE_CBC, symKey.data, NULL, hashblob,
356723e4046Schristos 					       offset, testblob, &rgbTcpaIdentityReq.symSize)))
357723e4046Schristos 			goto error;
358723e4046Schristos 
359723e4046Schristos 		rgbTcpaIdentityReq.symBlob = testblob;
360723e4046Schristos 
361723e4046Schristos 		/* XXX This should be DER encoded first. TPM1.1b section 9.4 */
362723e4046Schristos 		offset = 0;
363723e4046Schristos 		Trspi_LoadBlob_SYMMETRIC_KEY(&offset, hashblob, &symKey);
364723e4046Schristos 
365723e4046Schristos 		if ((result = Trspi_RSA_Public_Encrypt(hashblob, offset, encSymKey, &encSymKeySize,
366723e4046Schristos 						       caKey.pubKey.key, caKey.pubKey.keyLength,
367723e4046Schristos 						       65537, padding)))
368723e4046Schristos 			goto error;
369723e4046Schristos 
370723e4046Schristos 		rgbTcpaIdentityReq.asymSize = encSymKeySize;
371723e4046Schristos 		rgbTcpaIdentityReq.asymBlob = encSymKey;
372723e4046Schristos 	}
373723e4046Schristos 
374723e4046Schristos 	rgbTcpaIdentityReq.asymAlgorithm = asymParms;
375723e4046Schristos 	rgbTcpaIdentityReq.symAlgorithm = symParms;
376723e4046Schristos 
377723e4046Schristos 	/* XXX This should be DER encoded first. TPM1.1b section 9.4 */
378723e4046Schristos 	offset = 0;
379723e4046Schristos 	Trspi_LoadBlob_IDENTITY_REQ(&offset, idReqBlob, &rgbTcpaIdentityReq);
380723e4046Schristos 
381723e4046Schristos 	if (cb && cb->callback) {
382723e4046Schristos 		free(rgbTcpaIdentityReq.symBlob);
383723e4046Schristos 		free(rgbTcpaIdentityReq.asymBlob);
384723e4046Schristos 		free_tspi(tspContext, cb);
385723e4046Schristos 	}
386723e4046Schristos 
387723e4046Schristos 	if ((*prgbTcpaIdentityReq = calloc_tspi(tspContext, offset)) == NULL) {
388723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
389723e4046Schristos 		goto error;
390723e4046Schristos 	}
391723e4046Schristos 
392723e4046Schristos 	memcpy(*prgbTcpaIdentityReq, idReqBlob, offset);
393723e4046Schristos 	*pulTcpaIdentityReqLength = offset;
394723e4046Schristos error:
395723e4046Schristos 	authsess_free(xsap);
396723e4046Schristos 	free_key_refs(&caKey);
397*0861b331Schristos 	free(asymParms.parms);
398723e4046Schristos 	free(prgbIdentityBinding);
399723e4046Schristos 	free(prgbEndorsementCredential);
400723e4046Schristos 	free(prgbPlatformCredential);
401723e4046Schristos 	free(prgbConformanceCredential);
402723e4046Schristos 
403723e4046Schristos 	return result;
404723e4046Schristos }
405723e4046Schristos 
406723e4046Schristos TSS_RESULT
Tspi_TPM_ActivateIdentity(TSS_HTPM hTPM,TSS_HKEY hIdentKey,UINT32 ulAsymCAContentsBlobLength,BYTE * rgbAsymCAContentsBlob,UINT32 ulSymCAAttestationBlobLength,BYTE * rgbSymCAAttestationBlob,UINT32 * pulCredentialLength,BYTE ** prgbCredential)407723e4046Schristos Tspi_TPM_ActivateIdentity(TSS_HTPM hTPM,			/* in */
408723e4046Schristos 			  TSS_HKEY hIdentKey,			/* in */
409723e4046Schristos 			  UINT32 ulAsymCAContentsBlobLength,	/* in */
410723e4046Schristos 			  BYTE * rgbAsymCAContentsBlob,		/* in */
411723e4046Schristos 			  UINT32 ulSymCAAttestationBlobLength,	/* in */
412723e4046Schristos 			  BYTE * rgbSymCAAttestationBlob,	/* in */
413723e4046Schristos 			  UINT32 * pulCredentialLength,		/* out */
414723e4046Schristos 			  BYTE ** prgbCredential)		/* out */
415723e4046Schristos {
416723e4046Schristos 	TPM_AUTH idKeyAuth;
417723e4046Schristos 	TPM_AUTH ownerAuth;
418723e4046Schristos 	TSS_HCONTEXT tspContext;
419723e4046Schristos 	TSS_HPOLICY hIDPolicy, hTPMPolicy;
420723e4046Schristos 	UINT64 offset;
421723e4046Schristos 	BYTE credBlob[0x1000];
422723e4046Schristos 	TCPA_DIGEST digest;
423723e4046Schristos 	TSS_RESULT result;
424723e4046Schristos 	TCS_KEY_HANDLE tcsKeyHandle;
425723e4046Schristos 	TSS_BOOL usesAuth;
426723e4046Schristos 	TPM_AUTH *pIDKeyAuth;
427723e4046Schristos 	BYTE *symKeyBlob, *credCallback, *cb_var;
428723e4046Schristos 	UINT32 symKeyBlobLen, credLen, tmp;
429723e4046Schristos 	TCPA_SYMMETRIC_KEY symKey;
430723e4046Schristos 	TSS_CALLBACK *cb;
431723e4046Schristos 	Trspi_HashCtx hashCtx;
432723e4046Schristos 	TPM_SYM_CA_ATTESTATION symCAAttestation;
433723e4046Schristos 
434723e4046Schristos 	if (pulCredentialLength == NULL || prgbCredential == NULL)
435723e4046Schristos 		return TSPERR(TSS_E_BAD_PARAMETER);
436723e4046Schristos 
437723e4046Schristos 	if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
438723e4046Schristos 		return result;
439723e4046Schristos 
440723e4046Schristos 	if ((result = obj_tpm_get_cb12(hTPM, TSS_TSPATTRIB_TPM_CALLBACK_ACTIVATEIDENTITY, &tmp,
441723e4046Schristos 				       &cb_var)))
442723e4046Schristos 		return result;
443723e4046Schristos 
444723e4046Schristos 	cb = (TSS_CALLBACK *)cb_var;
445723e4046Schristos 	if (cb->callback == NULL) {
446723e4046Schristos 		free_tspi(tspContext, cb);
447723e4046Schristos 		cb = NULL;
448723e4046Schristos 	}
449723e4046Schristos 
450723e4046Schristos 	if ((result = obj_rsakey_get_tcs_handle(hIdentKey, &tcsKeyHandle)))
451723e4046Schristos 		return result;
452723e4046Schristos 
453723e4046Schristos 	if ((result = obj_rsakey_get_policy(hIdentKey, TSS_POLICY_USAGE,
454723e4046Schristos 					    &hIDPolicy, &usesAuth)))
455723e4046Schristos 		return result;
456723e4046Schristos 
457723e4046Schristos 	if ((result = obj_tpm_get_policy(hTPM, TSS_POLICY_USAGE, &hTPMPolicy)))
458723e4046Schristos 		return result;
459723e4046Schristos 
460723e4046Schristos 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
461723e4046Schristos 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ActivateIdentity);
462723e4046Schristos 	result |= Trspi_Hash_UINT32(&hashCtx, ulAsymCAContentsBlobLength);
463723e4046Schristos 	result |= Trspi_HashUpdate(&hashCtx, ulAsymCAContentsBlobLength, rgbAsymCAContentsBlob);
464723e4046Schristos 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
465723e4046Schristos 		return result;
466723e4046Schristos 
467723e4046Schristos 	if (usesAuth) {
468723e4046Schristos 		if ((result = secret_PerformAuth_OIAP(hIDPolicy, TPM_ORD_ActivateIdentity,
469723e4046Schristos 						      hIDPolicy, FALSE, &digest, &idKeyAuth)))
470723e4046Schristos 			return result;
471723e4046Schristos 		pIDKeyAuth = &idKeyAuth;
472723e4046Schristos 	} else {
473723e4046Schristos 		pIDKeyAuth = NULL;
474723e4046Schristos 	}
475723e4046Schristos 
476723e4046Schristos 	if ((result = secret_PerformAuth_OIAP(hTPM, TPM_ORD_ActivateIdentity, hTPMPolicy, FALSE,
477723e4046Schristos 					      &digest, &ownerAuth)))
478723e4046Schristos 		return result;
479723e4046Schristos 
480723e4046Schristos 	if ((result = TCS_API(tspContext)->ActivateTPMIdentity(tspContext, tcsKeyHandle,
481723e4046Schristos 							       ulAsymCAContentsBlobLength,
482723e4046Schristos 							       rgbAsymCAContentsBlob, pIDKeyAuth,
483723e4046Schristos 							       &ownerAuth, &symKeyBlobLen,
484723e4046Schristos 							       &symKeyBlob)))
485723e4046Schristos 		return result;
486723e4046Schristos 
487723e4046Schristos 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
488723e4046Schristos 	result |= Trspi_Hash_UINT32(&hashCtx, result);
489723e4046Schristos 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ActivateIdentity);
490723e4046Schristos 	result |= Trspi_HashUpdate(&hashCtx, symKeyBlobLen, symKeyBlob);
491723e4046Schristos 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
492723e4046Schristos 		return result;
493723e4046Schristos 
494723e4046Schristos 	if (usesAuth) {
495723e4046Schristos 		if ((result = obj_policy_validate_auth_oiap(hIDPolicy, &digest,
496723e4046Schristos 							    &idKeyAuth))) {
497723e4046Schristos 			LogDebugFn("Identity key auth validation of the symmetric key failed.");
498723e4046Schristos 			return result;
499723e4046Schristos 		}
500723e4046Schristos 	}
501723e4046Schristos 
502723e4046Schristos 	if ((result = obj_policy_validate_auth_oiap(hTPMPolicy, &digest,
503723e4046Schristos 						    &ownerAuth))) {
504723e4046Schristos 		LogDebugFn("Owner auth validation of the symmetric key failed.");
505723e4046Schristos 		return result;
506723e4046Schristos 	}
507723e4046Schristos 
508723e4046Schristos 	offset = 0;
509723e4046Schristos 	if ((result = Trspi_UnloadBlob_SYM_CA_ATTESTATION(&offset, rgbSymCAAttestationBlob,
510723e4046Schristos 							  &symCAAttestation))) {
511723e4046Schristos 		LogDebugFn("Error unloading CA's attestation blob.");
512723e4046Schristos 		return result;
513723e4046Schristos 	}
514723e4046Schristos 
515723e4046Schristos 	if (cb && cb->callback) {
516723e4046Schristos 		/* alloc the space for the callback to copy into */
517723e4046Schristos 		credCallback = calloc(1, ulSymCAAttestationBlobLength);
518723e4046Schristos 		if (credCallback == NULL) {
519723e4046Schristos 			LogDebug("malloc of %u bytes failed", ulSymCAAttestationBlobLength);
520723e4046Schristos 			free(symKeyBlob);
521723e4046Schristos 			free_tspi(tspContext, cb);
522723e4046Schristos 			return TSPERR(TSS_E_INTERNAL_ERROR);
523723e4046Schristos 		}
524723e4046Schristos 		credLen = ulSymCAAttestationBlobLength;
525723e4046Schristos 
526723e4046Schristos 		if ((result = ((TSS_RESULT (*)(PVOID, UINT32, BYTE *, UINT32, BYTE *, UINT32 *,
527723e4046Schristos 			       BYTE *))cb->callback)(cb->appData, symKeyBlobLen, symKeyBlob,
528723e4046Schristos 						     symCAAttestation.credSize,
529723e4046Schristos 						     symCAAttestation.credential,
530723e4046Schristos 						     &credLen, credCallback))) {
531723e4046Schristos 			LogDebug("ActivateIdentity callback returned error 0x%x", result);
532723e4046Schristos 			free(symCAAttestation.credential);
533723e4046Schristos 			free(symKeyBlob);
534723e4046Schristos 			free_tspi(tspContext, cb);
535723e4046Schristos 			free(credCallback);
536723e4046Schristos 			return TSPERR(TSS_E_INTERNAL_ERROR);
537723e4046Schristos 		}
538723e4046Schristos 		free(symCAAttestation.credential);
539723e4046Schristos 		free_tspi(tspContext, cb);
540723e4046Schristos 		free(symKeyBlob);
541723e4046Schristos 
542723e4046Schristos 		if ((*prgbCredential = calloc_tspi(tspContext, credLen)) == NULL) {
543723e4046Schristos 			free(credCallback);
544723e4046Schristos 			return TSPERR(TSS_E_OUTOFMEMORY);
545723e4046Schristos 		}
546723e4046Schristos 
547723e4046Schristos 		memcpy(*prgbCredential, credCallback, credLen);
548723e4046Schristos 		*pulCredentialLength = credLen;
549723e4046Schristos 		free(credCallback);
550723e4046Schristos 
551723e4046Schristos 		return TSS_SUCCESS;
552723e4046Schristos 	}
553723e4046Schristos 
554723e4046Schristos 	/* decrypt the symmetric blob using the recovered symmetric key */
555723e4046Schristos 	offset = 0;
556723e4046Schristos 	if ((result = Trspi_UnloadBlob_SYMMETRIC_KEY(&offset, symKeyBlob, &symKey))) {
557723e4046Schristos 		free(symCAAttestation.credential);
558723e4046Schristos 		free(symKeyBlob);
559723e4046Schristos 		return result;
560723e4046Schristos 	}
561723e4046Schristos 	free(symKeyBlob);
562723e4046Schristos 
563723e4046Schristos 	if ((result = Trspi_SymDecrypt(symKey.algId, symKey.encScheme, symKey.data, NULL,
564723e4046Schristos 				       symCAAttestation.credential, symCAAttestation.credSize,
565723e4046Schristos 				       credBlob, &credLen))) {
566723e4046Schristos 		free(symCAAttestation.credential);
567723e4046Schristos 		free(symKey.data);
568723e4046Schristos 		return result;
569723e4046Schristos 	}
570723e4046Schristos 	free(symCAAttestation.credential);
571723e4046Schristos 
572723e4046Schristos 	if ((*prgbCredential = calloc_tspi(tspContext, credLen)) == NULL) {
573723e4046Schristos 		free(symKey.data);
574723e4046Schristos 		return TSPERR(TSS_E_OUTOFMEMORY);
575723e4046Schristos 	}
576723e4046Schristos 
577723e4046Schristos 	free(symKey.data);
578723e4046Schristos 	memcpy(*prgbCredential, credBlob, credLen);
579723e4046Schristos 	*pulCredentialLength = credLen;
580723e4046Schristos 
581723e4046Schristos 	return TSS_SUCCESS;
582723e4046Schristos }
583