summaryrefslogtreecommitdiff
path: root/firmware/lib/tpm2_lite
diff options
context:
space:
mode:
authorAndrey Pronin <apronin@google.com>2016-07-22 18:45:07 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-07-26 17:31:56 -0700
commit0960682caa1fd27539b0c2100e4f8766ebe66640 (patch)
treeb1cf5c1004163ffe3bd6277ba3e9d88f3d1d236b /firmware/lib/tpm2_lite
parentca7251286655fe8865d0089bfc23b42ffececbf3 (diff)
downloadvboot-0960682caa1fd27539b0c2100e4f8766ebe66640.tar.gz
Implement GetCapabilities and reading flags for tpm2
For TPM2.0: 1) Implement TPM2_GetCapabilities command that allows reading TPM properties, including PERMANENT and STARTUP_CLEAR flags. 2) Implement 'getpf' and 'getvf' commands in tpmc. BRANCH=none BUG=chrome-os-partner:55210 BUG=chrome-os-partner:55250 TEST=boot on kevin, verify 'tpmc getpf' and 'tpmc getvf' Change-Id: I8490b2c92ebf7c266e27b7cb5898126a1b99b1a8 Reviewed-on: https://chromium-review.googlesource.com/362770 Commit-Ready: Andrey Pronin <apronin@chromium.org> Tested-by: Andrey Pronin <apronin@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'firmware/lib/tpm2_lite')
-rw-r--r--firmware/lib/tpm2_lite/marshaling.c109
-rw-r--r--firmware/lib/tpm2_lite/tlcl.c49
2 files changed, 145 insertions, 13 deletions
diff --git a/firmware/lib/tpm2_lite/marshaling.c b/firmware/lib/tpm2_lite/marshaling.c
index 3a22b682..61f726c4 100644
--- a/firmware/lib/tpm2_lite/marshaling.c
+++ b/firmware/lib/tpm2_lite/marshaling.c
@@ -53,6 +53,22 @@ static inline uint32_t read_be32(const void *src)
* has been extracted from the buffer.
*/
+static uint8_t unmarshal_u8(void **buffer, int *buffer_space)
+{
+ uint8_t value;
+
+ if (*buffer_space < sizeof(value)) {
+ *buffer_space = -1; /* Indicate a failure. */
+ return 0;
+ }
+
+ value = *(uint8_t *)(*buffer);
+ *buffer = (void *) ((uintptr_t) (*buffer) + sizeof(value));
+ *buffer_space -= sizeof(value);
+
+ return value;
+}
+
static uint16_t unmarshal_u16(void **buffer, int *buffer_space)
{
uint16_t value;
@@ -103,6 +119,22 @@ static void unmarshal_TPM2B_MAX_NV_BUFFER(void **buffer,
*size -= nv_buffer->t.size;
}
+static void unmarshal_authorization_section(void **buffer, int *size,
+ char *cmd_name)
+{
+ /*
+ * Let's ignore the authorisation section. It should be 5 bytes total,
+ * just confirm that this is the case and report any discrepancy.
+ */
+ if (*size != 5)
+ VBDEBUG(("%s:%d - unexpected authorisation section size %d "
+ "for %s\n",
+ __func__, __LINE__, *size, cmd_name));
+
+ *buffer = ((uint8_t *)(*buffer)) + *size;
+ *size = 0;
+}
+
static void unmarshal_nv_read(void **buffer, int *size,
struct nv_read_response *nvr)
{
@@ -120,16 +152,54 @@ static void unmarshal_nv_read(void **buffer, int *size,
if (*size < 0)
return;
- /*
- * Let's ignore the authorisation section. It should be 5 bytes total,
- * just confirm that this is the case and report any discrepancy.
- */
- if (*size != 5)
- VBDEBUG(("%s:%d - unexpected authorisation seciton size %d\n",
- __func__, __LINE__, *size));
- *buffer = ((uint8_t *)(*buffer)) + *size;
- *size = 0;
+ unmarshal_authorization_section(buffer, size, "NV_Read");
+}
+
+static void unmarshal_TPML_TAGGED_TPM_PROPERTY(void **buffer, int *size,
+ TPML_TAGGED_TPM_PROPERTY *prop)
+{
+ prop->count = unmarshal_u32(buffer, size);
+
+ if (prop->count != 1) {
+ *size = -1;
+ VBDEBUG(("%s:%d:Request to unmarshal unsupported "
+ "number of properties: %u\n",
+ __FILE__, __LINE__, prop->count));
+ return;
+ }
+
+ prop->tpm_property[0].property = unmarshal_u32(buffer, size);
+ prop->tpm_property[0].value = unmarshal_u32(buffer, size);
+}
+
+static void unmarshal_TPMS_CAPABILITY_DATA(void **buffer, int *size,
+ TPMS_CAPABILITY_DATA *cap_data)
+{
+ cap_data->capability = unmarshal_u32(buffer, size);
+
+ switch (cap_data->capability) {
+
+ case TPM_CAP_TPM_PROPERTIES:
+ unmarshal_TPML_TAGGED_TPM_PROPERTY(buffer, size,
+ &cap_data->data.
+ tpm_properties);
+ break;
+
+ default:
+ *size = -1;
+ VBDEBUG(("%s:%d:Request to unmarshal unsupported "
+ "capability %#x\n",
+ __FILE__, __LINE__, cap_data->capability));
+ }
+}
+
+static void unmarshal_get_capability(void **buffer, int *size,
+ struct get_capability_response *cap)
+{
+ /* Total size of the parameter field. */
+ cap->more_data = unmarshal_u8(buffer, size);
+ unmarshal_TPMS_CAPABILITY_DATA(buffer, size, &cap->capability_data);
}
@@ -309,6 +379,18 @@ static void marshal_hierarchy_control(void **buffer,
marshal_u8(buffer, command_body->state, buffer_space);
}
+static void marshal_get_capability(void **buffer,
+ struct tpm2_get_capability_cmd
+ *command_body,
+ int *buffer_space)
+{
+ tpm_tag = TPM_ST_NO_SESSIONS;
+
+ marshal_u32(buffer, command_body->capability, buffer_space);
+ marshal_u32(buffer, command_body->property, buffer_space);
+ marshal_u32(buffer, command_body->property_count, buffer_space);
+}
+
int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
void *buffer, int buffer_size)
{
@@ -338,6 +420,10 @@ int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
tpm_command_body, &body_size);
break;
+ case TPM2_GetCapability:
+ marshal_get_capability(&cmd_body, tpm_command_body, &body_size);
+ break;
+
default:
body_size = -1;
VBDEBUG(("%s:%d:Request to marshal unsupported command %#x\n",
@@ -385,6 +471,11 @@ struct tpm2_response *tpm_unmarshal_response(TPM_CC command,
&tpm2_resp.nvr);
break;
+ case TPM2_GetCapability:
+ unmarshal_get_capability(&response_body, &cr_size,
+ &tpm2_resp.cap);
+ break;
+
case TPM2_Hierarchy_Control:
case TPM2_NV_Write:
case TPM2_NV_WriteLock:
diff --git a/firmware/lib/tpm2_lite/tlcl.c b/firmware/lib/tpm2_lite/tlcl.c
index ae1fa5d8..9d7e1dfb 100644
--- a/firmware/lib/tpm2_lite/tlcl.c
+++ b/firmware/lib/tpm2_lite/tlcl.c
@@ -163,18 +163,59 @@ uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions)
return TPM_SUCCESS;
}
-uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags)
+static uint32_t tlcl_get_capability(TPM_CAP cap, TPM_PT property,
+ struct get_capability_response **presp)
{
- VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
+ struct tpm2_response *response;
+ struct tpm2_get_capability_cmd getcap;
+
+ getcap.capability = cap;
+ getcap.property = property;
+ getcap.property_count = 1;
+
+ response = tpm_process_command(TPM2_GetCapability, &getcap);
+ if (!response || response->hdr.tpm_code)
+ return TPM_E_IOERROR;
+ *presp = &response->cap;
+
return TPM_SUCCESS;
}
-uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS *pflags)
+static uint32_t tlcl_get_tpm_property(TPM_PT property, uint32_t *pvalue)
{
- VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
+ uint32_t rv;
+ struct get_capability_response *resp;
+ TPML_TAGGED_TPM_PROPERTY *tpm_prop;
+
+ rv = tlcl_get_capability(TPM_CAP_TPM_PROPERTIES, property, &resp);
+ if (rv != TPM_SUCCESS)
+ return rv;
+
+ if (resp->capability_data.capability != TPM_CAP_TPM_PROPERTIES)
+ return TPM_E_IOERROR;
+
+ tpm_prop = &resp->capability_data.data.tpm_properties;
+
+ if ((tpm_prop->count != 1) ||
+ (tpm_prop->tpm_property[0].property != property))
+ return TPM_E_IOERROR;
+
+ *pvalue = tpm_prop->tpm_property[0].value;
return TPM_SUCCESS;
}
+uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags)
+{
+ return tlcl_get_tpm_property(TPM_PT_PERMANENT,
+ (uint32_t *)pflags);
+}
+
+uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS *pflags)
+{
+ return tlcl_get_tpm_property(TPM_PT_STARTUP_CLEAR,
+ (uint32_t *)pflags);
+}
+
uint32_t TlclGetOwnership(uint8_t *owned)
{
*owned = 0;