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