/src/libtpms/src/tpm2/CommandAudit.c
Line | Count | Source |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Functions That Support Command Audit */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* */ |
7 | | /* Licenses and Notices */ |
8 | | /* */ |
9 | | /* 1. Copyright Licenses: */ |
10 | | /* */ |
11 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
12 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
13 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
14 | | /* derivative works, distribute, display and perform the Source Code and */ |
15 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
16 | | /* */ |
17 | | /* - The TCG grants to the user of the other parts of the specification */ |
18 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
19 | | /* display, and perform the specification solely for the purpose of */ |
20 | | /* developing products based on such documents. */ |
21 | | /* */ |
22 | | /* 2. Source Code Distribution Conditions: */ |
23 | | /* */ |
24 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
25 | | /* this list of conditions and the following disclaimers. */ |
26 | | /* */ |
27 | | /* - Redistributions in binary form must reproduce the above copyright */ |
28 | | /* licenses, this list of conditions and the following disclaimers in the */ |
29 | | /* documentation and/or other materials provided with the distribution. */ |
30 | | /* */ |
31 | | /* 3. Disclaimers: */ |
32 | | /* */ |
33 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
34 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
35 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
36 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
37 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
38 | | /* information on specification licensing rights available through TCG */ |
39 | | /* membership agreements. */ |
40 | | /* */ |
41 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
42 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
43 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
44 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
45 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
46 | | /* */ |
47 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
48 | | /* liability, including liability for infringement of any proprietary */ |
49 | | /* rights, relating to use of information in this specification and to the */ |
50 | | /* implementation of this specification, and TCG disclaims all liability for */ |
51 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
52 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
53 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
54 | | /* arising in any way out of use or reliance upon this specification or any */ |
55 | | /* information herein. */ |
56 | | /* */ |
57 | | /* (c) Copyright IBM Corp. and others, 2016 - 2023 */ |
58 | | /* */ |
59 | | /********************************************************************************/ |
60 | | |
61 | | //** Introduction |
62 | | // This file contains the functions that support command audit. |
63 | | |
64 | | //** Includes |
65 | | #include "Tpm.h" |
66 | | |
67 | | //** Functions |
68 | | |
69 | | //*** CommandAuditPreInstall_Init() |
70 | | // This function initializes the command audit list. This function simulates |
71 | | // the behavior of manufacturing. A function is used instead of a structure |
72 | | // definition because this is easier than figuring out the initialization value |
73 | | // for a bit array. |
74 | | // |
75 | | // This function would not be implemented outside of a manufacturing or |
76 | | // simulation environment. |
77 | | void CommandAuditPreInstall_Init(void) |
78 | 6.26k | { |
79 | | // Clear all the audit commands |
80 | 6.26k | MemorySet(gp.auditCommands, 0x00, sizeof(gp.auditCommands)); |
81 | | |
82 | | // TPM_CC_SetCommandCodeAuditStatus always being audited |
83 | 6.26k | CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus); |
84 | | |
85 | | // Set initial command audit hash algorithm to be context integrity hash |
86 | | // algorithm |
87 | 6.26k | gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG; |
88 | | |
89 | | // Set up audit counter to be 0 |
90 | 6.26k | gp.auditCounter = 0; |
91 | | |
92 | | // Write command audit persistent data to NV |
93 | 6.26k | NV_SYNC_PERSISTENT(auditCommands); |
94 | 6.26k | NV_SYNC_PERSISTENT(auditHashAlg); |
95 | 6.26k | NV_SYNC_PERSISTENT(auditCounter); |
96 | | |
97 | 6.26k | return; |
98 | 6.26k | } |
99 | | |
100 | | //*** CommandAuditStartup() |
101 | | // This function clears the command audit digest on a TPM Reset. |
102 | | BOOL CommandAuditStartup(STARTUP_TYPE type // IN: start up type |
103 | | ) |
104 | 6.26k | { |
105 | 6.26k | if((type != SU_RESTART) && (type != SU_RESUME)) |
106 | 6.26k | { |
107 | | // Reset the digest size to initialize the digest |
108 | 6.26k | gr.commandAuditDigest.t.size = 0; |
109 | 6.26k | } |
110 | 6.26k | return TRUE; |
111 | 6.26k | } |
112 | | |
113 | | //*** CommandAuditSet() |
114 | | // This function will SET the audit flag for a command. This function |
115 | | // will not SET the audit flag for a command that is not implemented. This |
116 | | // ensures that the audit status is not SET when TPM2_GetCapability() is |
117 | | // used to read the list of audited commands. |
118 | | // |
119 | | // This function is only used by TPM2_SetCommandCodeAuditStatus(). |
120 | | // |
121 | | // The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the |
122 | | // changes to be saved to NV after it is setting and clearing bits. |
123 | | // Return Type: BOOL |
124 | | // TRUE(1) command code audit status was changed |
125 | | // FALSE(0) command code audit status was not changed |
126 | | BOOL CommandAuditSet(TPM_CC commandCode // IN: command code |
127 | | ) |
128 | 11.6k | { |
129 | 11.6k | COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); |
130 | | |
131 | | // Only SET a bit if the corresponding command is implemented |
132 | 11.6k | if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) |
133 | 7.75k | { |
134 | | // Can't audit shutdown |
135 | 7.75k | if(commandCode != TPM_CC_Shutdown) |
136 | 7.63k | { |
137 | 7.63k | if(!TEST_BIT(commandIndex, gp.auditCommands)) |
138 | 7.25k | { |
139 | | // Set bit |
140 | 7.25k | SET_BIT(commandIndex, gp.auditCommands); |
141 | 7.25k | return TRUE; |
142 | 7.25k | } |
143 | 7.63k | } |
144 | 7.75k | } |
145 | | // No change |
146 | 4.43k | return FALSE; |
147 | 11.6k | } |
148 | | |
149 | | //*** CommandAuditClear() |
150 | | // This function will CLEAR the audit flag for a command. It will not CLEAR the |
151 | | // audit flag for TPM_CC_SetCommandCodeAuditStatus(). |
152 | | // |
153 | | // This function is only used by TPM2_SetCommandCodeAuditStatus(). |
154 | | // |
155 | | // The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the |
156 | | // changes to be saved to NV after it is setting and clearing bits. |
157 | | // Return Type: BOOL |
158 | | // TRUE(1) command code audit status was changed |
159 | | // FALSE(0) command code audit status was not changed |
160 | | BOOL CommandAuditClear(TPM_CC commandCode // IN: command code |
161 | | ) |
162 | 3.01k | { |
163 | 3.01k | COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); |
164 | | |
165 | | // Do nothing if the command is not implemented |
166 | 3.01k | if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) |
167 | 607 | { |
168 | | // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be |
169 | | // cleared |
170 | 607 | if(commandCode != TPM_CC_SetCommandCodeAuditStatus) |
171 | 531 | { |
172 | 531 | if(TEST_BIT(commandIndex, gp.auditCommands)) |
173 | 65 | { |
174 | | // Clear bit |
175 | 65 | CLEAR_BIT(commandIndex, gp.auditCommands); |
176 | 65 | return TRUE; |
177 | 65 | } |
178 | 531 | } |
179 | 607 | } |
180 | | // No change |
181 | 2.95k | return FALSE; |
182 | 3.01k | } |
183 | | |
184 | | //*** CommandAuditIsRequired() |
185 | | // This function indicates if the audit flag is SET for a command. |
186 | | // Return Type: BOOL |
187 | | // TRUE(1) command is audited |
188 | | // FALSE(0) command is not audited |
189 | | BOOL CommandAuditIsRequired(COMMAND_INDEX commandIndex // IN: command index |
190 | | ) |
191 | 20.4k | { |
192 | | // Check the bit map. If the bit is SET, command audit is required |
193 | 20.4k | return (TEST_BIT(commandIndex, gp.auditCommands)); |
194 | 20.4k | } |
195 | | |
196 | | //*** CommandAuditCapGetCCList() |
197 | | // This function returns a list of commands that have their audit bit SET. |
198 | | // |
199 | | // The list starts at the input commandCode. |
200 | | // Return Type: TPMI_YES_NO |
201 | | // YES if there are more command code available |
202 | | // NO all the available command code has been returned |
203 | | TPMI_YES_NO |
204 | | CommandAuditCapGetCCList(TPM_CC commandCode, // IN: start command code |
205 | | UINT32 count, // IN: count of returned TPM_CC |
206 | | TPML_CC* commandList // OUT: list of TPM_CC |
207 | | ) |
208 | 48 | { |
209 | 48 | TPMI_YES_NO more = NO; |
210 | 48 | COMMAND_INDEX commandIndex; |
211 | | |
212 | | // Initialize output handle list |
213 | 48 | commandList->count = 0; |
214 | | |
215 | | // The maximum count of command we may return is MAX_CAP_CC |
216 | 48 | if(count > MAX_CAP_CC) |
217 | 36 | count = MAX_CAP_CC; |
218 | | |
219 | | // Find the implemented command that has a command code that is the same or |
220 | | // higher than the input |
221 | | // Collect audit commands |
222 | 48 | for(commandIndex = GetClosestCommandIndex(commandCode); |
223 | 1.43k | commandIndex != UNIMPLEMENTED_COMMAND_INDEX; |
224 | 1.38k | commandIndex = GetNextCommandIndex(commandIndex)) |
225 | 1.39k | { |
226 | 1.39k | if(CommandAuditIsRequired(commandIndex)) |
227 | 13 | { |
228 | 13 | if(commandList->count < count) |
229 | 11 | { |
230 | | // If we have not filled up the return list, add this command |
231 | | // code to its |
232 | 11 | TPM_CC cc = |
233 | 11 | GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex); |
234 | 11 | if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) |
235 | 0 | cc += (1 << 29); |
236 | 11 | commandList->commandCodes[commandList->count] = cc; |
237 | 11 | commandList->count++; |
238 | 11 | } |
239 | 2 | else |
240 | 2 | { |
241 | | // If the return list is full but we still have command |
242 | | // available, report this and stop iterating |
243 | 2 | more = YES; |
244 | 2 | break; |
245 | 2 | } |
246 | 13 | } |
247 | 1.39k | } |
248 | | |
249 | 48 | return more; |
250 | 48 | } |
251 | | |
252 | | //*** CommandAuditCapGetOneCC() |
253 | | // This function returns true if a command has its audit bit set. |
254 | | BOOL CommandAuditCapGetOneCC(TPM_CC commandCode) // IN: command code |
255 | 0 | { |
256 | 0 | COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); |
257 | 0 | if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) |
258 | 0 | { |
259 | 0 | return CommandAuditIsRequired(commandIndex); |
260 | 0 | } |
261 | 0 | return FALSE; |
262 | 0 | } |
263 | | |
264 | | //*** CommandAuditGetDigest |
265 | | // This command is used to create a digest of the commands being audited. The |
266 | | // commands are processed in ascending numeric order with a list of TPM_CC being |
267 | | // added to a hash. This operates as if all the audited command codes were |
268 | | // concatenated and then hashed. |
269 | | void CommandAuditGetDigest(TPM2B_DIGEST* digest // OUT: command digest |
270 | | ) |
271 | 0 | { |
272 | 0 | TPM_CC commandCode; |
273 | 0 | COMMAND_INDEX commandIndex; |
274 | 0 | HASH_STATE hashState; |
275 | | |
276 | | // Start hash |
277 | 0 | digest->t.size = CryptHashStart(&hashState, gp.auditHashAlg); |
278 | | |
279 | | // Add command code |
280 | 0 | for(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++) |
281 | 0 | { |
282 | 0 | if(CommandAuditIsRequired(commandIndex)) |
283 | 0 | { |
284 | 0 | commandCode = GetCommandCode(commandIndex); |
285 | 0 | CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode); |
286 | 0 | } |
287 | 0 | } |
288 | | |
289 | | // Complete hash |
290 | 0 | CryptHashEnd2B(&hashState, &digest->b); |
291 | |
|
292 | 0 | return; |
293 | 0 | } |