summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMattias Nissler <mnissler@chromium.org>2017-12-08 14:13:25 +0100
committerMattias Nissler <mnissler@chromium.org>2018-04-13 10:03:34 +0000
commit2e62620ce740bff57b659905f3a4a929898834f6 (patch)
tree6ec38399fd040fe40b298f7e4acc6643acaa1ec4
parentbc5b2db15b93f37820574b8f14a1b2e165012403 (diff)
downloadvboot-2e62620ce740bff57b659905f3a4a929898834f6.tar.gz
tpm_lite: Support delegation family functionality.
Adds two new functions and their corresponding TPM commands to create delegation families and list the delegation family table, respectively. This isn't sufficient to meaningfully manage delegation families, but good enough for the (ab)use case of storing flags in delegation family labels, which we are going to do in order to strengthen encrypted stateful to guarantee recreation of the encrypted file system after TPM clear.. BRANCH=None BUG=chromium:788719 TEST=new unit tests Change-Id: I31beb662784a8fff450b485c7cabc553944d7772 Reviewed-on: https://chromium-review.googlesource.com/817199 Trybot-Ready: Mattias Nissler <mnissler@chromium.org> Tested-by: Mattias Nissler <mnissler@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org>
-rw-r--r--firmware/include/tlcl.h13
-rw-r--r--firmware/include/tpm1_tss_constants.h59
-rw-r--r--firmware/lib/tpm_lite/include/tlcl_structures.h11
-rw-r--r--firmware/lib/tpm_lite/tlcl.c52
-rw-r--r--tests/tlcl_tests.c85
-rw-r--r--utility/tlcl_generator.c24
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) {