Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | // |
| 23 | TPM_RC |
| 24 | TPM2_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 | } |