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