summaryrefslogtreecommitdiff
path: root/src/tspi/tspi_delegate.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
commitc3649a2def02c41d837ae1f79dda729ccb91e677 (patch)
treebea46dff212fdef977fe9094a70a939e8cc21885 /src/tspi/tspi_delegate.c
downloadtrousers-c3649a2def02c41d837ae1f79dda729ccb91e677.tar.gz
Imported Upstream version 0.3.9upstream/0.3.9upstream
Diffstat (limited to 'src/tspi/tspi_delegate.c')
-rw-r--r--src/tspi/tspi_delegate.c470
1 files changed, 470 insertions, 0 deletions
diff --git a/src/tspi/tspi_delegate.c b/src/tspi/tspi_delegate.c
new file mode 100644
index 0000000..c8fcb6a
--- /dev/null
+++ b/src/tspi/tspi_delegate.c
@@ -0,0 +1,470 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2007
+ *
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "trousers/tss.h"
+#include "trousers/trousers.h"
+#include "trousers_types.h"
+#include "spi_utils.h"
+#include "obj.h"
+#include "tsp_delegate.h"
+#include "tsplog.h"
+
+
+TSS_RESULT
+Tspi_TPM_Delegate_AddFamily(TSS_HTPM hTpm, /* in, must not be NULL */
+ BYTE bLabel, /* in */
+ TSS_HDELFAMILY* phFamily) /* out */
+{
+ TPM_FAMILY_ID familyID = 0;
+ UINT32 outDataSize;
+ BYTE *outData = NULL;
+ UINT64 offset;
+ TSS_RESULT result;
+
+ if (phFamily == NULL)
+ return TSPERR(TSS_E_BAD_PARAMETER);
+ *phFamily = NULL_HDELFAMILY;
+
+ if ((result = do_delegate_manage(hTpm, familyID, TPM_FAMILY_CREATE, sizeof(bLabel), &bLabel,
+ &outDataSize, &outData)))
+ return result;
+
+ offset = 0;
+ Trspi_UnloadBlob_UINT32(&offset, &familyID, outData);
+
+ /* Create or update the delfamily object */
+ if ((result = update_delfamily_object(hTpm, familyID)))
+ goto done;
+
+ obj_delfamily_find_by_familyid(hTpm, familyID, phFamily);
+ if (*phFamily == NULL_HDELFAMILY)
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+
+done:
+ free(outData);
+
+ return result;
+}
+
+TSS_RESULT
+Tspi_TPM_Delegate_GetFamily(TSS_HTPM hTpm, /* in, must not NULL */
+ UINT32 ulFamilyID, /* in */
+ TSS_HDELFAMILY* phFamily) /* out */
+{
+ TSS_RESULT result;
+
+ if (phFamily == NULL)
+ return TSPERR(TSS_E_BAD_PARAMETER);
+ *phFamily = NULL_HDELFAMILY;
+
+ /* Update the delfamily object */
+ if ((result = update_delfamily_object(hTpm, ulFamilyID)))
+ return result;
+
+ obj_delfamily_find_by_familyid(hTpm, ulFamilyID, phFamily);
+ if (*phFamily == NULL_HDELFAMILY)
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+
+ return result;
+}
+
+TSS_RESULT
+Tspi_TPM_Delegate_InvalidateFamily(TSS_HTPM hTpm, /* in, must not be NULL */
+ TSS_HDELFAMILY hFamily) /* in */
+{
+ TPM_FAMILY_ID familyID;
+ UINT32 outDataSize;
+ BYTE *outData = NULL;
+ TSS_RESULT result;
+
+ if ((result = obj_delfamily_get_familyid(hFamily, &familyID)))
+ return result;
+
+ if ((result = do_delegate_manage(hTpm, familyID, TPM_FAMILY_INVALIDATE, 0, NULL,
+ &outDataSize, &outData)))
+ return result;
+
+ /* Delete the delfamily object */
+ result = obj_delfamily_remove(hFamily, hTpm);
+
+ free(outData);
+
+ return result;
+}
+
+TSS_RESULT
+Tspi_TPM_Delegate_CreateDelegation(TSS_HOBJECT hObject, /* in */
+ BYTE bLabel, /* in */
+ UINT32 ulFlags, /* in */
+ TSS_HPCRS hPcrs, /* in */
+ TSS_HDELFAMILY hFamily, /* in */
+ TSS_HPOLICY hDelegation) /* in, out */
+{
+ TSS_RESULT result;
+
+ if (obj_is_tpm(hObject)) {
+ if ((result = create_owner_delegation(hObject, bLabel, ulFlags, hPcrs, hFamily,
+ hDelegation)))
+ return result;
+ } else if (obj_is_rsakey(hObject)) {
+ if ((result = create_key_delegation(hObject, bLabel, ulFlags, hPcrs, hFamily,
+ hDelegation)))
+ return result;
+ } else
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+Tspi_TPM_Delegate_CacheOwnerDelegation(TSS_HTPM hTpm, /* in */
+ TSS_HPOLICY hDelegation, /* in */
+ UINT32 ulIndex, /* in */
+ UINT32 ulFlags) /* in */
+{
+ TSS_HCONTEXT hContext;
+ TSS_HPOLICY hPolicy;
+ UINT32 blobSize;
+ BYTE *blob = NULL;
+ UINT32 secretMode = TSS_SECRET_MODE_NONE;
+ Trspi_HashCtx hashCtx;
+ TCPA_DIGEST digest;
+ TPM_AUTH ownerAuth, *pAuth;
+ TSS_RESULT result;
+
+ if ((result = obj_tpm_get_tsp_context(hTpm, &hContext)))
+ return result;
+
+ if ((result = obj_tpm_get_policy(hTpm, TSS_POLICY_USAGE, &hPolicy)))
+ return result;
+
+ if ((result = obj_policy_get_delegation_blob(hDelegation, TSS_DELEGATIONTYPE_OWNER,
+ &blobSize, &blob)))
+ return result;
+
+ if (ulFlags & ~TSS_DELEGATE_CACHEOWNERDELEGATION_OVERWRITEEXISTING) {
+ result = TSPERR(TSS_E_BAD_PARAMETER);
+ goto done;
+ }
+
+ if ((ulFlags & TSS_DELEGATE_CACHEOWNERDELEGATION_OVERWRITEEXISTING) == 0) {
+ TPM_DELEGATE_PUBLIC public;
+
+ /* Verify there is nothing occupying the specified row */
+ result = get_delegate_index(hContext, ulIndex, &public);
+ if (result == TSS_SUCCESS) {
+ free(public.pcrInfo.pcrSelection.pcrSelect);
+ result = TSPERR(TSS_E_DELFAMILY_ROWEXISTS);
+ goto done;
+ }
+ }
+
+ if (hPolicy != NULL_HPOLICY) {
+ if ((result = obj_policy_get_mode(hPolicy, &secretMode)))
+ goto done;
+ }
+
+ if (secretMode != TSS_SECRET_MODE_NONE) {
+ result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
+ result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_LoadOwnerDelegation);
+ result |= Trspi_Hash_UINT32(&hashCtx, ulIndex);
+ result |= Trspi_Hash_UINT32(&hashCtx, blobSize);
+ result |= Trspi_HashUpdate(&hashCtx, blobSize, blob);
+ if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
+ goto done;
+
+ pAuth = &ownerAuth;
+ if ((result = secret_PerformAuth_OIAP(hTpm, TPM_ORD_Delegate_LoadOwnerDelegation,
+ hPolicy, FALSE, &digest, pAuth)))
+ goto done;
+ } else
+ pAuth = NULL;
+
+ if ((result = TCS_API(hContext)->Delegate_LoadOwnerDelegation(hContext, ulIndex, blobSize,
+ blob, pAuth)))
+ goto done;
+
+ if (pAuth) {
+ result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
+ result |= Trspi_Hash_UINT32(&hashCtx, result);
+ result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_LoadOwnerDelegation);
+ if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
+ goto done;
+
+ if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth)))
+ goto done;
+ }
+
+ result = obj_policy_set_delegation_index(hDelegation, ulIndex);
+
+done:
+ free_tspi(hContext, blob);
+
+ return result;
+}
+
+TSS_RESULT
+Tspi_TPM_Delegate_UpdateVerificationCount(TSS_HTPM hTpm, /* in */
+ TSS_HPOLICY hDelegation) /* in, out */
+{
+ TSS_HCONTEXT hContext;
+ TSS_HPOLICY hPolicy;
+ UINT32 secretMode = TSS_SECRET_MODE_NONE;
+ Trspi_HashCtx hashCtx;
+ TCPA_DIGEST digest;
+ TPM_AUTH ownerAuth, *pAuth;
+ TSS_BOOL indexSet;
+ UINT32 inputSize;
+ BYTE *input = NULL;
+ UINT32 outputSize;
+ BYTE *output = NULL;
+ UINT64 offset;
+ TSS_RESULT result;
+
+ if ((result = obj_tpm_get_tsp_context(hTpm, &hContext)))
+ return result;
+
+ if ((result = obj_tpm_get_policy(hTpm, TSS_POLICY_USAGE, &hPolicy)))
+ return result;
+
+ if (hPolicy != NULL_HPOLICY) {
+ if ((result = obj_policy_get_mode(hPolicy, &secretMode)))
+ goto done;
+ }
+
+ if ((result = obj_policy_is_delegation_index_set(hDelegation, &indexSet)))
+ return result;
+ if (indexSet) {
+ UINT32 index;
+
+ if ((result = obj_policy_get_delegation_index(hDelegation, &index)))
+ return result;
+ inputSize = sizeof(UINT32);
+ input = calloc_tspi(hContext, inputSize);
+ if (!input) {
+ LogError("malloc of %zd bytes failed.", sizeof(UINT32));
+ return TSPERR(TSS_E_OUTOFMEMORY);
+ }
+ offset = 0;
+ Trspi_LoadBlob_UINT32(&offset, index, input);
+ } else {
+ if ((result = obj_policy_get_delegation_blob(hDelegation, 0,
+ &inputSize, &input)))
+ return result;
+ }
+
+ if (secretMode != TSS_SECRET_MODE_NONE) {
+ result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
+ result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_UpdateVerification);
+ result |= Trspi_Hash_UINT32(&hashCtx, inputSize);
+ result |= Trspi_HashUpdate(&hashCtx, inputSize, input);
+ if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
+ goto done;
+
+ pAuth = &ownerAuth;
+ if ((result = secret_PerformAuth_OIAP(hTpm, TPM_ORD_Delegate_UpdateVerification,
+ hPolicy, FALSE, &digest, pAuth)))
+ goto done;
+ } else
+ pAuth = NULL;
+
+ if ((result = TCS_API(hContext)->Delegate_UpdateVerificationCount(hContext, inputSize,
+ input, pAuth, &outputSize,
+ &output)))
+ goto done;
+
+ if (pAuth) {
+ result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
+ result |= Trspi_Hash_UINT32(&hashCtx, result);
+ result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_UpdateVerification);
+ result |= Trspi_Hash_UINT32(&hashCtx, outputSize);
+ result |= Trspi_HashUpdate(&hashCtx, outputSize, output);
+ if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
+ goto done;
+
+ if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth)))
+ goto done;
+ }
+
+ result = obj_policy_set_delegation_blob(hDelegation, 0, outputSize, output);
+
+done:
+ free_tspi(hContext, input);
+ free(output);
+
+ return result;
+}
+
+TSS_RESULT
+Tspi_TPM_Delegate_VerifyDelegation(TSS_HPOLICY hDelegation) /* in, out */
+{
+ TSS_HCONTEXT hContext;
+ UINT32 delegateSize;
+ BYTE *delegate = NULL;
+ TSS_RESULT result;
+
+ if ((result = obj_policy_get_tsp_context(hDelegation, &hContext)))
+ return result;
+
+ if ((result = obj_policy_get_delegation_blob(hDelegation, 0, &delegateSize, &delegate)))
+ return result;
+
+ result = TCS_API(hContext)->Delegate_VerifyDelegation(hContext, delegateSize, delegate);
+
+ free_tspi(hContext, delegate);
+
+ return result;
+}
+
+TSS_RESULT
+Tspi_TPM_Delegate_ReadTables(TSS_HCONTEXT hContext, /* in */
+ UINT32* pulFamilyTableSize, /* out */
+ TSS_FAMILY_TABLE_ENTRY** ppFamilyTable, /* out */
+ UINT32* pulDelegateTableSize, /* out */
+ TSS_DELEGATION_TABLE_ENTRY** ppDelegateTable) /* out */
+{
+ UINT32 tpmFamilyTableSize, tpmDelegateTableSize;
+ BYTE *tpmFamilyTable = NULL, *tpmDelegateTable = NULL;
+ TPM_FAMILY_TABLE_ENTRY tpmFamilyEntry;
+ TSS_FAMILY_TABLE_ENTRY tssFamilyEntry, *tssFamilyTable = NULL;
+ UINT32 tssFamilyTableSize = 0;
+ TPM_DELEGATE_PUBLIC tpmDelegatePublic;
+ TSS_DELEGATION_TABLE_ENTRY tssDelegateEntry, *tssDelegateTable = NULL;
+ UINT32 tssDelegateTableSize = 0;
+ UINT32 tableIndex;
+ UINT64 tpmOffset;
+ UINT64 tssOffset;
+ TSS_RESULT result;
+
+ if (!pulFamilyTableSize || !ppFamilyTable || !pulDelegateTableSize || !ppDelegateTable)
+ return TSPERR(TSS_E_BAD_PARAMETER);
+
+ if (!obj_is_context(hContext))
+ return TSPERR(TSS_E_INVALID_HANDLE);
+
+ if ((result = TCS_API(hContext)->Delegate_ReadTable(hContext, &tpmFamilyTableSize,
+ &tpmFamilyTable, &tpmDelegateTableSize,
+ &tpmDelegateTable)))
+ return result;
+
+ if (tpmFamilyTableSize > 0) {
+ /* Create the TSS_FAMILY_TABLE_ENTRY array */
+ for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmFamilyTableSize;) {
+ Trspi_UnloadBlob_TPM_FAMILY_TABLE_ENTRY(&tpmOffset, tpmFamilyTable,
+ &tpmFamilyEntry);
+
+ /* No pointers in the family table entries, so no
+ assignments required before doing LoadBlob */
+ Trspi_LoadBlob_TSS_FAMILY_TABLE_ENTRY(&tssOffset, NULL, &tssFamilyEntry);
+ }
+
+ if ((tssFamilyTable = calloc_tspi(hContext, tssOffset)) == NULL) {
+ LogError("malloc of %" PRIu64 " bytes failed.", tssOffset);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmFamilyTableSize; tssFamilyTableSize++) {
+ Trspi_UnloadBlob_TPM_FAMILY_TABLE_ENTRY(&tpmOffset, tpmFamilyTable,
+ &tpmFamilyEntry);
+
+ tssFamilyEntry.familyID = tpmFamilyEntry.familyID;
+ tssFamilyEntry.label = tpmFamilyEntry.label.label;
+ tssFamilyEntry.verificationCount = tpmFamilyEntry.verificationCount;
+ tssFamilyEntry.enabled =
+ (tpmFamilyEntry.flags & TPM_FAMFLAG_ENABLE) ? TRUE : FALSE;
+ tssFamilyEntry.locked =
+ (tpmFamilyEntry.flags & TPM_FAMFLAG_DELEGATE_ADMIN_LOCK) ? TRUE : FALSE;
+ Trspi_LoadBlob_TSS_FAMILY_TABLE_ENTRY(&tssOffset, (BYTE *)tssFamilyTable,
+ &tssFamilyEntry);
+ }
+ }
+
+ if (tpmDelegateTableSize > 0) {
+ /* Create the TSS_DELEGATION_TABLE_ENTRY array */
+ for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmDelegateTableSize;) {
+ Trspi_UnloadBlob_UINT32(&tpmOffset, &tableIndex, tpmDelegateTable);
+ if ((result = Trspi_UnloadBlob_TPM_DELEGATE_PUBLIC(&tpmOffset, tpmDelegateTable,
+ &tpmDelegatePublic))) {
+ free_tspi(hContext, tssFamilyTable);
+ goto done;
+ }
+
+ /* Some pointers in the delegate table entries, so
+ do some assignments before doing LoadBlob */
+ tssDelegateEntry.pcrInfo.sizeOfSelect =
+ tpmDelegatePublic.pcrInfo.pcrSelection.sizeOfSelect;
+ tssDelegateEntry.pcrInfo.selection =
+ tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect;
+ tssDelegateEntry.pcrInfo.sizeOfDigestAtRelease =
+ sizeof(tpmDelegatePublic.pcrInfo.digestAtRelease.digest);
+ tssDelegateEntry.pcrInfo.digestAtRelease =
+ tpmDelegatePublic.pcrInfo.digestAtRelease.digest;
+ Trspi_LoadBlob_TSS_DELEGATION_TABLE_ENTRY(&tssOffset, NULL,
+ &tssDelegateEntry);
+
+ free(tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect);
+ }
+
+ if ((tssDelegateTable = calloc_tspi(hContext, tssOffset)) == NULL) {
+ LogError("malloc of %" PRIu64 " bytes failed.", tssOffset);
+ free_tspi(hContext, tssFamilyTable);
+ result = TSPERR(TSS_E_OUTOFMEMORY);
+ goto done;
+ }
+ for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmDelegateTableSize; tssDelegateTableSize++) {
+ Trspi_UnloadBlob_UINT32(&tpmOffset, &tableIndex, tpmDelegateTable);
+ if ((result = Trspi_UnloadBlob_TPM_DELEGATE_PUBLIC(&tpmOffset,
+ tpmDelegateTable, &tpmDelegatePublic))) {
+ free_tspi(hContext, tssFamilyTable);
+ free_tspi(hContext, tssDelegateTable);
+ goto done;
+ }
+
+ tssDelegateEntry.tableIndex = tableIndex;
+ tssDelegateEntry.label = tpmDelegatePublic.label.label;
+ tssDelegateEntry.pcrInfo.sizeOfSelect =
+ tpmDelegatePublic.pcrInfo.pcrSelection.sizeOfSelect;
+ tssDelegateEntry.pcrInfo.selection =
+ tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect;
+ tssDelegateEntry.pcrInfo.localityAtRelease =
+ tpmDelegatePublic.pcrInfo.localityAtRelease;
+ tssDelegateEntry.pcrInfo.sizeOfDigestAtRelease =
+ sizeof(tpmDelegatePublic.pcrInfo.digestAtRelease.digest);
+ tssDelegateEntry.pcrInfo.digestAtRelease =
+ tpmDelegatePublic.pcrInfo.digestAtRelease.digest;
+ tssDelegateEntry.per1 = tpmDelegatePublic.permissions.per1;
+ tssDelegateEntry.per2 = tpmDelegatePublic.permissions.per2;
+ tssDelegateEntry.familyID = tpmDelegatePublic.familyID;
+ tssDelegateEntry.verificationCount = tpmDelegatePublic.verificationCount;
+ Trspi_LoadBlob_TSS_DELEGATION_TABLE_ENTRY(&tssOffset,
+ (BYTE *)tssDelegateTable, &tssDelegateEntry);
+
+ free(tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect);
+ }
+ }
+
+ *ppFamilyTable = tssFamilyTable;
+ *pulFamilyTableSize = tssFamilyTableSize;
+ *ppDelegateTable = tssDelegateTable;
+ *pulDelegateTableSize = tssDelegateTableSize;
+
+done:
+ free(tpmFamilyTable);
+ free(tpmDelegateTable);
+
+ return result;
+}
+