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
26TSS_RESULT
27Tspi_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
56done:
57	free(outData);
58
59	return result;
60}
61
62TSS_RESULT
63Tspi_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
84TSS_RESULT
85Tspi_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
108TSS_RESULT
109Tspi_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
132TSS_RESULT
133Tspi_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
213done:
214	free_tspi(hContext, blob);
215
216	return result;
217}
218
219TSS_RESULT
220Tspi_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
304done:
305	free_tspi(hContext, input);
306	free(output);
307
308	return result;
309}
310
311TSS_RESULT
312Tspi_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
332TSS_RESULT
333Tspi_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
464done:
465	free(tpmFamilyTable);
466	free(tpmDelegateTable);
467
468	return result;
469}
470
471