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

stefanberger / libtpms / 2735

pending completion
2735

cron

travis-ci-com

stefanberger
tpm2: rev164: Synchronize _TPM_Init() with upstream

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>

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

33726 of 44191 relevant lines covered (76.32%)

93553.55 hits per line

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

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