/src/ibmswtpm2/src/TpmFail.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Failure Mode Handling */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: TpmFail.c 1263 2018-07-12 13:56:36Z kgoldman $ */ |
7 | | /* */ |
8 | | /* Licenses and Notices */ |
9 | | /* */ |
10 | | /* 1. Copyright Licenses: */ |
11 | | /* */ |
12 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
13 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
14 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
15 | | /* derivative works, distribute, display and perform the Source Code and */ |
16 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
17 | | /* */ |
18 | | /* - The TCG grants to the user of the other parts of the specification */ |
19 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
20 | | /* display, and perform the specification solely for the purpose of */ |
21 | | /* developing products based on such documents. */ |
22 | | /* */ |
23 | | /* 2. Source Code Distribution Conditions: */ |
24 | | /* */ |
25 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
26 | | /* this list of conditions and the following disclaimers. */ |
27 | | /* */ |
28 | | /* - Redistributions in binary form must reproduce the above copyright */ |
29 | | /* licenses, this list of conditions and the following disclaimers in the */ |
30 | | /* documentation and/or other materials provided with the distribution. */ |
31 | | /* */ |
32 | | /* 3. Disclaimers: */ |
33 | | /* */ |
34 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
35 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
36 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
37 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
38 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
39 | | /* information on specification licensing rights available through TCG */ |
40 | | /* membership agreements. */ |
41 | | /* */ |
42 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
43 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
44 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
45 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
46 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
47 | | /* */ |
48 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
49 | | /* liability, including liability for infringement of any proprietary */ |
50 | | /* rights, relating to use of information in this specification and to the */ |
51 | | /* implementation of this specification, and TCG disclaims all liability for */ |
52 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
53 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
54 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
55 | | /* arising in any way out of use or reliance upon this specification or any */ |
56 | | /* information herein. */ |
57 | | /* */ |
58 | | /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | /* 9.17 TpmFail.c */ |
63 | | /* 9.17.1 Includes, Defines, and Types */ |
64 | | #define TPM_FAIL_C |
65 | | #include "Tpm.h" |
66 | | #include <assert.h> |
67 | | /* On MS C compiler, can save the alignment state and set the alignment to 1 for the duration of |
68 | | the TpmTypes.h include. This will avoid a lot of alignment warnings from the compiler for |
69 | | the unaligned structures. The alignment of the structures is not important as this function |
70 | | does not use any of the structures in TpmTypes.h and only include it for the #defines of the |
71 | | capabilities, properties, and command code values. */ |
72 | | #include "TpmTypes.h" |
73 | | /* 9.17.2 Typedefs */ |
74 | | /* These defines are used primarily for sizing of the local response buffer. */ |
75 | | typedef struct |
76 | | { |
77 | | TPM_ST tag; |
78 | | UINT32 size; |
79 | | TPM_RC code; |
80 | | } HEADER; |
81 | | typedef struct |
82 | | { |
83 | | BYTE tag[sizeof(TPM_ST)]; |
84 | | BYTE size[sizeof(UINT32)]; |
85 | | BYTE code[sizeof(TPM_RC)]; |
86 | | } PACKED_HEADER; |
87 | | typedef struct |
88 | | { |
89 | | BYTE size[sizeof(UINT16)]; |
90 | | struct |
91 | | { |
92 | | BYTE function[sizeof(UINT32)]; |
93 | | BYTE line[sizeof(UINT32)]; |
94 | | BYTE code[sizeof(UINT32)]; |
95 | | } values; |
96 | | BYTE returnCode[sizeof(TPM_RC)]; |
97 | | } GET_TEST_RESULT_PARAMETERS; |
98 | | typedef struct |
99 | | { |
100 | | BYTE moreData[sizeof(TPMI_YES_NO)]; |
101 | | BYTE capability[sizeof(TPM_CAP)]; // Always TPM_CAP_TPM_PROPERTIES |
102 | | BYTE tpmProperty[sizeof(TPML_TAGGED_TPM_PROPERTY)]; |
103 | | } GET_CAPABILITY_PARAMETERS; |
104 | | typedef struct |
105 | | { |
106 | | BYTE header[sizeof(PACKED_HEADER)]; |
107 | | BYTE getTestResult[sizeof(GET_TEST_RESULT_PARAMETERS)]; |
108 | | } TEST_RESPONSE; |
109 | | typedef struct |
110 | | { |
111 | | BYTE header[sizeof(PACKED_HEADER)]; |
112 | | BYTE getCap[sizeof(GET_CAPABILITY_PARAMETERS)]; |
113 | | } CAPABILITY_RESPONSE; |
114 | | typedef union |
115 | | { |
116 | | BYTE test[sizeof(TEST_RESPONSE)]; |
117 | | BYTE cap[sizeof(CAPABILITY_RESPONSE)]; |
118 | | } RESPONSES; |
119 | | /* Buffer to hold the responses. This may be a little larger than required due to padding that a |
120 | | compiler might add. */ |
121 | | /* NOTE: This is not in Global.c because of the specialized data definitions above. Since the data |
122 | | contained in this structure is not relevant outside of the execution of a single command (when |
123 | | the TPM is in failure mode. There is no compelling reason to move all the typedefs to Global.h |
124 | | and this structure to Global.c. */ |
125 | | #ifndef __IGNORE_STATE__ // Don't define this value |
126 | | static BYTE response[sizeof(RESPONSES)]; |
127 | | #endif |
128 | | /* 9.17.3 Local Functions */ |
129 | | /* 9.17.3.1 MarshalUint16() */ |
130 | | /* Function to marshal a 16 bit value to the output buffer. */ |
131 | | static INT32 |
132 | | MarshalUint16( |
133 | | UINT16 integer, |
134 | | BYTE **buffer |
135 | | ) |
136 | 0 | { |
137 | 0 | return UINT16_Marshal(&integer, buffer, NULL); |
138 | 0 | } |
139 | | /* 9.17.3.2 MarshalUint32() */ |
140 | | /* Function to marshal a 32 bit value to the output buffer. */ |
141 | | static INT32 |
142 | | MarshalUint32( |
143 | | UINT32 integer, |
144 | | BYTE **buffer |
145 | | ) |
146 | 0 | { |
147 | 0 | return UINT32_Marshal(&integer, buffer, NULL); |
148 | 0 | } |
149 | | /* 9.17.3.3 UnmarshalHeader() */ |
150 | | /* function to unmarshal the 10-byte command header. */ |
151 | | static BOOL |
152 | | UnmarshalHeader( |
153 | | HEADER *header, |
154 | | BYTE **buffer, |
155 | | INT32 *size |
156 | | ) |
157 | 0 | { |
158 | 0 | UINT32 usize; |
159 | 0 | TPM_RC ucode; |
160 | 0 | if(UINT16_Unmarshal(&header->tag, buffer, size) != TPM_RC_SUCCESS |
161 | 0 | || UINT32_Unmarshal(&usize, buffer, size) != TPM_RC_SUCCESS |
162 | 0 | || UINT32_Unmarshal(&ucode, buffer, size) != TPM_RC_SUCCESS) |
163 | 0 | return FALSE; |
164 | 0 | header->size = usize; |
165 | 0 | header->code = ucode; |
166 | 0 | return TRUE; |
167 | 0 | } |
168 | | /* 9.17.4 Public Functions */ |
169 | | /* 9.17.4.1 SetForceFailureMode() */ |
170 | | /* This function is called by the simulator to enable failure mode testing. */ |
171 | | LIB_EXPORT void |
172 | | SetForceFailureMode( |
173 | | void |
174 | | ) |
175 | 0 | { |
176 | | #if SIMULATION |
177 | | g_forceFailureMode = TRUE; |
178 | | #endif |
179 | 0 | return; |
180 | 0 | } |
181 | | /* 9.17.4.2 TpmFail() */ |
182 | | /* This function is called by TPM.lib when a failure occurs. It will set up the failure values to be |
183 | | returned on TPM2_GetTestResult(). */ |
184 | | NORETURN void |
185 | | TpmFail( |
186 | | #if FAIL_TRACE |
187 | | const char *function, |
188 | | int line, |
189 | | #endif |
190 | | int code |
191 | | ) |
192 | 0 | { |
193 | | // Save the values that indicate where the error occurred. |
194 | | // On a 64-bit machine, this may truncate the address of the string |
195 | | // of the function name where the error occurred. |
196 | 0 | #if FAIL_TRACE |
197 | 0 | s_failFunction = *(UINT32 *)&function; |
198 | 0 | s_failLine = line; |
199 | | #else |
200 | | s_failFunction = (UINT32)NULL; |
201 | | s_failLine = 0; |
202 | | #endif |
203 | 0 | s_failCode = code; |
204 | | // We are in failure mode |
205 | 0 | g_inFailureMode = TRUE; |
206 | | // if asserts are enabled, then do an assert unless the failure mode code |
207 | | // is being tested. |
208 | | #if SIMULATION |
209 | | # ifndef NDEBUG |
210 | | assert(g_forceFailureMode); |
211 | | # endif |
212 | | // Clear this flag |
213 | | g_forceFailureMode = FALSE; |
214 | | #endif |
215 | | // Jump to the failure mode code. |
216 | | // Note: only get here if asserts are off or if we are testing failure mode |
217 | 0 | _plat__Fail(); |
218 | 0 | } |
219 | | /* 9.17.5 TpmFailureMode */ |
220 | | /* This function is called by the interface code when the platform is in failure mode. */ |
221 | | void |
222 | | TpmFailureMode( |
223 | | unsigned int inRequestSize, // IN: command buffer size |
224 | | unsigned char *inRequest, // IN: command buffer |
225 | | unsigned int *outResponseSize, // OUT: response buffer size |
226 | | unsigned char **outResponse // OUT: response buffer |
227 | | ) |
228 | 0 | { |
229 | 0 | BYTE *buffer; |
230 | 0 | UINT32 marshalSize; |
231 | 0 | UINT32 capability; |
232 | 0 | HEADER header; // unmarshaled command header |
233 | 0 | UINT32 pt; // unmarshaled property type |
234 | 0 | UINT32 count; // unmarshaled property count |
235 | | // If there is no command buffer, then just return TPM_RC_FAILURE |
236 | 0 | if(inRequestSize == 0 || inRequest == NULL) |
237 | 0 | goto FailureModeReturn; |
238 | | // If the header is not correct for TPM2_GetCapability() or |
239 | | // TPM2_GetTestResult() then just return the in failure mode response; |
240 | 0 | buffer = inRequest; |
241 | 0 | if(!UnmarshalHeader(&header, &inRequest, (INT32 *)&inRequestSize)) |
242 | 0 | goto FailureModeReturn; |
243 | 0 | if(header.tag != TPM_ST_NO_SESSIONS |
244 | 0 | || header.size < 10) |
245 | 0 | goto FailureModeReturn; |
246 | 0 | switch(header.code) |
247 | 0 | { |
248 | 0 | case TPM_CC_GetTestResult: |
249 | | // make sure that the command size is correct |
250 | 0 | if(header.size != 10) |
251 | 0 | goto FailureModeReturn; |
252 | 0 | buffer = &response[10]; |
253 | 0 | marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer); |
254 | 0 | marshalSize += MarshalUint32(s_failFunction, &buffer); |
255 | 0 | marshalSize += MarshalUint32(s_failLine, &buffer); |
256 | 0 | marshalSize += MarshalUint32(s_failCode, &buffer); |
257 | 0 | if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) |
258 | 0 | marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer); |
259 | 0 | else |
260 | 0 | marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); |
261 | 0 | break; |
262 | 0 | case TPM_CC_GetCapability: |
263 | | // make sure that the size of the command is exactly the size |
264 | | // returned for the capability, property, and count |
265 | 0 | if(header.size != (10 + (3 * sizeof(UINT32))) |
266 | | // also verify that this is requesting TPM properties |
267 | 0 | || TPM_RC_SUCCESS != UINT32_Unmarshal(&capability, &inRequest, |
268 | 0 | (INT32 *)&inRequestSize) |
269 | 0 | || capability != TPM_CAP_TPM_PROPERTIES |
270 | 0 | || TPM_RC_SUCCESS != UINT32_Unmarshal(&pt, &inRequest, |
271 | 0 | (INT32 *)&inRequestSize) |
272 | 0 | || TPM_RC_SUCCESS != UINT32_Unmarshal(&count, &inRequest, |
273 | 0 | (INT32 *)&inRequestSize)) |
274 | 0 | goto FailureModeReturn; |
275 | | // If in failure mode because of an unrecoverable read error, and the |
276 | | // property is 0 and the count is 0, then this is an indication to |
277 | | // re-manufacture the TPM. Do the re-manufacture but stay in failure |
278 | | // mode until the TPM is reset. |
279 | | // Note: this behavior is not required by the specification and it is |
280 | | // OK to leave the TPM permanently bricked due to an unrecoverable NV |
281 | | // error. |
282 | 0 | if(count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) |
283 | 0 | { |
284 | 0 | g_manufactured = FALSE; |
285 | 0 | TPM_Manufacture(0); |
286 | 0 | } |
287 | 0 | if(count > 0) |
288 | 0 | count = 1; |
289 | 0 | else if(pt > TPM_PT_FIRMWARE_VERSION_2) |
290 | 0 | count = 0; |
291 | 0 | if(pt < TPM_PT_MANUFACTURER) |
292 | 0 | pt = TPM_PT_MANUFACTURER; |
293 | | // set up for return |
294 | 0 | buffer = &response[10]; |
295 | | // if the request was for a PT less than the last one |
296 | | // then we indicate more, otherwise, not. |
297 | 0 | if(pt < TPM_PT_FIRMWARE_VERSION_2) |
298 | 0 | *buffer++ = YES; |
299 | 0 | else |
300 | 0 | *buffer++ = NO; |
301 | 0 | marshalSize = 1; |
302 | | // indicate the capability type |
303 | 0 | marshalSize += MarshalUint32(capability, &buffer); |
304 | | // indicate the number of values that are being returned (0 or 1) |
305 | 0 | marshalSize += MarshalUint32(count, &buffer); |
306 | | // indicate the property |
307 | 0 | marshalSize += MarshalUint32(pt, &buffer); |
308 | 0 | if(count > 0) |
309 | 0 | switch(pt) |
310 | 0 | { |
311 | 0 | case TPM_PT_MANUFACTURER: |
312 | | // the vendor ID unique to each TPM manufacturer |
313 | 0 | #ifdef MANUFACTURER |
314 | 0 | pt = *(UINT32*)MANUFACTURER; |
315 | | #else |
316 | | pt = 0; |
317 | | #endif |
318 | 0 | break; |
319 | 0 | case TPM_PT_VENDOR_STRING_1: |
320 | | // the first four characters of the vendor ID string |
321 | 0 | #ifdef VENDOR_STRING_1 |
322 | 0 | pt = *(UINT32*)VENDOR_STRING_1; |
323 | | #else |
324 | | pt = 0; |
325 | | #endif |
326 | 0 | break; |
327 | 0 | case TPM_PT_VENDOR_STRING_2: |
328 | | // the second four characters of the vendor ID string |
329 | 0 | #ifdef VENDOR_STRING_2 |
330 | 0 | pt = *(UINT32*)VENDOR_STRING_2; |
331 | | #else |
332 | | pt = 0; |
333 | | #endif |
334 | 0 | break; |
335 | 0 | case TPM_PT_VENDOR_STRING_3: |
336 | | // the third four characters of the vendor ID string |
337 | | #ifdef VENDOR_STRING_3 |
338 | | pt = *(UINT32*)VENDOR_STRING_3; |
339 | | #else |
340 | 0 | pt = 0; |
341 | 0 | #endif |
342 | 0 | break; |
343 | 0 | case TPM_PT_VENDOR_STRING_4: |
344 | | // the fourth four characters of the vendor ID string |
345 | | #ifdef VENDOR_STRING_4 |
346 | | pt = *(UINT32*)VENDOR_STRING_4; |
347 | | #else |
348 | 0 | pt = 0; |
349 | 0 | #endif |
350 | 0 | break; |
351 | 0 | case TPM_PT_VENDOR_TPM_TYPE: |
352 | | // vendor-defined value indicating the TPM model |
353 | | // We just make up a number here |
354 | 0 | pt = 1; |
355 | 0 | break; |
356 | 0 | case TPM_PT_FIRMWARE_VERSION_1: |
357 | | // the more significant 32-bits of a vendor-specific value |
358 | | // indicating the version of the firmware |
359 | 0 | #ifdef FIRMWARE_V1 |
360 | 0 | pt = FIRMWARE_V1; |
361 | | #else |
362 | | pt = 0; |
363 | | #endif |
364 | 0 | break; |
365 | 0 | default: // TPM_PT_FIRMWARE_VERSION_2: |
366 | | // the less significant 32-bits of a vendor-specific value |
367 | | // indicating the version of the firmware |
368 | 0 | #ifdef FIRMWARE_V2 |
369 | 0 | pt = FIRMWARE_V2; |
370 | | #else |
371 | | pt = 0; |
372 | | #endif |
373 | 0 | break; |
374 | 0 | } |
375 | 0 | marshalSize += MarshalUint32(pt, &buffer); |
376 | 0 | break; |
377 | 0 | default: // default for switch (cc) |
378 | 0 | goto FailureModeReturn; |
379 | 0 | } |
380 | | // Now do the header |
381 | 0 | buffer = response; |
382 | 0 | marshalSize = marshalSize + 10; // Add the header size to the |
383 | | // stuff already marshaled |
384 | 0 | MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); // structure tag |
385 | 0 | MarshalUint32(marshalSize, &buffer); // responseSize |
386 | 0 | MarshalUint32(TPM_RC_SUCCESS, &buffer); // response code |
387 | 0 | *outResponseSize = marshalSize; |
388 | 0 | *outResponse = (unsigned char *)&response; |
389 | 0 | return; |
390 | 0 | FailureModeReturn: |
391 | 0 | buffer = response; |
392 | 0 | marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); |
393 | 0 | marshalSize += MarshalUint32(10, &buffer); |
394 | 0 | marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); |
395 | 0 | *outResponseSize = marshalSize; |
396 | 0 | *outResponse = (unsigned char *)response; |
397 | 0 | return; |
398 | 0 | } |
399 | | /* 9.17.6 UnmarshalFail() */ |
400 | | /* This is a stub that is used to catch an attempt to unmarshal an entry that is not defined. Don't |
401 | | ever expect this to be called but... */ |
402 | | void |
403 | | UnmarshalFail( |
404 | | void *type, |
405 | | BYTE **buffer, |
406 | | INT32 *size |
407 | | ) |
408 | 0 | { |
409 | 0 | NOT_REFERENCED(type); |
410 | 0 | NOT_REFERENCED(buffer); |
411 | 0 | NOT_REFERENCED(size); |
412 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
413 | 0 | } |