summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Pronin <apronin@chromium.org>2017-10-06 20:01:53 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-10-24 00:34:58 +0000
commitc1a7eb2c75c4007bddb0afc73189d9d15fb552c0 (patch)
treead2abd445df3b241a0217281ceac11142dacf1f9
parent96a0ead803c22fb5e55effb9d3a571a4c88f29db (diff)
downloadvboot-stabilize-9901.53.B.tar.gz
tlcl, tpmc: extend GetVersion to report vendor specific datastabilize-9901.77.Bstabilize-9901.54.Bstabilize-9901.53.Brelease-R62-9901.B
1) Extend TlclGetVersion to return vendor specific data, if requested. 2) Extend 'tpmc getver' to include vendor specific data. BRANCH=none BUG=chromium:771561 TEST=unit tests, running 'tpmc getver' Change-Id: Ic04c242d4e6f33b45a80479be9ab9777b317ebe2 Reviewed-on: https://chromium-review.googlesource.com/706240 Commit-Ready: Andrey Pronin <apronin@chromium.org> Tested-by: Andrey Pronin <apronin@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org> (cherry picked from commit 3b805725c15022783f0737a72b4f27962abf48cd) Reviewed-on: https://chromium-review.googlesource.com/733664 Commit-Queue: Andrey Pronin <apronin@chromium.org>
-rw-r--r--firmware/include/tlcl.h13
-rw-r--r--firmware/include/tpm2_tss_constants.h2
-rw-r--r--firmware/lib/tpm2_lite/tlcl.c49
-rw-r--r--firmware/lib/tpm_lite/mocked_tlcl.c7
-rw-r--r--firmware/lib/tpm_lite/tlcl.c32
-rw-r--r--tests/tlcl_tests.c69
-rw-r--r--utility/tpmc.c12
7 files changed, 170 insertions, 14 deletions
diff --git a/firmware/include/tlcl.h b/firmware/include/tlcl.h
index fba764c9..f8d94721 100644
--- a/firmware/include/tlcl.h
+++ b/firmware/include/tlcl.h
@@ -208,8 +208,17 @@ uint32_t TlclGetRandom(uint8_t *data, uint32_t length, uint32_t *size);
/**
* Requests version information from the TPM.
- */
-uint32_t TlclGetVersion(uint32_t *vendor, uint64_t *firmware_version);
+ * If vendor_specific_buf_size != NULL, requests also the vendor-specific
+ * variable-length part of the version:
+ * if vendor_specific_buf == NULL, determines its size and returns in
+ * *vendor_specific_buf_size;
+ * if vendor_specific_buf != NULL, fills the buffer until either the
+ * end of the vendor specific data or the end of the buffer, sets
+ * *vendor_specific_buf_size to the length of the filled data.
+ */
+uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version,
+ uint8_t* vendor_specific_buf,
+ size_t* vendor_specific_buf_size);
/**
* Issues the IFX specific FieldUpgradeInfoRequest2 TPM_FieldUpgrade subcommand
diff --git a/firmware/include/tpm2_tss_constants.h b/firmware/include/tpm2_tss_constants.h
index 53be3fb4..f44dc715 100644
--- a/firmware/include/tpm2_tss_constants.h
+++ b/firmware/include/tpm2_tss_constants.h
@@ -55,6 +55,8 @@
#define PT_GROUP ((TPM_PT)0x00000100)
#define PT_FIXED PT_GROUP
#define TPM_PT_MANUFACTURER (PT_FIXED + 5)
+#define TPM_PT_VENDOR_STRING_1 (PT_FIXED + 6)
+#define TPM_PT_VENDOR_STRING_4 (PT_FIXED + 9)
#define TPM_PT_FIRMWARE_VERSION_1 (PT_FIXED + 11)
#define TPM_PT_FIRMWARE_VERSION_2 (PT_FIXED + 12)
#define PT_VAR (PT_GROUP * 2)
diff --git a/firmware/lib/tpm2_lite/tlcl.c b/firmware/lib/tpm2_lite/tlcl.c
index bb212d24..89bf25a7 100644
--- a/firmware/lib/tpm2_lite/tlcl.c
+++ b/firmware/lib/tpm2_lite/tlcl.c
@@ -523,7 +523,25 @@ uint32_t TlclGetRandom(uint8_t *data, uint32_t length, uint32_t *size)
return TPM_E_IOERROR;
}
-uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version)
+// Converts TPM_PT_VENDOR_STRING_x |value| to an array of bytes in |buf|.
+// Returns the number of bytes in the array.
+// |buf| should be at least 4 bytes long.
+size_t tlcl_vendor_string_parse(uint32_t value, uint8_t* buf)
+{
+ size_t len = 0;
+ int shift = 24;
+ for (; len < 4; shift -= 8) {
+ uint8_t byte = (value >> shift) & 0xffu;
+ if (!byte)
+ break;
+ buf[len++] = byte;
+ }
+ return len;
+}
+
+uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version,
+ uint8_t* vendor_specific_buf,
+ size_t* vendor_specific_buf_size)
{
uint32_t result = tlcl_get_tpm_property(TPM_PT_MANUFACTURER, vendor);
if (result != TPM_SUCCESS)
@@ -539,6 +557,35 @@ uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version)
return result;
*firmware_version = ((uint64_t) version_1 << 32) | version_2;
+
+ if (!vendor_specific_buf_size)
+ return TPM_SUCCESS;
+
+ size_t total_size = 0;
+ uint32_t prop_id;
+ uint8_t prop_string[16];
+ for (prop_id = TPM_PT_VENDOR_STRING_1;
+ prop_id <= TPM_PT_VENDOR_STRING_4;
+ ++prop_id) {
+ uint32_t prop_value;
+ result = tlcl_get_tpm_property(prop_id, &prop_value);
+ if (result != TPM_SUCCESS)
+ break;
+
+ size_t prop_len = tlcl_vendor_string_parse(
+ prop_value, prop_string + total_size);
+ VbAssert(prop_len <= 4 &&
+ total_size + prop_len <= sizeof(prop_string));
+ total_size += prop_len;
+ if (prop_len < 4)
+ break;
+ }
+ if (vendor_specific_buf) {
+ if (total_size > *vendor_specific_buf_size)
+ total_size = *vendor_specific_buf_size;
+ memcpy(vendor_specific_buf, prop_string, total_size);
+ }
+ *vendor_specific_buf_size = total_size;
return TPM_SUCCESS;
}
diff --git a/firmware/lib/tpm_lite/mocked_tlcl.c b/firmware/lib/tpm_lite/mocked_tlcl.c
index def4810b..0abcb7c9 100644
--- a/firmware/lib/tpm_lite/mocked_tlcl.c
+++ b/firmware/lib/tpm_lite/mocked_tlcl.c
@@ -186,10 +186,15 @@ uint32_t TlclGetRandom(uint8_t* data, uint32_t length, uint32_t *size)
return TPM_SUCCESS;
}
-uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version)
+uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version,
+ uint8_t* vendor_specific_buf,
+ size_t* vendor_specific_buf_size)
{
*vendor = 0x4e4f4e45;
*firmware_version = 0x1;
+ if (vendor_specific_buf_size) {
+ *vendor_specific_buf_size = 0;
+ }
return TPM_SUCCESS;
}
diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c
index 59dd1208..6f71f2bc 100644
--- a/firmware/lib/tpm_lite/tlcl.c
+++ b/firmware/lib/tpm_lite/tlcl.c
@@ -513,7 +513,10 @@ uint32_t TlclGetRandom(uint8_t* data, uint32_t length, uint32_t *size)
return result;
}
-uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version) {
+uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version,
+ uint8_t* vendor_specific_buf,
+ size_t* vendor_specific_buf_size)
+{
uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
uint32_t result = TlclSendReceive(tpm_getversionval_cmd.buffer,
response, sizeof(response));
@@ -528,7 +531,9 @@ uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version) {
/* Verify size >= sizeof(TPM_CAP_VERSION_INFO). */
const uint32_t kSizeofCapVersionInfo = 15;
- if (size < kSizeofCapVersionInfo) {
+ if (size < kSizeofCapVersionInfo ||
+ kTpmResponseHeaderLength + sizeof(size) + size >
+ TPM_LARGE_ENOUGH_COMMAND_SIZE) {
return TPM_E_IOERROR;
}
@@ -546,6 +551,26 @@ uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version) {
FromTpmUint32(cursor, vendor);
cursor += sizeof(*vendor);
+ if (vendor_specific_buf_size) {
+ uint16_t vendor_specific_size;
+ FromTpmUint16(cursor, &vendor_specific_size);
+ cursor += sizeof(vendor_specific_size);
+
+ if (size < kSizeofCapVersionInfo + vendor_specific_size) {
+ return TPM_E_IOERROR;
+ }
+ if (vendor_specific_buf) {
+ if (vendor_specific_size > *vendor_specific_buf_size) {
+ vendor_specific_size =
+ *vendor_specific_buf_size;
+ }
+ memcpy(vendor_specific_buf, cursor,
+ vendor_specific_size);
+ cursor += vendor_specific_size;
+ }
+ *vendor_specific_buf_size = vendor_specific_size;
+ }
+
return TPM_SUCCESS;
}
@@ -563,7 +588,8 @@ static void ParseIFXFirmwarePackage(uint8_t** cursor,
uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO* info) {
uint32_t vendor;
uint64_t firmware_version;
- uint32_t result = TlclGetVersion(&vendor, &firmware_version);
+ uint32_t result =
+ TlclGetVersion(&vendor, &firmware_version, NULL, NULL);
if (result != TPM_SUCCESS) {
return result;
}
diff --git a/tests/tlcl_tests.c b/tests/tlcl_tests.c
index b8d64a86..c2f3681c 100644
--- a/tests/tlcl_tests.c
+++ b/tests/tlcl_tests.c
@@ -351,19 +351,54 @@ static void GetVersionTest(void)
uint32_t vendor;
uint64_t firmware_version;
+ uint8_t vendor_specific[32];
+ size_t vendor_specific_size;
ResetMocks();
calls[0].rsp = response;
calls[0].rsp_size = sizeof(response);
- TEST_EQ(TlclGetVersion(&vendor, &firmware_version), 0, "GetVersion");
+ TEST_EQ(TlclGetVersion(&vendor, &firmware_version, NULL, NULL), 0,
+ "GetVersion");
TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd");
TEST_EQ(vendor, 0x49465800, " vendor");
TEST_EQ(firmware_version, 0x420, " firmware_version");
ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ vendor_specific_size = 100;
+ TEST_EQ(TlclGetVersion(&vendor, &firmware_version,
+ NULL, &vendor_specific_size), 0,
+ "GetVersion - vendor specific size");
+ TEST_EQ(vendor_specific_size, 0xd, " vendor specific size");
+
+ ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ vendor_specific_size = sizeof(vendor_specific);
+ TEST_EQ(TlclGetVersion(&vendor, &firmware_version,
+ vendor_specific, &vendor_specific_size), 0,
+ "GetVersion - vendor specific data");
+ TEST_EQ(vendor_specific_size, 0xd, " vendor specific size");
+ TEST_EQ(memcmp(vendor_specific, response + 29, 0xd), 0,
+ " vendor specific data check");
+
+ ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ vendor_specific_size = 4;
+ TEST_EQ(TlclGetVersion(&vendor, &firmware_version,
+ vendor_specific, &vendor_specific_size), 0,
+ "GetVersion - vendor specific data, short buf");
+ TEST_EQ(vendor_specific_size, 4,
+ " min(vendor specific size, buf size)");
+ TEST_EQ(memcmp(vendor_specific, response + 29, 4), 0,
+ " vendor specific data check");
+
+ ResetMocks();
SetResponse(0, TPM_E_IOERROR, 0);
- TEST_EQ(TlclGetVersion(&vendor, &firmware_version), TPM_E_IOERROR,
- "GetVersion - error");
+ TEST_EQ(TlclGetVersion(&vendor, &firmware_version, NULL, NULL),
+ TPM_E_IOERROR, "GetVersion - error");
TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd");
/* Adjust response to indicate a 1 byte too short payload size. */
@@ -371,8 +406,32 @@ static void GetVersionTest(void)
ResetMocks();
calls[0].rsp = response;
calls[0].rsp_size = sizeof(response);
- TEST_EQ(TlclGetVersion(&vendor, &firmware_version), TPM_E_IOERROR,
- "GetVersion -- short");
+ TEST_EQ(TlclGetVersion(&vendor, &firmware_version, NULL, NULL),
+ TPM_E_IOERROR, "GetVersion -- short");
+ TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd");
+
+ /* Adjust response to indicate a payload size too long for the
+ * response buffer. */
+ ToTpmUint32(response + kTpmResponseHeaderLength,
+ TPM_LARGE_ENOUGH_COMMAND_SIZE - sizeof(uint32_t) -
+ kTpmResponseHeaderLength + 1);
+ ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ TEST_EQ(TlclGetVersion(&vendor, &firmware_version, NULL, NULL),
+ TPM_E_IOERROR, "GetVersion -- long");
+ TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd");
+
+ /* Restore the original payload length and adjust response to contain
+ * less vendor specific data than indicated in its size. */
+ ToTpmUint32(response + kTpmResponseHeaderLength, 0x1c);
+ ToTpmUint16(response + 27, 0xd + 1);
+ ResetMocks();
+ calls[0].rsp = response;
+ calls[0].rsp_size = sizeof(response);
+ TEST_EQ(TlclGetVersion(&vendor, &firmware_version,
+ NULL, &vendor_specific_size), TPM_E_IOERROR,
+ "GetVersion -- short with vendor specific");
TEST_EQ(calls[0].req_cmd, TPM_ORD_GetCapability, " cmd");
}
diff --git a/utility/tpmc.c b/utility/tpmc.c
index a36f7e94..0584e32e 100644
--- a/utility/tpmc.c
+++ b/utility/tpmc.c
@@ -460,10 +460,18 @@ static uint32_t HandlerSendRaw(void) {
static uint32_t HandlerGetVersion(void) {
uint32_t vendor;
uint64_t firmware_version;
- uint32_t result = TlclGetVersion(&vendor, &firmware_version);
+ uint8_t vendor_specific[32];
+ size_t vendor_specific_size = sizeof(vendor_specific);
+ uint32_t result = TlclGetVersion(&vendor, &firmware_version, vendor_specific,
+ &vendor_specific_size);
if (result == 0) {
- printf("vendor %08x\nfirmware_version %016" PRIx64 "\n",
+ printf("vendor %08x\nfirmware_version %016" PRIx64 "\nvendor_specific ",
vendor, firmware_version);
+ size_t n;
+ for (n = 0; n < vendor_specific_size; ++n) {
+ printf("%02x", vendor_specific[n]);
+ }
+ printf("\n");
}
return result;
}