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