xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tspi/tspi_quote2.c (revision 1023804e3833a0bd94414f2545512128f6502c74)
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