summaryrefslogtreecommitdiffstats
path: root/src/tpm2/Entity.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tpm2/Entity.c507
1 files changed, 507 insertions, 0 deletions
diff --git a/src/tpm2/Entity.c b/src/tpm2/Entity.c
new file mode 100644
index 0000000..6940262
--- /dev/null
+++ b/src/tpm2/Entity.c
@@ -0,0 +1,507 @@
+/********************************************************************************/
+/* */
+/* Accessing properties for handles of various types */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: Entity.c 1594 2020-03-26 22:15:48Z kgoldman $ */
+/* */
+/* Licenses and Notices */
+/* */
+/* 1. Copyright Licenses: */
+/* */
+/* - Trusted Computing Group (TCG) grants to the user of the source code in */
+/* this specification (the "Source Code") a worldwide, irrevocable, */
+/* nonexclusive, royalty free, copyright license to reproduce, create */
+/* derivative works, distribute, display and perform the Source Code and */
+/* derivative works thereof, and to grant others the rights granted herein. */
+/* */
+/* - The TCG grants to the user of the other parts of the specification */
+/* (other than the Source Code) the rights to reproduce, distribute, */
+/* display, and perform the specification solely for the purpose of */
+/* developing products based on such documents. */
+/* */
+/* 2. Source Code Distribution Conditions: */
+/* */
+/* - Redistributions of Source Code must retain the above copyright licenses, */
+/* this list of conditions and the following disclaimers. */
+/* */
+/* - Redistributions in binary form must reproduce the above copyright */
+/* licenses, this list of conditions and the following disclaimers in the */
+/* documentation and/or other materials provided with the distribution. */
+/* */
+/* 3. Disclaimers: */
+/* */
+/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
+/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
+/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
+/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
+/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
+/* information on specification licensing rights available through TCG */
+/* membership agreements. */
+/* */
+/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
+/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
+/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
+/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
+/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
+/* */
+/* - Without limitation, TCG and its members and licensors disclaim all */
+/* liability, including liability for infringement of any proprietary */
+/* rights, relating to use of information in this specification and to the */
+/* implementation of this specification, and TCG disclaims all liability for */
+/* cost of procurement of substitute goods or services, lost profits, loss */
+/* of use, loss of data or any incidental, consequential, direct, indirect, */
+/* or special damages, whether under contract, tort, warranty or otherwise, */
+/* arising in any way out of use or reliance upon this specification or any */
+/* information herein. */
+/* */
+/* (c) Copyright IBM Corp. and others, 2016 - 2020 */
+/* */
+/********************************************************************************/
+
+/* 9.4 Entity.c */
+/* 9.4.1 Description */
+/* The functions in this file are used for accessing properties for handles of various
+ types. Functions in other files require handles of a specific type but the functions in this file
+ allow use of any handle type. */
+/* 9.4.2 Includes */
+#include "Tpm.h"
+/* 9.4.3 Functions */
+/* 9.4.3.1 EntityGetLoadStatus() */
+/* This function will check that all the handles access loaded entities. */
+/* Error Returns Meaning */
+/* TPM_RC_HANDLE handle type does not match */
+/* TPM_RC_REFERENCE_Hx() entity is not present */
+/* TPM_RC_HIERARCHY entity belongs to a disabled hierarchy */
+/* TPM_RC_OBJECT_MEMORY handle is an evict object but there is no space to load it to RAM */
+TPM_RC
+EntityGetLoadStatus(
+ COMMAND *command // IN/OUT: command parsing structure
+ )
+{
+ UINT32 i;
+ TPM_RC result = TPM_RC_SUCCESS;
+ //
+ for(i = 0; i < command->handleNum; i++)
+ {
+ TPM_HANDLE handle = command->handles[i];
+ switch(HandleGetType(handle))
+ {
+ // For handles associated with hierarchies, the entity is present
+ // only if the associated enable is SET.
+ case TPM_HT_PERMANENT:
+ switch(handle)
+ {
+ case TPM_RH_OWNER:
+ if(!gc.shEnable)
+ result = TPM_RC_HIERARCHY;
+ break;
+#ifdef VENDOR_PERMANENT
+ case VENDOR_PERMANENT:
+#endif
+ case TPM_RH_ENDORSEMENT:
+ if(!gc.ehEnable)
+ result = TPM_RC_HIERARCHY;
+ break;
+ case TPM_RH_PLATFORM:
+ if(!g_phEnable)
+ result = TPM_RC_HIERARCHY;
+ break;
+ // null handle, PW session handle and lockout
+ // handle are always available
+ case TPM_RH_NULL:
+ case TPM_RS_PW:
+ // Need to be careful for lockout. Lockout is always available
+ // for policy checks but not always available when authValue
+ // is being checked.
+ case TPM_RH_LOCKOUT:
+ // Rather than have #ifdefs all over the code,
+ // CASE_ACT_HANDLE is defined in ACT.h. It is 'case TPM_RH_ACT_x:'
+ // FOR_EACH_ACT(CASE_ACT_HANDLE) creates a simple
+ // case TPM_RH_ACT_x: // for each of the implemented ACT.
+ FOR_EACH_ACT(CASE_ACT_HANDLE)
+ break;
+
+ default:
+ // If the implementation has a manufacturer-specific value
+ // then test for it here. Since this implementation does
+ // not have any, this implementation returns the same failure
+ // that unmarshaling of a bad handle would produce.
+ if(((TPM_RH)handle >= TPM_RH_AUTH_00)
+ && ((TPM_RH)handle <= TPM_RH_AUTH_FF))
+ // if the implementation has a manufacturer-specific value
+ result = TPM_RC_VALUE;
+ else
+ // The handle is in the range of reserved handles but is
+ // not implemented in this TPM.
+ result = TPM_RC_VALUE;
+ break;
+ }
+ break;
+ case TPM_HT_TRANSIENT:
+ // For a transient object, check if the handle is associated
+ // with a loaded object.
+ if(!IsObjectPresent(handle))
+ result = TPM_RC_REFERENCE_H0;
+ break;
+ case TPM_HT_PERSISTENT:
+ // Persistent object
+ // Copy the persistent object to RAM and replace the handle with the
+ // handle of the assigned slot. A TPM_RC_OBJECT_MEMORY,
+ // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by
+ // ObjectLoadEvict()
+ result = ObjectLoadEvict(&command->handles[i], command->index);
+ break;
+ case TPM_HT_HMAC_SESSION:
+ // For an HMAC session, see if the session is loaded
+ // and if the session in the session slot is actually
+ // an HMAC session.
+ if(SessionIsLoaded(handle))
+ {
+ SESSION *session;
+ session = SessionGet(handle);
+ // Check if the session is a HMAC session
+ if(session->attributes.isPolicy == SET)
+ result = TPM_RC_HANDLE;
+ }
+ else
+ result = TPM_RC_REFERENCE_H0;
+ break;
+ case TPM_HT_POLICY_SESSION:
+ // For a policy session, see if the session is loaded
+ // and if the session in the session slot is actually
+ // a policy session.
+ if(SessionIsLoaded(handle))
+ {
+ SESSION *session;
+ session = SessionGet(handle);
+ // Check if the session is a policy session
+ if(session->attributes.isPolicy == CLEAR)
+ result = TPM_RC_HANDLE;
+ }
+ else
+ result = TPM_RC_REFERENCE_H0;
+ break;
+ case TPM_HT_NV_INDEX:
+ // For an NV Index, use the TPM-specific routine
+ // to search the IN Index space.
+ result = NvIndexIsAccessible(handle);
+ break;
+ case TPM_HT_PCR:
+ // Any PCR handle that is unmarshaled successfully referenced
+ // a PCR that is defined.
+ break;
+#if CC_AC_Send
+ case TPM_HT_AC:
+ // Use the TPM-specific routine to search for the AC
+ result = AcIsAccessible(handle);
+ break;
+#endif
+ default:
+ // Any other handle type is a defect in the unmarshaling code.
+ FAIL(FATAL_ERROR_INTERNAL);
+ break;
+ }
+ if(result != TPM_RC_SUCCESS)
+ {
+ if(result == TPM_RC_REFERENCE_H0)
+ result = result + i;
+ else
+ result = RcSafeAddToResult(result, TPM_RC_H + g_rcIndex[i]);
+ break;
+ }
+ }
+ return result;
+}
+/* 9.4.3.2 EntityGetAuthValue() */
+/* This function is used to access the authValue associated with a handle. This function assumes
+ that the handle references an entity that is accessible and the handle is not for a persistent
+ objects. That is EntityGetLoadStatus() should have been called. Also, the accessibility of the
+ authValue should have been verified by IsAuthValueAvailable(). */
+/* This function copies the authorization value of the entity to auth. */
+/* Return Values Meaning */
+/* count number of bytes in the authValue with zeros stripped */
+UINT16
+EntityGetAuthValue(
+ TPMI_DH_ENTITY handle, // IN: handle of entity
+ TPM2B_AUTH *auth // OUT: authValue of the entity
+ )
+{
+ TPM2B_AUTH *pAuth = NULL;
+ auth->t.size = 0;
+ switch(HandleGetType(handle))
+ {
+ case TPM_HT_PERMANENT:
+ {
+ switch(handle)
+ {
+ case TPM_RH_OWNER:
+ // ownerAuth for TPM_RH_OWNER
+ pAuth = &gp.ownerAuth;
+ break;
+ case TPM_RH_ENDORSEMENT:
+ // endorsementAuth for TPM_RH_ENDORSEMENT
+ pAuth = &gp.endorsementAuth;
+ break;
+ // The ACT use platformAuth for auth
+ FOR_EACH_ACT(CASE_ACT_HANDLE)
+ case TPM_RH_PLATFORM:
+ // platformAuth for TPM_RH_PLATFORM
+ pAuth = &gc.platformAuth;
+ break;
+ case TPM_RH_LOCKOUT:
+ // lockoutAuth for TPM_RH_LOCKOUT
+ pAuth = &gp.lockoutAuth;
+ break;
+ case TPM_RH_NULL:
+ // nullAuth for TPM_RH_NULL. Return 0 directly here
+ return 0;
+ break;
+#ifdef VENDOR_PERMANENT
+ case VENDOR_PERMANENT:
+ // vendor authorization value
+ pAuth = &g_platformUniqueDetails;
+#endif
+ default:
+ // If any other permanent handle is present it is
+ // a code defect.
+ FAIL(FATAL_ERROR_INTERNAL);
+ break;
+ }
+ break;
+ }
+ case TPM_HT_TRANSIENT:
+ // authValue for an object
+ // A persistent object would have been copied into RAM
+ // and would have an transient object handle here.
+ {
+ OBJECT *object;
+ object = HandleToObject(handle);
+ // special handling if this is a sequence object
+ if(ObjectIsSequence(object))
+ {
+ pAuth = &((HASH_OBJECT *)object)->auth;
+ }
+ else
+ {
+ // Authorization is available only when the private portion of
+ // the object is loaded. The check should be made before
+ // this function is called
+ pAssert(object->attributes.publicOnly == CLEAR);
+ pAuth = &object->sensitive.authValue;
+ }
+ }
+ break;
+ case TPM_HT_NV_INDEX:
+ // authValue for an NV index
+ {
+ NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
+ pAssert(nvIndex != NULL);
+ pAuth = &nvIndex->authValue;
+ }
+ break;
+ case TPM_HT_PCR:
+ // authValue for PCR
+ pAuth = PCRGetAuthValue(handle);
+ break;
+ default:
+ // If any other handle type is present here, then there is a defect
+ // in the unmarshaling code.
+ FAIL(FATAL_ERROR_INTERNAL);
+ break;
+ }
+ // Copy the authValue
+ MemoryCopy2B((TPM2B *)auth, (TPM2B *)pAuth, sizeof(auth->t.buffer));
+ MemoryRemoveTrailingZeros(auth);
+ return auth->t.size;
+}
+/* 9.4.3.3 EntityGetAuthPolicy() */
+/* This function is used to access the authPolicy associated with a handle. This function assumes
+ that the handle references an entity that is accessible and the handle is not for a persistent
+ objects. That is EntityGetLoadStatus() should have been called. Also, the accessibility of the
+ authPolicy should have been verified by IsAuthPolicyAvailable(). */
+/* This function copies the authorization policy of the entity to authPolicy. */
+/* The return value is the hash algorithm for the policy. */
+TPMI_ALG_HASH
+EntityGetAuthPolicy(
+ TPMI_DH_ENTITY handle, // IN: handle of entity
+ TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity
+ )
+{
+ TPMI_ALG_HASH hashAlg = TPM_ALG_NULL;
+ authPolicy->t.size = 0;
+ switch(HandleGetType(handle))
+ {
+ case TPM_HT_PERMANENT:
+ switch(handle)
+ {
+ case TPM_RH_OWNER:
+ // ownerPolicy for TPM_RH_OWNER
+ *authPolicy = gp.ownerPolicy;
+ hashAlg = gp.ownerAlg;
+ break;
+ case TPM_RH_ENDORSEMENT:
+ // endorsementPolicy for TPM_RH_ENDORSEMENT
+ *authPolicy = gp.endorsementPolicy;
+ hashAlg = gp.endorsementAlg;
+ break;
+ case TPM_RH_PLATFORM:
+ // platformPolicy for TPM_RH_PLATFORM
+ *authPolicy = gc.platformPolicy;
+ hashAlg = gc.platformAlg;
+ break;
+ case TPM_RH_LOCKOUT:
+ // lockoutPolicy for TPM_RH_LOCKOUT
+ *authPolicy = gp.lockoutPolicy;
+ hashAlg = gp.lockoutAlg;
+ break;
+
+#define ACT_GET_POLICY(N) \
+ case TPM_RH_ACT_##N: \
+ *authPolicy = go.ACT_##N.authPolicy; \
+ hashAlg = go.ACT_##N.hashAlg; \
+ break;
+ // Get the policy for each implemented ACT
+ FOR_EACH_ACT(ACT_GET_POLICY)
+ default:
+ hashAlg = TPM_ALG_ERROR;
+ break;
+ }
+ break;
+ case TPM_HT_TRANSIENT:
+ // authPolicy for an object
+ {
+ OBJECT *object = HandleToObject(handle);
+ *authPolicy = object->publicArea.authPolicy;
+ hashAlg = object->publicArea.nameAlg;
+ }
+ break;
+ case TPM_HT_NV_INDEX:
+ // authPolicy for a NV index
+ {
+ NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
+ pAssert(nvIndex != 0);
+ *authPolicy = nvIndex->publicArea.authPolicy;
+ hashAlg = nvIndex->publicArea.nameAlg;
+ }
+ break;
+ case TPM_HT_PCR:
+ // authPolicy for a PCR
+ hashAlg = PCRGetAuthPolicy(handle, authPolicy);
+ break;
+ default:
+ // If any other handle type is present it is a code defect.
+ FAIL(FATAL_ERROR_INTERNAL);
+ break;
+ }
+ return hashAlg;
+}
+/* 9.4.3.4 EntityGetName() */
+/* This function returns the Name associated with a handle. */
+TPM2B_NAME *
+EntityGetName(
+ TPMI_DH_ENTITY handle, // IN: handle of entity
+ TPM2B_NAME *name // OUT: name of entity
+ )
+{
+ switch(HandleGetType(handle))
+ {
+ case TPM_HT_TRANSIENT:
+ {
+ // Name for an object
+ OBJECT *object = HandleToObject(handle);
+ // an object with no nameAlg has no name
+ if(object->publicArea.nameAlg == TPM_ALG_NULL)
+ name->b.size = 0;
+ else
+ *name = object->name;
+ break;
+ }
+ case TPM_HT_NV_INDEX:
+ // Name for a NV index
+ NvGetNameByIndexHandle(handle, name);
+ break;
+ default:
+ // For all other types, the handle is the Name
+ name->t.size = sizeof(TPM_HANDLE);
+ UINT32_TO_BYTE_ARRAY(handle, name->t.name);
+ break;
+ }
+ return name;
+}
+/* 9.4.3.5 EntityGetHierarchy() */
+/* This function returns the hierarchy handle associated with an entity. */
+/* a) A handle that is a hierarchy handle is associated with itself. */
+/* b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, is SET, otherwise it belongs
+ to TPM_RH_OWNER */
+/* c) An object handle belongs to its hierarchy. All other handles belong to the platform
+ hierarchy. or an NV Index. */
+TPMI_RH_HIERARCHY
+EntityGetHierarchy(
+ TPMI_DH_ENTITY handle // IN :handle of entity
+ )
+{
+ TPMI_RH_HIERARCHY hierarchy = TPM_RH_NULL;
+ switch(HandleGetType(handle))
+ {
+ case TPM_HT_PERMANENT:
+ // hierarchy for a permanent handle
+ switch(handle)
+ {
+ case TPM_RH_PLATFORM:
+ case TPM_RH_ENDORSEMENT:
+ case TPM_RH_NULL:
+ hierarchy = handle;
+ break;
+ // all other permanent handles are associated with the owner
+ // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT)
+ default:
+ hierarchy = TPM_RH_OWNER;
+ break;
+ }
+ break;
+ case TPM_HT_NV_INDEX:
+ // hierarchy for NV index
+ {
+ NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
+ pAssert(nvIndex != NULL);
+ // If only the platform can delete the index, then it is
+ // considered to be in the platform hierarchy, otherwise it
+ // is in the owner hierarchy.
+ if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV,
+ PLATFORMCREATE))
+ hierarchy = TPM_RH_PLATFORM;
+ else
+ hierarchy = TPM_RH_OWNER;
+ }
+ break;
+ case TPM_HT_TRANSIENT:
+ // hierarchy for an object
+ {
+ OBJECT *object;
+ object = HandleToObject(handle);
+ if(object->attributes.ppsHierarchy)
+ {
+ hierarchy = TPM_RH_PLATFORM;
+ }
+ else if(object->attributes.epsHierarchy)
+ {
+ hierarchy = TPM_RH_ENDORSEMENT;
+ }
+ else if(object->attributes.spsHierarchy)
+ {
+ hierarchy = TPM_RH_OWNER;
+ }
+ }
+ break;
+ case TPM_HT_PCR:
+ hierarchy = TPM_RH_OWNER;
+ break;
+ default:
+ FAIL(FATAL_ERROR_INTERNAL);
+ break;
+ }
+ // this is unreachable but it provides a return value for the default
+ // case which makes the compiler happy
+ return hierarchy;
+}