Coverage Report

Created: 2023-09-25 06:15

/src/ibmswtpm2/src/TpmFail.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*           Failure Mode Handling        */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: TpmFail.c 1263 2018-07-12 13:56:36Z kgoldman $   */
7
/*                    */
8
/*  Licenses and Notices              */
9
/*                    */
10
/*  1. Copyright Licenses:              */
11
/*                    */
12
/*  - Trusted Computing Group (TCG) grants to the user of the source code in  */
13
/*    this specification (the "Source Code") a worldwide, irrevocable,    */
14
/*    nonexclusive, royalty free, copyright license to reproduce, create  */
15
/*    derivative works, distribute, display and perform the Source Code and */
16
/*    derivative works thereof, and to grant others the rights granted herein.  */
17
/*                    */
18
/*  - The TCG grants to the user of the other parts of the specification  */
19
/*    (other than the Source Code) the rights to reproduce, distribute,   */
20
/*    display, and perform the specification solely for the purpose of    */
21
/*    developing products based on such documents.        */
22
/*                    */
23
/*  2. Source Code Distribution Conditions:         */
24
/*                    */
25
/*  - Redistributions of Source Code must retain the above copyright licenses,  */
26
/*    this list of conditions and the following disclaimers.      */
27
/*                    */
28
/*  - Redistributions in binary form must reproduce the above copyright   */
29
/*    licenses, this list of conditions and the following disclaimers in the  */
30
/*    documentation and/or other materials provided with the distribution.  */
31
/*                    */
32
/*  3. Disclaimers:               */
33
/*                    */
34
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
35
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
36
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
37
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.   */
38
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for    */
39
/*  information on specification licensing rights available through TCG   */
40
/*  membership agreements.              */
41
/*                    */
42
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED   */
43
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR   */
44
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR    */
45
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY    */
46
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.   */
47
/*                    */
48
/*  - Without limitation, TCG and its members and licensors disclaim all  */
49
/*    liability, including liability for infringement of any proprietary  */
50
/*    rights, relating to use of information in this specification and to the */
51
/*    implementation of this specification, and TCG disclaims all liability for */
52
/*    cost of procurement of substitute goods or services, lost profits, loss   */
53
/*    of use, loss of data or any incidental, consequential, direct, indirect,  */
54
/*    or special damages, whether under contract, tort, warranty or otherwise,  */
55
/*    arising in any way out of use or reliance upon this specification or any  */
56
/*    information herein.             */
57
/*                    */
58
/*  (c) Copyright IBM Corp. and others, 2016 - 2018       */
59
/*                    */
60
/********************************************************************************/
61
62
/* 9.17 TpmFail.c */
63
/* 9.17.1 Includes, Defines, and Types */
64
#define     TPM_FAIL_C
65
#include    "Tpm.h"
66
#include    <assert.h>
67
/*     On MS C compiler, can save the alignment state and set the alignment to 1 for the duration of
68
       the TpmTypes.h include.  This will avoid a lot of alignment warnings from the compiler for
69
       the unaligned structures. The alignment of the structures is not important as this function
70
       does not use any of the structures in TpmTypes.h and only include it for the #defines of the
71
       capabilities, properties, and command code values. */
72
#include "TpmTypes.h"
73
/*     9.17.2 Typedefs */
74
/* These defines are used primarily for sizing of the local response buffer. */
75
typedef struct
76
{
77
    TPM_ST          tag;
78
    UINT32          size;
79
    TPM_RC          code;
80
} HEADER;
81
typedef struct
82
{
83
    BYTE            tag[sizeof(TPM_ST)];
84
    BYTE            size[sizeof(UINT32)];
85
    BYTE            code[sizeof(TPM_RC)];
86
} PACKED_HEADER;
87
typedef struct
88
{
89
    BYTE             size[sizeof(UINT16)];
90
    struct
91
    {
92
  BYTE         function[sizeof(UINT32)];
93
  BYTE         line[sizeof(UINT32)];
94
  BYTE         code[sizeof(UINT32)];
95
    } values;
96
    BYTE             returnCode[sizeof(TPM_RC)];
97
} GET_TEST_RESULT_PARAMETERS;
98
typedef struct
99
{
100
    BYTE         moreData[sizeof(TPMI_YES_NO)];
101
    BYTE         capability[sizeof(TPM_CAP)]; // Always TPM_CAP_TPM_PROPERTIES
102
    BYTE         tpmProperty[sizeof(TPML_TAGGED_TPM_PROPERTY)];
103
} GET_CAPABILITY_PARAMETERS;
104
typedef struct
105
{
106
    BYTE         header[sizeof(PACKED_HEADER)];
107
    BYTE         getTestResult[sizeof(GET_TEST_RESULT_PARAMETERS)];
108
} TEST_RESPONSE;
109
typedef struct
110
{
111
    BYTE         header[sizeof(PACKED_HEADER)];
112
    BYTE         getCap[sizeof(GET_CAPABILITY_PARAMETERS)];
113
} CAPABILITY_RESPONSE;
114
typedef union
115
{
116
    BYTE         test[sizeof(TEST_RESPONSE)];
117
    BYTE         cap[sizeof(CAPABILITY_RESPONSE)];
118
} RESPONSES;
119
/* Buffer to hold the responses. This may be a little larger than required due to padding that a
120
   compiler might add. */
