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
25TSS_RESULT
26Tspi_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	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
145TSS_RESULT
146Tspi_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	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	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
295done:
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
305TSS_RESULT
306Tspi_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	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
395done:
396	free_key_refs(&tssKey);
397	free(outData);
398
399	return result;
400}
401