blob: 0198bbfe2982b945e49c2ee88af0a0545d217052 [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// 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//
23TPM_RC
24TPM2_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 Bohra4ed3aa2015-07-30 10:44:16 -070032 nameSize = CryptGetHashDigestSize(in->publicInfo.t.nvPublic.nameAlg);
Vadim Bendebury56797522015-05-20 10:32:25 -070033
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 Collard5cb743a2018-06-26 20:07:49 +080040 // Indexes in the virtual range are reserved.
41 if (_plat__NvGetHandleVirtualOffset(in->publicInfo.t.nvPublic.nvIndex))
42 return TPM_RC_NV_AUTHORIZATION;
43
Vadim Bendebury56797522015-05-20 10:32:25 -070044// 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 Bohra4ed3aa2015-07-30 10:44:16 -070052 attributes = in->publicInfo.t.nvPublic.attributes;
Vadim Bendebury56797522015-05-20 10:32:25 -070053
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 Bohra4ed3aa2015-07-30 10:44:16 -070057 && (in->publicInfo.t.nvPublic.dataSize != 8))
Vadim Bendebury56797522015-05-20 10:32:25 -070058 return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
59
60 // check that the authPolicy consistent with hash algorithm
Jocelyn Bohra4ed3aa2015-07-30 10:44:16 -070061 if( in->publicInfo.t.nvPublic.authPolicy.t.size != 0
62 && in->publicInfo.t.nvPublic.authPolicy.t.size != nameSize)
Vadim Bendebury56797522015-05-20 10:32:25 -070063 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 Bohra4ed3aa2015-07-30 10:44:16 -0700130 if( ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == SET
Vadim Bendebury56797522015-05-20 10:32:25 -0700131 && in->authHandle == TPM_RH_OWNER
132 )
Jocelyn Bohra4ed3aa2015-07-30 10:44:16 -0700133 || ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == CLEAR
Vadim Bendebury56797522015-05-20 10:32:25 -0700134 && 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 Bohra4ed3aa2015-07-30 10:44:16 -0700141 if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE == SET
Vadim Bendebury56797522015-05-20 10:32:25 -0700142 && 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 Bohra4ed3aa2015-07-30 10:44:16 -0700148 if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_EXTEND == SET
149 && in->publicInfo.t.nvPublic.dataSize != nameSize
Vadim Bendebury56797522015-05-20 10:32:25 -0700150 )
151 return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
152
153 // See if the index is already defined.
Jocelyn Bohra4ed3aa2015-07-30 10:44:16 -0700154 if(NvIsUndefinedIndex(in->publicInfo.t.nvPublic.nvIndex))
Vadim Bendebury56797522015-05-20 10:32:25 -0700155 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 Bohra4ed3aa2015-07-30 10:44:16 -0700159 result = NvDefineIndex(&in->publicInfo.t.nvPublic, &in->auth);
Vadim Bendebury56797522015-05-20 10:32:25 -0700160 if(result != TPM_RC_SUCCESS)
161 return result;
162
163 return TPM_RC_SUCCESS;
164
165}