Coverage Report

Created: 2023-06-07 06:46

/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
#ifndef __IGNORE_STATE__ // Don't define this value
70
static BYTE response[sizeof(RESPONSES)];
71
#endif
72
//
73
//
74
//          Local Functions
75
//
76
//         MarshalUint16()
77
//
78
//     Function to marshal a 16 bit value to the output buffer.
79
//
80
static INT32
81
MarshalUint16(
82
    UINT16               integer,
83
    BYTE                 **buffer,
84
    INT32                *size
85
    )
86
0
{
87
0
    return UINT16_Marshal(&integer, buffer, size);
88
0
}
89
//
90
//
91
//         MarshalUint32()
92
//
93
//     Function to marshal a 32 bit value to the output buffer.
94
static INT32
95
MarshalUint32(
96
    UINT32               integer,
97
    BYTE                **buffer,
98
    INT32               *size
99
    )
100
0
{
101
0
    return UINT32_Marshal(&integer, buffer, size);
102
0
}
103
//
104
//
105
//         UnmarshalHeader()
106
//
107
//     Funtion to unmarshal the 10-byte command header.
108
//
109
static BOOL
110
UnmarshalHeader(
111
    HEADER              *header,
112
    BYTE                **buffer,
113
    INT32               *size
114
    )
115
0
{
116
0
    UINT32 usize;
117
0
    TPM_RC ucode;
118
0
    if(     UINT16_Unmarshal(&header->tag, buffer, size) != TPM_RC_SUCCESS
119
0
        || UINT32_Unmarshal(&usize, buffer, size) != TPM_RC_SUCCESS
120
0
        || UINT32_Unmarshal(&ucode, buffer, size) != TPM_RC_SUCCESS
121
0
        )
122
0
        return FALSE;
123
0
    header->size = usize;
124
0
    header->code = ucode;
125
0
    return TRUE;
126
0
}
127
//
128
//
129
//          Public Functions
130
//
131
//         SetForceFailureMode()
132
//
133
//     This function is called by the simulator to enable failure mode testing.
134
//
135
LIB_EXPORT void
136
SetForceFailureMode(
137
    void
138
    )
139
0
{
140
0
    g_forceFailureMode = TRUE;
141
0
    return;
142
0
}
143
144
//
145
//
146
//         TpmFail()
147
//
148
//     This function is called by TPM.lib when a failure occurs. It will set up the failure values to be returned on
149
//     TPM2_GetTestResult().
150
//
151
void
152
TpmFail(
153
    const char                         *function,
154
    int line,                 int       code
155
    )
156
0
{
157
    // Save the values that indicate where the error occurred.
158
    // On a 64-bit machine, this may truncate the address of the string
159
    // of the function name where the error occurred.
160
0
    memcpy(&s_failFunction, function, sizeof(s_failFunction));
161
0
    s_failLine = line;
162
0
    s_failCode = code;
163
    // if asserts are enabled, then do an assert unless the failure mode code
164
    // is being tested
165
0
    assert(g_forceFailureMode);
166
    // Clear this flag
167
0
    g_forceFailureMode = FALSE;
168
    // Jump to the failure mode code.
169
    // Note: only get here if asserts are off or if we are testing failure mode
170
0
#ifndef EMBEDDED_MODE
171
0
    longjmp(&g_jumpBuffer[0], 1);
172
0
#endif
173
0
}
174
//
175
//
176
//          TpmFailureMode
177
//
178
//      This function is called by the interface code when the platform is in failure mode.
179
//
180
void
181
TpmFailureMode (
182
    unsigned   int       inRequestSize,          //   IN: command buffer size
183
    unsigned   char     *inRequest,              //   IN: command buffer
184
    unsigned   int      *outResponseSize,        //   OUT: response buffer size
185
    unsigned   char     **outResponse            //   OUT: response buffer
186
    )
