174 lines
6.5 KiB
C
174 lines
6.5 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 "PolicyCounterTimer_fp.h"
|
|
#include "Policy_spt_fp.h"
|
|
//
|
|
//
|
|
// Error Returns Meaning
|
|
//
|
|
// TPM_RC_POLICY the comparison of the selected portion of the TPMS_TIME_INFO with
|
|
// operandB failed
|
|
// TPM_RC_RANGE offset + size exceed size of TPMS_TIME_INFO structure
|
|
//
|
|
TPM_RC
|
|
TPM2_PolicyCounterTimer(
|
|
PolicyCounterTimer_In *in // IN: input parameter list
|
|
)
|
|
{
|
|
TPM_RC result;
|
|
SESSION *session;
|
|
TIME_INFO infoData; // data buffer of TPMS_TIME_INFO
|
|
TPM_CC commandCode = TPM_CC_PolicyCounterTimer;
|
|
HASH_STATE hashState;
|
|
TPM2B_DIGEST argHash;
|
|
|
|
// Input Validation
|
|
|
|
// If the command is going to use any part of the counter or timer, need
|
|
// to verify that time is advancing.
|
|
// The time and clock vales are the first two 64-bit values in the clock
|
|
if(in->offset < sizeof(UINT64) + sizeof(UINT64))
|
|
{
|
|
// Using Clock or Time so see if clock is running. Clock doesn't run while
|
|
// NV is unavailable.
|
|
// TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned here.
|
|
result = NvIsAvailable();
|
|
if(result != TPM_RC_SUCCESS)
|
|
return result;
|
|
}
|
|
// 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)
|
|
{
|
|
// Get time data info. The size of time info data equals the input
|
|
// operand B size. A TPM_RC_RANGE error may be returned at this point
|
|
result = TimeGetRange(in->offset, in->operandB.t.size, &infoData);
|
|
if(result != TPM_RC_SUCCESS) return result;
|
|
|
|
// Arithmetic Comparison
|
|
switch(in->operation)
|
|
{
|
|
case TPM_EO_EQ:
|
|
// compare A = B
|
|
if(CryptCompare(in->operandB.t.size, infoData,
|
|
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, infoData,
|
|
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, infoData,
|
|
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, infoData,
|
|
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, infoData,
|
|
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, infoData,
|
|
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, infoData,
|
|
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, infoData,
|
|
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, infoData,
|
|
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, infoData,
|
|
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( (infoData[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((infoData[i] & in->operandB.t.buffer[i]) != 0)
|
|
return TPM_RC_POLICY;
|
|
}
|
|
break;
|
|
default:
|
|
pAssert(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Internal Data Update
|
|
|
|
// Start argument list 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 hash
|
|
CryptCompleteHash2B(&hashState, &argHash.b);
|
|
|
|
// update policyDigest
|
|
// start hash
|
|
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);
|
|
|
|
// complete the digest
|
|
CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
|
|
|
|
return TPM_RC_SUCCESS;
|
|
}
|