121
/* NOTE: This is not in Global.c because of the specialized data definitions above. Since the data
122
   contained in this structure is not relevant outside of the execution of a single command (when
123
   the TPM is in failure mode. There is no compelling reason to move all the typedefs to Global.h
124
   and this structure to Global.c. */
125
#ifndef __IGNORE_STATE__ // Don't define this value
126
static BYTE response[sizeof(RESPONSES)];
127
#endif
128
/* 9.17.3 Local Functions */
129
/* 9.17.3.1 MarshalUint16() */
130
/* Function to marshal a 16 bit value to the output buffer. */
131
static INT32
132
MarshalUint16(
133
        UINT16          integer,
134
        BYTE            **buffer
135
        )
136
0
{
137
0
    return UINT16_Marshal(&integer, buffer, NULL);
138
0
}
139
/* 9.17.3.2 MarshalUint32() */
140
/* Function to marshal a 32 bit value to the output buffer. */
141
static INT32
142
MarshalUint32(
143
        UINT32           integer,
144
        BYTE            **buffer
145
        )
146
0
{
147
0
    return UINT32_Marshal(&integer, buffer, NULL);
148
0
}
149
/* 9.17.3.3 UnmarshalHeader() */
150
/* function to unmarshal the 10-byte command header. */
151
static BOOL
152
UnmarshalHeader(
153
    HEADER          *header,
154
    BYTE            **buffer,
155
    INT32           *size
156
    )
157
0
{
158
0
    UINT32 usize;
159
0
    TPM_RC ucode;
160
0
    if(UINT16_Unmarshal(&header->tag, buffer, size) != TPM_RC_SUCCESS
161
0
       || UINT32_Unmarshal(&usize, buffer, size) != TPM_RC_SUCCESS
162
0
       || UINT32_Unmarshal(&ucode, buffer, size) != TPM_RC_SUCCESS)
163
0
  return FALSE;
164
0
    header->size = usize;
165
0
    header->code = ucode;
166
0
    return TRUE;
167
0
}
168
/* 9.17.4 Public Functions */
169
/* 9.17.4.1 SetForceFailureMode() */
170
/* This function is called by the simulator to enable failure mode testing. */
171
LIB_EXPORT void
172
SetForceFailureMode(
173
        void
174
        )
175
0
{
176
#if SIMULATION
177
    g_forceFailureMode = TRUE;
178
#endif
179
0
    return;
180
0
}
181
/* 9.17.4.2 TpmFail() */
182
/* This function is called by TPM.lib when a failure occurs. It will set up the failure values to be
183
   returned on TPM2_GetTestResult(). */
184
NORETURN void
185
TpmFail(
186
#if FAIL_TRACE
187
  const char      *function,
188
  int              line,
189
#endif
190
  int              code
191
  )
192
0
{
193
    // Save the values that indicate where the error occurred.
194
    // On a 64-bit machine, this may truncate the address of the string
195
    // of the function name where the error occurred.
196
0
#if FAIL_TRACE
197
0
    s_failFunction = *(UINT32 *)&function;
198
0
    s_failLine = line;
199
#else
200
    s_failFunction = (UINT32)NULL;
201
    s_failLine = 0;
202
#endif
203
0
    s_failCode = code;
204
    // We are in failure mode
205
0
    g_inFailureMode = TRUE;
206
    // if asserts are enabled, then do an assert unless the failure mode code
207
    // is being tested.
208
#if SIMULATION
209
#   ifndef NDEBUG
210
    assert(g_forceFailureMode);
211
#   endif
212
    // Clear this flag
213
    g_forceFailureMode = FALSE;
214
#endif
215
    // Jump to the failure mode code.
216
    // Note: only get here if asserts are off or if we are testing failure mode
217
0
    _plat__Fail();
218
0
}
219
/* 9.17.5 TpmFailureMode */
220
/* This function is called by the interface code when the platform is in failure mode. */
221
void
222
TpmFailureMode(
223
         unsigned int     inRequestSize,     // IN: command buffer size
224
         unsigned char   *inRequest,         // IN: command buffer
225
         unsigned int    *outResponseSize,   // OUT: response buffer size
226
         unsigned char   **outResponse       // OUT: response buffer
227
         )