187
0
{
188
0
    BYTE                *buffer;
189
0
    INT32                bufferSize;
190
0
    UINT32               marshalSize;
191
0
    UINT32               capability;
192
0
    HEADER               header;     // unmarshaled command header
193
0
    UINT32               pt;     // unmarshaled property type
194
0
    UINT32               count; // unmarshaled property count
195
    // If there is no command buffer, then just return TPM_RC_FAILURE
196
0
    if(inRequestSize == 0 || inRequest == NULL)
197
0
        goto FailureModeReturn;
198
    // If the header is not correct for TPM2_GetCapability() or
199
    // TPM2_GetTestResult() then just return the in failure mode response;
200
0
    buffer = inRequest;
201
0
    if(!UnmarshalHeader(&header, &inRequest, (INT32 *)&inRequestSize))
202
0
        goto FailureModeReturn;
203
0
    if(   header.tag != TPM_ST_NO_SESSIONS
204
0
       || header.size < 10)
205
0
       goto FailureModeReturn;
206
0
    switch (header.code) {
207
0
    case TPM_CC_GetTestResult:
208
         // make sure that the command size is correct
209
0
         if(header.size != 10)
210
0
              goto FailureModeReturn;
211
0
         buffer = &response[10];
212
0
         bufferSize = MAX_RESPONSE_SIZE-10;
213
0
         marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer, &bufferSize);
214
0
         marshalSize += MarshalUint32(s_failFunction, &buffer, &bufferSize);
215
0
         marshalSize += MarshalUint32(s_failLine, &buffer, &bufferSize);
216
0
         marshalSize += MarshalUint32(s_failCode, &buffer, &bufferSize);
217
0
         if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
218
0
              marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer, &bufferSize);
219
0
         else
220
0
              marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer, &bufferSize);
221
//
222
0
        break;
223
0
   case TPM_CC_GetCapability:
224
       // make sure that the size of the command is exactly the size
225
       // returned for the capability, property, and count
226
0
       if(     header.size!= (10 + (3 * sizeof(UINT32)))
227
               // also verify that this is requesting TPM properties
228
0
           ||      (UINT32_Unmarshal(&capability, &inRequest,
229
0
                                     (INT32 *)&inRequestSize)
230
0
               != TPM_RC_SUCCESS)
231
0
           || (capability != TPM_CAP_TPM_PROPERTIES)
232
0
           ||      (UINT32_Unmarshal(&pt, &inRequest, (INT32 *)&inRequestSize)
233
0
               != TPM_RC_SUCCESS)
234
0
           ||      (UINT32_Unmarshal(&count, &inRequest, (INT32 *)&inRequestSize)
235
0
               != TPM_RC_SUCCESS)
236
0
           )
237
0
              goto FailureModeReturn;
238
        // If in failure mode because of an unrecoverable read error, and the
239
        // property is 0 and the count is 0, then this is an indication to
240
        // re-manufacture the TPM. Do the re-manufacture but stay in failure
241
        // mode until the TPM is reset.
242
        // Note: this behavior is not required by the specification and it is
243
        // OK to leave the TPM permanently bricked due to an unrecoverable NV
244
        // error.
