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(&quoteinfo, 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