Coverage Report

Created: 2025-07-12 06:49

/src/tpm2/TpmFail.c
Line
Count
Source (jump to first uncovered line)
1
// This file was extracted from the TCG Published
2
// Trusted Platform Module Library
3
// Part 4: Supporting Routines
4
// Family "2.0"
5
// Level 00 Revision 01.16
6
// October 30, 2014
7
8
#define        TPM_FAIL_C
9
#include       "InternalRoutines.h"
10
#include       <assert.h>
11
//
12
//      On MS C compiler, can save the alignment state and set the alignment to 1 for the duration of the
13
//      TPM_Types.h include. This will avoid a lot of alignment warnings from the compiler for the unaligned
14
//      structures. The alignment of the structures is not important as this function does not use any of the
15
//      structures in TPM_Types.h and only include it for the #defines of the capabilities, properties, and
16
//      command code values.
17
//
18
#pragma pack(push, 1)
19
#include "TPM_Types.h"
20
#pragma pack (pop)
21
#include "swap.h"
22
//
23
//
24
//          Typedefs
25
//
26
//      These defines are used primarily for sizing of the local response buffer.
27
//
28
#pragma pack(push,1)
29
typedef struct {
30
   TPM_ST           tag;
31
   UINT32           size;
32
   TPM_RC           code;
33
} HEADER;
34
typedef struct {
35
   UINT16       size;
36
   struct {
37
       UINT32       function;
38
       UINT32       line;
39
       UINT32       code;
40
   } values;
41
   TPM_RC       returnCode;
42
} GET_TEST_RESULT_PARAMETERS;
43
typedef struct {
44
   TPMI_YES_NO                   moreData;
45
   TPM_CAP                       capability; // Always TPM_CAP_TPM_PROPERTIES
46
   TPML_TAGGED_TPM_PROPERTY      tpmProperty; // a single tagged property
47
} GET_CAPABILITY_PARAMETERS;
48
typedef struct {
49
   HEADER header;
50
   GET_TEST_RESULT_PARAMETERS getTestResult;
51
} TEST_RESPONSE;
52
typedef struct {
53
   HEADER header;
54
   GET_CAPABILITY_PARAMETERS     getCap;
55
} CAPABILITY_RESPONSE;
56
typedef union {
57
   TEST_RESPONSE            test;
58
   CAPABILITY_RESPONSE      cap;
59
} RESPONSES;
60
#pragma pack(pop)
61
//
62
//     Buffer to hold the responses. This may be a little larger than required due to padding that a compiler
63
//     might add.
64
//
65
//     NOTE:           This is not in Global.c because of the specialized data definitions above. Since the data contained in this
66
//                     structure is not relevant outside of the execution of a single command (when the TPM is in failure mode. There
67
//                     is no compelling reason to move all the typedefs to Global.h and this structure to Global.c.
68
//
69
static BYTE response[sizeof(RESPONSES)];
70
//
71
//
72
//          Local Functions
73
//
74
//         MarshalUint16()
75
//
76
//     Function to marshal a 16 bit value to the output buffer.
77
//
78
static INT32
79
MarshalUint16(
80
    UINT16               integer,
81
    BYTE                 **buffer,
82
    INT32                *size
83
    )
84
0
{
85
0
    return UINT16_Marshal(&integer, buffer, size);
86
0
}
87
//
88
//
89
//         MarshalUint32()
90
//
91
//     Function to marshal a 32 bit value to the output buffer.
92
static INT32
93
MarshalUint32(
94
    UINT32               integer,
95
    BYTE                **buffer,
96
    INT32               *size
97
    )
98
0
{
99
0
    return UINT32_Marshal(&integer, buffer, size);
100
0
}
101
//
102
//
103
//         UnmarshalHeader()
104
//
105
//     Funtion to unmarshal the 10-byte command header.
106
//
107
static BOOL
108
UnmarshalHeader(
109
    HEADER              *header,
110
    BYTE                **buffer,
111
    INT32               *size
112
    )
113
0
{
114
0
    UINT32 usize;
115
0
    TPM_RC ucode;
116
0
    if(     UINT16_Unmarshal(&header->tag, buffer, size) != TPM_RC_SUCCESS
117
0
        || UINT32_Unmarshal(&usize, buffer, size) != TPM_RC_SUCCESS
118
0
        || UINT32_Unmarshal(&ucode, buffer, size) != TPM_RC_SUCCESS
119
0
        )
120
0
        return FALSE;
121
0
    header->size = usize;
122
0
    header->code = ucode;
123
0
    return TRUE;
124
0
}
125
//
126
//
127
//          Public Functions
128
//
129
//         SetForceFailureMode()
130
//
131
//     This function is called by the simulator to enable failure mode testing.
132
//
133
LIB_EXPORT void
134
SetForceFailureMode(
135
    void
136
    )
