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