Home | History | Annotate | Download | only in tpm2
      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 }
    190