1// This file was extracted from the TCG Published 2// Trusted Platform Module Library 3// Part 3: Commands 4// Family "2.0" 5// Level 00 Revision 01.16 6// October 30, 2014 7 8#include "InternalRoutines.h" 9#include "PolicyNV_fp.h" 10#include "Policy_spt_fp.h" 11#include "NV_spt_fp.h" // Include NV support routine for read access check 12// 13// 14// Error Returns Meaning 15// 16// TPM_RC_AUTH_TYPE NV index authorization type is not correct 17// TPM_RC_NV_LOCKED NV index read locked 18// TPM_RC_NV_UNINITIALIZED the NV index has not been initialized 19// TPM_RC_POLICY the comparison to the NV contents failed 20// TPM_RC_SIZE the size of nvIndex data starting at offset is less than the size of 21// operandB 22// 23TPM_RC 24TPM2_PolicyNV( 25 PolicyNV_In *in // IN: input parameter list 26 ) 27{ 28 TPM_RC result; 29 SESSION *session; 30 NV_INDEX nvIndex; 31 BYTE nvBuffer[sizeof(in->operandB.t.buffer)]; 32 TPM2B_NAME nvName; 33 TPM_CC commandCode = TPM_CC_PolicyNV; 34 HASH_STATE hashState; 35 TPM2B_DIGEST argHash; 36 37// Input Validation 38 39 // Get NV index information 40 NvGetIndexInfo(in->nvIndex, &nvIndex); 41 42 // Get pointer to the session structure 43 session = SessionGet(in->policySession); 44 45 //If this is a trial policy, skip all validations and the operation 46 if(session->attributes.isTrialPolicy == CLEAR) 47 { 48 // NV Read access check. NV index should be allowed for read. A 49 // TPM_RC_AUTH_TYPE or TPM_RC_NV_LOCKED error may be return at this 50 // point 51 result = NvReadAccessChecks(in->authHandle, in->nvIndex); 52 if(result != TPM_RC_SUCCESS) return result; 53 54 // Valid NV data size should not be smaller than input operandB size 55 if((nvIndex.publicArea.dataSize - in->offset) < in->operandB.t.size) 56 return TPM_RC_SIZE + RC_PolicyNV_operandB; 57 58 // Arithmetic Comparison 59 60 // Get NV data. The size of NV data equals the input operand B size 61 NvGetIndexData(in->nvIndex, &nvIndex, in->offset, 62 in->operandB.t.size, nvBuffer); 63 64 switch(in->operation) 65 { 66 case TPM_EO_EQ: 67 // compare A = B 68 if(CryptCompare(in->operandB.t.size, nvBuffer, 69 in->operandB.t.size, in->operandB.t.buffer) != 0) 70 return TPM_RC_POLICY; 71 break; 72 case TPM_EO_NEQ: 73 // compare A != B 74 if(CryptCompare(in->operandB.t.size, nvBuffer, 75 in->operandB.t.size, in->operandB.t.buffer) == 0) 76 return TPM_RC_POLICY; 77 break; 78 case TPM_EO_SIGNED_GT: 79 // compare A > B signed 80 if(CryptCompareSigned(in->operandB.t.size, nvBuffer, 81 in->operandB.t.size, in->operandB.t.buffer) <= 0) 82 return TPM_RC_POLICY; 83 break; 84 case TPM_EO_UNSIGNED_GT: 85 // compare A > B unsigned 86 if(CryptCompare(in->operandB.t.size, nvBuffer, 87 in->operandB.t.size, in->operandB.t.buffer) <= 0) 88 return TPM_RC_POLICY; 89 break; 90 case TPM_EO_SIGNED_LT: 91 // compare A < B signed 92 if(CryptCompareSigned(in->operandB.t.size, nvBuffer, 93 in->operandB.t.size, in->operandB.t.buffer) >= 0) 94 return TPM_RC_POLICY; 95 break; 96 case TPM_EO_UNSIGNED_LT: 97 // compare A < B unsigned 98 if(CryptCompare(in->operandB.t.size, nvBuffer, 99 in->operandB.t.size, in->operandB.t.buffer) >= 0) 100 return TPM_RC_POLICY; 101 break; 102 case TPM_EO_SIGNED_GE: 103 // compare A >= B signed 104 if(CryptCompareSigned(in->operandB.t.size, nvBuffer, 105 in->operandB.t.size, in->operandB.t.buffer) < 0) 106 return TPM_RC_POLICY; 107 break; 108 case TPM_EO_UNSIGNED_GE: 109 // compare A >= B unsigned 110 if(CryptCompare(in->operandB.t.size, nvBuffer, 111 in->operandB.t.size, in->operandB.t.buffer) < 0) 112 return TPM_RC_POLICY; 113 break; 114 case TPM_EO_SIGNED_LE: 115 // compare A <= B signed 116 if(CryptCompareSigned(in->operandB.t.size, nvBuffer, 117 in->operandB.t.size, in->operandB.t.buffer) > 0) 118 return TPM_RC_POLICY; 119 break; 120 case TPM_EO_UNSIGNED_LE: 121 // compare A <= B unsigned 122 if(CryptCompare(in->operandB.t.size, nvBuffer, 123 in->operandB.t.size, in->operandB.t.buffer) > 0) 124 return TPM_RC_POLICY; 125 break; 126 case TPM_EO_BITSET: 127 // All bits SET in B are SET in A. ((A&B)=B) 128 { 129 UINT32 i; 130 for (i = 0; i < in->operandB.t.size; i++) 131 if((nvBuffer[i] & in->operandB.t.buffer[i]) 132 != in->operandB.t.buffer[i]) 133 return TPM_RC_POLICY; 134 } 135 break; 136 case TPM_EO_BITCLEAR: 137 // All bits SET in B are CLEAR in A. ((A&B)=0) 138 { 139 UINT32 i; 140 for (i = 0; i < in->operandB.t.size; i++) 141 if((nvBuffer[i] & in->operandB.t.buffer[i]) != 0) 142 return TPM_RC_POLICY; 143 } 144 break; 145 default: 146 pAssert(FALSE); 147 break; 148 } 149 } 150 151// Internal Data Update 152 153 // Start argument hash 154 argHash.t.size = CryptStartHash(session->authHashAlg, &hashState); 155 156 // add operandB 157 CryptUpdateDigest2B(&hashState, &in->operandB.b); 158 159 // add offset 160 CryptUpdateDigestInt(&hashState, sizeof(UINT16), &in->offset); 161 162 // add operation 163 CryptUpdateDigestInt(&hashState, sizeof(TPM_EO), &in->operation); 164 165 // complete argument digest 166 CryptCompleteHash2B(&hashState, &argHash.b); 167 168 // Update policyDigest 169 // Start digest 170 CryptStartHash(session->authHashAlg, &hashState); 171 172 // add old digest 173 CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b); 174 175 // add commandCode 176 CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode); 177 178 // add argument digest 179 CryptUpdateDigest2B(&hashState, &argHash.b); 180 181 // Adding nvName 182 nvName.t.size = EntityGetName(in->nvIndex, &nvName.t.name); 183 CryptUpdateDigest2B(&hashState, &nvName.b); 184 185 // complete the digest 186 CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b); 187 188 return TPM_RC_SUCCESS; 189} 190