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