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 { 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 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 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 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 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 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