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. 2007
8 *
9 */
10
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <inttypes.h>
16
17 #include "trousers/tss.h"
18 #include "trousers/trousers.h"
19 #include "trousers_types.h"
20 #include "spi_utils.h"
21 #include "obj.h"
22 #include "tsp_delegate.h"
23 #include "tsplog.h"
24
25
26 TSS_RESULT
Tspi_TPM_Delegate_AddFamily(TSS_HTPM hTpm,BYTE bLabel,TSS_HDELFAMILY * phFamily)27 Tspi_TPM_Delegate_AddFamily(TSS_HTPM hTpm, /* in, must not be NULL */
28 BYTE bLabel, /* in */
29 TSS_HDELFAMILY* phFamily) /* out */
30 {
31 TPM_FAMILY_ID familyID = 0;
32 UINT32 outDataSize;
33 BYTE *outData = NULL;
34 UINT64 offset;
35 TSS_RESULT result;
36
37 if (phFamily == NULL)
38 return TSPERR(TSS_E_BAD_PARAMETER);
39 *phFamily = NULL_HDELFAMILY;
40
41 if ((result = do_delegate_manage(hTpm, familyID, TPM_FAMILY_CREATE, sizeof(bLabel), &bLabel,
42 &outDataSize, &outData)))
43 return result;
44
45 offset = 0;
46 Trspi_UnloadBlob_UINT32(&offset, &familyID, outData);
47
48 /* Create or update the delfamily object */
49 if ((result = update_delfamily_object(hTpm, familyID)))
50 goto done;
51
52 obj_delfamily_find_by_familyid(hTpm, familyID, phFamily);
53 if (*phFamily == NULL_HDELFAMILY)
54 result = TSPERR(TSS_E_INTERNAL_ERROR);
55
56 done:
57 free(outData);
58
59 return result;
60 }
61
62 TSS_RESULT
Tspi_TPM_Delegate_GetFamily(TSS_HTPM hTpm,UINT32 ulFamilyID,TSS_HDELFAMILY * phFamily)63 Tspi_TPM_Delegate_GetFamily(TSS_HTPM hTpm, /* in, must not NULL */
64 UINT32 ulFamilyID, /* in */
65 TSS_HDELFAMILY* phFamily) /* out */
66 {
67 TSS_RESULT result;
68
69 if (phFamily == NULL)
70 return TSPERR(TSS_E_BAD_PARAMETER);
71 *phFamily = NULL_HDELFAMILY;
72
73 /* Update the delfamily object */
74 if ((result = update_delfamily_object(hTpm, ulFamilyID)))
75 return result;
76
77 obj_delfamily_find_by_familyid(hTpm, ulFamilyID, phFamily);
78 if (*phFamily == NULL_HDELFAMILY)
79 result = TSPERR(TSS_E_BAD_PARAMETER);
80
81 return result;
82 }
83
84 TSS_RESULT
Tspi_TPM_Delegate_InvalidateFamily(TSS_HTPM hTpm,TSS_HDELFAMILY hFamily)85 Tspi_TPM_Delegate_InvalidateFamily(TSS_HTPM hTpm, /* in, must not be NULL */
86 TSS_HDELFAMILY hFamily) /* in */
87 {
88 TPM_FAMILY_ID familyID;
89 UINT32 outDataSize;
90 BYTE *outData = NULL;
91 TSS_RESULT result;
92
93 if ((result = obj_delfamily_get_familyid(hFamily, &familyID)))
94 return result;
95
96 if ((result = do_delegate_manage(hTpm, familyID, TPM_FAMILY_INVALIDATE, 0, NULL,
97 &outDataSize, &outData)))
98 return result;
99
100 /* Delete the delfamily object */
101 result = obj_delfamily_remove(hFamily, hTpm);
102
103 free(outData);
104
105 return result;
106 }
107
108 TSS_RESULT
Tspi_TPM_Delegate_CreateDelegation(TSS_HOBJECT hObject,BYTE bLabel,UINT32 ulFlags,TSS_HPCRS hPcrs,TSS_HDELFAMILY hFamily,TSS_HPOLICY hDelegation)109 Tspi_TPM_Delegate_CreateDelegation(TSS_HOBJECT hObject, /* in */
110 BYTE bLabel, /* in */
111 UINT32 ulFlags, /* in */
112 TSS_HPCRS hPcrs, /* in */
113 TSS_HDELFAMILY hFamily, /* in */
114 TSS_HPOLICY hDelegation) /* in, out */
115 {
116 TSS_RESULT result;
117
118 if (obj_is_tpm(hObject)) {
119 if ((result = create_owner_delegation(hObject, bLabel, ulFlags, hPcrs, hFamily,
120 hDelegation)))
121 return result;
122 } else if (obj_is_rsakey(hObject)) {
123 if ((result = create_key_delegation(hObject, bLabel, ulFlags, hPcrs, hFamily,
124 hDelegation)))
125 return result;
126 } else
127 return TSPERR(TSS_E_INVALID_HANDLE);
128
129 return TSS_SUCCESS;
130 }
131
132 TSS_RESULT
Tspi_TPM_Delegate_CacheOwnerDelegation(TSS_HTPM hTpm,TSS_HPOLICY hDelegation,UINT32 ulIndex,UINT32 ulFlags)133 Tspi_TPM_Delegate_CacheOwnerDelegation(TSS_HTPM hTpm, /* in */
134 TSS_HPOLICY hDelegation, /* in */
135 UINT32 ulIndex, /* in */
136 UINT32 ulFlags) /* in */
137 {
138 TSS_HCONTEXT hContext;
139 TSS_HPOLICY hPolicy;
140 UINT32 blobSize;
141 BYTE *blob = NULL;
142 UINT32 secretMode = TSS_SECRET_MODE_NONE;
143 Trspi_HashCtx hashCtx;
144 TCPA_DIGEST digest;
145 TPM_AUTH ownerAuth, *pAuth;
146 TSS_RESULT result;
147
148 if ((result = obj_tpm_get_tsp_context(hTpm, &hContext)))
149 return result;
150
151 if ((result = obj_tpm_get_policy(hTpm, TSS_POLICY_USAGE, &hPolicy)))
152 return result;
153
154 if ((result = obj_policy_get_delegation_blob(hDelegation, TSS_DELEGATIONTYPE_OWNER,
155 &blobSize, &blob)))
156 return result;
157
158 if (ulFlags & ~TSS_DELEGATE_CACHEOWNERDELEGATION_OVERWRITEEXISTING) {
159 result = TSPERR(TSS_E_BAD_PARAMETER);
160 goto done;
161 }
162
163 if ((ulFlags & TSS_DELEGATE_CACHEOWNERDELEGATION_OVERWRITEEXISTING) == 0) {
164 TPM_DELEGATE_PUBLIC public;
165
166 /* Verify there is nothing occupying the specified row */
167 result = get_delegate_index(hContext, ulIndex, &public);
168 if (result == TSS_SUCCESS) {
169 free(public.pcrInfo.pcrSelection.pcrSelect);
170 result = TSPERR(TSS_E_DELFAMILY_ROWEXISTS);
171 goto done;
172 }
173 }
174
175 if (hPolicy != NULL_HPOLICY) {
176 if ((result = obj_policy_get_mode(hPolicy, &secretMode)))
177 goto done;
178 }
179
180 if (secretMode != TSS_SECRET_MODE_NONE) {
181 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
182 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_LoadOwnerDelegation);
183 result |= Trspi_Hash_UINT32(&hashCtx, ulIndex);
184 result |= Trspi_Hash_UINT32(&hashCtx, blobSize);
185 result |= Trspi_HashUpdate(&hashCtx, blobSize, blob);
186 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
187 goto done;
188
189 pAuth = &ownerAuth;
190 if ((result = secret_PerformAuth_OIAP(hTpm, TPM_ORD_Delegate_LoadOwnerDelegation,
191 hPolicy, FALSE, &digest, pAuth)))
192 goto done;
193 } else
194 pAuth = NULL;
195
196 if ((result = TCS_API(hContext)->Delegate_LoadOwnerDelegation(hContext, ulIndex, blobSize,
197 blob, pAuth)))
198 goto done;
199
200 if (pAuth) {
201 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
202 result |= Trspi_Hash_UINT32(&hashCtx, result);
203 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_LoadOwnerDelegation);
204 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
205 goto done;
206
207 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth)))
208 goto done;
209 }
210
211 result = obj_policy_set_delegation_index(hDelegation, ulIndex);
212
213 done:
214 free_tspi(hContext, blob);
215
216 return result;
217 }
218
219 TSS_RESULT
Tspi_TPM_Delegate_UpdateVerificationCount(TSS_HTPM hTpm,TSS_HPOLICY hDelegation)220 Tspi_TPM_Delegate_UpdateVerificationCount(TSS_HTPM hTpm, /* in */
221 TSS_HPOLICY hDelegation) /* in, out */
222 {
223 TSS_HCONTEXT hContext;
224 TSS_HPOLICY hPolicy;
225 UINT32 secretMode = TSS_SECRET_MODE_NONE;
226 Trspi_HashCtx hashCtx;
227 TCPA_DIGEST digest;
228 TPM_AUTH ownerAuth, *pAuth;
229 TSS_BOOL indexSet;
230 UINT32 inputSize;
231 BYTE *input = NULL;
232 UINT32 outputSize;
233 BYTE *output = NULL;
234 UINT64 offset;
235 TSS_RESULT result;
236
237 if ((result = obj_tpm_get_tsp_context(hTpm, &hContext)))
238 return result;
239
240 if ((result = obj_tpm_get_policy(hTpm, TSS_POLICY_USAGE, &hPolicy)))
241 return result;
242
243 if (hPolicy != NULL_HPOLICY) {
244 if ((result = obj_policy_get_mode(hPolicy, &secretMode)))
245 goto done;
246 }
247
248 if ((result = obj_policy_is_delegation_index_set(hDelegation, &indexSet)))
249 return result;
250 if (indexSet) {
251 UINT32 index;
252
253 if ((result = obj_policy_get_delegation_index(hDelegation, &index)))
254 return result;
255 inputSize = sizeof(UINT32);
256 input = calloc_tspi(hContext, inputSize);
257 if (!input) {
258 LogError("malloc of %zd bytes failed.", sizeof(UINT32));
259 return TSPERR(TSS_E_OUTOFMEMORY);
260 }
261 offset = 0;
262 Trspi_LoadBlob_UINT32(&offset, index, input);
263 } else {
264 if ((result = obj_policy_get_delegation_blob(hDelegation, 0,
265 &inputSize, &input)))
266 return result;
267 }
268
269 if (secretMode != TSS_SECRET_MODE_NONE) {
270 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
271 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_UpdateVerification);
272 result |= Trspi_Hash_UINT32(&hashCtx, inputSize);
273 result |= Trspi_HashUpdate(&hashCtx, inputSize, input);
274 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
275 goto done;
276
277 pAuth = &ownerAuth;
278 if ((result = secret_PerformAuth_OIAP(hTpm, TPM_ORD_Delegate_UpdateVerification,
279 hPolicy, FALSE, &digest, pAuth)))
280 goto done;
281 } else
282 pAuth = NULL;
283
284 if ((result = TCS_API(hContext)->Delegate_UpdateVerificationCount(hContext, inputSize,
285 input, pAuth, &outputSize,
286 &output)))
287 goto done;
288
289 if (pAuth) {
290 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
291 result |= Trspi_Hash_UINT32(&hashCtx, result);
292 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_UpdateVerification);
293 result |= Trspi_Hash_UINT32(&hashCtx, outputSize);
294 result |= Trspi_HashUpdate(&hashCtx, outputSize, output);
295 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
296 goto done;
297
298 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth)))
299 goto done;
300 }
301
302 result = obj_policy_set_delegation_blob(hDelegation, 0, outputSize, output);
303
304 done:
305 free_tspi(hContext, input);
306 free(output);
307
308 return result;
309 }
310
311 TSS_RESULT
Tspi_TPM_Delegate_VerifyDelegation(TSS_HPOLICY hDelegation)312 Tspi_TPM_Delegate_VerifyDelegation(TSS_HPOLICY hDelegation) /* in, out */
313 {
314 TSS_HCONTEXT hContext;
315 UINT32 delegateSize;
316 BYTE *delegate = NULL;
317 TSS_RESULT result;
318
319 if ((result = obj_policy_get_tsp_context(hDelegation, &hContext)))
320 return result;
321
322 if ((result = obj_policy_get_delegation_blob(hDelegation, 0, &delegateSize, &delegate)))
323 return result;
324
325 result = TCS_API(hContext)->Delegate_VerifyDelegation(hContext, delegateSize, delegate);
326
327 free_tspi(hContext, delegate);
328
329 return result;
330 }
331
332 TSS_RESULT
Tspi_TPM_Delegate_ReadTables(TSS_HCONTEXT hContext,UINT32 * pulFamilyTableSize,TSS_FAMILY_TABLE_ENTRY ** ppFamilyTable,UINT32 * pulDelegateTableSize,TSS_DELEGATION_TABLE_ENTRY ** ppDelegateTable)333 Tspi_TPM_Delegate_ReadTables(TSS_HCONTEXT hContext, /* in */
334 UINT32* pulFamilyTableSize, /* out */
335 TSS_FAMILY_TABLE_ENTRY** ppFamilyTable, /* out */
336 UINT32* pulDelegateTableSize, /* out */
337 TSS_DELEGATION_TABLE_ENTRY** ppDelegateTable) /* out */
338 {
339 UINT32 tpmFamilyTableSize, tpmDelegateTableSize;
340 BYTE *tpmFamilyTable = NULL, *tpmDelegateTable = NULL;
341 TPM_FAMILY_TABLE_ENTRY tpmFamilyEntry;
342 TSS_FAMILY_TABLE_ENTRY tssFamilyEntry, *tssFamilyTable = NULL;
343 UINT32 tssFamilyTableSize = 0;
344 TPM_DELEGATE_PUBLIC tpmDelegatePublic;
345 TSS_DELEGATION_TABLE_ENTRY tssDelegateEntry, *tssDelegateTable = NULL;
346 UINT32 tssDelegateTableSize = 0;
347 UINT32 tableIndex;
348 UINT64 tpmOffset;
349 UINT64 tssOffset;
350 TSS_RESULT result;
351
352 if (!pulFamilyTableSize || !ppFamilyTable || !pulDelegateTableSize || !ppDelegateTable)
353 return TSPERR(TSS_E_BAD_PARAMETER);
354
355 if (!obj_is_context(hContext))
356 return TSPERR(TSS_E_INVALID_HANDLE);
357
358 if ((result = TCS_API(hContext)->Delegate_ReadTable(hContext, &tpmFamilyTableSize,
359 &tpmFamilyTable, &tpmDelegateTableSize,
360 &tpmDelegateTable)))
361 return result;
362
363 if (tpmFamilyTableSize > 0) {
364 /* Create the TSS_FAMILY_TABLE_ENTRY array */
365 for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmFamilyTableSize;) {
366 Trspi_UnloadBlob_TPM_FAMILY_TABLE_ENTRY(&tpmOffset, tpmFamilyTable,
367 &tpmFamilyEntry);
368
369 /* No pointers in the family table entries, so no
370 assignments required before doing LoadBlob */
371 Trspi_LoadBlob_TSS_FAMILY_TABLE_ENTRY(&tssOffset, NULL, &tssFamilyEntry);
372 }
373
374 if ((tssFamilyTable = calloc_tspi(hContext, tssOffset)) == NULL) {
375 LogError("malloc of %" PRIu64 " bytes failed.", tssOffset);
376 result = TSPERR(TSS_E_OUTOFMEMORY);
377 goto done;
378 }
379 for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmFamilyTableSize; tssFamilyTableSize++) {
380 Trspi_UnloadBlob_TPM_FAMILY_TABLE_ENTRY(&tpmOffset, tpmFamilyTable,
381 &tpmFamilyEntry);
382
383 tssFamilyEntry.familyID = tpmFamilyEntry.familyID;
384 tssFamilyEntry.label = tpmFamilyEntry.label.label;
385 tssFamilyEntry.verificationCount = tpmFamilyEntry.verificationCount;
386 tssFamilyEntry.enabled =
387 (tpmFamilyEntry.flags & TPM_FAMFLAG_ENABLE) ? TRUE : FALSE;
388 tssFamilyEntry.locked =
389 (tpmFamilyEntry.flags & TPM_FAMFLAG_DELEGATE_ADMIN_LOCK) ? TRUE : FALSE;
390 Trspi_LoadBlob_TSS_FAMILY_TABLE_ENTRY(&tssOffset, (BYTE *)tssFamilyTable,
391 &tssFamilyEntry);
392 }
393 }
394
395 if (tpmDelegateTableSize > 0) {
396 /* Create the TSS_DELEGATION_TABLE_ENTRY array */
397 for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmDelegateTableSize;) {
398 Trspi_UnloadBlob_UINT32(&tpmOffset, &tableIndex, tpmDelegateTable);
399 if ((result = Trspi_UnloadBlob_TPM_DELEGATE_PUBLIC(&tpmOffset, tpmDelegateTable,
400 &tpmDelegatePublic))) {
401 free_tspi(hContext, tssFamilyTable);
402 goto done;
403 }
404
405 /* Some pointers in the delegate table entries, so
406 do some assignments before doing LoadBlob */
407 tssDelegateEntry.pcrInfo.sizeOfSelect =
408 tpmDelegatePublic.pcrInfo.pcrSelection.sizeOfSelect;
409 tssDelegateEntry.pcrInfo.selection =
410 tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect;
411 tssDelegateEntry.pcrInfo.sizeOfDigestAtRelease =
412 sizeof(tpmDelegatePublic.pcrInfo.digestAtRelease.digest);
413 tssDelegateEntry.pcrInfo.digestAtRelease =
414 tpmDelegatePublic.pcrInfo.digestAtRelease.digest;
415 Trspi_LoadBlob_TSS_DELEGATION_TABLE_ENTRY(&tssOffset, NULL,
416 &tssDelegateEntry);
417
418 free(tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect);
419 }
420
421 if ((tssDelegateTable = calloc_tspi(hContext, tssOffset)) == NULL) {
422 LogError("malloc of %" PRIu64 " bytes failed.", tssOffset);
423 free_tspi(hContext, tssFamilyTable);
424 result = TSPERR(TSS_E_OUTOFMEMORY);
425 goto done;
426 }
427 for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmDelegateTableSize; tssDelegateTableSize++) {
428 Trspi_UnloadBlob_UINT32(&tpmOffset, &tableIndex, tpmDelegateTable);
429 if ((result = Trspi_UnloadBlob_TPM_DELEGATE_PUBLIC(&tpmOffset,
430 tpmDelegateTable, &tpmDelegatePublic))) {
431 free_tspi(hContext, tssFamilyTable);
432 free_tspi(hContext, tssDelegateTable);
433 goto done;
434 }
435
436 tssDelegateEntry.tableIndex = tableIndex;
437 tssDelegateEntry.label = tpmDelegatePublic.label.label;
438 tssDelegateEntry.pcrInfo.sizeOfSelect =
439 tpmDelegatePublic.pcrInfo.pcrSelection.sizeOfSelect;
440 tssDelegateEntry.pcrInfo.selection =
441 tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect;
442 tssDelegateEntry.pcrInfo.localityAtRelease =
443 tpmDelegatePublic.pcrInfo.localityAtRelease;
444 tssDelegateEntry.pcrInfo.sizeOfDigestAtRelease =
445 sizeof(tpmDelegatePublic.pcrInfo.digestAtRelease.digest);
446 tssDelegateEntry.pcrInfo.digestAtRelease =
447 tpmDelegatePublic.pcrInfo.digestAtRelease.digest;
448 tssDelegateEntry.per1 = tpmDelegatePublic.permissions.per1;
449 tssDelegateEntry.per2 = tpmDelegatePublic.permissions.per2;
450 tssDelegateEntry.familyID = tpmDelegatePublic.familyID;
451 tssDelegateEntry.verificationCount = tpmDelegatePublic.verificationCount;
452 Trspi_LoadBlob_TSS_DELEGATION_TABLE_ENTRY(&tssOffset,
453 (BYTE *)tssDelegateTable, &tssDelegateEntry);
454
455 free(tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect);
456 }
457 }
458
459 *ppFamilyTable = tssFamilyTable;
460 *pulFamilyTableSize = tssFamilyTableSize;
461 *ppDelegateTable = tssDelegateTable;
462 *pulDelegateTableSize = tssDelegateTableSize;
463
464 done:
465 free(tpmFamilyTable);
466 free(tpmDelegateTable);
467
468 return result;
469 }
470
471