Home | History | Annotate | Download | only in tpm2
      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