1 /* Microsoft Reference Implementation for TPM 2.0
2 *
3 * The copyright in this software is being made available under the BSD License,
4 * included below. This software may be subject to other third party and
5 * contributor rights, including patent rights, and no such rights are granted
6 * under this license.
7 *
8 * Copyright (c) Microsoft Corporation
9 *
10 * All rights reserved.
11 *
12 * BSD License
13 *
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
16 *
17 * Redistributions of source code must retain the above copyright notice, this list
18 * of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright notice, this
21 * list of conditions and the following disclaimer in the documentation and/or
22 * other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 #include "Tpm.h"
36 #include "NV_DefineSpace_fp.h"
37
38 #if CC_NV_DefineSpace // Conditional expansion of this file
39
40 /*(See part 3 specification)
41 // Define a NV index space
42 */
43 // Return Type: TPM_RC
44 // TPM_RC_HIERARCHY for authorizations using TPM_RH_PLATFORM
45 // phEnable_NV is clear preventing access to NV
46 // data in the platform hierarchy.
47 // TPM_RC_ATTRIBUTES attributes of the index are not consistent
48 // TPM_RC_NV_DEFINED index already exists
49 // TPM_RC_NV_SPACE insufficient space for the index
50 // TPM_RC_SIZE 'auth->size' or 'publicInfo->authPolicy.size' is
51 // larger than the digest size of
52 // 'publicInfo->nameAlg'; or 'publicInfo->dataSize'
53 // is not consistent with 'publicInfo->attributes'
54 // (this includes the case when the index is
55 // larger than a MAX_NV_BUFFER_SIZE but the
56 // TPMA_NV_WRITEALL attribute is SET)
57 TPM_RC
TPM2_NV_DefineSpace(NV_DefineSpace_In * in)58 TPM2_NV_DefineSpace(
59 NV_DefineSpace_In *in // IN: input parameter list
60 )
61 {
62 TPMA_NV attributes = in->publicInfo.nvPublic.attributes;
63 UINT16 nameSize;
64
65 nameSize = CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg);
66
67 // Input Validation
68
69 // Checks not specific to type
70
71 // If the UndefineSpaceSpecial command is not implemented, then can't have
72 // an index that can only be deleted with policy
73 #if CC_NV_UndefineSpaceSpecial == NO
74 if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE))
75 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
76 #endif
77
78 // check that the authPolicy consistent with hash algorithm
79
80 if(in->publicInfo.nvPublic.authPolicy.t.size != 0
81 && in->publicInfo.nvPublic.authPolicy.t.size != nameSize)
82 return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
83
84 // make sure that the authValue is not too large
85 if(MemoryRemoveTrailingZeros(&in->auth)
86 > CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg))
87 return TPM_RCS_SIZE + RC_NV_DefineSpace_auth;
88
89 // If an index is being created by the owner and shEnable is
90 // clear, then we would not reach this point because ownerAuth
91 // can't be given when shEnable is CLEAR. However, if phEnable
92 // is SET but phEnableNV is CLEAR, we have to check here
93 if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR)
94 return TPM_RCS_HIERARCHY + RC_NV_DefineSpace_authHandle;
95
96 // Attribute checks
97 // Eliminate the unsupported types
98 switch(GET_TPM_NT(attributes))
99 {
100 #if CC_NV_Increment == YES
101 case TPM_NT_COUNTER:
102 #endif
103 #if CC_NV_SetBits == YES
104 case TPM_NT_BITS:
105 #endif
106 #if CC_NV_Extend == YES
107 case TPM_NT_EXTEND:
108 #endif
109 #if CC_PolicySecret == YES && defined TPM_NT_PIN_PASS
110 case TPM_NT_PIN_PASS:
111 case TPM_NT_PIN_FAIL:
112 #endif
113 case TPM_NT_ORDINARY:
114 break;
115 default:
116 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
117 break;
118 }
119 // Check that the sizes are OK based on the type
120 switch(GET_TPM_NT(attributes))
121 {
122 case TPM_NT_ORDINARY:
123 // Can't exceed the allowed size for the implementation
124 if(in->publicInfo.nvPublic.dataSize > MAX_NV_INDEX_SIZE)
125 return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
126 break;
127 case TPM_NT_EXTEND:
128 if(in->publicInfo.nvPublic.dataSize != nameSize)
129 return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
130 break;
131 default:
132 // Everything else needs a size of 8
133 if(in->publicInfo.nvPublic.dataSize != 8)
134 return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
135 break;
136 }
137 // Handle other specifics
138 switch(GET_TPM_NT(attributes))
139 {
140 case TPM_NT_COUNTER:
141 // Counter can't have TPMA_NV_CLEAR_STCLEAR SET (don't clear counters)
142 if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR))
143 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
144 break;
145 #ifdef TPM_NT_PIN_FAIL
146 case TPM_NT_PIN_FAIL:
147 // NV_NO_DA must be SET and AUTHWRITE must be CLEAR
148 // NOTE: As with a PIN_PASS index, the authValue of the index is not
149 // available until the index is written. If AUTHWRITE is the only way to
150 // write then index, it could never be written. Rather than go through
151 // all of the other possible ways to write the Index, it is simply
152 // prohibited to write the index with the authValue. Other checks
153 // below will insure that there seems to be a way to write the index
154 // (i.e., with platform authorization , owner authorization,
155 // or with policyAuth.)
156 // It is not allowed to create a PIN Index that can't be modified.
157 if(!IS_ATTRIBUTE(attributes, TPMA_NV, NO_DA))
158 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
159 #endif
160 #ifdef TPM_NT_PIN_PASS
161 case TPM_NT_PIN_PASS:
162 // AUTHWRITE must be CLEAR (see note above to TPM_NT_PIN_FAIL)
163 if(IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE)
164 || IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)
165 || IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE))
166 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
167 #endif // this comes before break because PIN_FAIL falls through
168 break;
169 default:
170 break;
171 }
172
173 // Locks may not be SET and written cannot be SET
174 if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN)
175 || IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED)
176 || IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED))
177 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
178
179 // There must be a way to read the index.
180 if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD)
181 && !IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD)
182 && !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHREAD)
183 && !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYREAD))
184 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
185
186 // There must be a way to write the index
187 if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE)
188 && !IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE)
189 && !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE)
190 && !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYWRITE))
191 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
192
193 // An index with TPMA_NV_CLEAR_STCLEAR can't have TPMA_NV_WRITEDEFINE SET
194 if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR)
195 && IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE))
196 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
197
198 // Make sure that the creator of the index can delete the index
199 if((IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE)
200 && in->authHandle == TPM_RH_OWNER)
201 || (!IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE)
202 && in->authHandle == TPM_RH_PLATFORM))
203 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_authHandle;
204
205 // If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by
206 // the platform
207 if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE)
208 && TPM_RH_PLATFORM != in->authHandle)
209 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
210
211 // Make sure that the TPMA_NV_WRITEALL is not set if the index size is larger
212 // than the allowed NV buffer size.
213 if(in->publicInfo.nvPublic.dataSize > MAX_NV_BUFFER_SIZE
214 && IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL))
215 return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
216
217 // And finally, see if the index is already defined.
218 if(NvIndexIsDefined(in->publicInfo.nvPublic.nvIndex))
219 return TPM_RC_NV_DEFINED;
220
221 // Internal Data Update
222 // define the space. A TPM_RC_NV_SPACE error may be returned at this point
223 return NvDefineIndex(&in->publicInfo.nvPublic, &in->auth);
224 }
225
226 #endif // CC_NV_DefineSpace