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