Coverage Report

Created: 2026-02-11 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}