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 | |
| 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 | |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 48 | attributes = in->publicInfo.t.nvPublic.attributes; |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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) |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 53 | && (in->publicInfo.t.nvPublic.dataSize != 8)) |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 54 | return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo; |
| 55 | |
| 56 | // check that the authPolicy consistent with hash algorithm |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 57 | if( in->publicInfo.t.nvPublic.authPolicy.t.size != 0 |
| 58 | && in->publicInfo.t.nvPublic.authPolicy.t.size != nameSize) |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 126 | if( ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == SET |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 127 | && in->authHandle == TPM_RH_OWNER |
| 128 | ) |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 129 | || ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == CLEAR |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 137 | if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE == SET |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 144 | if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_EXTEND == SET |
| 145 | && in->publicInfo.t.nvPublic.dataSize != nameSize |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 146 | ) |
| 147 | return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; |
| 148 | |
| 149 | // See if the index is already defined. |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 150 | if(NvIsUndefinedIndex(in->publicInfo.t.nvPublic.nvIndex)) |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 155 | result = NvDefineIndex(&in->publicInfo.t.nvPublic, &in->auth); |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 156 | if(result != TPM_RC_SUCCESS) |
| 157 | return result; |
| 158 | |
| 159 | return TPM_RC_SUCCESS; |
| 160 | |
| 161 | } |