• 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