161 lines
6.1 KiB
C
161 lines
6.1 KiB
C
// This file was extracted from the TCG Published
|
|
// Trusted Platform Module Library
|
|
// Part 3: Commands
|
|
// Family "2.0"
|
|
// Level 00 Revision 01.16
|
|
// October 30, 2014
|
|
|
|
#include "InternalRoutines.h"
|
|
#include "NV_DefineSpace_fp.h"
|
|
//
|
|
//
|
|
// Error Returns Meaning
|
|
//
|
|
// TPM_RC_NV_ATTRIBUTES attributes of the index are not consistent
|
|
// TPM_RC_NV_DEFINED index already exists
|
|
// TPM_RC_HIERARCHY for authorizations using TPM_RH_PLATFORM phEnable_NV is
|
|
// clear.
|
|
// TPM_RC_NV_SPACE Insufficient space for the index
|
|
// TPM_RC_SIZE 'auth->size' or 'publicInfo->authPolicy.size' is larger than the digest
|
|
// size of 'publicInfo->nameAlg', or 'publicInfo->dataSize' is not
|
|
// consistent with 'publicInfo->attributes'.
|
|
//
|
|
TPM_RC
|
|
TPM2_NV_DefineSpace(
|
|
NV_DefineSpace_In *in // IN: input parameter list
|
|
)
|
|
{
|
|
TPM_RC result;
|
|
TPMA_NV attributes;
|
|
UINT16 nameSize;
|
|
|
|
nameSize = CryptGetHashDigestSize(in->publicInfo.t.nvPublic.nameAlg);
|
|
|
|
// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
|
|
// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
|
|
result = NvIsAvailable();
|
|
if(result != TPM_RC_SUCCESS)
|
|
return result;
|
|
|
|
// Input Validation
|
|
// If an index is being created by the owner and shEnable is
|
|
// clear, then we would not reach this point because ownerAuth
|
|
// can't be given when shEnable is CLEAR. However, if phEnable
|
|
// is SET but phEnableNV is CLEAR, we have to check here
|
|
if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR)
|
|
return TPM_RC_HIERARCHY + RC_NV_DefineSpace_authHandle;
|
|
|
|
attributes = in->publicInfo.t.nvPublic.attributes;
|
|
|
|
//TPMS_NV_PUBLIC validation.
|
|
// Counters and bit fields must have a size of 8
|
|
if ( (attributes.TPMA_NV_COUNTER == SET || attributes.TPMA_NV_BITS == SET)
|
|
&& (in->publicInfo.t.nvPublic.dataSize != 8))
|
|
return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
|
|
|
|
// check that the authPolicy consistent with hash algorithm
|
|
if( in->publicInfo.t.nvPublic.authPolicy.t.size != 0
|
|
&& in->publicInfo.t.nvPublic.authPolicy.t.size != nameSize)
|
|
return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
|
|
|
|
// make sure that the authValue is not too large
|
|
MemoryRemoveTrailingZeros(&in->auth);
|
|
if(in->auth.t.size > nameSize)
|
|
return TPM_RC_SIZE + RC_NV_DefineSpace_auth;
|
|
|
|
//TPMA_NV validation.
|
|
// Locks may not be SET and written cannot be SET
|
|
if( attributes.TPMA_NV_WRITTEN == SET
|
|
|| attributes.TPMA_NV_WRITELOCKED == SET
|
|
|| attributes.TPMA_NV_READLOCKED == SET)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
|
|
// There must be a way to read the index
|
|
if( attributes.TPMA_NV_OWNERREAD == CLEAR
|
|
&& attributes.TPMA_NV_PPREAD == CLEAR
|
|
&& attributes.TPMA_NV_AUTHREAD == CLEAR
|
|
&& attributes.TPMA_NV_POLICYREAD == CLEAR)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
|
|
// There must be a way to write the index
|
|
if( attributes.TPMA_NV_OWNERWRITE == CLEAR
|
|
&& attributes.TPMA_NV_PPWRITE == CLEAR
|
|
&& attributes.TPMA_NV_AUTHWRITE == CLEAR
|
|
&& attributes.TPMA_NV_POLICYWRITE == CLEAR)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
|
|
// Make sure that no attribute is used that is not supported by the proper
|
|
// command
|
|
#if CC_NV_Increment == NO
|
|
if( attributes.TPMA_NV_COUNTER == SET)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
#endif
|
|
#if CC_NV_SetBits == NO
|
|
if( attributes.TPMA_NV_BITS == SET)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
#endif
|
|
#if CC_NV_Extend == NO
|
|
if( attributes.TPMA_NV_EXTEND == SET)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
#endif
|
|
#if CC_NV_UndefineSpaceSpecial == NO
|
|
if( attributes.TPMA_NV_POLICY_DELETE == SET)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
#endif
|
|
|
|
// Can be COUNTER or BITS or EXTEND but not more than one
|
|
if( attributes.TPMA_NV_COUNTER == SET
|
|
&& attributes.TPMA_NV_BITS == SET)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
if( attributes.TPMA_NV_COUNTER == SET
|
|
&& attributes.TPMA_NV_EXTEND == SET)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
if( attributes.TPMA_NV_BITS == SET
|
|
&& attributes.TPMA_NV_EXTEND == SET)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
|
|
// An index with TPMA_NV_CLEAR_STCLEAR can't be a counter and can't have
|
|
// TPMA_NV_WRITEDEFINE SET
|
|
if( attributes.TPMA_NV_CLEAR_STCLEAR == SET
|
|
&& ( attributes.TPMA_NV_COUNTER == SET
|
|
|| attributes.TPMA_NV_WRITEDEFINE == SET)
|
|
)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
|
|
// Make sure that the creator of the index can delete the index
|
|
if( ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == SET
|
|
&& in->authHandle == TPM_RH_OWNER
|
|
)
|
|
|| ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == CLEAR
|
|
&& in->authHandle == TPM_RH_PLATFORM
|
|
)
|
|
)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle;
|
|
|
|
// If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by
|
|
// the platform
|
|
if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE == SET
|
|
&& TPM_RH_PLATFORM != in->authHandle
|
|
)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
|
|
// If the NV index is used as a PCR, the data size must match the digest
|
|
// size
|
|
if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_EXTEND == SET
|
|
&& in->publicInfo.t.nvPublic.dataSize != nameSize
|
|
)
|
|
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
|
|
|
|
// See if the index is already defined.
|
|
if(NvIsUndefinedIndex(in->publicInfo.t.nvPublic.nvIndex))
|
|
return TPM_RC_NV_DEFINED;
|
|
|
|
// Internal Data Update
|
|
// define the space. A TPM_RC_NV_SPACE error may be returned at this point
|
|
result = NvDefineIndex(&in->publicInfo.t.nvPublic, &in->auth);
|
|
if(result != TPM_RC_SUCCESS)
|
|
return result;
|
|
|
|
return TPM_RC_SUCCESS;
|
|
|
|
}
|