Home | History | Annotate | Line # | Download | only in tspi
      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
     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
     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
     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
    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
    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
    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
    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
    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