137
0
{
138
0
    g_forceFailureMode = TRUE;
139
0
    return;
140
0
}
141
142
//
143
//
144
//         TpmFail()
145
//
146
//     This function is called by TPM.lib when a failure occurs. It will set up the failure values to be returned on
147
//     TPM2_GetTestResult().
148
//
149
void
150
TpmFail(
151
    const char                         *function,
152
    int line,                 int       code
153
    )
154
0
{
155
    // Save the values that indicate where the error occurred.
156
    // On a 64-bit machine, this may truncate the address of the string
157
    // of the function name where the error occurred.
158
0
    memcpy(&s_failFunction, function, sizeof(s_failFunction));
159
0
    s_failLine = line;
160
0
    s_failCode = code;
161
    // if asserts are enabled, then do an assert unless the failure mode code
162
    // is being tested
163
0
    assert(g_forceFailureMode);
164
    // Clear this flag
165
0
    g_forceFailureMode = FALSE;
166
    // Jump to the failure mode code.
167
    // Note: only get here if asserts are off or if we are testing failure mode
168
0
#ifndef EMBEDDED_MODE
169
0
    longjmp(&g_jumpBuffer[0], 1);
170
0
#endif
171
0
}
172
//
173
//
174
//          TpmFailureMode
175
//
176
//      This function is called by the interface code when the platform is in failure mode.
177
//
178
void
179
TpmFailureMode (
180
    unsigned   int       inRequestSize,          //   IN: command buffer size
181
    unsigned   char     *inRequest,              //   IN: command buffer
182
    unsigned   int      *outResponseSize,        //   OUT: response buffer size
183
    unsigned   char     **outResponse            //   OUT: response buffer
184
    )
185
0
{
186
0
    BYTE                *buffer;
187
0
    INT32                bufferSize;
188
0
    UINT32               marshalSize;
189
0
    UINT32               capability;
190
0
    HEADER               header;     // unmarshaled command header
191
0
    UINT32               pt;     // unmarshaled property type
192
0
    UINT32               count; // unmarshaled property count
193
    // If there is no command buffer, then just return TPM_RC_FAILURE
194
0
    if(inRequestSize == 0 || inRequest == NULL)
195
0
        goto FailureModeReturn;
196
    // If the header is not correct for TPM2_GetCapability() or
197
    // TPM2_GetTestResult() then just return the in failure mode response;
198
0
    buffer = inRequest;
199
0
    if(!UnmarshalHeader(&header, &inRequest, (INT32 *)&inRequestSize))
200
0
        goto FailureModeReturn;
201
0
    if(   header.tag != TPM_ST_NO_SESSIONS
202
0
       || header.size < 10)
203
0
       goto FailureModeReturn;
204
0
    switch (header.code) {
205
0
    case TPM_CC_GetTestResult:
206
         // make sure that the command size is correct
207
0
         if(header.size != 10)
208
0
              goto FailureModeReturn;
209
0
         buffer = &response[10];
210
0
         bufferSize = MAX_RESPONSE_SIZE-10;
211
0
         marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer, &bufferSize);
212
0
         marshalSize += MarshalUint32(s_failFunction, &buffer, &bufferSize);
213
0
         marshalSize += MarshalUint32(s_failLine, &buffer, &bufferSize);
214
0
         marshalSize += MarshalUint32(s_failCode, &buffer, &bufferSize);
215
0
         if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
216
0
              marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer, &bufferSize);
217
0
         else
218
0
              marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer, &bufferSize);
219
//
220
0
        break;
221
0
   case TPM_CC_GetCapability:
222
       // make sure that the size of the command is exactly the size
223
       // returned for the capability, property, and count
224
0
       if(     header.size!= (10 + (3 * sizeof(UINT32)))
225
               // also verify that this is requesting TPM properties
226
0
           ||      (UINT32_Unmarshal(&capability, &inRequest,
227
0
                                     (INT32 *)&inRequestSize)
228
0
               != TPM_RC_SUCCESS)
229
0
           || (capability != TPM_CAP_TPM_PROPERTIES)
230
0
           ||      (UINT32_Unmarshal(&pt, &inRequest, (INT32 *)&inRequestSize)
231
0
               != TPM_RC_SUCCESS)
232
0
           ||      (UINT32_Unmarshal(&count, &inRequest, (INT32 *)&inRequestSize)
233
0
               != TPM_RC_SUCCESS)
234
0
           )
235
0
              goto FailureModeReturn;
236
        // If in failure mode because of an unrecoverable read error, and the
237
        // property is 0 and the count is 0, then this is an indication to
238
        // re-manufacture the TPM. Do the re-manufacture but stay in failure
239
        // mode until the TPM is reset.
240
        // Note: this behavior is not required by the specification and it is
241
        // OK to leave the TPM permanently bricked due to an unrecoverable NV
242
        // error.