228
0
{
229
0
    BYTE            *buffer;
230
0
    UINT32           marshalSize;
231
0
    UINT32           capability;
232
0
    HEADER           header;    // unmarshaled command header
233
0
    UINT32           pt;    // unmarshaled property type
234
0
    UINT32           count; // unmarshaled property count
235
    // If there is no command buffer, then just return TPM_RC_FAILURE
236
0
    if(inRequestSize == 0 || inRequest == NULL)
237
0
  goto FailureModeReturn;
238
    // If the header is not correct for TPM2_GetCapability() or
239
    // TPM2_GetTestResult() then just return the in failure mode response;
240
0
    buffer = inRequest;
241
0
    if(!UnmarshalHeader(&header, &inRequest, (INT32 *)&inRequestSize))
242
0
  goto FailureModeReturn;
243
0
    if(header.tag != TPM_ST_NO_SESSIONS
244
0
       || header.size < 10)
245
0
  goto FailureModeReturn;
246
0
    switch(header.code)
247
0
  {
248
0
    case TPM_CC_GetTestResult:
249
      // make sure that the command size is correct
250
0
      if(header.size != 10)
251
0
    goto FailureModeReturn;
252
0
      buffer = &response[10];
253
0
      marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer);
254
0
      marshalSize += MarshalUint32(s_failFunction, &buffer);
255
0
      marshalSize += MarshalUint32(s_failLine, &buffer);
256
0
      marshalSize += MarshalUint32(s_failCode, &buffer);
257
0
      if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
258
0
    marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer);
259
0
      else
260
0
    marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer);
261
0
      break;
262
0
    case TPM_CC_GetCapability:
263
      // make sure that the size of the command is exactly the size
264
      // returned for the capability, property, and count
265
0
      if(header.size != (10 + (3 * sizeof(UINT32)))
266
         // also verify that this is requesting TPM properties
267
0
         || TPM_RC_SUCCESS != UINT32_Unmarshal(&capability, &inRequest,
268
0
                 (INT32 *)&inRequestSize)
269
0
         || capability != TPM_CAP_TPM_PROPERTIES
270
0
         || TPM_RC_SUCCESS != UINT32_Unmarshal(&pt, &inRequest,
271
0
                 (INT32 *)&inRequestSize)
272
0
         || TPM_RC_SUCCESS != UINT32_Unmarshal(&count, &inRequest,
273
0
                 (INT32 *)&inRequestSize))
274
0
    goto FailureModeReturn;
275
      // If in failure mode because of an unrecoverable read error, and the
276
      // property is 0 and the count is 0, then this is an indication to
277
      // re-manufacture the TPM. Do the re-manufacture but stay in failure
278
      // mode until the TPM is reset.
279
      // Note: this behavior is not required by the specification and it is
280
      // OK to leave the TPM permanently bricked due to an unrecoverable NV
281
      // error.
