1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 4: Supporting Routines
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7
8 #include "InternalRoutines.h"
9 //
10 //
11 // Functions
12 //
13 // CommandAuditPreInstall_Init()
14 //
15 // This function initializes the command audit list. This function is simulates the behavior of manufacturing. A
16 // function is used instead of a structure definition because this is easier than figuring out the initialization
17 // value for a bit array.
18 // This function would not be implemented outside of a manufacturing or simulation environment.
19 //
20 void
CommandAuditPreInstall_Init(void)21 CommandAuditPreInstall_Init(
22 void
23 )
24 {
25 // Clear all the audit commands
26 MemorySet(gp.auditComands, 0x00,
27 ((TPM_CC_LAST - TPM_CC_FIRST + 1) + 7) / 8);
28 // TPM_CC_SetCommandCodeAuditStatus always being audited
29 if(CommandIsImplemented(TPM_CC_SetCommandCodeAuditStatus))
30 CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus);
31 // Set initial command audit hash algorithm to be context integrity hash
32 // algorithm
33 gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG;
34 // Set up audit counter to be 0
35 gp.auditCounter = 0;
36 // Write command audit persistent data to NV
37 NvWriteReserved(NV_AUDIT_COMMANDS, &gp.auditComands);
38 NvWriteReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg);
39 NvWriteReserved(NV_AUDIT_COUNTER, &gp.auditCounter);
40 return;
41 }
42 //
43 //
44 // CommandAuditStartup()
45 //
46 // This function clears the command audit digest on a TPM Reset.
47 //
48 void
CommandAuditStartup(STARTUP_TYPE type)49 CommandAuditStartup(
50 STARTUP_TYPE type // IN: start up type
51 )
52 {
53 if(type == SU_RESET)
54 {
55 // Reset the digest size to initialize the digest
56 gr.commandAuditDigest.t.size = 0;
57 }
58 }
59 //
60 //
61 // CommandAuditSet()
62 //
63 // This function will SET the audit flag for a command. This function will not SET the audit flag for a
64 // command that is not implemented. This ensures that the audit status is not SET when
65 // TPM2_GetCapability() is used to read the list of audited commands.
66 // This function is only used by TPM2_SetCommandCodeAuditStatus().
67 // The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to
68 // NV after it is setting and clearing bits.
69 //
70 // Return Value Meaning
71 //
72 // TRUE the command code audit status was changed
73 // FALSE the command code audit status was not changed
74 //
75 BOOL
CommandAuditSet(TPM_CC commandCode)76 CommandAuditSet(
77 TPM_CC commandCode // IN: command code
78 )
79 {
80 UINT32 bitPos;
81 // Only SET a bit if the corresponding command is implemented
82 if(CommandIsImplemented(commandCode))
83 {
84 // Can't audit shutdown
85 if(commandCode != TPM_CC_Shutdown)
86 {
87 bitPos = commandCode - TPM_CC_FIRST;
88 if(!BitIsSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands)))
89 {
90 // Set bit
91 BitSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands));
92 return TRUE;
93 }
94 }
95 }
96 // No change
97 return FALSE;
98 }
99 //
100 //
101 // CommandAuditClear()
102 //
103 // This function will CLEAR the audit flag for a command. It will not CLEAR the audit flag for
104 // TPM_CC_SetCommandCodeAuditStatus().
105 // This function is only used by TPM2_SetCommandCodeAuditStatus().
106 // The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to
107 // NV after it is setting and clearing bits.
108 //
109 //
110 //
111 // Return Value Meaning
112 //
113 // TRUE the command code audit status was changed
114 // FALSE the command code audit status was not changed
115 //
116 BOOL
CommandAuditClear(TPM_CC commandCode)117 CommandAuditClear(
118 TPM_CC commandCode // IN: command code
119 )
120 {
121 UINT32 bitPos;
122 // Do nothing if the command is not implemented
123 if(CommandIsImplemented(commandCode))
124 {
125 // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be
126 // cleared
127 if(commandCode != TPM_CC_SetCommandCodeAuditStatus)
128 {
129 bitPos = commandCode - TPM_CC_FIRST;
130 if(BitIsSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands)))
131 {
132 // Clear bit
133 BitClear(bitPos, &gp.auditComands[0], sizeof(gp.auditComands));
134 return TRUE;
135 }
136 }
137 }
138 // No change
139 return FALSE;
140 }
141 //
142 //
143 // CommandAuditIsRequired()
144 //
145 // This function indicates if the audit flag is SET for a command.
146 //
147 // Return Value Meaning
148 //
149 // TRUE if command is audited
150 // FALSE if command is not audited
151 //
152 BOOL
CommandAuditIsRequired(TPM_CC commandCode)153 CommandAuditIsRequired(
154 TPM_CC commandCode // IN: command code
155 )
156 {
157 UINT32 bitPos;
158 bitPos = commandCode - TPM_CC_FIRST;
159 // Check the bit map. If the bit is SET, command audit is required
160 if((gp.auditComands[bitPos/8] & (1 << (bitPos % 8))) != 0)
161 return TRUE;
162 else
163 return FALSE;
164 }
165 //
166 //
167 // CommandAuditCapGetCCList()
168 //
169 // This function returns a list of commands that have their audit bit SET.
170 // Family "2.0" TCG Published Page 111
171 // Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014
172 // Trusted Platform Module Library Part 4: Supporting Routines
173 //
174 //
175 // The list starts at the input commandCode.
176 //
177 // Return Value Meaning
178 //
179 // YES if there are more command code available
180 // NO all the available command code has been returned
181 //
182 TPMI_YES_NO
CommandAuditCapGetCCList(TPM_CC commandCode,UINT32 count,TPML_CC * commandList)183 CommandAuditCapGetCCList(
184 TPM_CC commandCode, // IN: start command code
185 UINT32 count, // IN: count of returned TPM_CC
186 TPML_CC *commandList // OUT: list of TPM_CC
187 )
188 {
189 TPMI_YES_NO more = NO;
190 UINT32 i;
191 // Initialize output handle list
192 commandList->count = 0;
193 // The maximum count of command we may return is MAX_CAP_CC
194 if(count > MAX_CAP_CC) count = MAX_CAP_CC;
195 // If the command code is smaller than TPM_CC_FIRST, start from TPM_CC_FIRST
196 if(commandCode < TPM_CC_FIRST) commandCode = TPM_CC_FIRST;
197 // Collect audit commands
198 for(i = commandCode; i <= TPM_CC_LAST; i++)
199 {
200 if(CommandAuditIsRequired(i))
201 {
202 if(commandList->count < count)
203 {
204 // If we have not filled up the return list, add this command
205 // code to it
206 commandList->commandCodes[commandList->count] = i;
207 commandList->count++;
208 }
209 else
210 {
211 // If the return list is full but we still have command
212 // available, report this and stop iterating
213 more = YES;
214 break;
215 }
216 }
217 }
218 return more;
219 }
220 //
221 //
222 // CommandAuditGetDigest
223 //
224 // This command is used to create a digest of the commands being audited. The commands are processed
225 // in ascending numeric order with a list of TPM_CC being added to a hash. This operates as if all the
226 // audited command codes were concatenated and then hashed.
227 //
228 void
CommandAuditGetDigest(TPM2B_DIGEST * digest)229 CommandAuditGetDigest(
230 TPM2B_DIGEST *digest // OUT: command digest
231 )
232 {
233 TPM_CC i;
234 HASH_STATE hashState;
235 // Start hash
236 digest->t.size = CryptStartHash(gp.auditHashAlg, &hashState);
237 // Add command code
238 for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++)
239 {
240 if(CommandAuditIsRequired(i))
241 {
242 CryptUpdateDigestInt(&hashState, sizeof(i), &i);
243 }
244 }
245 // Complete hash
246 CryptCompleteHash2B(&hashState, &digest->b);
247 return;
248 }
249