blob: 9c6ce727a38beac6b17b136aba298c63c899dc97 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 3: Commands
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014
#include "InternalRoutines.h"
#include "NV_DefineSpace_fp.h"
//
//
// Error Returns Meaning
//
// TPM_RC_NV_ATTRIBUTES attributes of the index are not consistent
// TPM_RC_NV_DEFINED index already exists
// TPM_RC_HIERARCHY for authorizations using TPM_RH_PLATFORM phEnable_NV is
// clear.
// TPM_RC_NV_SPACE Insufficient space for the index
// TPM_RC_SIZE 'auth->size' or 'publicInfo->authPolicy.size' is larger than the digest
// size of 'publicInfo->nameAlg', or 'publicInfo->dataSize' is not
// consistent with 'publicInfo->attributes'.
//
TPM_RC
TPM2_NV_DefineSpace(
NV_DefineSpace_In *in // IN: input parameter list
)
{
TPM_RC result;
TPMA_NV attributes;
UINT16 nameSize;
nameSize = CryptGetHashDigestSize(in->publicInfo.t.nvPublic.nameAlg);
// Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
// TPM_RC_NV_RATE or TPM_RC_SUCCESS.
result = NvIsAvailable();
if(result != TPM_RC_SUCCESS)
return result;
// Input Validation
// If an index is being created by the owner and shEnable is
// clear, then we would not reach this point because ownerAuth
// can't be given when shEnable is CLEAR. However, if phEnable
// is SET but phEnableNV is CLEAR, we have to check here
if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR)
return TPM_RC_HIERARCHY + RC_NV_DefineSpace_authHandle;
attributes = in->publicInfo.t.nvPublic.attributes;
//TPMS_NV_PUBLIC validation.
// Counters and bit fields must have a size of 8
if ( (attributes.TPMA_NV_COUNTER == SET || attributes.TPMA_NV_BITS == SET)
&& (in->publicInfo.t.nvPublic.dataSize != 8))
return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
// check that the authPolicy consistent with hash algorithm
if( in->publicInfo.t.nvPublic.authPolicy.t.size != 0
&& in->publicInfo.t.nvPublic.authPolicy.t.size != nameSize)
return TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo;
// make sure that the authValue is not too large
MemoryRemoveTrailingZeros(&in->auth);
if(in->auth.t.size > nameSize)
return TPM_RC_SIZE + RC_NV_DefineSpace_auth;
//TPMA_NV validation.
// Locks may not be SET and written cannot be SET
if( attributes.TPMA_NV_WRITTEN == SET
|| attributes.TPMA_NV_WRITELOCKED == SET
|| attributes.TPMA_NV_READLOCKED == SET)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// There must be a way to read the index
if( attributes.TPMA_NV_OWNERREAD == CLEAR
&& attributes.TPMA_NV_PPREAD == CLEAR
&& attributes.TPMA_NV_AUTHREAD == CLEAR
&& attributes.TPMA_NV_POLICYREAD == CLEAR)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// There must be a way to write the index
if( attributes.TPMA_NV_OWNERWRITE == CLEAR
&& attributes.TPMA_NV_PPWRITE == CLEAR
&& attributes.TPMA_NV_AUTHWRITE == CLEAR
&& attributes.TPMA_NV_POLICYWRITE == CLEAR)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// Make sure that no attribute is used that is not supported by the proper
// command
#if CC_NV_Increment == NO
if( attributes.TPMA_NV_COUNTER == SET)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif
#if CC_NV_SetBits == NO
if( attributes.TPMA_NV_BITS == SET)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif
#if CC_NV_Extend == NO
if( attributes.TPMA_NV_EXTEND == SET)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif
#if CC_NV_UndefineSpaceSpecial == NO
if( attributes.TPMA_NV_POLICY_DELETE == SET)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif
// Can be COUNTER or BITS or EXTEND but not more than one
if( attributes.TPMA_NV_COUNTER == SET
&& attributes.TPMA_NV_BITS == SET)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
if( attributes.TPMA_NV_COUNTER == SET
&& attributes.TPMA_NV_EXTEND == SET)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
if( attributes.TPMA_NV_BITS == SET
&& attributes.TPMA_NV_EXTEND == SET)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// An index with TPMA_NV_CLEAR_STCLEAR can't be a counter and can't have
// TPMA_NV_WRITEDEFINE SET
if( attributes.TPMA_NV_CLEAR_STCLEAR == SET
&& ( attributes.TPMA_NV_COUNTER == SET
|| attributes.TPMA_NV_WRITEDEFINE == SET)
)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// Make sure that the creator of the index can delete the index
if( ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == SET
&& in->authHandle == TPM_RH_OWNER
)
|| ( in->publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE == CLEAR
&& in->authHandle == TPM_RH_PLATFORM
)
)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle;
// If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by
// the platform
if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE == SET
&& TPM_RH_PLATFORM != in->authHandle
)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// If the NV index is used as a PCR, the data size must match the digest
// size
if( in->publicInfo.t.nvPublic.attributes.TPMA_NV_EXTEND == SET
&& in->publicInfo.t.nvPublic.dataSize != nameSize
)
return TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// See if the index is already defined.
if(NvIsUndefinedIndex(in->publicInfo.t.nvPublic.nvIndex))
return TPM_RC_NV_DEFINED;
// Internal Data Update
// define the space. A TPM_RC_NV_SPACE error may be returned at this point
result = NvDefineIndex(&in->publicInfo.t.nvPublic, &in->auth);
if(result != TPM_RC_SUCCESS)
return result;
return TPM_RC_SUCCESS;
}
|