diff options
-rw-r--r-- | firmware/include/tlcl.h | 13 | ||||
-rw-r--r-- | firmware/include/tpm1_tss_constants.h | 59 | ||||
-rw-r--r-- | firmware/lib/tpm_lite/include/tlcl_structures.h | 11 | ||||
-rw-r--r-- | firmware/lib/tpm_lite/tlcl.c | 52 | ||||
-rw-r--r-- | tests/tlcl_tests.c | 85 | ||||
-rw-r--r-- | utility/tlcl_generator.c | 24 |
6 files changed, 223 insertions, 21 deletions
diff --git a/firmware/include/tlcl.h b/firmware/include/tlcl.h index a2a6308e..1b08ec9c 100644 --- a/firmware/include/tlcl.h +++ b/firmware/include/tlcl.h @@ -272,6 +272,19 @@ uint32_t TlclTakeOwnership(uint8_t enc_owner_auth[TPM_RSA_2048_LEN], uint8_t enc_srk_auth[TPM_RSA_2048_LEN], uint8_t owner_auth[TPM_AUTH_DATA_LEN]); +/** + * Create a delegation family with the specified [family_label]. + */ +uint32_t TlclCreateDelegationFamily(uint8_t family_label); + +/** + * Read the delegation family table. Entries are stored in [table]. The size of + * the family table array must be specified in [table_size]. [table_size] gets + * updated to indicate actual number of table entries available. + */ +uint32_t TlclReadDelegationFamilyTable(TPM_FAMILY_TABLE_ENTRY *table, + uint32_t* table_size); + #endif /* TPM2_MODE */ #endif /* CHROMEOS_ENVIRONMENT */ diff --git a/firmware/include/tpm1_tss_constants.h b/firmware/include/tpm1_tss_constants.h index 572d5c61..e91ccf6f 100644 --- a/firmware/include/tpm1_tss_constants.h +++ b/firmware/include/tpm1_tss_constants.h @@ -46,6 +46,10 @@ typedef uint32_t TPM_COMMAND_CODE; typedef uint16_t TPM_PHYSICAL_PRESENCE; typedef uint16_t TPM_STARTUP_TYPE; typedef uint32_t TPM_CAPABILITY_AREA; +typedef uint8_t TPM_FAMILY_LABEL; +typedef uint32_t TPM_FAMILY_ID; +typedef uint32_t TPM_FAMILY_VERIFICATION; +typedef uint32_t TPM_FAMILY_FLAGS; #define TPM_CAP_FLAG ((uint32_t) 0x00000004) #define TPM_CAP_FLAG_PERMANENT ((uint32_t) 0x00000108) @@ -70,6 +74,8 @@ typedef uint32_t TPM_CAPABILITY_AREA; #define TPM_ET_OWNER ((uint32_t) 0x02) +#define TPM_FAMILY_CREATE ((uint32_t) 0x00000001) + #define TPM_ST_CLEAR ((uint16_t) 0x0001) #define TPM_ST_STATE ((uint16_t) 0x0002) #define TPM_ST_DEACTIVATED ((uint16_t) 0x0003) @@ -177,6 +183,15 @@ typedef struct tdTPM_NONCE uint8_t nonce[TPM_SHA1BASED_NONCE_LEN]; } TPM_NONCE; +typedef struct tdTPM_FAMILY_TABLE_ENTRY +{ + TPM_STRUCTURE_TAG tag; + TPM_FAMILY_LABEL familyLabel; + TPM_FAMILY_ID familyID; + TPM_FAMILY_VERIFICATION verificationCount; + TPM_FAMILY_FLAGS flags; +} TPM_FAMILY_TABLE_ENTRY; + typedef struct tdTPM_IFX_FIRMWAREPACKAGE { uint32_t FwPackageIdentifier; uint32_t Version; @@ -203,26 +218,28 @@ typedef struct tdTPM_NV_AUTH_POLICY /* Ordinals */ -#define TPM_ORD_ContinueSelfTest ((uint32_t) 0x00000053) -#define TPM_ORD_Extend ((uint32_t) 0x00000014) -#define TPM_ORD_FieldUpgrade ((uint32_t) 0x000000AA) -#define TPM_ORD_ForceClear ((uint32_t) 0x0000005D) -#define TPM_ORD_GetCapability ((uint32_t) 0x00000065) -#define TPM_ORD_GetRandom ((uint32_t) 0x00000046) -#define TPM_ORD_NV_DefineSpace ((uint32_t) 0x000000CC) -#define TPM_ORD_NV_ReadValue ((uint32_t) 0x000000CF) -#define TPM_ORD_NV_WriteValue ((uint32_t) 0x000000CD) -#define TPM_ORD_OIAP ((uint32_t) 0x0000000A) -#define TPM_ORD_OSAP ((uint32_t) 0x0000000B) -#define TPM_ORD_PcrRead ((uint32_t) 0x00000015) -#define TPM_ORD_PhysicalEnable ((uint32_t) 0x0000006F) -#define TPM_ORD_PhysicalDisable ((uint32_t) 0x00000070) -#define TSC_ORD_PhysicalPresence ((uint32_t) 0x4000000A) -#define TPM_ORD_PhysicalSetDeactivated ((uint32_t) 0x00000072) -#define TPM_ORD_ReadPubek ((uint32_t) 0x0000007C) -#define TPM_ORD_SaveState ((uint32_t) 0x00000098) -#define TPM_ORD_SelfTestFull ((uint32_t) 0x00000050) -#define TPM_ORD_Startup ((uint32_t) 0x00000099) -#define TPM_ORD_TakeOwnership ((uint32_t) 0x0000000D) +#define TPM_ORD_ContinueSelfTest ((uint32_t) 0x00000053) +#define TPM_ORD_Delegate_Manage ((uint32_t) 0x000000D2) +#define TPM_ORD_Delegate_ReadTable ((uint32_t) 0x000000DB) +#define TPM_ORD_Extend ((uint32_t) 0x00000014) +#define TPM_ORD_FieldUpgrade ((uint32_t) 0x000000AA) +#define TPM_ORD_ForceClear ((uint32_t) 0x0000005D) +#define TPM_ORD_GetCapability ((uint32_t) 0x00000065) +#define TPM_ORD_GetRandom ((uint32_t) 0x00000046) +#define TPM_ORD_NV_DefineSpace ((uint32_t) 0x000000CC) +#define TPM_ORD_NV_ReadValue ((uint32_t) 0x000000CF) +#define TPM_ORD_NV_WriteValue ((uint32_t) 0x000000CD) +#define TPM_ORD_OIAP ((uint32_t) 0x0000000A) +#define TPM_ORD_OSAP ((uint32_t) 0x0000000B) +#define TPM_ORD_PcrRead ((uint32_t) 0x00000015) +#define TPM_ORD_PhysicalEnable ((uint32_t) 0x0000006F) +#define TPM_ORD_PhysicalDisable ((uint32_t) 0x00000070) +#define TSC_ORD_PhysicalPresence ((uint32_t) 0x4000000A) +#define TPM_ORD_PhysicalSetDeactivated ((uint32_t) 0x00000072) +#define TPM_ORD_ReadPubek ((uint32_t) 0x0000007C) +#define TPM_ORD_SaveState ((uint32_t) 0x00000098) +#define TPM_ORD_SelfTestFull ((uint32_t) 0x00000050) +#define TPM_ORD_Startup ((uint32_t) 0x00000099) +#define TPM_ORD_TakeOwnership ((uint32_t) 0x0000000D) #endif /* ! __VBOOT_REFERENCE_FIRMWARE_INCLUDE_TPM1_TSS_CONSTANTS_H */ diff --git a/firmware/lib/tpm_lite/include/tlcl_structures.h b/firmware/lib/tpm_lite/include/tlcl_structures.h index 73ed889e..a3772328 100644 --- a/firmware/lib/tpm_lite/include/tlcl_structures.h +++ b/firmware/lib/tpm_lite/include/tlcl_structures.h @@ -1,5 +1,16 @@ /* This file is automatically generated */ +const struct s_tpm_delegate_read_table_cmd{ + uint8_t buffer[10]; +} tpm_delegate_read_table_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xdb, }, +}; + +const struct s_tpm_create_delegation_family_cmd{ + uint8_t buffer[23]; + uint16_t familyLabel; +} tpm_create_delegation_family_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x17, 0x0, 0x0, 0x0, 0xd2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, }, +22, }; + const struct s_tpm_takeownership_cmd{ uint8_t buffer[624]; uint16_t encOwnerAuth; diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c index fe82bd71..37d0fe20 100644 --- a/firmware/lib/tpm_lite/tlcl.c +++ b/firmware/lib/tpm_lite/tlcl.c @@ -1215,4 +1215,56 @@ uint32_t TlclTakeOwnership(uint8_t enc_owner_auth[TPM_RSA_2048_LEN], return TPM_SUCCESS; } +uint32_t TlclCreateDelegationFamily(uint8_t family_label) +{ + struct s_tpm_create_delegation_family_cmd cmd; + memcpy(&cmd, &tpm_create_delegation_family_cmd, sizeof(cmd)); + cmd.buffer[tpm_create_delegation_family_cmd.familyLabel] = family_label; + return Send(cmd.buffer); +} + +uint32_t TlclReadDelegationFamilyTable(TPM_FAMILY_TABLE_ENTRY *table, + uint32_t* table_size) +{ + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t result = TlclSendReceive(tpm_delegate_read_table_cmd.buffer, + response, sizeof(response)); + if (result != TPM_SUCCESS) { + return result; + } + + uint32_t size; + FromTpmUint32(response + sizeof(uint16_t), &size); + if (size < kTpmRequestHeaderLength + sizeof(uint32_t) || + size > sizeof(response)) { + return TPM_E_INVALID_RESPONSE; + } + + const uint8_t* cursor = response + kTpmRequestHeaderLength; + uint32_t table_bytes = ReadTpmUint32(&cursor); + + if (table_bytes > size - (cursor - response)) { + return TPM_E_INVALID_RESPONSE; + } + + uint32_t table_entries = table_bytes / sizeof(TPM_FAMILY_TABLE_ENTRY); + int i; + for (i = 0; i < table_entries; ++i) { + if (i >= *table_size || !table) { + result = TPM_E_BUFFER_SIZE; + break; + } + + table[i].tag = ReadTpmUint16(&cursor); + table[i].familyLabel = *cursor++; + table[i].familyID = ReadTpmUint32(&cursor); + table[i].verificationCount = ReadTpmUint32(&cursor); + table[i].flags = ReadTpmUint32(&cursor); + } + + *table_size = table_entries; + + return result; +} + #endif /* CHROMEOS_ENVIRONMENT */ diff --git a/tests/tlcl_tests.c b/tests/tlcl_tests.c index 65c48f50..b7f288a3 100644 --- a/tests/tlcl_tests.c +++ b/tests/tlcl_tests.c @@ -991,6 +991,91 @@ void TakeOwnershipTest(void) { sizeof(take_ownership_response)); } +/** + * Test ReadDelegationFamilyTable + */ +void ReadDelegationFamilyTableTest(void) { + uint8_t response[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x25, + 0x17, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x25, 0x42, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + TPM_FAMILY_TABLE_ENTRY table[20]; + uint32_t table_size; + + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + table_size = 8; + TEST_EQ(TlclReadDelegationFamilyTable(table, &table_size), + TPM_SUCCESS, "ReadDelegationFamilyTable"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_Delegate_ReadTable, " cmd"); + TEST_EQ(table_size, 2, " table_size"); + TEST_EQ(table[0].tag, 0x25, " table[0].tag"); + TEST_EQ(table[0].familyLabel, 0x17, " table[0].familyLabel"); + TEST_EQ(table[0].familyID, 0x4f, " table[0].familyID"); + TEST_EQ(table[0].verificationCount, 0x1, + " table[0].verificationCount"); + TEST_EQ(table[0].flags, 0x2, " table[0].flags"); + TEST_EQ(table[1].tag, 0x25, " table[1].tag"); + TEST_EQ(table[1].familyLabel, 0x42, " table[1].familyLabel"); + TEST_EQ(table[1].familyID, 0x50, " table[1].familyID"); + TEST_EQ(table[1].verificationCount, 0x1, + " table[1].verificationCount"); + TEST_EQ(table[1].flags, 0x0, " table[1].flags"); + + /* Test that required table size is returned if more space required. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + table_size = 1; + TEST_EQ(TlclReadDelegationFamilyTable(table, &table_size), + TPM_E_BUFFER_SIZE, "ReadDelegationFamilyTable"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_Delegate_ReadTable, " cmd"); + TEST_EQ(table_size, 2, " table_size"); + + /* Test that an overlong response gets caught. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + ToTpmUint32(response + sizeof(uint16_t), TPM_LARGE_ENOUGH_COMMAND_SIZE + + 1); + TEST_EQ(TlclReadDelegationFamilyTable(table, &table_size), + TPM_E_INVALID_RESPONSE, + "ReadDelegationFamilyTable - too long response"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_Delegate_ReadTable, " cmd"); + ToTpmUint32(response + sizeof(uint16_t), sizeof(response)); + + /* Test that a short response gets caught. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + ToTpmUint32(response + sizeof(uint16_t), + kTpmRequestHeaderLength + sizeof(uint32_t) - 1); + TEST_EQ(TlclReadDelegationFamilyTable(table, &table_size), + TPM_E_INVALID_RESPONSE, + "ReadDelegationFamilyTable - too short response"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_Delegate_ReadTable, " cmd"); + ToTpmUint32(response + sizeof(uint16_t), sizeof(response)); + + /* Test that long table size in response gets caught. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + table_size = 20; + ToTpmUint32(response + kTpmResponseHeaderLength, + TPM_LARGE_ENOUGH_COMMAND_SIZE); + TEST_EQ(TlclReadDelegationFamilyTable(table, &table_size), + TPM_E_INVALID_RESPONSE, + "ReadDelegationFamilyTable - overlong family table"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_Delegate_ReadTable, " cmd"); + ToTpmUint32(response + kTpmResponseHeaderLength, 0x1e); +} + int main(void) { TlclTest(); diff --git a/utility/tlcl_generator.c b/utility/tlcl_generator.c index bb3301f0..c545bed1 100644 --- a/utility/tlcl_generator.c +++ b/utility/tlcl_generator.c @@ -495,6 +495,28 @@ Command* BuildTakeOwnershipCommand(void) { return cmd; } +Command* BuildCreateDelegationFamilyCommand(void) { + int size = kTpmRequestHeaderLength + 3 * sizeof(uint32_t) + sizeof(uint8_t); + Command* cmd = newCommand(TPM_ORD_Delegate_Manage, size); + cmd->name = "tpm_create_delegation_family_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, sizeof(uint32_t), + 0 /* familyID */); + AddInitializedField(cmd, kTpmRequestHeaderLength + sizeof(uint32_t), + sizeof(uint32_t), TPM_FAMILY_CREATE); + AddInitializedField(cmd, kTpmRequestHeaderLength + 2 * sizeof(uint32_t), + sizeof(uint32_t), sizeof(uint8_t) /* opDataSize */); + AddVisibleField(cmd, "familyLabel", + kTpmRequestHeaderLength + 3 * sizeof(uint32_t)); + return cmd; +} + +Command* BuildReadDelegationFamilyTableCommand(void) { + Command* cmd = + newCommand(TPM_ORD_Delegate_ReadTable, kTpmRequestHeaderLength); + cmd->name = "tpm_delegate_read_table_cmd"; + return cmd; +} + /* Output the fields of a structure. */ void OutputFields(Field* fld) { @@ -621,6 +643,8 @@ Command* (*builders[])(void) = { BuildOIAPCommand, BuildOSAPCommand, BuildTakeOwnershipCommand, + BuildCreateDelegationFamilyCommand, + BuildReadDelegationFamilyTableCommand, }; static void FreeFields(Field* fld) { |