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