diff options
Diffstat (limited to '')
-rw-r--r-- | src/tpm2/Entity.c | 507 |
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; +} |