Coverage Report

Created: 2025-08-29 06:04

/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
}