xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tspi/tspi_quote2.c (revision a24efa7dea9f1f56c3bdb15a927d3516792ace1c)
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
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 			if (*versionInfoSize > 0)
167 				free(*versionInfo);
168 			free(sig);
169 			return result;
170 		}
171 
172 		/* Set both digestAtRelease and localityAtRelease */
173 		if ((result = obj_pcrs_set_locality(hPcrComposite, pcrInfo.localityAtRelease))) {
174 			free(pcrDataOut);
175 			if (*versionInfoSize > 0)
176 				free(*versionInfo);
177 			free(sig);
178 			return result;
179 		}
180 
181 		if ((result = obj_pcrs_set_digest_at_release(hPcrComposite,
182 							     pcrInfo.digestAtRelease))) {
183 			free(pcrDataOut);
184 			if (*versionInfoSize > 0)
185 				free(*versionInfo);
186 			free(sig);
187 			return result;
188 		}
189 	}
190 
191 	/* generate TPM_QUOTE_INFO2 struct */
192 	memset(&quoteinfo, 0, sizeof(quoteinfo));
193 	offset = 0;
194 	/* 1. Add Structure TAG */
195 	quoteinfo[offset++] = 0x00;
196 	quoteinfo[offset++] = (BYTE) TPM_TAG_QUOTE_INFO2;
197 
198 	/* 2. add "QUT2" */
199 	quoteinfo[offset++]='Q';
200 	quoteinfo[offset++]='U';
201 	quoteinfo[offset++]='T';
202 	quoteinfo[offset++]='2';
203 
204 	/* 3. AntiReplay Nonce - add the external data*/
205 	Trspi_LoadBlob(&offset, TCPA_SHA1_160_HASH_LEN, quoteinfo,
206 			antiReplay.nonce);
207 	/* 4. add the infoshort TPM_PCR_INFO_SHORT data */
208 	Trspi_LoadBlob(&offset,pcrDataOutSize,quoteinfo,pcrDataOut);
209 	free(pcrDataOut);
210 
211 	if (fAddVersion)
212 		Trspi_LoadBlob(&offset,*versionInfoSize,quoteinfo,*versionInfo);
213 	else {
214 		/* versionInfo was not allocated and versionInfoSize has invalid value */
215 		*versionInfoSize = 0;
216 		*versionInfo = NULL;
217 	}
218 
219 	LogDebug("TPM_QUOTE_INFO2 data: ");
220 	LogDebugData(offset,quoteinfo);
221 
222 	if (pValidationData == NULL) {
223 		if ((result = Trspi_Hash(TSS_HASH_SHA1, offset, quoteinfo, digest.digest))) {
224 			free(sig);
225 			if (*versionInfoSize > 0)
226 				free(*versionInfo);
227 			return result;
228 		}
229 		if ((result = __tspi_rsa_verify(hIdentKey,TSS_HASH_SHA1,sizeof(digest.digest),
230 					 digest.digest, sigSize, sig))) {
231 			free(sig);
232 			if (*versionInfoSize > 0)
233 				free(*versionInfo);
234 			return TSPERR(TSS_E_VERIFICATION_FAILED);
235 		}
236 		free(sig);
237 	} else {
238 		pValidationData->rgbValidationData = calloc_tspi(tspContext, sigSize);
239 		if (pValidationData->rgbValidationData == NULL) {
240 			LogError("malloc of %u bytes failed.", sigSize);
241 			free(sig);
242 			if (*versionInfoSize > 0)
243 				free(*versionInfo);
244 			return TSPERR(TSS_E_OUTOFMEMORY);
245 		}
246 		pValidationData->ulValidationDataLength = sigSize;
247 		memcpy(pValidationData->rgbValidationData, sig, sigSize);
248 		free(sig);
249 
250 		pValidationData->rgbData = calloc_tspi(tspContext, offset);
251 		if (pValidationData->rgbData == NULL) {
252 			LogError("malloc of %" PRIu64 " bytes failed.", offset);
253 			free_tspi(tspContext, pValidationData->rgbValidationData);
254 			pValidationData->rgbValidationData = NULL;
255 			pValidationData->ulValidationDataLength = 0;
256 			if (*versionInfoSize > 0)
257 				free(*versionInfo);
258 			return TSPERR(TSS_E_OUTOFMEMORY);
259 		}
260 		pValidationData->ulDataLength = (UINT32)offset;
261 		memcpy(pValidationData->rgbData, quoteinfo, offset);
262 	}
263 
264 
265 	if(*versionInfoSize > 0) {
266 		if(fAddVersion) {
267 			/* tag versionInfo so that it can be free'd by the app through Tspi_Context_FreeMemory */
268 			if ((result = __tspi_add_mem_entry(tspContext, *versionInfo))) {
269 				free_tspi(tspContext, pValidationData->rgbValidationData);
270 				pValidationData->rgbValidationData = NULL;
271 				pValidationData->ulValidationDataLength = 0;
272 				free_tspi(tspContext, pValidationData->rgbData);
273 				pValidationData->rgbData = NULL;
274 				pValidationData->ulDataLength = 0;
275 				free(*versionInfo);
276 				return result;
277 			}
278 		}
279 		else {
280 			free(*versionInfo);
281 		}
282         }
283 
284 	LogDebug("Tspi_TPM_Quote2 End");
285 	return TSS_SUCCESS;
286 }
287