243
0
        if( count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
244
0
        {
245
0
            g_manufactured = FALSE;
246
0
            TPM_Manufacture(0);
247
0
        }
248
0
        if(count > 0)
249
0
            count = 1;
250
0
        else if(pt > TPM_PT_FIRMWARE_VERSION_2)
251
0
            count = 0;
252
0
        if(pt < TPM_PT_MANUFACTURER)
253
0
            pt = TPM_PT_MANUFACTURER;
254
        // set up for return
255
0
        buffer = &response[10];
256
0
        bufferSize = MAX_RESPONSE_SIZE-10;
257
        // if the request was for a PT less than the last one
258
        // then we indicate more, otherwise, not.
259
0
        if(pt < TPM_PT_FIRMWARE_VERSION_2)
260
0
             *buffer++ = YES;
261
0
        else
262
0
             *buffer++ = NO;
263
0
        marshalSize = 1;
264
        // indicate     the capability type
265
0
        marshalSize     += MarshalUint32(capability, &buffer, &bufferSize);
266
        // indicate     the number of values that are being returned (0 or 1)
267
0
        marshalSize     += MarshalUint32(count, &buffer, &bufferSize);
268
        // indicate     the property
269
0
        marshalSize     += MarshalUint32(pt, &buffer, &bufferSize);
270
0
        if(count > 0)
271
0
            switch (pt) {
272
0
            case TPM_PT_MANUFACTURER:
273
            // the vendor ID unique to each TPM manufacturer
274
0
#ifdef   MANUFACTURER
275
0
            pt = *(UINT32*)MANUFACTURER;
276
#else
277
              pt = 0;
278
#endif
279
0
            break;
280
0
        case TPM_PT_VENDOR_STRING_1:
281
            // the first four characters of the vendor ID string
282
0
#ifdef   VENDOR_STRING_1
283
0
            pt = *(UINT32*)VENDOR_STRING_1;
284
#else
285
             pt = 0;
286
#endif
287
0
            break;
288
0
        case TPM_PT_VENDOR_STRING_2:
289
            // the second four characters of the vendor ID string
290
0
#ifdef   VENDOR_STRING_2
291
0
            pt = *(UINT32*)VENDOR_STRING_2;
292
#else
293
             pt = 0;
294
#endif
295
0
            break;
296
0
        case TPM_PT_VENDOR_STRING_3:
297
            // the third four characters of the vendor ID string
298
#ifdef   VENDOR_STRING_3
299
            pt = *(UINT32*)VENDOR_STRING_3;
300
#else
301
0
             pt = 0;
302
0
#endif
303
0
            break;
304
0
        case TPM_PT_VENDOR_STRING_4:
305
            // the fourth four characters of the vendor ID string
306
#ifdef   VENDOR_STRING_4
307
            pt = *(UINT32*)VENDOR_STRING_4;
308
#else
309
0
             pt = 0;
310
0
#endif
311
0
            break;
312
0
        case TPM_PT_VENDOR_TPM_TYPE:
313
            // vendor-defined value indicating the TPM model
314
            // We just make up a number here
315
0
            pt = 1;
316
0
            break;
317
0
        case TPM_PT_FIRMWARE_VERSION_1:
318
            // the more significant 32-bits of a vendor-specific value
319
            // indicating the version of the firmware
320
0
#ifdef   FIRMWARE_V1
321
0
            pt = FIRMWARE_V1;
322
#else
323
             pt = 0;
324
#endif
325
0
            break;
326
0
        default: // TPM_PT_FIRMWARE_VERSION_2:
327
            // the less significant 32-bits of a vendor-specific value
328
            // indicating the version of the firmware
329
0
#ifdef   FIRMWARE_V2
330
0
            pt = FIRMWARE_V2;
331
#else
332
             pt = 0;
333
#endif
334
0
           break;
335
0
       }
336
0
       marshalSize += MarshalUint32(pt, &buffer, &bufferSize);
337
0
       break;
338
0
   default: // default for switch (cc)
339
0
       goto FailureModeReturn;
340
0
   }
341
   // Now do the header
342
0
   buffer = response;
343
0
   bufferSize = 10;
344
0
   marshalSize = marshalSize + 10; // Add the header size to the
345
                                   // stuff already marshaled
346
0
   MarshalUint16(TPM_ST_NO_SESSIONS, &buffer, &bufferSize); // structure tag
347
0
   MarshalUint32(marshalSize, &buffer, &bufferSize); // responseSize
348
0
   MarshalUint32(TPM_RC_SUCCESS, &buffer, &bufferSize); // response code
349
0
   *outResponseSize = marshalSize;
350
0
   *outResponse = (unsigned char *)&response;
351
0
   return;
352
0
FailureModeReturn:
353
0
   buffer = response;
354
0
   bufferSize = 10;
355
0
   marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer, &bufferSize);
356
0
   marshalSize += MarshalUint32(10, &buffer, &bufferSize);
357
0
   marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer, &bufferSize);
358
0
   *outResponseSize = marshalSize;
359
0
   *outResponse = (unsigned char *)response;
360
0
   return;
361
0
}