// 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; }