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 TPM2_NV_DefineSpace(NV_DefineSpace_In * in)24TPM2_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