• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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