summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2016-07-06 09:07:54 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-07-09 11:25:24 -0700
commitae703f681965ffdbe676fa291d445f765f93e2ab (patch)
tree086909c7ba02eb7a3172ec00268e5e03bfe5cff9
parenteb4f39d3db535109959cacc9a6066ec8400c0875 (diff)
downloadvboot-ae703f681965ffdbe676fa291d445f765f93e2ab.tar.gz
tpm2: add nvram lock and hierarchy control commands
The firmware needs to lock the kernel rollback index before starting up the kernel. The TPM2_NV_WriteLock command is used for that. We also want to limit the amount of control the user space apps have over TPM. With TPM1.2 it was achieved by deasserting physical presence. TPM2 specification allows to achieve the same goal by disabling Platform Hierarchy, which is active out of reset. BRANCH=none BUG=chrome-os-partner:50465 TEST=verified that all commands succeed and chrome OS boots up fine. Change-Id: Ia5893460e0b29f1945cb2aae45a5f10b08fe1ed1 Reviewed-on: https://chromium-review.googlesource.com/358351 Commit-Ready: Vadim Bendebury <vbendeb@chromium.org> Tested-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-by: Darren Krahn <dkrahn@chromium.org>
-rw-r--r--firmware/include/tpm2_tss_constants.h17
-rw-r--r--firmware/lib/tpm2_lite/marshaling.c41
-rw-r--r--firmware/lib/tpm2_lite/tlcl.c48
3 files changed, 102 insertions, 4 deletions
diff --git a/firmware/include/tpm2_tss_constants.h b/firmware/include/tpm2_tss_constants.h
index cec91e61..fa341c0f 100644
--- a/firmware/include/tpm2_tss_constants.h
+++ b/firmware/include/tpm2_tss_constants.h
@@ -17,8 +17,10 @@
#define TPM_ST_SESSIONS 0x8002
/* TPM2 command codes. */
-#define TPM2_NV_Write ((TPM_CC)0x00000137)
-#define TPM2_NV_Read ((TPM_CC)0x0000014E)
+#define TPM2_Hierarchy_Control ((TPM_CC)0x00000121)
+#define TPM2_NV_Write ((TPM_CC)0x00000137)
+#define TPM2_NV_WriteLock ((TPM_CC)0x00000138)
+#define TPM2_NV_Read ((TPM_CC)0x0000014E)
/* TCG Spec defined, verify for TPM2. */
#define TPM_E_BADINDEX ((uint32_t) 0x00000002)
@@ -32,9 +34,11 @@
#define TPM_RS_PW 0x40000009
+typedef uint8_t TPMI_YES_NO;
typedef uint32_t TPM_CC;
typedef uint32_t TPM_HANDLE;
typedef TPM_HANDLE TPMI_RH_NV_INDEX;
+typedef TPM_HANDLE TPMI_RH_ENABLES;
typedef struct {
uint16_t size;
@@ -61,6 +65,15 @@ struct tpm2_nv_write_cmd {
uint16_t offset;
};
+struct tpm2_nv_write_lock_cmd {
+ TPMI_RH_NV_INDEX nvIndex;
+};
+
+struct tpm2_hierarchy_control_cmd {
+ TPMI_RH_ENABLES enable;
+ TPMI_YES_NO state;
+};
+
/* Common command/response header. */
struct tpm_header {
uint16_t tpm_tag;
diff --git a/firmware/lib/tpm2_lite/marshaling.c b/firmware/lib/tpm2_lite/marshaling.c
index 672ffad0..29746cd7 100644
--- a/firmware/lib/tpm2_lite/marshaling.c
+++ b/firmware/lib/tpm2_lite/marshaling.c
@@ -273,6 +273,36 @@ static void marshal_nv_read(void **buffer,
marshal_u16(buffer, command_body->offset, buffer_space);
}
+static void marshal_nv_write_lock(void **buffer,
+ struct tpm2_nv_write_lock_cmd *command_body,
+ int *buffer_space)
+{
+ struct tpm2_session_header session_header;
+
+ tpm_tag = TPM_ST_SESSIONS;
+ marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
+ marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
+ Memset(&session_header, 0, sizeof(session_header));
+ session_header.session_handle = TPM_RS_PW;
+ marshal_session_header(buffer, &session_header, buffer_space);
+}
+
+static void marshal_hierarchy_control(void **buffer,
+ struct tpm2_hierarchy_control_cmd
+ *command_body,
+ int *buffer_space)
+{
+ struct tpm2_session_header session_header;
+
+ tpm_tag = TPM_ST_SESSIONS;
+ marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
+ Memset(&session_header, 0, sizeof(session_header));
+ session_header.session_handle = TPM_RS_PW;
+ marshal_session_header(buffer, &session_header, buffer_space);
+
+ marshal_TPM_HANDLE(buffer, command_body->enable, buffer_space);
+ marshal_u8(buffer, command_body->state, buffer_space);
+}
int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
void *buffer, int buffer_size)
@@ -294,6 +324,15 @@ int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
marshal_nv_write(&cmd_body, tpm_command_body, &body_size);
break;
+ case TPM2_NV_WriteLock:
+ marshal_nv_write_lock(&cmd_body, tpm_command_body, &body_size);
+ break;
+
+ case TPM2_Hierarchy_Control:
+ marshal_hierarchy_control(&cmd_body,
+ tpm_command_body, &body_size);
+ break;
+
default:
body_size = -1;
VBDEBUG(("%s:%d:Request to marshal unsupported command %#x\n",
@@ -341,7 +380,9 @@ struct tpm2_response *tpm_unmarshal_response(TPM_CC command,
&tpm2_resp.nvr);
break;
+ case TPM2_Hierarchy_Control:
case TPM2_NV_Write:
+ case TPM2_NV_WriteLock:
/* Session data included in response can be safely ignored. */
cr_size = 0;
break;
diff --git a/firmware/lib/tpm2_lite/tlcl.c b/firmware/lib/tpm2_lite/tlcl.c
index 5202c600..efd73928 100644
--- a/firmware/lib/tpm2_lite/tlcl.c
+++ b/firmware/lib/tpm2_lite/tlcl.c
@@ -7,6 +7,7 @@
* in the firmware
*/
+#include "rollback_index.h"
#include "tpm2_marshaling.h"
#include "utility.h"
@@ -73,14 +74,57 @@ uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions)
return TPM_SUCCESS;
}
+static uint32_t tlcl_lock_nv_write(uint32_t index)
+{
+ struct tpm2_response *response;
+ struct tpm2_nv_write_lock_cmd nv_wl;
+
+ nv_wl.nvIndex = HR_NV_INDEX + index;
+ response = tpm_process_command(TPM2_NV_WriteLock, &nv_wl);
+
+ if (!response || response->hdr.tpm_code)
+ return TPM_E_INTERNAL_INCONSISTENCY;
+
+ return TPM_SUCCESS;
+}
+
+static uint32_t tlcl_disable_platform_hierarchy(void)
+{
+ struct tpm2_response *response;
+ struct tpm2_hierarchy_control_cmd hc;
+
+ hc.enable = TPM_RH_PLATFORM;
+ hc.state = 0;
+
+ response = tpm_process_command(TPM2_Hierarchy_Control, &hc);
+
+ if (!response || response->hdr.tpm_code)
+ return TPM_E_INTERNAL_INCONSISTENCY;
+
+ return TPM_SUCCESS;
+}
+
/**
* Turn off physical presence and locks it off until next reboot. The TPM
* error code is returned.
+ *
+ * The name of the function was kept to maintain the existing TPM API, but
+ * TPM2.0 does not have to use the Physical Presence concept. Instead it just
+ * removes platform authorization - this makes sure that firmware and kernel
+ * rollback counter spaces can not be modified.
+ *
+ * It also explicitly locks the kernel rollback counter space (the FW rollback
+ * counter space was locked before RW firmware started.)
*/
uint32_t TlclLockPhysicalPresence(void)
{
- VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
- return TPM_SUCCESS;
+ uint32_t rv;
+
+ rv = tlcl_lock_nv_write(KERNEL_NV_INDEX);
+ if (rv == TPM_SUCCESS)
+ rv = tlcl_disable_platform_hierarchy();
+
+ return rv;
}
uint32_t TlclRead(uint32_t index, void* data, uint32_t length)