189 lines
6.8 KiB
C
189 lines
6.8 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 "PolicyNV_fp.h"
|
|
#include "Policy_spt_fp.h"
|
|
#include "NV_spt_fp.h" // Include NV support routine for read access check
|
|
//
|
|
//
|
|
// Error Returns Meaning
|
|
//
|
|
// TPM_RC_AUTH_TYPE NV index authorization type is not correct
|
|
// TPM_RC_NV_LOCKED NV index read locked
|
|
// TPM_RC_NV_UNINITIALIZED the NV index has not been initialized
|
|
// TPM_RC_POLICY the comparison to the NV contents failed
|
|
// TPM_RC_SIZE the size of nvIndex data starting at offset is less than the size of
|
|
// operandB
|
|
//
|
|
TPM_RC
|
|
TPM2_PolicyNV(
|
|
PolicyNV_In *in // IN: input parameter list
|
|
)
|
|
{
|
|
TPM_RC result;
|
|
SESSION *session;
|
|
NV_INDEX nvIndex;
|
|
BYTE nvBuffer[sizeof(in->operandB.t.buffer)];
|
|
TPM2B_NAME nvName;
|
|
TPM_CC commandCode = TPM_CC_PolicyNV;
|
|
HASH_STATE hashState;
|
|
TPM2B_DIGEST argHash;
|
|
|
|
// Input Validation
|
|
|
|
// Get NV index information
|
|
NvGetIndexInfo(in->nvIndex, &nvIndex);
|
|
|
|
// Get pointer to the session structure
|
|
session = SessionGet(in->policySession);
|
|
|
|
//If this is a trial policy, skip all validations and the operation
|
|
if(session->attributes.isTrialPolicy == CLEAR)
|
|
{
|
|
// NV Read access check. NV index should be allowed for read. A
|
|
// TPM_RC_AUTH_TYPE or TPM_RC_NV_LOCKED error may be return at this
|
|
// point
|
|
result = NvReadAccessChecks(in->authHandle, in->nvIndex);
|
|
if(result != TPM_RC_SUCCESS) return result;
|
|
|
|
// Valid NV data size should not be smaller than input operandB size
|
|
if((nvIndex.publicArea.dataSize - in->offset) < in->operandB.t.size)
|
|
return TPM_RC_SIZE + RC_PolicyNV_operandB;
|
|
|
|
// Arithmetic Comparison
|
|
|
|
// Get NV data. The size of NV data equals the input operand B size
|
|
NvGetIndexData(in->nvIndex, &nvIndex, in->offset,
|
|
in->operandB.t.size, nvBuffer);
|
|
|
|
switch(in->operation)
|
|
{
|
|
case TPM_EO_EQ:
|
|
// compare A = B
|
|
if(CryptCompare(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) != 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_NEQ:
|
|
// compare A != B
|
|
if(CryptCompare(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) == 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_SIGNED_GT:
|
|
// compare A > B signed
|
|
if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) <= 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_UNSIGNED_GT:
|
|
// compare A > B unsigned
|
|
if(CryptCompare(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) <= 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_SIGNED_LT:
|
|
// compare A < B signed
|
|
if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) >= 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_UNSIGNED_LT:
|
|
// compare A < B unsigned
|
|
if(CryptCompare(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) >= 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_SIGNED_GE:
|
|
// compare A >= B signed
|
|
if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) < 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_UNSIGNED_GE:
|
|
// compare A >= B unsigned
|
|
if(CryptCompare(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) < 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_SIGNED_LE:
|
|
// compare A <= B signed
|
|
if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) > 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_UNSIGNED_LE:
|
|
// compare A <= B unsigned
|
|
if(CryptCompare(in->operandB.t.size, nvBuffer,
|
|
in->operandB.t.size, in->operandB.t.buffer) > 0)
|
|
return TPM_RC_POLICY;
|
|
break;
|
|
case TPM_EO_BITSET:
|
|
// All bits SET in B are SET in A. ((A&B)=B)
|
|
{
|
|
UINT32 i;
|
|
for (i = 0; i < in->operandB.t.size; i++)
|
|
if((nvBuffer[i] & in->operandB.t.buffer[i])
|
|
!= in->operandB.t.buffer[i])
|
|
return TPM_RC_POLICY;
|
|
}
|
|
break;
|
|
case TPM_EO_BITCLEAR:
|
|
// All bits SET in B are CLEAR in A. ((A&B)=0)
|
|
{
|
|
UINT32 i;
|
|
for (i = 0; i < in->operandB.t.size; i++)
|
|
if((nvBuffer[i] & in->operandB.t.buffer[i]) != 0)
|
|
return TPM_RC_POLICY;
|
|
}
|
|
break;
|
|
default:
|
|
pAssert(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Internal Data Update
|
|
|
|
// Start argument hash
|
|
argHash.t.size = CryptStartHash(session->authHashAlg, &hashState);
|
|
|
|
// add operandB
|
|
CryptUpdateDigest2B(&hashState, &in->operandB.b);
|
|
|
|
// add offset
|
|
CryptUpdateDigestInt(&hashState, sizeof(UINT16), &in->offset);
|
|
|
|
// add operation
|
|
CryptUpdateDigestInt(&hashState, sizeof(TPM_EO), &in->operation);
|
|
|
|
// complete argument digest
|
|
CryptCompleteHash2B(&hashState, &argHash.b);
|
|
|
|
// Update policyDigest
|
|
// Start digest
|
|
CryptStartHash(session->authHashAlg, &hashState);
|
|
|
|
// add old digest
|
|
CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
|
|
|
|
// add commandCode
|
|
CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
|
|
|
|
// add argument digest
|
|
CryptUpdateDigest2B(&hashState, &argHash.b);
|
|
|
|
// Adding nvName
|
|
nvName.t.size = EntityGetName(in->nvIndex, &nvName.t.name);
|
|
CryptUpdateDigest2B(&hashState, &nvName.b);
|
|
|
|
// complete the digest
|
|
CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
|
|
|
|
return TPM_RC_SUCCESS;
|
|
}
|