• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stefanberger / libtpms / #2047

02 Jan 2026 05:02PM UTC coverage: 77.211% (-0.01%) from 77.225%
#2047

push

travis-ci

web-flow
Merge af9de2478 into 03ff2481e

1 of 1 new or added line in 1 file covered. (100.0%)

523 existing lines in 42 files now uncovered.

36060 of 46703 relevant lines covered (77.21%)

101760.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.41
/src/tpm2/ExecCommand.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                             ExecCommand                                        */
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
/* 6.2 ExecCommand.c */
62
/* This file contains the entry function ExecuteCommand() which provides the main control flow for
63
   TPM command execution. */
64
#include "Tpm.h"
65
#include "ExecCommand_fp.h"
66

67
#define TPM_HAVE_TPM2_DECLARATIONS
68
#include "tpm_library_intern.h"  // libtpms added
69

70
/* Uncomment this next #include if doing static command/response buffer sizing */
71
// #include "CommandResponseSizes_fp.h"
72
// The function performs the following steps.
73
// a)        Parses the command header from input buffer.
74
// b)        Calls ParseHandleBuffer() to parse the handle area of the command.
75
//     c)        Validates that each of the handles references a loaded entity.
76
//     d)        Calls ParseSessionBuffer() () to:
77
// 1)        unmarshal and parse the session area;
78
// 2)        check the authorizations; and
79
// 3)        when necessary, decrypt a parameter.
80
//       e)        Calls CommandDispatcher() to:
81
// 1)        unmarshal the command parameters from the command buffer;
82
// 2)        call the routine that performs the command actions; and
83
// 3)        marshal the responses into the response buffer.
84
// f)        If any error occurs in any of the steps above create the error response and return.
85
// g)        Calls BuildResponseSession() to:
86
// 1)        when necessary, encrypt a parameter
87
//       2)        build the response authorization sessions
88
//       3)        update the audit sessions and nonces
89
//       h)        Calls BuildResponseHeader() to complete the construction of the response.
90

91
//           responseSize is set by the caller to the maximum number of bytes available in the output
92
//           buffer. ExecuteCommand() will adjust the value and return the number of bytes placed in
93
//           the buffer.
94
//           response is also set by the caller to indicate the buffer into which ExecuteCommand() is
95
//           to place the response.
96
//           request and response may point to the same buffer
97
//           NOTE: As of February, 2016, the failure processing has been moved to the platform-specific
98
//           code. When the TPM code encounters an unrecoverable failure, it will SET g_inFailureMode
99
//           and call _plat__Fail(). That function should not return but may call ExecuteCommand().
100
LIB_EXPORT void
101
ExecuteCommand(
17,666✔
102
               uint32_t         requestSize,   // IN: command buffer size
103
               unsigned char   *request,       // IN: command buffer
104
               uint32_t        *responseSize,  // IN/OUT: response buffer size
105
               unsigned char   **response      // IN/OUT: response buffer
106
               )
