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
25 TSS_RESULT
Tspi_TPM_Quote(TSS_HTPM hTPM,TSS_HKEY hIdentKey,TSS_HPCRS hPcrComposite,TSS_VALIDATION * pValidationData)26 Tspi_TPM_Quote(TSS_HTPM hTPM, /* in */
27 TSS_HKEY hIdentKey, /* in */
28 TSS_HPCRS hPcrComposite, /* in */
29 TSS_VALIDATION * pValidationData) /* in, out */
30 {
31 TCPA_RESULT result;
32 TPM_AUTH privAuth;
33 TPM_AUTH *pPrivAuth = &privAuth;
34 UINT64 offset;
35 TCPA_DIGEST digest;
36 TCS_KEY_HANDLE tcsKeyHandle;
37 TSS_HPOLICY hPolicy;
38 TCPA_NONCE antiReplay;
39 UINT32 pcrDataSize;
40 BYTE pcrData[128];
41 UINT32 validationLength = 0;
42 BYTE *validationData = NULL;
43 UINT32 pcrDataOutSize;
44 BYTE *pcrDataOut;
45 UINT32 keyDataSize;
46 BYTE *keyData;
47 TSS_KEY keyContainer;
48 BYTE quoteinfo[1024];
49 TSS_BOOL usesAuth;
50 TSS_HCONTEXT tspContext;
51 TCPA_VERSION version = {1, 1, 0, 0};
52 Trspi_HashCtx hashCtx;
53
54 if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
55 return result;
56
57 if (hPcrComposite && !obj_is_pcrs(hPcrComposite))
58 return TSPERR(TSS_E_INVALID_HANDLE);
59
60 /* get the identKey Policy */
61 if ((result = obj_rsakey_get_policy(hIdentKey, TSS_POLICY_USAGE, &hPolicy, &usesAuth)))
62 return result;
63
64 /* get the Identity TCS keyHandle */
65 if ((result = obj_rsakey_get_tcs_handle(hIdentKey, &tcsKeyHandle)))
66 return result;
67
68 if (pValidationData == NULL) {
69 if ((result = get_local_random(tspContext, FALSE, sizeof(TCPA_NONCE),
70 (BYTE **)antiReplay.nonce)))
71 return result;
72 } else {
73 if (pValidationData->ulExternalDataLength < sizeof(antiReplay.nonce))
74 return TSPERR(TSS_E_BAD_PARAMETER);
75
76 memcpy(antiReplay.nonce, pValidationData->rgbExternalData,
77 sizeof(antiReplay.nonce));
78 }
79
80 pcrDataSize = 0;
81 if (hPcrComposite) {
82 if ((result = obj_pcrs_get_selection(hPcrComposite, &pcrDataSize, pcrData)))
83 return result;
84 }
85
86 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
87 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Quote);
88 result |= Trspi_HashUpdate(&hashCtx, TPM_SHA1_160_HASH_LEN, antiReplay.nonce);
89 result |= Trspi_HashUpdate(&hashCtx, pcrDataSize, pcrData);
90 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
91 return result;
92
93 if (usesAuth) {
94 if ((result = secret_PerformAuth_OIAP(hIdentKey, TPM_ORD_Quote, hPolicy, FALSE,
95 &digest, &privAuth))) {
96 return result;
97 }
98 pPrivAuth = &privAuth;
99 } else {
100 pPrivAuth = NULL;
101 }
102
103 if ((result = TCS_API(tspContext)->Quote(tspContext, tcsKeyHandle, &antiReplay, pcrDataSize,
104 pcrData, pPrivAuth, &pcrDataOutSize, &pcrDataOut,
105 &validationLength, &validationData)))
106 return result;
107
108 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
109 result |= Trspi_Hash_UINT32(&hashCtx, result);
110 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Quote);
111 result |= Trspi_HashUpdate(&hashCtx, pcrDataOutSize, pcrDataOut);
112 result |= Trspi_Hash_UINT32(&hashCtx, validationLength);
113 result |= Trspi_HashUpdate(&hashCtx, validationLength, validationData);
114 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
115 return result;
116
117 if (usesAuth == TRUE) {
118 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, &privAuth))) {
119 free(pcrDataOut);
120 free(validationData);
121 return result;
122 }
123 }
124
125 if (hPcrComposite) {
126 TCPA_PCR_COMPOSITE pcrComp;
127
128 __tspi_memset(&pcrComp, 0, sizeof(pcrComp));
129 offset = 0;
130 if ((result = Trspi_UnloadBlob_PCR_COMPOSITE(&offset, pcrDataOut, &pcrComp))) {
131 free(pcrDataOut);
132 free(pcrComp.pcrValue);
133 free(pcrComp.select.pcrSelect);
134 free(validationData);
135 return result;
136 }
137
138 if ((result = obj_pcrs_set_values(hPcrComposite, &pcrComp))) {
139 free(pcrDataOut);
140 free(pcrComp.pcrValue);
141 free(pcrComp.select.pcrSelect);
142 free(validationData);
143 return result;
144 }
145
146 free(pcrComp.pcrValue);
147 free(pcrComp.select.pcrSelect);
148 }
149
150 if ((result = Tspi_GetAttribData(hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
151 TSS_TSPATTRIB_KEYBLOB_BLOB, &keyDataSize, &keyData))) {
152 free(pcrDataOut);
153 free(validationData);
154 return result;
155 }
156
157 /* create the validation data */
158 offset = 0;
159 __tspi_memset(&keyContainer, 0, sizeof(TSS_KEY));
160 if ((result = UnloadBlob_TSS_KEY(&offset, keyData, &keyContainer)))
161 return result;
162
163 /* creating pcrCompositeHash */
164 Trspi_Hash(TSS_HASH_SHA1, pcrDataOutSize, pcrDataOut, digest.digest);
165 free(pcrDataOut);
166
167 /* generate Quote_info struct */
168 /* 1. add version */
169 offset = 0;
170 if (keyContainer.hdr.key12.tag == TPM_TAG_KEY12)
171 Trspi_LoadBlob_TCPA_VERSION(&offset, quoteinfo, version);
172 else
173 Trspi_LoadBlob_TCPA_VERSION(&offset, quoteinfo, keyContainer.hdr.key11.ver);
174 /* 2. add "QUOT" */
175 quoteinfo[offset++] = 'Q';
176 quoteinfo[offset++] = 'U';
177 quoteinfo[offset++] = 'O';
178 quoteinfo[offset++] = 'T';
179 /* 3. Composite Hash */
180 Trspi_LoadBlob(&offset, TCPA_SHA1_160_HASH_LEN, quoteinfo,
181 digest.digest);
182 /* 4. AntiReplay Nonce */
183 Trspi_LoadBlob(&offset, TCPA_SHA1_160_HASH_LEN, quoteinfo,
184 antiReplay.nonce);
185
186 if (pValidationData == NULL) {
187 /* validate the data here */
188 Trspi_Hash(TSS_HASH_SHA1, offset, quoteinfo, digest.digest);
189
190 if ((result = Trspi_Verify(TSS_HASH_SHA1, digest.digest, 20,
191 keyContainer.pubKey.key,
192 keyContainer.pubKey.keyLength,
193 validationData,
194 validationLength))) {
195 free_key_refs(&keyContainer);
196 free(validationData);
197 return result;
198 }
199 free_key_refs(&keyContainer);
200 } else {
201 free_key_refs(&keyContainer);
202
203 pValidationData->rgbValidationData = calloc_tspi(tspContext, validationLength);
204 if (pValidationData->rgbValidationData == NULL) {
205 LogError("malloc of %u bytes failed.", validationLength);
206 return TSPERR(TSS_E_OUTOFMEMORY);
207 }
208 pValidationData->ulValidationDataLength = validationLength;
209 memcpy(pValidationData->rgbValidationData, validationData, validationLength);
210 free(validationData);
211
212 pValidationData->rgbData = calloc_tspi(tspContext, offset);
213 if (pValidationData->rgbData == NULL) {
214 LogError("malloc of %" PRIu64 " bytes failed.", offset);
215 free_tspi(tspContext, pValidationData->rgbValidationData);
216 pValidationData->rgbValidationData = NULL;
217 pValidationData->ulValidationDataLength = 0;
218 return TSPERR(TSS_E_OUTOFMEMORY);
219 }
220 pValidationData->ulDataLength = (UINT32)offset;
221 memcpy(pValidationData->rgbData, quoteinfo, offset);
222 }
223
224 return TSS_SUCCESS;
225 }
226