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 "NV_DefineSpace_fp.h"
     10 //
     11 //
     12 //     Error Returns                 Meaning
     13 //
     14 //     TPM_RC_NV_ATTRIBUTES          attributes of the index are not consistent
     15 //     TPM_RC_NV_DEFINED             index already exists
     16 //     TPM_RC_HIERARCHY              for authorizations using TPM_RH_PLATFORM phEnable_NV is
     17 //                                   clear.
     18 //     TPM_RC_NV_SPACE               Insufficient space for the index
     19 //     TPM_RC_SIZE                   'auth->size' or 'publicInfo->authPolicy.size' is larger than the digest
     20 //                                   size of 'publicInfo->nameAlg', or 'publicInfo->dataSize' is not
     21 //                                   consistent with 'publicInfo->attributes'.
     22 //
     23 TPM_RC
     24 TPM2_NV_DefineSpace(
     25    NV_DefineSpace_In   *in                  // IN: input parameter list
     26    )
     27 {
     28    TPM_RC          result;
     29    TPMA_NV         attributes;
     30    UINT16          nameSize;
     31 
     32    nameSize = CryptGetHashDigestSize(in->publicInfo.t.nvPublic.nameAlg);
     33 
     34    // Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
     35    // TPM_RC_NV_RATE or TPM_RC_SUCCESS.
     36    result = NvIsAvailable();
     37    if(result != TPM_RC_SUCCESS)
     38        return result;
     39 
     40 // Input Validation
     41    // If an index is being created by the owner and shEnable is
     42    // clear, then we would not reach this point because ownerAuth
     43    // can't be given when shEnable is CLEAR. However, if phEnable
     44    // is SET but phEnableNV is CLEAR, we have to check here
     45    if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR)
     46        return TPM_RC_HIERARCHY + RC_NV_DefineSpace_authHandle;
     47 
     48    attributes = in->publicInfo.t.nvPublic.attributes;
     49 
     50    //TPMS_NV_PUBLIC validation.
     51    // Counters and bit fields must have a size of 8
     52    if (   (attributes.TPMA_NV_COUNTER == SET || attributes.TPMA_NV_BITS == SET)
     53        && (in->publicInfo.t.nvPublic.dataSize != 8))
     54        return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
     55 
     56    // check that the authPolicy consistent with hash algorithm
     57    if(   in->publicInfo.t.nvPublic.authPolicy.t.size != 0
     58       && in->publicInfo.t.nvPublic.authPolicy.t.size != nameSize)
     59        return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
     60 
     61    // make sure that the authValue is not too large
     62    MemoryRemoveTrailingZeros(&in->auth);
     63    if(in->auth.t.size > nameSize)
     64        return TPM_RC_SIZE + RC_NV_DefineSpace_auth;
     65 
     66    //TPMA_NV validation.
     67    // Locks may not be SET and written cannot be SET
     68    if(   attributes.TPMA_NV_WRITTEN == SET
     69       || attributes.TPMA_NV_WRITELOCKED == SET
     70       || attributes.TPMA_NV_READLOCKED == SET)
     71        return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
     72 
     73    // There must be a way to read the index
     74    if(   attributes.TPMA_NV_OWNERREAD == CLEAR
     75       && attributes.TPMA_NV_PPREAD == CLEAR
     76       && attributes.TPMA_NV_AUTHREAD == CLEAR
     77       && attributes.TPMA_NV_POLICYREAD == CLEAR)
     78        return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
     79 
     80    // There must be a way to write the index
     81    if(   attributes.TPMA_NV_OWNERWRITE == CLEAR
     82       && attributes.TPMA_NV_PPWRITE == CLEAR
     83       && attributes.TPMA_NV_AUTHWRITE == CLEAR
     84       && attributes.TPMA_NV_POLICYWRITE == CLEAR)
     85        return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
     86 
     87    // Make sure that no attribute is used that is not supported by the proper
     88    // command
     89 #if CC_NV_Increment == NO
     90    if( attributes.TPMA_NV_COUNTER == SET)
     91        return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
     92 #endif
     93 #if CC_NV_SetBits == NO
     94       if( attributes.TPMA_NV_BITS == SET)
     95           return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
     96 #endif
     97 #if CC_NV_Extend == NO
     98      if( attributes.TPMA_NV_EXTEND == SET)
     99          return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
    100 #endif
    101 #if CC_NV_UndefineSpaceSpecial == NO
    102     if( attributes.TPMA_NV_POLICY_DELETE == SET)
    103         return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
    104 #endif
    105 
    106    // Can be COUNTER or BITS or EXTEND but not more than one
    107    if( attributes.TPMA_NV_COUNTER == SET
    108       && attributes.TPMA_NV_BITS == SET)
    109        return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
    110    if(   attributes.TPMA_NV_COUNTER == SET
    111       && attributes.TPMA_NV_EXTEND == SET)
    112        return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
    113    if(   attributes.TPMA_NV_BITS == SET
    114       && attributes.TPMA_NV_EXTEND == SET)
    115        return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
    116 
    117    // An index with TPMA_NV_CLEAR_STCLEAR can't be a counter and can't have
    118    // TPMA_NV_WRITEDEFINE SET
    119    if(     attributes.TPMA_NV_CLEAR_STCLEAR == SET
    120        && (    attributes.TPMA_NV_COUNTER == SET
    121             || attributes.TPMA_NV_WRITEDEFINE == SET)
    122       )
    123        return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
    124 
    125    // Make sure that the creator of the index can delete the index
    126    if( (    in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == SET
    127           && in->authHandle == TPM_RH_OWNER
    128          )
    129       || (   in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == CLEAR
    130           && in->authHandle == TPM_RH_PLATFORM
    131          )
    132      )
    133          return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle;
    134 
    135   // If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by
    136   // the platform
    137   if(    in->publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE == SET
    138      && TPM_RH_PLATFORM != in->authHandle
    139     )
    140       return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
    141 
    142   // If the NV index is used as a PCR, the data size must match the digest
    143   // size
    144   if(   in->publicInfo.t.nvPublic.attributes.TPMA_NV_EXTEND == SET
    145      && in->publicInfo.t.nvPublic.dataSize != nameSize
    146     )
    147       return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
    148 
    149   // See if the index is already defined.
    150   if(NvIsUndefinedIndex(in->publicInfo.t.nvPublic.nvIndex))
    151       return TPM_RC_NV_DEFINED;
    152 
    153 // Internal Data Update
    154    // define the space. A TPM_RC_NV_SPACE error may be returned at this point
    155    result = NvDefineIndex(&in->publicInfo.t.nvPublic, &in->auth);
    156    if(result != TPM_RC_SUCCESS)
    157        return result;
    158 
    159   return TPM_RC_SUCCESS;
    160 
    161 }
    162