• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
MarshalUint16(UINT16 integer,BYTE ** buffer,INT32 * size)81  MarshalUint16(
82      UINT16               integer,
83      BYTE                 **buffer,
84      INT32                *size
85      )
86  {
87      return UINT16_Marshal(&integer, buffer, size);
88  }
89  //
90  //
91  //         MarshalUint32()
92  //
93  //     Function to marshal a 32 bit value to the output buffer.
94  static INT32
MarshalUint32(UINT32 integer,BYTE ** buffer,INT32 * size)95  MarshalUint32(
96      UINT32               integer,
97      BYTE                **buffer,
98      INT32               *size
99      )
100  {
101      return UINT32_Marshal(&integer, buffer, size);
102  }
103  //
104  //
105  //         UnmarshalHeader()
106  //
107  //     Funtion to unmarshal the 10-byte command header.
108  //
109  static BOOL
UnmarshalHeader(HEADER * header,BYTE ** buffer,INT32 * size)110  UnmarshalHeader(
111      HEADER              *header,
112      BYTE                **buffer,
113      INT32               *size
114      )
115  {
116      UINT32 usize;
117      TPM_RC ucode;
118      if(     UINT16_Unmarshal(&header->tag, buffer, size) != TPM_RC_SUCCESS
119          || UINT32_Unmarshal(&usize, buffer, size) != TPM_RC_SUCCESS
120          || UINT32_Unmarshal(&ucode, buffer, size) != TPM_RC_SUCCESS
121          )
122          return FALSE;
123      header->size = usize;
124      header->code = ucode;
125      return TRUE;
126  }
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
SetForceFailureMode(void)136  SetForceFailureMode(
137      void
138      )
139  {
140      g_forceFailureMode = TRUE;
141      return;
142  }
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
TpmFail(const char * function,int line,int code)152  TpmFail(
153      const char                         *function,
154      int line,                 int       code
155      )
156  {
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      memcpy(&s_failFunction, function, sizeof(s_failFunction));
161      s_failLine = line;
162      s_failCode = code;
163      // if asserts are enabled, then do an assert unless the failure mode code
164      // is being tested
165      assert(g_forceFailureMode);
166      // Clear this flag
167      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  #ifndef EMBEDDED_MODE
171      longjmp(&g_jumpBuffer[0], 1);
172  #endif
173  }
174  //
175  //
176  //          TpmFailureMode
177  //
178  //      This function is called by the interface code when the platform is in failure mode.
179  //
180  void
TpmFailureMode(unsigned int inRequestSize,unsigned char * inRequest,unsigned int * outResponseSize,unsigned char ** outResponse)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  {
188      BYTE                *buffer;
189      INT32                bufferSize;
190      UINT32               marshalSize;
191      UINT32               capability;
192      HEADER               header;     // unmarshaled command header
193      UINT32               pt;     // unmarshaled property type
194      UINT32               count; // unmarshaled property count
195      // If there is no command buffer, then just return TPM_RC_FAILURE
196      if(inRequestSize == 0 || inRequest == NULL)
197          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      buffer = inRequest;
201      if(!UnmarshalHeader(&header, &inRequest, (INT32 *)&inRequestSize))
202          goto FailureModeReturn;
203      if(   header.tag != TPM_ST_NO_SESSIONS
204         || header.size < 10)
205         goto FailureModeReturn;
206      switch (header.code) {
207      case TPM_CC_GetTestResult:
208           // make sure that the command size is correct
209           if(header.size != 10)
210                goto FailureModeReturn;
211           buffer = &response[10];
212           bufferSize = MAX_RESPONSE_SIZE-10;
213           marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer, &bufferSize);
214           marshalSize += MarshalUint32(s_failFunction, &buffer, &bufferSize);
215           marshalSize += MarshalUint32(s_failLine, &buffer, &bufferSize);
216           marshalSize += MarshalUint32(s_failCode, &buffer, &bufferSize);
217           if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
218                marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer, &bufferSize);
219           else
220                marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer, &bufferSize);
221  //
222          break;
223     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         if(     header.size!= (10 + (3 * sizeof(UINT32)))
227                 // also verify that this is requesting TPM properties
228             ||      (UINT32_Unmarshal(&capability, &inRequest,
229                                       (INT32 *)&inRequestSize)
230                 != TPM_RC_SUCCESS)
231             || (capability != TPM_CAP_TPM_PROPERTIES)
232             ||      (UINT32_Unmarshal(&pt, &inRequest, (INT32 *)&inRequestSize)
233                 != TPM_RC_SUCCESS)
234             ||      (UINT32_Unmarshal(&count, &inRequest, (INT32 *)&inRequestSize)
235                 != TPM_RC_SUCCESS)
236             )
237                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          if( count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
246          {
247              g_manufactured = FALSE;
248              TPM_Manufacture(0);
249          }
250          if(count > 0)
251              count = 1;
252          else if(pt > TPM_PT_FIRMWARE_VERSION_2)
253              count = 0;
254          if(pt < TPM_PT_MANUFACTURER)
255              pt = TPM_PT_MANUFACTURER;
256          // set up for return
257          buffer = &response[10];
258          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          if(pt < TPM_PT_FIRMWARE_VERSION_2)
262               *buffer++ = YES;
263          else
264               *buffer++ = NO;
265          marshalSize = 1;
266          // indicate     the capability type
267          marshalSize     += MarshalUint32(capability, &buffer, &bufferSize);
268          // indicate     the number of values that are being returned (0 or 1)
269          marshalSize     += MarshalUint32(count, &buffer, &bufferSize);
270          // indicate     the property
271          marshalSize     += MarshalUint32(pt, &buffer, &bufferSize);
272          if(count > 0)
273              switch (pt) {
274              case TPM_PT_MANUFACTURER:
275              // the vendor ID unique to each TPM manufacturer
276  #ifdef   MANUFACTURER
277              pt = *(UINT32*)MANUFACTURER;
278  #else
279                pt = 0;
280  #endif
281              break;
282          case TPM_PT_VENDOR_STRING_1:
283              // the first four characters of the vendor ID string
284  #ifdef   VENDOR_STRING_1
285              pt = *(UINT32*)VENDOR_STRING_1;
286  #else
287               pt = 0;
288  #endif
289              break;
290          case TPM_PT_VENDOR_STRING_2:
291              // the second four characters of the vendor ID string
292  #ifdef   VENDOR_STRING_2
293              pt = *(UINT32*)VENDOR_STRING_2;
294  #else
295               pt = 0;
296  #endif
297              break;
298          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               pt = 0;
304  #endif
305              break;
306          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               pt = 0;
312  #endif
313              break;
314          case TPM_PT_VENDOR_TPM_TYPE:
315              // vendor-defined value indicating the TPM model
316              // We just make up a number here
317              pt = 1;
318              break;
319          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  #ifdef   FIRMWARE_V1
323              pt = FIRMWARE_V1;
324  #else
325               pt = 0;
326  #endif
327              break;
328          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  #ifdef   FIRMWARE_V2
332              pt = FIRMWARE_V2;
333  #else
334               pt = 0;
335  #endif
336             break;
337         }
338         marshalSize += MarshalUint32(pt, &buffer, &bufferSize);
339         break;
340     default: // default for switch (cc)
341         goto FailureModeReturn;
342     }
343     // Now do the header
344     buffer = response;
345     bufferSize = 10;
346     marshalSize = marshalSize + 10; // Add the header size to the
347                                     // stuff already marshaled
348     MarshalUint16(TPM_ST_NO_SESSIONS, &buffer, &bufferSize); // structure tag
349     MarshalUint32(marshalSize, &buffer, &bufferSize); // responseSize
350     MarshalUint32(TPM_RC_SUCCESS, &buffer, &bufferSize); // response code
351     *outResponseSize = marshalSize;
352     *outResponse = (unsigned char *)&response;
353     return;
354  FailureModeReturn:
355     buffer = response;
356     bufferSize = 10;
357     marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer, &bufferSize);
358     marshalSize += MarshalUint32(10, &buffer, &bufferSize);
359     marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer, &bufferSize);
360     *outResponseSize = marshalSize;
361     *outResponse = (unsigned char *)response;
362     return;
363  }
364