Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | ) |
| 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. |
| 93 | static INT32 |
| 94 | MarshalUint32( |
| 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 | // |
| 107 | static BOOL |
| 108 | UnmarshalHeader( |
| 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 | // |
| 133 | LIB_EXPORT void |
| 134 | SetForceFailureMode( |
| 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 | // |
| 148 | void |
| 149 | TpmFail( |
| 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 | // |
| 175 | void |
| 176 | TpmFailureMode ( |
| 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; |
| 345 | FailureModeReturn: |
| 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 | } |