107
{
108
    // Command local variables
109
    UINT32               commandSize;
17,666✔
110
    COMMAND              command;
17,666✔
111
    // Response local variables
112
    UINT32               maxResponse = *responseSize;
17,666✔
113
    TPM_RC               result;            // return code for the command
17,666✔
114

115
    /* check for an unreasonably large command size, since it's cast to a signed integer later */
116
    if (requestSize > INT32_MAX) {
17,666✔
UNCOV
117
        result = TPM_RC_SUCCESS;
×
UNCOV
118
        goto Cleanup;
×
119
    }
120
    // This next function call is used in development to size the command and response
121
    // buffers. The values printed are the sizes of the internal structures and
122
    // not the sizes of the canonical forms of he command response structures. Also,
123
    // the sizes do not include the tag, command.code, requestSize, or the authorization
124
    // fields.
125
    //CommandResponseSizes();
126
    // Set flags for NV access state. This should happen before any other
127
    // operation that may require a NV write. Note, that this needs to be done
128
    // even when in failure mode. Otherwise, g_updateNV would stay SET while in
129
    // Failure mode and the NV would be written on each call.
130
    g_updateNV = UT_NONE;
17,666✔
131
    g_clearOrderly = FALSE;
17,666✔
132
    if(g_inFailureMode)
17,666✔
133
        {
134
            // Do failure mode processing
UNCOV
135
            TpmFailureMode(requestSize, request, responseSize, response);
×
UNCOV
136
            return;
×
137
        }
138
    // Query platform to get the NV state.  The result state is saved internally
139
    // and will be reported by NvIsAvailable(). The reference code requires that
140
    // accessibility of NV does not change during the execution of a command.
141
    // Specifically, if NV is available when the command execution starts and then
142
    // is not available later when it is necessary to write to NV, then the TPM
143
    // will go into failure mode.
144
    NvCheckState();
17,666✔
145
    // Due to the limitations of the simulation, TPM clock must be explicitly
146
    // synchronized with the system clock whenever a command is received.
147
    // This function call is not necessary in a hardware TPM. However, taking
148
    // a snapshot of the hardware timer at the beginning of the command allows
149
    // the time value to be consistent for the duration of the command execution.
150
    TimeUpdateToCurrent();
17,666✔
151
    // Any command through this function will unceremoniously end the
152
    // _TPM_Hash_Data/_TPM_Hash_End sequence.
153
    if(g_DRTMHandle != TPM_RH_UNASSIGNED)
17,666✔
UNCOV
154
        ObjectTerminateEvent();
×
155
    // Get command buffer size and command buffer.
156
    command.tag = 0;                                // libtpms added: Coverity
17,666✔
157
    command.parameterBuffer = request;
17,666✔
158
    command.parameterSize = requestSize;
17,666✔
159
    // Parse command header: tag, commandSize and command.code.
160
    // First parse the tag. The unmarshaling routine will validate
161
    // that it is either TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS.
162
    result = TPMI_ST_COMMAND_TAG_Unmarshal(&command.tag,
17,666✔
163
                                           &command.parameterBuffer,
164
                                           &command.parameterSize);
165
    if(result != TPM_RC_SUCCESS)
17,666✔
166
        goto Cleanup;
12✔
167
    // Unmarshal the commandSize indicator.
168
    result = UINT32_Unmarshal(&commandSize,
17,654✔
169
                              &command.parameterBuffer,
170
                              &command.parameterSize);
171
    if(result != TPM_RC_SUCCESS)
17,654✔
172
        goto Cleanup;
4✔
173
    // On a TPM that receives bytes on a port, the number of bytes that were
174
    // received on that port is requestSize it must be identical to commandSize.
175
    // In addition, commandSize must not be larger than MAX_COMMAND_SIZE allowed
176
    // by the implementation. The check against MAX_COMMAND_SIZE may be redundant
177
    // as the input processing (the function that receives the command bytes and
178
    // places them in the input buffer) would likely have the input truncated when
179
    // it reaches MAX_COMMAND_SIZE, and requestSize would not equal commandSize.
180
    if(commandSize != requestSize || commandSize > MAX_COMMAND_SIZE)
17,650✔
181
        {
182
            result = TPM_RC_COMMAND_SIZE;
4✔
183
            goto Cleanup;
4✔
184
        }
185
    // Unmarshal the command code.
186
    result = TPM_CC_Unmarshal(&command.code, &command.parameterBuffer,
17,646✔
187
                              &command.parameterSize);
188
    if(result != TPM_RC_SUCCESS)
17,646✔
189
        goto Cleanup;
4✔
190
    // Check to see if the command is implemented.
191
    command.index = CommandCodeToCommandIndex(command.code);
17,642✔
192
    if(UNIMPLEMENTED_COMMAND_INDEX == command.index)
17,642✔
193
        {
194
            result = TPM_RC_COMMAND_CODE;
5✔
195
            goto Cleanup;
5✔
196
        }
197
#if  FIELD_UPGRADE_IMPLEMENTED  == YES
198
    // If the TPM is in FUM, then the only allowed command is
199
    // TPM_CC_FieldUpgradeData.
200
    if(IsFieldUgradeMode() && (command.code != TPM_CC_FieldUpgradeData))
201
        {
202
            result = TPM_RC_UPGRADE;
203
            goto Cleanup;
204
        }
205
    else
206
#endif
207
        // Excepting FUM, the TPM only accepts TPM2_Startup() after
208
        // _TPM_Init. After getting a TPM2_Startup(), TPM2_Startup()
209
        // is no longer allowed.
210
        if((!TPMIsStarted() && command.code != TPM_CC_Startup)
17,637✔
211
           || (TPMIsStarted() && command.code == TPM_CC_Startup))
17,612✔
212
            {
213
                result = TPM_RC_INITIALIZE;
36✔
214
                goto Cleanup;
36✔
215
            }
216
    // Start regular command process.
217
    NvIndexCacheInit();
17,601✔
218
    // Parse Handle buffer.
219
    result = ParseHandleBuffer(&command);
17,601✔
220
    if(result != TPM_RC_SUCCESS)
17,601✔
221
        goto Cleanup;
514✔
222
    // All handles in the handle area are required to reference TPM-resident
223
    // entities.
224
    result = EntityGetLoadStatus(&command);
17,087✔
225
    if(result != TPM_RC_SUCCESS)
17,087✔
226
        goto Cleanup;
370✔
227
    // Authorization session handling for the command.
228
    ClearCpRpHashes(&command);
16,717✔
229
    if(command.tag == TPM_ST_SESSIONS)
16,717✔
230
        {
231
            // Find out session buffer size.
232
            result = UINT32_Unmarshal((UINT32 *)&command.authSize,
6,246✔
233
                                      &command.parameterBuffer,
234
                                      &command.parameterSize);
235
            if(result != TPM_RC_SUCCESS)
6,246✔
236
                goto Cleanup;
4✔
237
            // Perform sanity check on the unmarshaled value. If it is smaller than
238
            // the smallest possible session or larger than the remaining size of
239
            // the command, then it is an error. NOTE: This check could pass but the
240
            // session size could still be wrong. That will be determined after the
241
            // sessions are unmarshaled.
242
            if(command.authSize < 9
6,242✔
243
               || command.authSize > command.parameterSize)
6,226✔
244
                {
245
                    result = TPM_RC_SIZE;
24✔
246
                    goto Cleanup;
24✔
247
                }
248
            command.parameterSize -= command.authSize;
6,218✔
249
            // The actions of ParseSessionBuffer() are described in the introduction.
250
            // As the sessions are parsed command.parameterBuffer is advanced so, on a
251
            // successful return, command.parameterBuffer should be pointing at the
252
            // first byte of the parameters.
253
            result = ParseSessionBuffer(&command);
6,218✔
254
            if(result != TPM_RC_SUCCESS)
6,218✔
255
                goto Cleanup;
273✔
256
        }
257
    else
258
        {
259
            command.authSize = 0;
10,471✔
260
            // The command has no authorization sessions.
261
            // If the command requires authorizations, then CheckAuthNoSession() will
262
            // return an error.
263
            result = CheckAuthNoSession(&command);
10,471✔
264
            if(result != TPM_RC_SUCCESS)
10,471✔
265
                goto Cleanup;
24✔
266
        }
267
    // Set up the response buffer pointers. CommandDispatch will marshal the
268
    // response parameters starting at the address in command.responseBuffer.
269
    //    *response = MemoryGetResponseBuffer(command.index);
270
    // leave space for the command header
271
    command.responseBuffer = *response + STD_RESPONSE_HEADER;
16,392✔
272
    // leave space for the parameter size field if needed
273
    if(command.tag == TPM_ST_SESSIONS)
16,392✔
274
        command.responseBuffer += sizeof(UINT32);
5,945✔
275
    if(IsHandleInResponse(command.index))
16,392✔
276
        command.responseBuffer += sizeof(TPM_HANDLE);
2,618✔
277
    // CommandDispatcher returns a response handle buffer and a response parameter
278
    // buffer if it succeeds. It will also set the parameterSize field in the
279
    // buffer if the tag is TPM_RC_SESSIONS.
280
    result = CommandDispatcher(&command);
16,392✔
281
    if(result != TPM_RC_SUCCESS)
16,392✔
282
        goto Cleanup;
1,930✔
283
    // Build the session area at the end of the parameter area.
284
    result = BuildResponseSession(&command);
14,462✔
285
    if(result != TPM_RC_SUCCESS)
14,462✔
286
        {
287
            goto Cleanup;
288
        }
289
 Cleanup:
14,462✔
290
    if(g_clearOrderly == TRUE
17,666✔
291
       && NV_IS_ORDERLY)
482✔
292
        {
293
#if USE_DA_USED
294
            gp.orderlyState = g_daUsed ? SU_DA_USED_VALUE : SU_NONE_VALUE;
2✔
295
#else
296
            gp.orderlyState = SU_NONE_VALUE;
297
#endif
298
            NV_SYNC_PERSISTENT(orderlyState);
2✔
299
        }
300
    // This implementation loads an "evict" object to a transient object slot in
301
    // RAM whenever an "evict" object handle is used in a command so that the
302
    // access to any object is the same. These temporary objects need to be
303
    // cleared from RAM whether the command succeeds or fails.
304
    ObjectCleanupEvict();
17,666✔
305
    // The parameters and sessions have been marshaled. Now tack on the header and
306
    // set the sizes
307
    BuildResponseHeader(&command, *response, result);
17,666✔
308
    // Try to commit all the writes to NV if any NV write happened during this
309
    // command execution. This check should be made for both succeeded and failed
310
    // commands, because a failed one may trigger a NV write in DA logic as well.
311
    // This is the only place in the command execution path that may call the NV
312
    // commit. If the NV commit fails, the TPM should be put in failure mode.
313
    if((g_updateNV != UT_NONE) && !g_inFailureMode)
17,666✔
314
        {
315
            if(g_updateNV == UT_ORDERLY)
6,693✔
316
                NvUpdateIndexOrderlyData();
15✔
317
            if(!NvCommit())
6,693✔
UNCOV
318
                FAIL(FATAL_ERROR_INTERNAL);
×
319
            g_updateNV = UT_NONE;
6,693✔
320
        }
321
    pAssert((UINT32)command.parameterSize <= maxResponse);
17,666✔
322
    // Clear unused bits in response buffer.
323
    MemorySet(*response + *responseSize, 0, maxResponse - *responseSize);
17,666✔
324
    // as a final act, and not before, update the response size.
325
    *responseSize = (UINT32)command.parameterSize;
17,666✔
326
    return;
17,666✔
327
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc