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-2006
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_AuthorizeMigrationTicket(TSS_HTPM hTPM,TSS_HKEY hMigrationKey,TSS_MIGRATION_SCHEME migrationScheme,UINT32 * pulMigTicketLength,BYTE ** prgbMigTicket)26 Tspi_TPM_AuthorizeMigrationTicket(TSS_HTPM hTPM,			/* in */
27 				  TSS_HKEY hMigrationKey,		/* in */
28 				  TSS_MIGRATION_SCHEME migrationScheme,	/* in */
29 				  UINT32 * pulMigTicketLength,		/* out */
30 				  BYTE ** prgbMigTicket)		/* out */
31 {
32 	UINT64 offset;
33 	TCPA_DIGEST digest;
34 	TCPA_RESULT result;
35 	TSS_HPOLICY hOwnerPolicy;
36 	UINT32 migrationKeySize;
37 	BYTE *migrationKeyBlob;
38 	TSS_KEY tssKey;
39 	BYTE pubKeyBlob[0x1000];
40 	TPM_AUTH ownerAuth;
41 	UINT32 pubKeySize;
42 	TSS_HCONTEXT tspContext;
43 	UINT32 tpmMigrationScheme;
44 	Trspi_HashCtx hashCtx;
45 
46 	if (pulMigTicketLength == NULL || prgbMigTicket == NULL)
47 		return TSPERR(TSS_E_BAD_PARAMETER);
48 
49 	if ((result = obj_tpm_get_tsp_context(hTPM, &tspContext)))
50 		return result;
51 
52 	/*  get the tpm Policy */
53 	if ((result = obj_tpm_get_policy(hTPM, TSS_POLICY_USAGE, &hOwnerPolicy)))
54 		return result;
55 
56 	switch (migrationScheme) {
57 		case TSS_MS_MIGRATE:
58 			tpmMigrationScheme = TCPA_MS_MIGRATE;
59 			break;
60 		case TSS_MS_REWRAP:
61 			tpmMigrationScheme = TCPA_MS_REWRAP;
62 			break;
63 		case TSS_MS_MAINT:
64 			tpmMigrationScheme = TCPA_MS_MAINT;
65 			break;
66 #ifdef TSS_BUILD_CMK
67 		case TSS_MS_RESTRICT_MIGRATE:
68 			tpmMigrationScheme = TPM_MS_RESTRICT_MIGRATE;
69 			break;
70 
71 		case TSS_MS_RESTRICT_APPROVE_DOUBLE:
72 			tpmMigrationScheme = TPM_MS_RESTRICT_APPROVE_DOUBLE;
73 			break;
74 #endif
75 		default:
76 			return TSPERR(TSS_E_BAD_PARAMETER);
77 			break;
78 	}
79 
80 	/*  Get the migration key blob */
81 	if ((result = obj_rsakey_get_blob(hMigrationKey, &migrationKeySize, &migrationKeyBlob)))
82 		return result;
83 
84 	/* First, turn the keyBlob into a TSS_KEY structure */
85 	offset = 0;
86 	__tspi_memset(&tssKey, 0, sizeof(TSS_KEY));
87 	if ((result = UnloadBlob_TSS_KEY(&offset, migrationKeyBlob, &tssKey))) {
88 		free_tspi(tspContext, migrationKeyBlob);
89 		return result;
90 	}
91 	free_tspi(tspContext, migrationKeyBlob);
92 
93 	/* Then pull the _PUBKEY portion out of that struct into a blob */
94 	offset = 0;
95 	Trspi_LoadBlob_KEY_PARMS(&offset, pubKeyBlob, &tssKey.algorithmParms);
96 	Trspi_LoadBlob_STORE_PUBKEY(&offset, pubKeyBlob, &tssKey.pubKey);
97 	pubKeySize = offset;
98 	free_key_refs(&tssKey);
99 
100 	/* Auth */
101 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
102 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_AuthorizeMigrationKey);
103 	result |= Trspi_Hash_UINT16(&hashCtx, tpmMigrationScheme);
104 	result |= Trspi_HashUpdate(&hashCtx, pubKeySize, pubKeyBlob);
105 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
106 		return result;
107 
108 	if ((result = secret_PerformAuth_OIAP(hTPM, TPM_ORD_AuthorizeMigrationKey, hOwnerPolicy,
109 					      FALSE, &digest, &ownerAuth)))
110 		return result;
111 
112 	/* Send command */
113 	if ((result = TCS_API(tspContext)->AuthorizeMigrationKey(tspContext, migrationScheme,
114 								 pubKeySize, pubKeyBlob, &ownerAuth,
115 								 pulMigTicketLength,
116 								 prgbMigTicket)))
117 		return result;
118 
119 	/* Validate Auth */
120 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
121 	result |= Trspi_Hash_UINT32(&hashCtx, result);
122 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_AuthorizeMigrationKey);
123 	result |= Trspi_HashUpdate(&hashCtx, *pulMigTicketLength, *prgbMigTicket);
124 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) {
125 		*pulMigTicketLength = 0;
126 		free(*prgbMigTicket);
127 		return result;
128 	}
129 
130 	if ((result = obj_policy_validate_auth_oiap(hOwnerPolicy, &digest, &ownerAuth))) {
131 		*pulMigTicketLength = 0;
132 		free(*prgbMigTicket);
133 		return result;
134 	}
135 
136 	if ((result = __tspi_add_mem_entry(tspContext, *prgbMigTicket))) {
137 		*pulMigTicketLength = 0;
138 		free(*prgbMigTicket);
139 		return result;
140 	}
141 
142 	return TSS_SUCCESS;
143 }
144 
145 TSS_RESULT
Tspi_Key_CreateMigrationBlob(TSS_HKEY hKeyToMigrate,TSS_HKEY hParentKey,UINT32 ulMigTicketLength,BYTE * rgbMigTicket,UINT32 * pulRandomLength,BYTE ** prgbRandom,UINT32 * pulMigrationBlobLength,BYTE ** prgbMigrationBlob)146 Tspi_Key_CreateMigrationBlob(TSS_HKEY hKeyToMigrate,		/* in */
147 			     TSS_HKEY hParentKey,		/* in */
148 			     UINT32 ulMigTicketLength,		/* in */
149 			     BYTE * rgbMigTicket,		/* in */
150 			     UINT32 * pulRandomLength,		/* out */
151 			     BYTE ** prgbRandom,		/* out */
152 			     UINT32 * pulMigrationBlobLength,	/* out */
153 			     BYTE ** prgbMigrationBlob)		/* out */
154 {
155 	TPM_AUTH parentAuth, entityAuth;
156 	TPM_AUTH *pParentAuth;
157 	TCPA_RESULT result;
158 	UINT64 offset;
159 	TCPA_DIGEST digest;
160 	UINT32 keyToMigrateSize;
161 	BYTE *keyToMigrateBlob = NULL;
162 	TSS_HPOLICY hParentPolicy;
163 	TSS_HPOLICY hMigratePolicy;
164 	TCPA_MIGRATIONKEYAUTH migAuth;
165 	TSS_KEY tssKey;
166 	TCS_KEY_HANDLE parentHandle;
167 	TSS_BOOL parentUsesAuth;
168 	UINT32 randomSize;
169 	BYTE *random = NULL;
170 	UINT32 blobSize;
171 	BYTE *blob = NULL;
172 	TSS_HCONTEXT tspContext;
173 	Trspi_HashCtx hashCtx;
174 
175 	__tspi_memset(&tssKey, 0, sizeof(TSS_KEY));
176 
177 	if (pulRandomLength == NULL || prgbRandom == NULL || rgbMigTicket == NULL ||
178 	    pulMigrationBlobLength == NULL || prgbMigrationBlob == NULL)
179 		return TSPERR(TSS_E_BAD_PARAMETER);
180 
181 	if (!obj_is_rsakey(hKeyToMigrate))
182 		return TSPERR(TSS_E_INVALID_HANDLE);
183 
184 	if ((result = obj_rsakey_get_tsp_context(hKeyToMigrate, &tspContext)))
185 		return result;
186 
187 	if ((result = obj_rsakey_get_blob(hKeyToMigrate, &keyToMigrateSize, &keyToMigrateBlob)))
188 		goto done;
189 
190 	if ((result = obj_rsakey_get_policy(hParentKey, TSS_POLICY_USAGE, &hParentPolicy,
191 					    &parentUsesAuth)))
192 		goto done;
193 
194 	if ((result = obj_rsakey_get_policy(hKeyToMigrate, TSS_POLICY_MIGRATION, &hMigratePolicy,
195 					    NULL)))
196 		goto done;
197 
198 	/*  Parsing the migration scheme from the blob and key object */
199 	__tspi_memset(&migAuth, 0, sizeof(TCPA_MIGRATIONKEYAUTH));
200 
201 	offset = 0;
202 	if ((result = Trspi_UnloadBlob_MIGRATIONKEYAUTH(&offset, rgbMigTicket, &migAuth)))
203 		goto done;
204 
205 	/* free these now, since none are used below */
206 	free(migAuth.migrationKey.algorithmParms.parms);
207 	migAuth.migrationKey.algorithmParms.parmSize = 0;
208 	free(migAuth.migrationKey.pubKey.key);
209 	migAuth.migrationKey.pubKey.keyLength = 0;
210 
211 	offset = 0;
212 	if ((result = UnloadBlob_TSS_KEY(&offset, keyToMigrateBlob, &tssKey)))
213 		goto done;
214 
215 	/* Generate the Authorization data */
216 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
217 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CreateMigrationBlob);
218 	result |= Trspi_Hash_UINT16(&hashCtx, migAuth.migrationScheme);
219 	result |= Trspi_HashUpdate(&hashCtx, ulMigTicketLength, rgbMigTicket);
220 	result |= Trspi_Hash_UINT32(&hashCtx, tssKey.encSize);
221 	result |= Trspi_HashUpdate(&hashCtx, tssKey.encSize, tssKey.encData);
222 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
223 		goto done;
224 
225 	if (parentUsesAuth) {
226 		if ((result = secret_PerformAuth_OIAP(hParentPolicy, TPM_ORD_CreateMigrationBlob,
227 						      hParentPolicy, FALSE, &digest,
228 						      &parentAuth)))
229 			goto done;
230 		pParentAuth = &parentAuth;
231 	} else {
232 		pParentAuth = NULL;
233 	}
234 
235 	if ((result = secret_PerformAuth_OIAP(hKeyToMigrate, TPM_ORD_CreateMigrationBlob,
236 					      hMigratePolicy, FALSE, &digest, &entityAuth)))
237 		goto done;
238 
239 	if ((result = obj_rsakey_get_tcs_handle(hParentKey, &parentHandle)))
240 		goto done;
241 
242 	if ((result = TCS_API(tspContext)->CreateMigrationBlob(tspContext, parentHandle,
243 							       migAuth.migrationScheme,
244 							       ulMigTicketLength, rgbMigTicket,
245 							       tssKey.encSize, tssKey.encData,
246 							       pParentAuth, &entityAuth,
247 							       &randomSize, &random,
248 							       &blobSize, &blob)))
249 		goto done;
250 
251 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
252 	result |= Trspi_Hash_UINT32(&hashCtx, result);
253 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_CreateMigrationBlob);
254 	result |= Trspi_Hash_UINT32(&hashCtx, randomSize);
255 	result |= Trspi_HashUpdate(&hashCtx, randomSize, random);
256 	result |= Trspi_Hash_UINT32(&hashCtx, blobSize);
257 	result |= Trspi_HashUpdate(&hashCtx, blobSize, blob);
258 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
259 		goto done;
260 
261 	if (parentUsesAuth) {
262 		if ((result = obj_policy_validate_auth_oiap(hParentPolicy, &digest, &parentAuth)))
263 			goto done;
264 	}
265 
266 	if ((result = obj_policy_validate_auth_oiap(hMigratePolicy, &digest, &entityAuth)))
267 		goto done;
268 
269 	free(tssKey.encData);
270 	tssKey.encSize = blobSize;
271 	tssKey.encData = blob;
272 	/* Set blob to null since it will now be freed during key ref freeing */
273 	blob = NULL;
274 
275 	offset = 0;
276 	LoadBlob_TSS_KEY(&offset, NULL, &tssKey);
277 
278 	*pulMigrationBlobLength = offset;
279 	*prgbMigrationBlob = calloc_tspi(tspContext, *pulMigrationBlobLength);
280 	if (*prgbMigrationBlob == NULL) {
281 		LogError("malloc of %u bytes failed.", *pulMigrationBlobLength);
282 		result = TSPERR(TSS_E_OUTOFMEMORY);
283 		goto done;
284 	}
285 	offset = 0;
286 	LoadBlob_TSS_KEY(&offset, *prgbMigrationBlob, &tssKey);
287 
288 	if (randomSize) {
289 		if ((result = __tspi_add_mem_entry(tspContext, random)))
290 			goto done;
291 	}
292 	*pulRandomLength = randomSize;
293 	*prgbRandom = random;
294 
295 done:
296 	if (result)
297 		free(random);
298 	free_tspi(tspContext, keyToMigrateBlob);
299 	free_key_refs(&tssKey);
300 	free(blob);
301 
302 	return result;
303 }
304 
305 TSS_RESULT
Tspi_Key_ConvertMigrationBlob(TSS_HKEY hKeyToMigrate,TSS_HKEY hParentKey,UINT32 ulRandomLength,BYTE * rgbRandom,UINT32 ulMigrationBlobLength,BYTE * rgbMigrationBlob)306 Tspi_Key_ConvertMigrationBlob(TSS_HKEY hKeyToMigrate,		/* in */
307 			      TSS_HKEY hParentKey,		/* in */
308 			      UINT32 ulRandomLength,		/* in */
309 			      BYTE * rgbRandom,			/* in */
310 			      UINT32 ulMigrationBlobLength,	/* in */
311 			      BYTE * rgbMigrationBlob)		/* in */
312 {
313 	TCPA_RESULT result;
314 	TSS_KEY tssKey;
315 	UINT32 outDataSize;
316 	BYTE *outData = NULL;
317 	TCS_KEY_HANDLE parentHandle;
318 	TPM_AUTH parentAuth;
319 	TSS_HPOLICY hParentPolicy;
320 	TCPA_DIGEST digest;
321 	TSS_BOOL useAuth;
322 	TPM_AUTH *pParentAuth;
323 	TSS_HCONTEXT tspContext;
324 	Trspi_HashCtx hashCtx;
325 	UINT64 offset;
326 
327 	__tspi_memset(&tssKey, 0, sizeof(TSS_KEY));
328 
329 	if ((result = obj_rsakey_get_tsp_context(hKeyToMigrate, &tspContext)))
330 		return result;
331 
332 	if (!obj_is_rsakey(hParentKey))
333 		return TSPERR(TSS_E_INVALID_HANDLE);
334 
335 	/* Get the parent key handle */
336 	if ((result = obj_rsakey_get_tcs_handle(hParentKey, &parentHandle)))
337 		return result;
338 
339 	/* Get the policy */
340 	if ((result = obj_rsakey_get_policy(hParentKey, TSS_POLICY_USAGE,
341 					&hParentPolicy, &useAuth)))
342 		return result;
343 
344 	offset = 0;
345 	if ((result = UnloadBlob_TSS_KEY(&offset, rgbMigrationBlob, &tssKey)))
346 		return result;
347 
348 	/* Generate the authorization */
349 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
350 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ConvertMigrationBlob);
351 	result |= Trspi_Hash_UINT32(&hashCtx, tssKey.encSize);
352 	result |= Trspi_HashUpdate(&hashCtx, tssKey.encSize, tssKey.encData);
353 	result |= Trspi_Hash_UINT32(&hashCtx, ulRandomLength);
354 	result |= Trspi_HashUpdate(&hashCtx, ulRandomLength, rgbRandom);
355 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
356 		goto done;
357 
358 	if (useAuth) {
359 		if ((result = secret_PerformAuth_OIAP(hParentPolicy, TPM_ORD_ConvertMigrationBlob,
360 						      hParentPolicy, FALSE, &digest, &parentAuth)))
361 			goto done;
362 		pParentAuth = &parentAuth;
363 	} else {
364 		pParentAuth = NULL;
365 	}
366 
367 	if ((result = TCS_API(tspContext)->ConvertMigrationBlob(tspContext, parentHandle,
368 								tssKey.encSize, tssKey.encData,
369 								ulRandomLength, rgbRandom,
370 								pParentAuth,
371 								&outDataSize, &outData)))
372 		goto done;
373 
374 	/* add validation */
375 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
376 	result |= Trspi_Hash_UINT32(&hashCtx, result);
377 	result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ConvertMigrationBlob);
378 	result |= Trspi_Hash_UINT32(&hashCtx, outDataSize);
379 	result |= Trspi_HashUpdate(&hashCtx, outDataSize, outData);
380 	if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
381 		goto done;
382 
383 	if (useAuth) {
384 		if ((result = obj_policy_validate_auth_oiap(hParentPolicy, &digest, &parentAuth)))
385 			goto done;
386 	}
387 
388 	/* Set the key object to the now migrated key */
389 	if ((result = obj_rsakey_set_tcpakey(hKeyToMigrate, ulMigrationBlobLength, rgbMigrationBlob)))
390 		goto done;
391 	if ((result = obj_rsakey_set_privkey(hKeyToMigrate, TRUE, outDataSize, outData)))
392 		goto done;
393 	result = obj_rsakey_set_tcs_handle(hKeyToMigrate, 0);
394 
395 done:
396 	free_key_refs(&tssKey);
397 	free(outData);
398 
399 	return result;
400 }
401