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