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 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.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 #include "authsess.h"
24 
25 
26 TSS_RESULT
Tspi_Data_Seal(TSS_HENCDATA hEncData,TSS_HKEY hEncKey,UINT32 ulDataLength,BYTE * rgbDataToSeal,TSS_HPCRS hPcrComposite)27 Tspi_Data_Seal(TSS_HENCDATA hEncData,	/* in */
28 	       TSS_HKEY hEncKey,	/* in */
29 	       UINT32 ulDataLength,	/* in */
30 	       BYTE * rgbDataToSeal,	/* in */
31 	       TSS_HPCRS hPcrComposite)	/* in */
32 {
33 	TPM_DIGEST digest;
34 	TSS_RESULT result;
35 	TSS_HPOLICY hPolicy, hEncPolicy;
36 	BYTE *encData = NULL;
37 	BYTE *pcrData = NULL;
38 	UINT32 encDataSize;
39 	UINT32 pcrDataSize;
40 	UINT32 pcrInfoType = TSS_PCRS_STRUCT_DEFAULT;
41 	UINT32 sealOrdinal = TPM_ORD_Seal;
42 	TCS_KEY_HANDLE tcsKeyHandle;
43 	TSS_HCONTEXT tspContext;
44 	Trspi_HashCtx hashCtx;
45 	BYTE *sealData = NULL;
46 	struct authsess *xsap = NULL;
47 #ifdef TSS_BUILD_SEALX
48 	UINT32 protectMode;
49 #endif
50 
51 	if (rgbDataToSeal == NULL)
52 		return TSPERR(TSS_E_BAD_PARAMETER);
53 
54 	if ((result = obj_encdata_get_tsp_context(hEncData, &tspContext)))
55 		return result;
56 
57 	if ((result = obj_rsakey_get_policy(hEncKey, TSS_POLICY_USAGE,
58 					    &hPolicy, NULL)))
59 		return result;
60 
61 	if ((result = obj_encdata_get_policy(hEncData, TSS_POLICY_USAGE,
62 					     &hEncPolicy)))
63 		return result;
64 
65 	if ((result = obj_rsakey_get_tcs_handle(hEncKey, &tcsKeyHandle)))
66 		return result;
67 
68 #ifdef TSS_BUILD_SEALX
69 	/* Get the TSS_TSPATTRIB_ENCDATASEAL_PROTECT_MODE attribute
70 	   to determine the seal function to invoke */
71 	if ((result = obj_encdata_get_seal_protect_mode(hEncData, &protectMode)))
72 		return result;
73 
74 	if (protectMode == TSS_TSPATTRIB_ENCDATASEAL_NO_PROTECT) {
75 		sealOrdinal = TPM_ORD_Seal;
76 		pcrInfoType = 0;
77 	} else if (protectMode == TSS_TSPATTRIB_ENCDATASEAL_PROTECT) {
78 		sealOrdinal = TPM_ORD_Sealx;
79 		pcrInfoType = TSS_PCRS_STRUCT_INFO_LONG;
80 	} else
81 		return TSPERR(TSS_E_INTERNAL_ERROR);
82 #endif
83 
84 	/* If PCR's are of interest */
85 	pcrDataSize = 0;
86 	if (hPcrComposite) {
87 		if ((result = obj_pcrs_create_info_type(hPcrComposite, &pcrInfoType, &pcrDataSize,
88 							&pcrData)))
89 			return result;
90 	}
91 
92 	if ((result = authsess_xsap_init(tspContext, hEncKey, hEncData, TSS_AUTH_POLICY_REQUIRED,
93 					 sealOrdinal, TPM_ET_KEYHANDLE, &xsap)))
94 		goto error;
95 
96 #ifdef TSS_BUILD_SEALX
97 	if (sealOrdinal == TPM_ORD_Seal)
98 		sealData = rgbDataToSeal;
99 	else {
100 		if ((sealData = (BYTE *)calloc(1, ulDataLength)) == NULL) {
101 			LogError("malloc of %u bytes failed", ulDataLength);
102 			result = TSPERR(TSS_E_OUTOFMEMORY);
103 			goto error;
104 		}
105 
106 		if ((result =
107 		     ((TSS_RESULT (*)(PVOID, TSS_HKEY, TSS_HENCDATA, TSS_ALGORITHM_ID,
108 		     UINT32, BYTE *, BYTE *, BYTE *, BYTE *, UINT32, BYTE *,
109 		     BYTE *))xsap->cb_sealx.callback)(xsap->cb_sealx.appData, hEncKey, hEncData,
110 						      xsap->cb_sealx.alg, sizeof(TPM_NONCE),
111 						      xsap->auth.NonceEven.nonce,
112 						      xsap->auth.NonceOdd.nonce,
113 						      xsap->nonceEvenxSAP.nonce,
114 						      xsap->nonceOddxSAP.nonce, ulDataLength,
115 						      rgbDataToSeal, sealData)))
116 			goto error;
117 	}
118 #else
119 	sealData = rgbDataToSeal;
120 #endif
121 
122 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
123 	result |= Trspi_Hash_UINT32(&hashCtx, sealOrdinal);
124 	result |= Trspi_Hash_ENCAUTH(&hashCtx, xsap->encAuthUse.authdata);
125 	result |= Trspi_Hash_UINT32(&hashCtx, pcrDataSize);
126 	result |= Trspi_HashUpdate(&hashCtx, pcrDataSize, pcrData);
127 	result |= Trspi_Hash_UINT32(&hashCtx, ulDataLength);
128 	result |= Trspi_HashUpdate(&hashCtx, ulDataLength, sealData);
129 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) {
130 		goto error;
131 	}
132 
133 	if ((result = authsess_xsap_hmac(xsap, &digest)))
134 		goto error;
135 
136 #ifdef TSS_BUILD_SEALX
137 	if (sealOrdinal == TPM_ORD_Seal) {
138 		if ((result = TCS_API(tspContext)->Seal(tspContext, tcsKeyHandle, &xsap->encAuthUse,
139 							pcrDataSize, pcrData, ulDataLength,
140 							sealData, xsap->pAuth, &encDataSize,
141 							&encData))) {
142 			goto error;
143 		}
144 	} else if (sealOrdinal == TPM_ORD_Sealx) {
145 		if ((result = TCS_API(tspContext)->Sealx(tspContext, tcsKeyHandle, &xsap->encAuthUse,
146 						    pcrDataSize, pcrData, ulDataLength, sealData,
147 						    xsap->pAuth, &encDataSize, &encData))) {
148 			goto error;
149 		}
150 	} else {
151 		result = TSPERR(TSS_E_INTERNAL_ERROR);
152 		goto error;
153 	}
154 #else
155 	if ((result = TCS_API(tspContext)->Seal(tspContext, tcsKeyHandle, &xsap->encAuthUse,
156 						pcrDataSize, pcrData, ulDataLength, sealData,
157 						xsap->pAuth, &encDataSize, &encData)))
158 		goto error;
159 #endif
160 
161 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
162 	result |= Trspi_Hash_UINT32(&hashCtx, result);
163 	result |= Trspi_Hash_UINT32(&hashCtx, sealOrdinal);
164 	result |= Trspi_HashUpdate(&hashCtx, encDataSize, encData);
165 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
166 		goto error;
167 
168 	if ((result = authsess_xsap_verify(xsap, &digest)))
169 		goto error;
170 
171 	/* Need to set the object with the blob and the pcr's */
172 	if ((result = obj_encdata_set_data(hEncData, encDataSize, encData)))
173 		goto error;
174 
175 	if (pcrDataSize)
176 		result = obj_encdata_set_pcr_info(hEncData, pcrInfoType, pcrData);
177 
178 error:
179 	authsess_free(xsap);
180 	free(encData);
181 	free(pcrData);
182 	if (sealData != rgbDataToSeal)
183 		free(sealData);
184 	return result;
185 }
186 
187 TSS_RESULT
Tspi_Data_Unseal(TSS_HENCDATA hEncData,TSS_HKEY hKey,UINT32 * pulUnsealedDataLength,BYTE ** prgbUnsealedData)188 Tspi_Data_Unseal(TSS_HENCDATA hEncData,		/* in */
189 		 TSS_HKEY hKey,			/* in */
190 		 UINT32 * pulUnsealedDataLength,/* out */
191 		 BYTE ** prgbUnsealedData)	/* out */
192 {
193 	UINT64 offset;
194 	TPM_AUTH privAuth2;
195 	TPM_DIGEST digest;
196 	TPM_NONCE authLastNonceEven;
197 	TSS_RESULT result;
198 	TSS_HPOLICY hPolicy, hEncPolicy;
199 	TCS_KEY_HANDLE tcsKeyHandle;
200         TSS_HCONTEXT tspContext;
201 	UINT32 ulDataLen, unSealedDataLen;
202 	BYTE *data = NULL, *unSealedData = NULL, *maskedData;
203 	UINT16 mask;
204 	Trspi_HashCtx hashCtx;
205 	struct authsess *xsap = NULL;
206 
207 	if (pulUnsealedDataLength == NULL || prgbUnsealedData == NULL)
208 		return TSPERR(TSS_E_BAD_PARAMETER);
209 
210 	if ((result = obj_encdata_get_tsp_context(hEncData, &tspContext)))
211 		return result;
212 
213 	if ((result = obj_rsakey_get_policy(hKey, TSS_POLICY_USAGE, &hPolicy, NULL)))
214 		return result;
215 
216 	if ((result = obj_encdata_get_policy(hEncData, TSS_POLICY_USAGE, &hEncPolicy)))
217 		return result;
218 
219 	if ((result = obj_encdata_get_data(hEncData, &ulDataLen, &data)))
220 		return result == (TSS_E_INVALID_OBJ_ACCESS | TSS_LAYER_TSP) ?
221 		       TSPERR(TSS_E_ENC_NO_DATA) :
222 		       result;
223 
224 	offset = 0;
225 	Trspi_UnloadBlob_UINT16(&offset, &mask, data);
226 	if (mask == TPM_TAG_STORED_DATA12) {
227 		/* The second UINT16 in a TPM_STORED_DATA12 is the entity type. If its non-zero
228 		 * then we must unmask the unsealed data after it returns from the TCS */
229 		Trspi_UnloadBlob_UINT16(&offset, &mask, data);
230 	} else
231 		mask = 0;
232 
233 	if ((result = obj_rsakey_get_tcs_handle(hKey, &tcsKeyHandle)))
234 		goto error;
235 
236 	if ((result = authsess_xsap_init(tspContext, hKey, hEncData, TSS_AUTH_POLICY_REQUIRED,
237 					 TPM_ORD_Unseal, TPM_ET_KEYHANDLE, &xsap)))
238 		goto error;
239 
240 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
241 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Unseal);
242 	result |= Trspi_HashUpdate(&hashCtx, ulDataLen, data);
243 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
244 		goto error;
245 
246 	if ((result = authsess_xsap_hmac(xsap, &digest)))
247 		goto error;
248 
249 	if ((result = secret_PerformAuth_OIAP(hEncData, TPM_ORD_Unseal, hEncPolicy, FALSE, &digest,
250 					      &privAuth2)))
251 		goto error;
252 
253 	if (mask) {
254 		/* save off last nonce even to pass to sealx callback */
255 		   memcpy(authLastNonceEven.nonce, xsap->auth.NonceEven.nonce, sizeof(TPM_NONCE));
256 	}
257 
258 	if ((result = TCS_API(tspContext)->Unseal(tspContext, tcsKeyHandle, ulDataLen, data,
259 						  xsap->pAuth, &privAuth2, &unSealedDataLen,
260 						  &unSealedData)))
261 		goto error;
262 
263 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
264 	result |= Trspi_Hash_UINT32(&hashCtx, TSS_SUCCESS);
265 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Unseal);
266 	result |= Trspi_Hash_UINT32(&hashCtx, unSealedDataLen);
267 	result |= Trspi_HashUpdate(&hashCtx, unSealedDataLen, unSealedData);
268 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) {
269 		free(unSealedData);
270 		goto error;
271 	}
272 
273 	if ((result = authsess_xsap_verify(xsap, &digest))) {
274 		free(unSealedData);
275 		goto error;
276 	}
277 
278 	if ((result = obj_policy_validate_auth_oiap(hEncPolicy, &digest, &privAuth2))) {
279 		free(unSealedData);
280 		goto error;
281 	}
282 
283 	/* If the data is masked, use the callback set up in authsess_xsap_init */
284 	if (mask) {
285 		maskedData = unSealedData;
286 
287 		if ((unSealedData = calloc_tspi(tspContext, unSealedDataLen)) == NULL) {
288 			free(maskedData);
289 			LogError("malloc of %u bytes failed", unSealedDataLen);
290 			result = TSPERR(TSS_E_OUTOFMEMORY);
291 			goto error;
292 		}
293 
294 		/* XXX pass in out saved-off authLastNonceEven. This conflicts with the
295 		 * description of the rgbNonceEven parameter in the spec, but without it, its not
296 		 * possible to compute the MGF1 key */
297 		if ((result =
298 		     ((TSS_RESULT (*)(PVOID, TSS_HKEY, TSS_HENCDATA, TSS_ALGORITHM_ID,
299 		       UINT32, BYTE *, BYTE *, BYTE *, BYTE *, UINT32, BYTE *,
300 		       BYTE *))xsap->cb_sealx.callback)(xsap->cb_sealx.appData, hKey, hEncData,
301 							 xsap->cb_sealx.alg, sizeof(TPM_NONCE),
302 							 authLastNonceEven.nonce,
303 							 xsap->auth.NonceOdd.nonce,
304 							 xsap->nonceEvenxSAP.nonce,
305 							 xsap->nonceOddxSAP.nonce,
306 							 unSealedDataLen, maskedData,
307 							 unSealedData))) {
308 			free(maskedData);
309 			goto error;
310 		}
311 
312 		free(maskedData);
313 	} else {
314 		if ((result = __tspi_add_mem_entry(tspContext, unSealedData)))
315 			goto error;
316 	}
317 
318 	*pulUnsealedDataLength = unSealedDataLen;
319 	*prgbUnsealedData = unSealedData;
320 
321 error:
322 	authsess_free(xsap);
323 	if (data)
324 		free_tspi(tspContext, data);
325 
326 	return result;
327 }
328