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