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-2007
8 *
9 */
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <inttypes.h>
15
16 #include "trousers/tss.h"
17 #include "trousers/trousers.h"
18 #include "trousers_types.h"
19 #include "spi_utils.h"
20 #include "capabilities.h"
21 #include "tsplog.h"
22 #include "obj.h"
23
24 TSS_RESULT
Tspi_TPM_Quote2(TSS_HTPM hTPM,TSS_HKEY hIdentKey,TSS_BOOL fAddVersion,TSS_HPCRS hPcrComposite,TSS_VALIDATION * pValidationData,UINT32 * versionInfoSize,BYTE ** versionInfo)25 Tspi_TPM_Quote2(TSS_HTPM hTPM, // in
26 TSS_HKEY hIdentKey, // in
27 TSS_BOOL fAddVersion, // in
28 TSS_HPCRS hPcrComposite, // in
29 TSS_VALIDATION* pValidationData, // in, out
30 UINT32* versionInfoSize, // out
31 BYTE** versionInfo) // out
32 {
33 TPM_RESULT result;
34 TSS_HCONTEXT tspContext;
35 TPM_AUTH privAuth;
36 TPM_AUTH *pPrivAuth = &privAuth;
37 UINT64 offset;
38 TPM_DIGEST digest;
39 TSS_BOOL usesAuth;
40 TCS_KEY_HANDLE tcsKeyHandle;
41 TSS_HPOLICY hPolicy;
42 TPM_NONCE antiReplay;
43 UINT32 pcrDataSize;
44 BYTE pcrData[128];
45 UINT32 sigSize = 0;
46 BYTE *sig = NULL;
47 UINT32 pcrDataOutSize;
48 BYTE *pcrDataOut;
49 BYTE quoteinfo[1024];
50 Trspi_HashCtx hashCtx;
51
52 LogDebug("Tspi_TPM_Quote2 Start:");
53
54 /* Takes the context that this TPM handle is on */
55 if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
56 return result;
57
58 /* Test if the hPcrComposite is valid */
59 if ((hPcrComposite) && !obj_is_pcrs(hPcrComposite))
60 return TSPERR(TSS_E_INVALID_HANDLE);
61
62 /* get the identKey Policy */
63 if ((result = obj_rsakey_get_policy(hIdentKey, TSS_POLICY_USAGE, &hPolicy, &usesAuth)))
64 return result;
65
66 /* get the Identity TCS keyHandle */
67 if ((result = obj_rsakey_get_tcs_handle(hIdentKey, &tcsKeyHandle)))
68 return result;
69
70 /* Sets the validation data - if NULL, TSS provides it's own random value. If
71 * not NULL, takes the validation external data and sets the antiReplay data
72 * with this */
73 if (pValidationData == NULL) {
74 LogDebug("Internal Verify:");
75 if ((result = get_local_random(tspContext, FALSE, sizeof(TPM_NONCE),
76 (BYTE **)antiReplay.nonce)))
77 return result;
78 } else {
79 LogDebug("External Verify:");
80 if (pValidationData->ulExternalDataLength < sizeof(antiReplay.nonce))
81 return TSPERR(TSS_E_BAD_PARAMETER);
82
83 memcpy(antiReplay.nonce, pValidationData->rgbExternalData,
84 sizeof(antiReplay.nonce));
85 }
86
87 /* Create the TPM_PCR_COMPOSITE object */
88 pcrDataSize = 0;
89 if (hPcrComposite) {
90 /* Load the PCR Selection Object into the pcrData */
91 if ((result = obj_pcrs_get_selection(hPcrComposite, &pcrDataSize, pcrData)))
92 return result;
93 }
94
95 if (usesAuth) {
96 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
97 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Quote2);
98 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, antiReplay.nonce);
99 result |= Trspi_HashUpdate(&hashCtx, pcrDataSize, pcrData);
100 result |= Trspi_Hash_BOOL(&hashCtx,fAddVersion);
101 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
102 return result;
103 if ((result = secret_PerformAuth_OIAP(hIdentKey, TPM_ORD_Quote2, hPolicy, FALSE,
104 &digest, &privAuth))) {
105 return result;
106 }
107 pPrivAuth = &privAuth;
108 } else {
109 pPrivAuth = NULL;
110 }
111
112 /* Send to TCS */
113 if ((result = TCS_API(tspContext)->Quote2(tspContext, tcsKeyHandle, &antiReplay,
114 pcrDataSize, pcrData, fAddVersion, pPrivAuth,
115 &pcrDataOutSize, &pcrDataOut, versionInfoSize,
116 versionInfo, &sigSize, &sig)))
117 return result;
118
119 #ifdef TSS_DEBUG
120 LogDebug("Got TCS Response:");
121 LogDebug(" pcrDataOutSize: %u",pcrDataOutSize);
122 LogDebug(" pcrDataOut:");
123 LogDebugData(pcrDataOutSize,pcrDataOut);
124 LogDebug(" versionInfoSize: %u",*versionInfoSize);
125 LogDebug(" versionInfo:");
126 if (*versionInfoSize >0)
127 LogDebugData(*versionInfoSize,*versionInfo);
128 LogDebug(" sigSize: %u",sigSize);
129 LogDebug(" sig:");
130 LogDebugData(sigSize,sig);
131 #endif
132
133 if (usesAuth) {
134 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
135 result |= Trspi_Hash_UINT32(&hashCtx, result);
136 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Quote2);
137 result |= Trspi_HashUpdate(&hashCtx, pcrDataOutSize, pcrDataOut);
138 result |= Trspi_Hash_UINT32(&hashCtx,*versionInfoSize);
139 if (*versionInfoSize > 0)
140 result |= Trspi_HashUpdate(&hashCtx, *versionInfoSize,*versionInfo);
141 result |= Trspi_Hash_UINT32(&hashCtx, sigSize);
142 result |= Trspi_HashUpdate(&hashCtx, sigSize, sig);
143 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) {
144 free(pcrDataOut);
145 if (*versionInfoSize > 0)
146 free(*versionInfo);
147 free(sig);
148 return result;
149 }
150 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, &privAuth))) {
151 free(pcrDataOut);
152 if (*versionInfoSize > 0)
153 free(*versionInfo);
154 free(sig);
155 return result;
156 }
157 }
158
159 /* Set the pcrDataOut back to the TSS */
160 if (hPcrComposite){
161 TPM_PCR_INFO_SHORT pcrInfo;
162
163 offset = 0;
164 if ((result = Trspi_UnloadBlob_PCR_INFO_SHORT(&offset, pcrDataOut, &pcrInfo))) {
165 free(pcrDataOut);
166 free(pcrInfo.pcrSelection.pcrSelect);
167 if (*versionInfoSize > 0)
168 free(*versionInfo);
169 free(sig);
170 return result;
171 }
172 free(pcrInfo.pcrSelection.pcrSelect);
173
174 /* Set both digestAtRelease and localityAtRelease */
175 if ((result = obj_pcrs_set_locality(hPcrComposite, pcrInfo.localityAtRelease))) {
176 free(pcrDataOut);
177 if (*versionInfoSize > 0)
178 free(*versionInfo);
179 free(sig);
180 return result;
181 }
182
183 if ((result = obj_pcrs_set_digest_at_release(hPcrComposite,
184 pcrInfo.digestAtRelease))) {
185 free(pcrDataOut);
186 if (*versionInfoSize > 0)
187 free(*versionInfo);
188 free(sig);
189 return result;
190 }
191 }
192
193 /* generate TPM_QUOTE_INFO2 struct */
194 __tspi_memset("einfo, 0, sizeof(quoteinfo));
195 offset = 0;
196 /* 1. Add Structure TAG */
197 quoteinfo[offset++] = 0x00;
198 quoteinfo[offset++] = (BYTE) TPM_TAG_QUOTE_INFO2;
199
200 /* 2. add "QUT2" */
201 quoteinfo[offset++]='Q';
202 quoteinfo[offset++]='U';
203 quoteinfo[offset++]='T';
204 quoteinfo[offset++]='2';
205
206 /* 3. AntiReplay Nonce - add the external data*/
207 Trspi_LoadBlob(&offset, TCPA_SHA1_160_HASH_LEN, quoteinfo,
208 antiReplay.nonce);
209 /* 4. add the infoshort TPM_PCR_INFO_SHORT data */
210 Trspi_LoadBlob(&offset,pcrDataOutSize,quoteinfo,pcrDataOut);
211 free(pcrDataOut);
212
213 if (fAddVersion)
214 Trspi_LoadBlob(&offset,*versionInfoSize,quoteinfo,*versionInfo);
215 else {
216 /* versionInfo was not allocated and versionInfoSize has invalid value */
217 *versionInfoSize = 0;
218 *versionInfo = NULL;
219 }
220
221 LogDebug("TPM_QUOTE_INFO2 data: ");
222 LogDebugData(offset,quoteinfo);
223
224 if (pValidationData == NULL) {
225 if ((result = Trspi_Hash(TSS_HASH_SHA1, offset, quoteinfo, digest.digest))) {
226 free(sig);
227 if (*versionInfoSize > 0)
228 free(*versionInfo);
229 return result;
230 }
231 if ((result = __tspi_rsa_verify(hIdentKey,TSS_HASH_SHA1,sizeof(digest.digest),
232 digest.digest, sigSize, sig))) {
233 free(sig);
234 if (*versionInfoSize > 0)
235 free(*versionInfo);
236 return TSPERR(TSS_E_VERIFICATION_FAILED);
237 }
238 free(sig);
239 } else {
240 pValidationData->rgbValidationData = calloc_tspi(tspContext, sigSize);
241 if (pValidationData->rgbValidationData == NULL) {
242 LogError("malloc of %u bytes failed.", sigSize);
243 free(sig);
244 if (*versionInfoSize > 0)
245 free(*versionInfo);
246 return TSPERR(TSS_E_OUTOFMEMORY);
247 }
248 pValidationData->ulValidationDataLength = sigSize;
249 memcpy(pValidationData->rgbValidationData, sig, sigSize);
250 free(sig);
251
252 pValidationData->rgbData = calloc_tspi(tspContext, offset);
253 if (pValidationData->rgbData == NULL) {
254 LogError("malloc of %" PRIu64 " bytes failed.", offset);
255 free_tspi(tspContext, pValidationData->rgbValidationData);
256 pValidationData->rgbValidationData = NULL;
257 pValidationData->ulValidationDataLength = 0;
258 if (*versionInfoSize > 0)
259 free(*versionInfo);
260 return TSPERR(TSS_E_OUTOFMEMORY);
261 }
262 pValidationData->ulDataLength = (UINT32)offset;
263 memcpy(pValidationData->rgbData, quoteinfo, offset);
264 }
265
266
267 if(*versionInfoSize > 0) {
268 if(fAddVersion && pValidationData) {
269 /* tag versionInfo so that it can be free'd by the app through Tspi_Context_FreeMemory */
270 if ((result = __tspi_add_mem_entry(tspContext, *versionInfo))) {
271 free_tspi(tspContext, pValidationData->rgbValidationData);
272 pValidationData->rgbValidationData = NULL;
273 pValidationData->ulValidationDataLength = 0;
274 free_tspi(tspContext, pValidationData->rgbData);
275 pValidationData->rgbData = NULL;
276 pValidationData->ulDataLength = 0;
277 free(*versionInfo);
278 return result;
279 }
280 }
281 else {
282 free(*versionInfo);
283 }
284 }
285
286 LogDebug("Tspi_TPM_Quote2 End");
287 return TSS_SUCCESS;
288 }
289