summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMattias Nissler <mnissler@chromium.org>2017-12-05 16:27:42 +0100
committerMattias Nissler <mnissler@chromium.org>2018-04-13 10:03:37 +0000
commitdc060ace1b461e09a8e0547f180377d707ff347d (patch)
treed849c2a4281ffbf77aa73f4f2edef2a197cb1ca4
parentec9040c4ef51bef43e8c94c1ecd953145861d834 (diff)
downloadvboot-dc060ace1b461e09a8e0547f180377d707ff347d.tar.gz
tpm_lite: Add TlclGetSpaceInfo
The new TlclGetSpaceInfo function returns more detailed information about a defined NVRAM space. The existing TlclGetPermissions function is now using TlclGetSpaceInfo behind the scenes. BRANCH=None BUG=chromium:788719 TEST=New unit tests. Change-Id: I6c4f490d575788b696fd742a69e81e2767ec50f1 Reviewed-on: https://chromium-review.googlesource.com/937705 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.h11
-rw-r--r--firmware/lib/tpm2_lite/tlcl.c23
-rw-r--r--firmware/lib/tpm_lite/include/tlcl_structures.h5
-rw-r--r--firmware/lib/tpm_lite/tlcl.c113
-rw-r--r--tests/tlcl_tests.c83
-rw-r--r--utility/tlcl_generator.c9
6 files changed, 218 insertions, 26 deletions
diff --git a/firmware/include/tlcl.h b/firmware/include/tlcl.h
index 1b08ec9c..28508c3f 100644
--- a/firmware/include/tlcl.h
+++ b/firmware/include/tlcl.h
@@ -213,6 +213,17 @@ uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest);
uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions);
/**
+ * Get the public information about the NVRAM space identified by |index|. All
+ * other parameters are filled in with the respective information.
+ * |auth_policy_size| is both an input an output parameter. It should contain
+ * the available buffer size in |auth_policy| and will be updated to indicate
+ * the size of the filled in auth policy upon return. If the buffer size is not
+ * sufficient, the return value will be TPM_E_BUFFER_SIZE.
+ */
+uint32_t TlclGetSpaceInfo(uint32_t index, uint32_t *attributes, uint32_t *size,
+ void* auth_policy, uint32_t* auth_policy_size);
+
+/**
* Get the entire set of permanent flags.
*/
uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags);
diff --git a/firmware/lib/tpm2_lite/tlcl.c b/firmware/lib/tpm2_lite/tlcl.c
index 70d584f0..9c0ab887 100644
--- a/firmware/lib/tpm2_lite/tlcl.c
+++ b/firmware/lib/tpm2_lite/tlcl.c
@@ -313,6 +313,29 @@ uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions)
return rv;
}
+uint32_t TlclGetSpaceInfo(uint32_t index, uint32_t *attributes, uint32_t *size,
+ void* auth_policy, uint32_t* auth_policy_size)
+{
+ uint32_t rv;
+ struct nv_read_public_response *resp;
+
+ rv = tlcl_nv_read_public(index, &resp);
+ if (rv != TPM_SUCCESS)
+ return rv;
+
+ *attributes = resp->nvPublic.attributes;
+ *size = resp->nvPublic.dataSize;
+ if (resp->nvPublic.authPolicy.size > *auth_policy_size) {
+ return TPM_E_BUFFER_SIZE;
+ }
+
+ *auth_policy_size = resp->nvPublic.authPolicy.size;
+ memcpy(auth_policy, resp->nvPublic.authPolicy.buffer,
+ *auth_policy_size);
+
+ return TPM_SUCCESS;
+}
+
static uint32_t tlcl_get_capability(TPM_CAP cap, TPM_PT property,
struct get_capability_response **presp)
{
diff --git a/firmware/lib/tpm_lite/include/tlcl_structures.h b/firmware/lib/tpm_lite/include/tlcl_structures.h
index a3772328..8a17ccc8 100644
--- a/firmware/lib/tpm_lite/include/tlcl_structures.h
+++ b/firmware/lib/tpm_lite/include/tlcl_structures.h
@@ -59,10 +59,10 @@ const struct s_tpm_getownership_cmd{
} tpm_getownership_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x11, },
};
-const struct s_tpm_getpermissions_cmd{
+const struct s_tpm_getspaceinfo_cmd{
uint8_t buffer[22];
uint16_t index;
-} tpm_getpermissions_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x4, },
+} tpm_getspaceinfo_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x4, },
18, };
const struct s_tpm_getstclearflags_cmd{
@@ -179,4 +179,3 @@ const struct s_tpm_nv_definespace_cmd{
12, 16, 42, 70, 77, };
const int kWriteInfoLength = 12;
-const int kNvDataPublicPermissionsOffset = 60;
diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c
index 37d0fe20..d7dfade9 100644
--- a/firmware/lib/tpm_lite/tlcl.c
+++ b/firmware/lib/tpm_lite/tlcl.c
@@ -834,21 +834,110 @@ uint32_t TlclExtend(int pcr_num, const uint8_t* in_digest,
uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions)
{
- struct s_tpm_getpermissions_cmd cmd;
- uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
- uint8_t* nvdata;
- uint32_t result;
- uint32_t size;
+ uint32_t dummy_attributes;
+ TPM_NV_AUTH_POLICY dummy_policy;
+ uint32_t dummy_policy_size = sizeof(dummy_policy);
- memcpy(&cmd, &tpm_getpermissions_cmd, sizeof(cmd));
- ToTpmUint32(cmd.buffer + tpm_getpermissions_cmd.index, index);
- result = TlclSendReceive(cmd.buffer, response, sizeof(response));
- if (result != TPM_SUCCESS)
+ return TlclGetSpaceInfo(index, permissions, &dummy_attributes,
+ &dummy_policy, &dummy_policy_size);
+}
+
+static int DecodePCRInfo(const uint8_t** cursor,
+ const uint8_t* end,
+ TPM_PCR_INFO_SHORT* pcr_info)
+{
+ const size_t available_size = end - *cursor;
+ if (available_size < sizeof(uint16_t)) {
+ return 0;
+ }
+
+ uint16_t size_of_select = 0;
+ FromTpmUint16(*cursor, &size_of_select);
+
+ /* Compute the actual size of the encoded PCR selection (which is a
+ * variable-length field). */
+ const size_t encoded_pcr_info_size = sizeof(TPM_PCR_INFO_SHORT) -
+ sizeof(pcr_info->pcrSelection.pcrSelect) + size_of_select;
+ if (available_size < encoded_pcr_info_size ||
+ size_of_select > sizeof(pcr_info->pcrSelection.pcrSelect)) {
+ return 0;
+ }
+
+ memset(&pcr_info->pcrSelection, 0, sizeof(pcr_info->pcrSelection));
+ const size_t pcr_selection_size =
+ sizeof(size_of_select) + size_of_select;
+ memcpy(&pcr_info->pcrSelection, *cursor, pcr_selection_size);
+ *cursor += pcr_selection_size;
+
+ pcr_info->localityAtRelease = **cursor;
+ (*cursor)++;
+
+ memcpy(&pcr_info->digestAtRelease, *cursor, sizeof(TPM_COMPOSITE_HASH));
+ *cursor += sizeof(TPM_COMPOSITE_HASH);
+
+ return 1;
+}
+
+uint32_t TlclGetSpaceInfo(uint32_t index, uint32_t *attributes, uint32_t *size,
+ void* auth_policy, uint32_t* auth_policy_size)
+{
+ TPM_NV_AUTH_POLICY* policy;
+ uint32_t buffer_size = *auth_policy_size;
+ *auth_policy_size = sizeof(TPM_NV_AUTH_POLICY);
+ if (buffer_size < sizeof(TPM_NV_AUTH_POLICY)) {
+ return TPM_E_BUFFER_SIZE;
+ }
+ policy = auth_policy;
+
+ struct s_tpm_getspaceinfo_cmd cmd;
+ memcpy(&cmd, &tpm_getspaceinfo_cmd, sizeof(cmd));
+ ToTpmUint32(cmd.buffer + tpm_getspaceinfo_cmd.index, index);
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+ uint32_t result = TlclSendReceive(cmd.buffer, response,
+ sizeof(response));
+ if (result != TPM_SUCCESS) {
return result;
+ }
- nvdata = response + kTpmResponseHeaderLength + sizeof(size);
- FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions);
- return result;
+ uint32_t response_size = TpmCommandSize(response);
+ if (response_size > sizeof(response)) {
+ return TPM_E_RESPONSE_TOO_LARGE;
+ }
+
+ const uint8_t* cursor = response + kTpmResponseHeaderLength;
+ uint32_t cap_size = ReadTpmUint32(&cursor);
+ if (cap_size >
+ response_size - sizeof(cap_size) - kTpmResponseHeaderLength) {
+ return TPM_E_INVALID_RESPONSE;
+ }
+ const uint8_t* end = cursor + cap_size;
+
+ cursor += sizeof(uint16_t); /* skip tag */
+ uint32_t response_index = ReadTpmUint32(&cursor);
+ if (index != response_index) {
+ return TPM_E_INVALID_RESPONSE;
+ }
+
+ if (!DecodePCRInfo(&cursor, end, &policy->pcr_info_read) ||
+ !DecodePCRInfo(&cursor, end, &policy->pcr_info_write)) {
+ return TPM_E_INVALID_RESPONSE;
+ }
+
+ /* Make sure that the remaining data in the buffer matches the size of
+ * the remaining fields to decode. */
+ if (end - cursor !=
+ 2 * sizeof(uint32_t) + 3 * sizeof(uint8_t) + sizeof(uint16_t)) {
+ return TPM_E_INVALID_RESPONSE;
+ }
+
+ cursor += sizeof(uint16_t); /* skip TPM_NV_ATTRIBUTES tag */
+ *attributes = ReadTpmUint32(&cursor);
+ cursor += sizeof(uint8_t); /* skip bReadSTClear */
+ cursor += sizeof(uint8_t); /* skip bWriteSTClear */
+ cursor += sizeof(uint8_t); /* skip bWriteDefine */
+ *size = ReadTpmUint32(&cursor);
+
+ return TPM_SUCCESS;
}
uint32_t TlclGetOwnership(uint8_t* owned)
diff --git a/tests/tlcl_tests.c b/tests/tlcl_tests.c
index b7f288a3..55e897cb 100644
--- a/tests/tlcl_tests.c
+++ b/tests/tlcl_tests.c
@@ -466,6 +466,83 @@ static void PcrTest(void)
}
/**
+ * Test TlclGetSpaceInfo.
+ */
+static void GetSpaceInfoTest(void)
+{
+ uint8_t response[] = {
+ 0x00, 0xc4, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x18,
+ 0x20, 0x00, 0x00, 0x04, 0x00, 0x03, 0x01, 0x00,
+ 0x00, 0x01, 0xb3, 0x2b, 0x96, 0x30, 0xd3, 0x21,
+ 0x1e, 0x99, 0x78, 0x9e, 0xd3, 0x1f, 0x11, 0x8e,
+ 0x96, 0xbc, 0xf7, 0x7e, 0x7b, 0x06, 0x00, 0x03,
+ 0x20, 0x00, 0x00, 0x10, 0x3b, 0xb2, 0x69, 0x03,
+ 0x3d, 0x12, 0xe1, 0x99, 0x87, 0xe9, 0x3d, 0xf1,
+ 0x11, 0xe8, 0x69, 0xcb, 0x7f, 0xe7, 0xb7, 0x60,
+ 0x00, 0x17, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x45,
+ };
+
+ uint32_t attributes = 0;
+ uint32_t size = 0;
+ TPM_NV_AUTH_POLICY policy;
+ uint32_t policy_size = sizeof(policy);
+
+ /* Test successful parsing. */
+ ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ TEST_EQ(TlclGetSpaceInfo(0x20000004, &attributes, &size, &policy,
+ &policy_size),
+ TPM_SUCCESS, "GetSpaceInfo");
+ TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd");
+ TEST_EQ(policy_size, sizeof(policy), " policy_size");
+ TEST_EQ(attributes, TPM_NV_PER_WRITEDEFINE, " attributes");
+ TEST_EQ(size, 0x45, " size");
+ TEST_EQ(memcmp(&policy, response + 20, sizeof(policy)), 0, " policy");
+
+ /* Test that GetPermissions returns the attributes as well. */
+ ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ TEST_EQ(TlclGetPermissions(0x20000004, &attributes),
+ TPM_SUCCESS, "GetPermissions");
+ TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd");
+ TEST_EQ(attributes, TPM_NV_PER_WRITEDEFINE, " attributes");
+
+ /* Test whether a short response gets detected. */
+ ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ ToTpmUint32(response + 10, 0x46);
+ TEST_EQ(TlclGetSpaceInfo(0x20000004, &attributes, &size, &policy,
+ &policy_size),
+ TPM_E_INVALID_RESPONSE, "GetSpaceInfo short length");
+ ToTpmUint32(response + 10, 0x47);
+
+ /* Test whether an overlong PCR selection length causes failure. */
+ ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ ToTpmUint16(response + 20, 4);
+ TEST_EQ(TlclGetSpaceInfo(0x20000004, &attributes, &size, &policy,
+ &policy_size),
+ TPM_E_INVALID_RESPONSE, "GetSpaceInfo overlong pcr selection");
+ ToTpmUint16(response + 20, 3);
+
+ /* Test that a short policy buffer triggers an error. */
+ ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ policy_size = sizeof(policy) - 1;
+ TEST_EQ(TlclGetSpaceInfo(0x20000004, &attributes, &size, &policy,
+ &policy_size),
+ TPM_E_BUFFER_SIZE, "GetSpaceInfo short policy buffer");
+ TEST_EQ(sizeof(policy), policy_size, " policy_size");
+}
+
+/**
* Test flags / capabilities
*
* TODO: check params/data read/written.
@@ -475,7 +552,6 @@ static void FlagsTest(void)
TPM_PERMANENT_FLAGS pflags;
TPM_STCLEAR_FLAGS vflags;
uint8_t disable = 0, deactivated = 0, nvlocked = 0;
- uint32_t u;
uint8_t buf[32];
ResetMocks();
@@ -493,10 +569,6 @@ static void FlagsTest(void)
TEST_EQ(TlclGetFlags(&disable, &deactivated, &nvlocked), 0, "GetFlags");
ResetMocks();
- TEST_EQ(TlclGetPermissions(1, &u), 0, "GetPermissions");
- TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd");
-
- ResetMocks();
TEST_EQ(TlclGetOwnership(buf), 0, "GetOwnership");
TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd");
}
@@ -1084,6 +1156,7 @@ int main(void)
DefineSpaceExTest();
InitNvAuthPolicyTest();
PcrTest();
+ GetSpaceInfoTest();
FlagsTest();
RandomTest();
GetVersionTest();
diff --git a/utility/tlcl_generator.c b/utility/tlcl_generator.c
index c545bed1..c021ed36 100644
--- a/utility/tlcl_generator.c
+++ b/utility/tlcl_generator.c
@@ -338,14 +338,14 @@ Command* BuildGetSTClearFlagsCommand(void) {
return cmd;
}
-Command* BuildGetPermissionsCommand(void) {
+Command* BuildGetSpaceInfoCommand(void) {
int size = (kTpmRequestHeaderLength +
sizeof(TPM_CAPABILITY_AREA) + /* capArea */
sizeof(uint32_t) + /* subCapSize */
sizeof(uint32_t)); /* subCap */
Command* cmd = newCommand(TPM_ORD_GetCapability, size);
- cmd->name = "tpm_getpermissions_cmd";
+ cmd->name = "tpm_getspaceinfo_cmd";
AddInitializedField(cmd, kTpmRequestHeaderLength,
sizeof(TPM_CAPABILITY_AREA), TPM_CAP_NV_INDEX);
AddInitializedField(cmd, kTpmRequestHeaderLength +
@@ -634,7 +634,7 @@ Command* (*builders[])(void) = {
BuildPhysicalSetDeactivatedCommand,
BuildGetFlagsCommand,
BuildGetSTClearFlagsCommand,
- BuildGetPermissionsCommand,
+ BuildGetSpaceInfoCommand,
BuildGetOwnershipCommand,
BuildGetRandomCommand,
BuildExtendCommand,
@@ -676,9 +676,6 @@ int main(void) {
printf("/* This file is automatically generated */\n\n");
OutputCommands(commands);
printf("const int kWriteInfoLength = %d;\n", (int) sizeof(TPM_WRITE_INFO));
- printf("const int kNvDataPublicPermissionsOffset = %d;\n",
- (int) (offsetof(TPM_NV_DATA_PUBLIC, permission) +
- offsetof(TPM_NV_ATTRIBUTES, attributes)));
FreeCommands(commands);
return 0;