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