245
0
        if( count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
246
0
        {
247
0
            g_manufactured = FALSE;
248
0
            TPM_Manufacture(0);
249
0
        }
250
0
        if(count > 0)
251
0
            count = 1;
252
0
        else if(pt > TPM_PT_FIRMWARE_VERSION_2)
253
0
            count = 0;
254
0
        if(pt < TPM_PT_MANUFACTURER)
255
0
            pt = TPM_PT_MANUFACTURER;
256
        // set up for return
257
0
        buffer = &response[10];
258
0
        bufferSize = MAX_RESPONSE_SIZE-10;
259
        // if the request was for a PT less than the last one
260
        // then we indicate more, otherwise, not.
261
0
        if(pt < TPM_PT_FIRMWARE_VERSION_2)
262
0
             *buffer++ = YES;
263
0
        else
264
0
             *buffer++ = NO;
265
0
        marshalSize = 1;
266
        // indicate     the capability type
267
0
        marshalSize     += MarshalUint32(capability, &buffer, &bufferSize);
268
        // indicate     the number of values that are being returned (0 or 1)
269
0
        marshalSize     += MarshalUint32(count, &buffer, &bufferSize);
270
        // indicate     the property
271
0
        marshalSize     += MarshalUint32(pt, &buffer, &bufferSize);
272
0
        if(count > 0)
273
0
            switch (pt) {
274
0
            case TPM_PT_MANUFACTURER:
275
            // the vendor ID unique to each TPM manufacturer
276
0
#ifdef   MANUFACTURER
277
0
            pt = *(UINT32*)MANUFACTURER;
278
#else
279
              pt = 0;
280
#endif
281
0
            break;
282
0
        case TPM_PT_VENDOR_STRING_1:
283
            // the first four characters of the vendor ID string
284
0
#ifdef   VENDOR_STRING_1
285
0
            pt = *(UINT32*)VENDOR_STRING_1;
286
#else
287
             pt = 0;
288
#endif
289
0
            break;
290
0
        case TPM_PT_VENDOR_STRING_2:
291
            // the second four characters of the vendor ID string
292
0
#ifdef   VENDOR_STRING_2
293
0
            pt = *(UINT32*)VENDOR_STRING_2;
294
#else
295
             pt = 0;
296
#endif
297
0
            break;
298
0
        case TPM_PT_VENDOR_STRING_3:
299
            // the third four characters of the vendor ID string
300
#ifdef   VENDOR_STRING_3
301
            pt = *(UINT32*)VENDOR_STRING_3;
302
#else
303
0
             pt = 0;
304
0
#endif
305
0
            break;
306
0
        case TPM_PT_VENDOR_STRING_4:
307
            // the fourth four characters of the vendor ID string
308
#ifdef   VENDOR_STRING_4
309
            pt = *(UINT32*)VENDOR_STRING_4;
310
#else
311
0
             pt = 0;
312
0
#endif
313
0
            break;
314
0
        case TPM_PT_VENDOR_TPM_TYPE:
315
            // vendor-defined value indicating the TPM model
316
            // We just make up a number here
317
0
            pt = 1;
318
0
            break;
319
0
        case TPM_PT_FIRMWARE_VERSION_1:
320
            // the more significant 32-bits of a vendor-specific value
321
            // indicating the version of the firmware
322
0
#ifdef   FIRMWARE_V1
323
0
            pt = FIRMWARE_V1;
324
#else
325
             pt = 0;
326
#endif
327
0
            break;
328
0
        default: // TPM_PT_FIRMWARE_VERSION_2:
329
            // the less significant 32-bits of a vendor-specific value
330
            // indicating the version of the firmware
331
0
#ifdef   FIRMWARE_V2
332
0
            pt = FIRMWARE_V2;
333
#else
334
             pt = 0;
335
#endif
336
0
           break;
337
0
       }
338
0
       marshalSize += MarshalUint32(pt, &buffer, &bufferSize);
339
0
       break;
340
0
   default: // default for switch (cc)
341
0
       goto FailureModeReturn;
342
0
   }
343
   // Now do the header
344
0
   buffer = response;
345
0
   bufferSize = 10;
346
0
   marshalSize = marshalSize + 10; // Add the header size to the
347
                                   // stuff already marshaled
348
0
   MarshalUint16(TPM_ST_NO_SESSIONS, &buffer, &bufferSize); // structure tag
349
0
   MarshalUint32(marshalSize, &buffer, &bufferSize); // responseSize
350
0
   MarshalUint32(TPM_RC_SUCCESS, &buffer, &bufferSize); // response code
351
0
   *outResponseSize = marshalSize;
352
0
   *outResponse = (unsigned char *)&response;
353
0
   return;
354
0
FailureModeReturn:
355
0
   buffer = response;
356
0
   bufferSize = 10;
357
0
   marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer, &bufferSize);
358
0
   marshalSize += MarshalUint32(10, &buffer, &bufferSize);
359
0
   marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer, &bufferSize);
360
0
   *outResponseSize = marshalSize;
361
0
   *outResponse = (unsigned char *)response;
362
0
   return;
363
0
}