From aab52651d3df11c6a7908e1d07bd81a98d38bea7 Mon Sep 17 00:00:00 2001 From: Mattias Nissler Date: Fri, 7 Jul 2017 10:26:43 +0200 Subject: Add support for IFX FieldUpgradeInfoRequest2 command Add tpm_lite library support for the IFX specific TPM_FieldUpgrade subcommand "FieldUpgradeInfoRequest2". Expose this via tpmc so it can be used from shell scripts. BRANCH=none BUG=chromium:728130 TEST=Builds and tpmc ifxfieldupgradeinfo prints plausible results. Reviewed-on: https://chromium-review.googlesource.com/562772 Commit-Ready: Mattias Nissler Tested-by: Mattias Nissler Reviewed-by: Mattias Nissler BUG=chromium:761803 Change-Id: I80cf4d82de34e5010393918df2a317ea62e17095 Reviewed-on: https://chromium-review.googlesource.com/657427 Reviewed-by: Mattias Nissler Tested-by: Mattias Nissler --- firmware/include/tlcl.h | 6 ++ firmware/include/tpm1_tss_constants.h | 20 +++++ firmware/include/tpm2_tss_constants.h | 4 + firmware/lib/tpm2_lite/tlcl.c | 6 ++ firmware/lib/tpm_lite/include/tlcl_structures.h | 5 ++ firmware/lib/tpm_lite/mocked_tlcl.c | 6 ++ firmware/lib/tpm_lite/tlcl.c | 71 +++++++++++++++++ tests/tlcl_tests.c | 100 ++++++++++++++++++++++++ utility/tlcl_generator.c | 16 ++++ utility/tpmc.c | 28 +++++++ 10 files changed, 262 insertions(+) diff --git a/firmware/include/tlcl.h b/firmware/include/tlcl.h index 293beb68..fba764c9 100644 --- a/firmware/include/tlcl.h +++ b/firmware/include/tlcl.h @@ -211,4 +211,10 @@ uint32_t TlclGetRandom(uint8_t *data, uint32_t length, uint32_t *size); */ uint32_t TlclGetVersion(uint32_t *vendor, uint64_t *firmware_version); +/** + * Issues the IFX specific FieldUpgradeInfoRequest2 TPM_FieldUpgrade subcommand + * and fills in [info] with results. + */ +uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO *info); + #endif /* TPM_LITE_TLCL_H_ */ diff --git a/firmware/include/tpm1_tss_constants.h b/firmware/include/tpm1_tss_constants.h index 12aca825..972f7a3b 100644 --- a/firmware/include/tpm1_tss_constants.h +++ b/firmware/include/tpm1_tss_constants.h @@ -20,6 +20,7 @@ #define TPM_E_AREA_LOCKED ((uint32_t) 0x0000003c) #define TPM_E_BADINDEX ((uint32_t) 0x00000002) +#define TPM_E_BAD_ORDINAL ((uint32_t) 0x0000000a) #define TPM_E_BAD_PRESENCE ((uint32_t) 0x0000002d) #define TPM_E_IOERROR ((uint32_t) 0x0000001f) #define TPM_E_INVALID_POSTINIT ((uint32_t) 0x00000026) @@ -168,6 +169,24 @@ typedef struct tdTPM_NONCE uint8_t nonce[TPM_SHA1BASED_NONCE_LEN]; } TPM_NONCE; +typedef struct tdTPM_IFX_FIRMWAREPACKAGE { + uint32_t FwPackageIdentifier; + uint32_t Version; + uint32_t StaleVersion; +} TPM_IFX_FIRMWAREPACKAGE; + +typedef struct tdTPM_IFX_FIELDUPGRADEINFO +{ + uint16_t wMaxDataSize; + TPM_IFX_FIRMWAREPACKAGE sBootloaderFirmwarePackage; + TPM_IFX_FIRMWAREPACKAGE sFirmwarePackages[2]; + uint16_t wSecurityModuleStatus; + TPM_IFX_FIRMWAREPACKAGE sProcessFirmwarePackage; + uint16_t wFieldUpgradeCounter; +} TPM_IFX_FIELDUPGRADEINFO; + +#define TPM_IFX_FieldUpgradeInfoRequest2 ((uint8_t) 0x11) + /* Ordinals */ #define TPM_ORD_ContinueSelfTest ((uint32_t) 0x00000053) @@ -187,5 +206,6 @@ typedef struct tdTPM_NONCE #define TPM_ORD_SaveState ((uint32_t) 0x00000098) #define TPM_ORD_SelfTestFull ((uint32_t) 0x00000050) #define TPM_ORD_Startup ((uint32_t) 0x00000099) +#define TPM_ORD_FieldUpgrade ((uint32_t) 0x000000AA) #endif /* ! __VBOOT_REFERENCE_FIRMWARE_INCLUDE_TPM1_TSS_CONSTANTS_H */ diff --git a/firmware/include/tpm2_tss_constants.h b/firmware/include/tpm2_tss_constants.h index 0354004e..53be3fb4 100644 --- a/firmware/include/tpm2_tss_constants.h +++ b/firmware/include/tpm2_tss_constants.h @@ -273,6 +273,10 @@ typedef struct { uint32_t orderly : 1; } TPM_STCLEAR_FLAGS; +typedef struct tdTPM_IFX_FIELDUPGRADEINFO +{ +} TPM_IFX_FIELDUPGRADEINFO; + /* TODO(apronin): For TPM2 certain properties must be received using * TPM2_GetCapability instead of being hardcoded as they are now: * TPM_MAX_COMMAND_SIZE -> use TPM_PT_MAX_COMMAND_SIZE for TPM2. diff --git a/firmware/lib/tpm2_lite/tlcl.c b/firmware/lib/tpm2_lite/tlcl.c index 56829f11..bb212d24 100644 --- a/firmware/lib/tpm2_lite/tlcl.c +++ b/firmware/lib/tpm2_lite/tlcl.c @@ -541,3 +541,9 @@ uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version) *firmware_version = ((uint64_t) version_1 << 32) | version_2; return TPM_SUCCESS; } + +uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO* info) +{ + VB2_DEBUG("NOT YET IMPLEMENTED\n"); + return TPM_E_IOERROR; +} diff --git a/firmware/lib/tpm_lite/include/tlcl_structures.h b/firmware/lib/tpm_lite/include/tlcl_structures.h index cec33110..6ddb8855 100644 --- a/firmware/lib/tpm_lite/include/tlcl_structures.h +++ b/firmware/lib/tpm_lite/include/tlcl_structures.h @@ -1,5 +1,10 @@ /* This file is automatically generated */ +const struct s_tpm_ifx_fieldupgradeinforequest2_cmd{ + uint8_t buffer[13]; +} tpm_ifx_fieldupgradeinforequest2_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xd, 0x0, 0x0, 0x0, 0xaa, 0x11, 0x0, 0x0, }, +}; + const struct s_tpm_getversionval_cmd{ uint8_t buffer[18]; } tpm_getversionval_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x1a, 0x0, 0x0, 0x0, 0x0, }, diff --git a/firmware/lib/tpm_lite/mocked_tlcl.c b/firmware/lib/tpm_lite/mocked_tlcl.c index 2de6ec79..def4810b 100644 --- a/firmware/lib/tpm_lite/mocked_tlcl.c +++ b/firmware/lib/tpm_lite/mocked_tlcl.c @@ -205,3 +205,9 @@ uint32_t TlclSendReceive(const uint8_t* request, uint8_t* response, { return TPM_SUCCESS; } + +uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO* info) +{ + memset(info, 0, sizeof(*info)); + return TPM_SUCCESS; +} diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c index 14acf966..59dd1208 100644 --- a/firmware/lib/tpm_lite/tlcl.c +++ b/firmware/lib/tpm_lite/tlcl.c @@ -548,3 +548,74 @@ uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version) { return TPM_SUCCESS; } + +static void ParseIFXFirmwarePackage(uint8_t** cursor, + TPM_IFX_FIRMWAREPACKAGE* firmware_package) { + + FromTpmUint32(*cursor, &firmware_package->FwPackageIdentifier); + *cursor += sizeof(firmware_package->FwPackageIdentifier); + FromTpmUint32(*cursor, &firmware_package->Version); + *cursor += sizeof(firmware_package->Version); + FromTpmUint32(*cursor, &firmware_package->StaleVersion); + *cursor += sizeof(firmware_package->StaleVersion); +} + +uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO* info) { + uint32_t vendor; + uint64_t firmware_version; + uint32_t result = TlclGetVersion(&vendor, &firmware_version); + if (result != TPM_SUCCESS) { + return result; + } + if (vendor != 0x49465800) { + return TPM_E_BAD_ORDINAL; + } + + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + result = TlclSendReceive(tpm_ifx_fieldupgradeinforequest2_cmd.buffer, + response, sizeof(response)); + if (result != TPM_SUCCESS) { + return result; + } + + uint8_t* cursor = response + kTpmResponseHeaderLength; + + uint16_t size; + FromTpmUint16(cursor, &size); + cursor += sizeof(size); + + /* Comments below indicate skipped fields of unknown purpose that are + * marked "internal" in the firmware updater source. */ + cursor += sizeof(uint16_t); /* internal1 */ + FromTpmUint16(cursor, &info->wMaxDataSize); + cursor += sizeof(info->wMaxDataSize); + cursor += sizeof(uint16_t); /* sSecurityModuleLogic.internal1 */ + cursor += sizeof(uint32_t); /* sSecurityModuleLogic.internal2 */ + cursor += sizeof(uint8_t[34]); /* sSecurityModuleLogic.internal3 */ + ParseIFXFirmwarePackage(&cursor, &info->sBootloaderFirmwarePackage); + uint16_t fw_entry_count; + FromTpmUint16(cursor, &fw_entry_count); + cursor += sizeof(fw_entry_count); + if (fw_entry_count > ARRAY_SIZE(info->sFirmwarePackages)) { + return TPM_E_IOERROR; + } + uint16_t i; + for (i = 0; i < fw_entry_count; ++i) { + ParseIFXFirmwarePackage(&cursor, &info->sFirmwarePackages[i]); + } + FromTpmUint16(cursor, &info->wSecurityModuleStatus); + cursor += sizeof(info->wSecurityModuleStatus); + ParseIFXFirmwarePackage(&cursor, &info->sProcessFirmwarePackage); + cursor += sizeof(uint16_t); /* internal6 */ + cursor += sizeof(uint8_t[6]); /* internal7 */ + FromTpmUint16(cursor, &info->wFieldUpgradeCounter); + cursor += sizeof(info->wFieldUpgradeCounter); + + uint32_t parsed_bytes = cursor - response; + VbAssert(parsed_bytes <= TPM_LARGE_ENOUGH_COMMAND_SIZE); + if (parsed_bytes > kTpmResponseHeaderLength + sizeof(size) + size) { + return TPM_E_IOERROR; + } + + return result; +} diff --git a/tests/tlcl_tests.c b/tests/tlcl_tests.c index f06947b9..b8d64a86 100644 --- a/tests/tlcl_tests.c +++ b/tests/tlcl_tests.c @@ -376,6 +376,105 @@ static void GetVersionTest(void) TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd"); } +/** + * Test IFX FieldUpgradeInfoRequest2 + */ +static void IFXFieldUpgradeInfoTest(void) +{ + uint8_t version_response[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x30, + 0x01, 0x02, 0x04, 0x20, 0x00, 0x02, 0x03, 0x49, + 0x46, 0x58, 0x00, 0x00, 0x0d, 0x04, 0x20, 0x03, + 0x6f, 0x00, 0x74, 0x70, 0x6d, 0x33, 0x38, 0xff, + 0xff, 0xff + }; + uint8_t upgrade_info_response[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6a, 0x03, 0x02, 0x04, 0x9c, + 0x04, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xee, 0xee, 0x5a, 0x3c, + 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f + }; + + ResetMocks(); + calls[0].rsp = version_response; + calls[0].rsp_size = sizeof(version_response); + calls[1].rsp = upgrade_info_response; + calls[1].rsp_size = sizeof(upgrade_info_response); + TPM_IFX_FIELDUPGRADEINFO info; + TEST_EQ(TlclIFXFieldUpgradeInfo(&info), 0, "IFXFieldUpgradeInfo"); + TEST_EQ(calls[1].req_cmd, TPM_ORD_FieldUpgrade, " cmd"); + TEST_EQ(info.wMaxDataSize, 1180, " wMaxDatasize"); + TEST_EQ(info.sBootloaderFirmwarePackage.FwPackageIdentifier, 0x50100, + " bootloader FWPackageIdeintifier"); + TEST_EQ(info.sBootloaderFirmwarePackage.Version, 0xffff, + " bootloader Version"); + TEST_EQ(info.sBootloaderFirmwarePackage.StaleVersion, 0x0, + " bootloader StaleVersion"); + TEST_EQ(info.sFirmwarePackages[0].FwPackageIdentifier, 0x4010100, + " fw[0] FWPackageIdeintifier"); + TEST_EQ(info.sFirmwarePackages[0].Version, 0xbe, + " fw[0] Version"); + TEST_EQ(info.sFirmwarePackages[0].StaleVersion, 0x0, + " fw[0] StaleVersion"); + TEST_EQ(info.sFirmwarePackages[1].FwPackageIdentifier, 0x4010200, + " fw[1] FWPackageIdeintifier"); + TEST_EQ(info.sFirmwarePackages[1].Version, 0x0, + " fw[1] Version"); + TEST_EQ(info.sFirmwarePackages[1].StaleVersion, 0xffffeeee, + " fw[1] StaleVersion"); + TEST_EQ(info.wSecurityModuleStatus, 0x5a3c, " wSecurityModuleStatus"); + TEST_EQ(info.sProcessFirmwarePackage.FwPackageIdentifier, 0x4010200, + " process FWPackageIdeintifier"); + TEST_EQ(info.sProcessFirmwarePackage.Version, 0x832, + " process Version"); + TEST_EQ(info.sProcessFirmwarePackage.StaleVersion, 0x0, + " process StaleVersion"); + TEST_EQ(info.wFieldUpgradeCounter, 0x3f, " wFieldUpgradeCounter"); + + ResetMocks(); + calls[0].rsp = version_response; + calls[0].rsp_size = sizeof(version_response); + SetResponse(1, TPM_E_IOERROR, sizeof(upgrade_info_response) - 1); + TEST_EQ(TlclIFXFieldUpgradeInfo(&info), TPM_E_IOERROR, + "IFXFieldUpgradeInfo - error"); + TEST_EQ(calls[1].req_cmd, TPM_ORD_FieldUpgrade, " cmd"); + + /* Adjust response to indicate a 1 byte too short payload size. */ + ToTpmUint16(upgrade_info_response + kTpmRequestHeaderLength, + sizeof(upgrade_info_response) - kTpmRequestHeaderLength - + sizeof(uint16_t) - 1); + ResetMocks(); + calls[0].rsp = version_response; + calls[0].rsp_size = sizeof(version_response); + calls[1].rsp = upgrade_info_response; + calls[1].rsp_size = sizeof(upgrade_info_response); + TEST_EQ(TlclIFXFieldUpgradeInfo(&info), TPM_E_IOERROR, + "IFXFieldUpgradeInfo - short"); + TEST_EQ(calls[1].req_cmd, TPM_ORD_FieldUpgrade, " cmd"); + + /* Adjust version response to claim a non-IFX vendor. */ + ToTpmUint32(version_response + kTpmResponseHeaderLength + + sizeof(uint32_t), 0); + ResetMocks(); + calls[0].rsp = version_response; + calls[0].rsp_size = sizeof(version_response); + TEST_EQ(TlclIFXFieldUpgradeInfo(&info), TPM_E_IOERROR, + "IFXFieldUpgradeInfo - bad vendor"); + TEST_EQ(calls[1].req_cmd, TPM_ORD_FieldUpgrade, " cmd"); +} + int main(void) { TlclTest(); @@ -385,6 +484,7 @@ int main(void) FlagsTest(); RandomTest(); GetVersionTest(); + IFXFieldUpgradeInfoTest(); return gTestSuccess ? 0 : 255; } diff --git a/utility/tlcl_generator.c b/utility/tlcl_generator.c index 70ce5fd9..bb7ed819 100644 --- a/utility/tlcl_generator.c +++ b/utility/tlcl_generator.c @@ -404,6 +404,21 @@ Command* BuildGetVersionValCommand(void) { return cmd; } +Command* BuildIFXFieldUpgradeInfoRequest2Command(void) { + int size = (kTpmRequestHeaderLength + + sizeof(TPM_IFX_FieldUpgradeInfoRequest2) + + sizeof(uint16_t)); + Command* cmd = newCommand(TPM_ORD_FieldUpgrade, size); + cmd->name = "tpm_ifx_fieldupgradeinforequest2_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_IFX_FieldUpgradeInfoRequest2), + TPM_IFX_FieldUpgradeInfoRequest2); + AddInitializedField(cmd, kTpmRequestHeaderLength + + sizeof(TPM_IFX_FieldUpgradeInfoRequest2), + sizeof(uint16_t), 0); + return cmd; +} + /* Output the fields of a structure. */ void OutputFields(Field* fld) { @@ -526,6 +541,7 @@ Command* (*builders[])(void) = { BuildGetRandomCommand, BuildExtendCommand, BuildGetVersionValCommand, + BuildIFXFieldUpgradeInfoRequest2Command, }; static void FreeFields(Field* fld) { diff --git a/utility/tpmc.c b/utility/tpmc.c index ae45ca1c..a36f7e94 100644 --- a/utility/tpmc.c +++ b/utility/tpmc.c @@ -468,6 +468,31 @@ static uint32_t HandlerGetVersion(void) { return result; } +#ifndef TPM2_MODE +static void PrintIFXFirmwarePackage(TPM_IFX_FIRMWAREPACKAGE* firmware_package, + const char* prefix) { + printf("%s_package_id %08x\n", prefix, + firmware_package->FwPackageIdentifier); + printf("%s_version %08x\n", prefix, firmware_package->Version); + printf("%s_stale_version %08x\n", prefix, firmware_package->StaleVersion); +} + +static uint32_t HandlerIFXFieldUpgradeInfo(void) { + TPM_IFX_FIELDUPGRADEINFO info; + uint32_t result = TlclIFXFieldUpgradeInfo(&info); + if (result == 0) { + printf("max_data_size %u\n", info.wMaxDataSize); + PrintIFXFirmwarePackage(&info.sBootloaderFirmwarePackage, "bootloader"); + PrintIFXFirmwarePackage(&info.sFirmwarePackages[0], "fw0"); + PrintIFXFirmwarePackage(&info.sFirmwarePackages[1], "fw1"); + printf("status %04x\n", info.wSecurityModuleStatus); + PrintIFXFirmwarePackage(&info.sProcessFirmwarePackage, "process_fw"); + printf("field_upgrade_counter %u\n", info.wFieldUpgradeCounter); + } + return result; +} +#endif + #ifdef TPM2_MODE static uint32_t HandlerDoNothingForTPM2(void) { return 0; @@ -548,6 +573,9 @@ command_record command_table[] = { HandlerSendRaw }, { "getversion", "getver", "get TPM vendor and firmware version", HandlerGetVersion }, + { "ifxfieldupgradeinfo", "ifxfui", + TPM20_NOT_IMPLEMENTED("read and print IFX field upgrade info", + HandlerIFXFieldUpgradeInfo) }, }; static int n_commands = sizeof(command_table) / sizeof(command_table[0]); -- cgit v1.2.1