282
0
      if(count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
283
0
    {
284
0
        g_manufactured = FALSE;
285
0
        TPM_Manufacture(0);
286
0
    }
287
0
      if(count > 0)
288
0
    count = 1;
289
0
      else if(pt > TPM_PT_FIRMWARE_VERSION_2)
290
0
    count = 0;
291
0
      if(pt < TPM_PT_MANUFACTURER)
292
0
    pt = TPM_PT_MANUFACTURER;
293
      // set up for return
294
0
      buffer = &response[10];
295
      // if the request was for a PT less than the last one
296
      // then we indicate more, otherwise, not.
297
0
      if(pt < TPM_PT_FIRMWARE_VERSION_2)
298
0
    *buffer++ = YES;
299
0
      else
300
0
    *buffer++ = NO;
301
0
      marshalSize = 1;
302
      // indicate the capability type
303
0
      marshalSize += MarshalUint32(capability, &buffer);
304
      // indicate the number of values that are being returned (0 or 1)
305
0
      marshalSize += MarshalUint32(count, &buffer);
306
      // indicate the property
307
0
      marshalSize += MarshalUint32(pt, &buffer);
308
0
      if(count > 0)
309
0
    switch(pt)
310
0
        {
311
0
          case TPM_PT_MANUFACTURER:
312
      // the vendor ID unique to each TPM manufacturer
313
0
#ifdef  MANUFACTURER
314
0
      pt = *(UINT32*)MANUFACTURER;
315
#else
316
      pt = 0;
317
#endif
318
0
      break;
319
0
          case TPM_PT_VENDOR_STRING_1:
320
      // the first four characters of the vendor ID string
321
0
#ifdef  VENDOR_STRING_1
322
0
      pt = *(UINT32*)VENDOR_STRING_1;
323
#else
324
      pt = 0;
325
#endif
326
0
      break;
327
0
          case TPM_PT_VENDOR_STRING_2:
328
      // the second four characters of the vendor ID string
329
0
#ifdef  VENDOR_STRING_2
330
0
      pt = *(UINT32*)VENDOR_STRING_2;
331
#else
332
      pt = 0;
333
#endif
334
0
      break;
335
0
          case TPM_PT_VENDOR_STRING_3:
336
      // the third four characters of the vendor ID string
337
#ifdef  VENDOR_STRING_3
338
      pt = *(UINT32*)VENDOR_STRING_3;
339
#else
340
0
      pt = 0;
341
0
#endif
342
0
      break;
343
0
          case TPM_PT_VENDOR_STRING_4:
344
      // the fourth four characters of the vendor ID string
345
#ifdef  VENDOR_STRING_4
346
      pt = *(UINT32*)VENDOR_STRING_4;
347
#else
348
0
      pt = 0;
349
0
#endif
350
0
      break;
351
0
          case TPM_PT_VENDOR_TPM_TYPE:
352
      // vendor-defined value indicating the TPM model
353
      // We just make up a number here
354
0
      pt = 1;
355
0
      break;
356
0
          case TPM_PT_FIRMWARE_VERSION_1:
357
      // the more significant 32-bits of a vendor-specific value
358
      // indicating the version of the firmware
359
0
#ifdef  FIRMWARE_V1
360
0
      pt = FIRMWARE_V1;
361
#else
362
      pt = 0;
363
#endif
364
0
      break;
365
0
          default: // TPM_PT_FIRMWARE_VERSION_2:
366
      // the less significant 32-bits of a vendor-specific value
367
      // indicating the version of the firmware
368
0
#ifdef  FIRMWARE_V2
369
0
      pt = FIRMWARE_V2;
370
#else
371
      pt = 0;
372
#endif
373
0
      break;
374
0
        }
375
0
      marshalSize += MarshalUint32(pt, &buffer);
376
0
      break;
377
0
    default: // default for switch (cc)
378
0
      goto FailureModeReturn;
379
0
  }
380
    // Now do the header
381
0
    buffer = response;
382
0
    marshalSize = marshalSize + 10; // Add the header size to the
383
    // stuff already marshaled
384
0
    MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); // structure tag
385
0
    MarshalUint32(marshalSize, &buffer);  // responseSize
386
0
    MarshalUint32(TPM_RC_SUCCESS, &buffer); // response code
387
0
    *outResponseSize = marshalSize;
388
0
    *outResponse = (unsigned char *)&response;
389
0
    return;
390
0
 FailureModeReturn:
391
0
    buffer = response;
392
0
    marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer);
393
0
    marshalSize += MarshalUint32(10, &buffer);
394
0
    marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer);
395
0
    *outResponseSize = marshalSize;
396
0
    *outResponse = (unsigned char *)response;
397
0
    return;
398
0
}
399
/* 9.17.6 UnmarshalFail() */
400
/* This is a stub that is used to catch an attempt to unmarshal an entry that is not defined. Don't
401
   ever expect this to be called but... */
402
void
403
UnmarshalFail(
404
        void            *type,
405
        BYTE            **buffer,
406
        INT32           *size
407
        )
408
0
{
409
0
    NOT_REFERENCED(type);
410
0
    NOT_REFERENCED(buffer);
411
0
    NOT_REFERENCED(size);
412
0
    FAIL(FATAL_ERROR_INTERNAL);
413
0
}