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 "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 | |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 32 | nameSize = CryptGetHashDigestSize(in->publicInfo.t.nvPublic.nameAlg); |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | |
Louis Collard | 5cb743a | 2018-06-26 20:07:49 +0800 | [diff] [blame] | 40 | // Indexes in the virtual range are reserved. |
| 41 | if (_plat__NvGetHandleVirtualOffset(in->publicInfo.t.nvPublic.nvIndex)) |
| 42 | return TPM_RC_NV_AUTHORIZATION; |
| 43 | |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 44 | // Input Validation |
| 45 | // If an index is being created by the owner and shEnable is |
| 46 | // clear, then we would not reach this point because ownerAuth |
| 47 | // can't be given when shEnable is CLEAR. However, if phEnable |
| 48 | // is SET but phEnableNV is CLEAR, we have to check here |
| 49 | if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR) |
| 50 | return TPM_RC_HIERARCHY + RC_NV_DefineSpace_authHandle; |
| 51 | |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 52 | attributes = in->publicInfo.t.nvPublic.attributes; |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 53 | |
| 54 | //TPMS_NV_PUBLIC validation. |
| 55 | // Counters and bit fields must have a size of 8 |
| 56 | if ( (attributes.TPMA_NV_COUNTER == SET || attributes.TPMA_NV_BITS == SET) |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 57 | && (in->publicInfo.t.nvPublic.dataSize != 8)) |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 58 | return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo; |
| 59 | |
| 60 | // check that the authPolicy consistent with hash algorithm |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 61 | if( in->publicInfo.t.nvPublic.authPolicy.t.size != 0 |
| 62 | && in->publicInfo.t.nvPublic.authPolicy.t.size != nameSize) |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 63 | return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo; |
| 64 | |
| 65 | // make sure that the authValue is not too large |
| 66 | MemoryRemoveTrailingZeros(&in->auth); |
| 67 | if(in->auth.t.size > nameSize) |
| 68 | return TPM_RC_SIZE + RC_NV_DefineSpace_auth; |
| 69 | |
| 70 | //TPMA_NV validation. |
| 71 | // Locks may not be SET and written cannot be SET |
| 72 | if( attributes.TPMA_NV_WRITTEN == SET |
| 73 | || attributes.TPMA_NV_WRITELOCKED == SET |
| 74 | || attributes.TPMA_NV_READLOCKED == SET) |
| 75 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 76 | |
| 77 | // There must be a way to read the index |
| 78 | if( attributes.TPMA_NV_OWNERREAD == CLEAR |
| 79 | && attributes.TPMA_NV_PPREAD == CLEAR |
| 80 | && attributes.TPMA_NV_AUTHREAD == CLEAR |
| 81 | && attributes.TPMA_NV_POLICYREAD == CLEAR) |
| 82 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 83 | |
| 84 | // There must be a way to write the index |
| 85 | if( attributes.TPMA_NV_OWNERWRITE == CLEAR |
| 86 | && attributes.TPMA_NV_PPWRITE == CLEAR |
| 87 | && attributes.TPMA_NV_AUTHWRITE == CLEAR |
| 88 | && attributes.TPMA_NV_POLICYWRITE == CLEAR) |
| 89 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 90 | |
| 91 | // Make sure that no attribute is used that is not supported by the proper |
| 92 | // command |
| 93 | #if CC_NV_Increment == NO |
| 94 | if( attributes.TPMA_NV_COUNTER == SET) |
| 95 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 96 | #endif |
| 97 | #if CC_NV_SetBits == NO |
| 98 | if( attributes.TPMA_NV_BITS == SET) |
| 99 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 100 | #endif |
| 101 | #if CC_NV_Extend == NO |
| 102 | if( attributes.TPMA_NV_EXTEND == SET) |
| 103 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 104 | #endif |
| 105 | #if CC_NV_UndefineSpaceSpecial == NO |
| 106 | if( attributes.TPMA_NV_POLICY_DELETE == SET) |
| 107 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 108 | #endif |
| 109 | |
| 110 | // Can be COUNTER or BITS or EXTEND but not more than one |
| 111 | if( attributes.TPMA_NV_COUNTER == SET |
| 112 | && attributes.TPMA_NV_BITS == SET) |
| 113 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 114 | if( attributes.TPMA_NV_COUNTER == SET |
| 115 | && attributes.TPMA_NV_EXTEND == SET) |
| 116 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 117 | if( attributes.TPMA_NV_BITS == SET |
| 118 | && attributes.TPMA_NV_EXTEND == SET) |
| 119 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 120 | |
| 121 | // An index with TPMA_NV_CLEAR_STCLEAR can't be a counter and can't have |
| 122 | // TPMA_NV_WRITEDEFINE SET |
| 123 | if( attributes.TPMA_NV_CLEAR_STCLEAR == SET |
| 124 | && ( attributes.TPMA_NV_COUNTER == SET |
| 125 | || attributes.TPMA_NV_WRITEDEFINE == SET) |
| 126 | ) |
| 127 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 128 | |
| 129 | // Make sure that the creator of the index can delete the index |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 130 | if( ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == SET |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 131 | && in->authHandle == TPM_RH_OWNER |
| 132 | ) |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 133 | || ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == CLEAR |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 134 | && in->authHandle == TPM_RH_PLATFORM |
| 135 | ) |
| 136 | ) |
| 137 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle; |
| 138 | |
| 139 | // If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by |
| 140 | // the platform |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 141 | if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE == SET |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 142 | && TPM_RH_PLATFORM != in->authHandle |
| 143 | ) |
| 144 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 145 | |
| 146 | // If the NV index is used as a PCR, the data size must match the digest |
| 147 | // size |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 148 | if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_EXTEND == SET |
| 149 | && in->publicInfo.t.nvPublic.dataSize != nameSize |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 150 | ) |
| 151 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 152 | |
| 153 | // See if the index is already defined. |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 154 | if(NvIsUndefinedIndex(in->publicInfo.t.nvPublic.nvIndex)) |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 155 | return TPM_RC_NV_DEFINED; |
| 156 | |
| 157 | // Internal Data Update |
| 158 | // define the space. A TPM_RC_NV_SPACE error may be returned at this point |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 159 | result = NvDefineIndex(&in->publicInfo.t.nvPublic, &in->auth); |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 160 | if(result != TPM_RC_SUCCESS) |
| 161 | return result; |
| 162 | |
| 163 | return TPM_RC_SUCCESS; |
| 164 | |
| 165 | } |