[SLOF] [PATCH v4 09/33] tpm: Add support for controlling the states of the TPM

Stefan Berger stefanb at linux.vnet.ibm.com
Thu Dec 12 07:27:04 AEDT 2019


This patch adds support for controlling the various states of
the TPM, such as enabling and disabling the TPM, deactivating
and activating it, and clearing ownership.

The TPM menu implementation will call these functions by
calling tpm_process_opcode with an opcode indicating as to
how the state of the TPM is to be changed.

Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
---
 lib/libtpm/tcgbios.c     | 203 +++++++++++++++++++++++++++++++++++++++
 lib/libtpm/tcgbios.h     |   1 +
 lib/libtpm/tcgbios_int.h |  35 +++++++
 lib/libtpm/tpm.code      |  12 +++
 lib/libtpm/tpm.in        |   1 +
 5 files changed, 252 insertions(+)

diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 401bb1c..8bd684c 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -56,6 +56,8 @@ struct tpm_state {
 
 static struct tpm_state tpm_state;
 
+typedef uint8_t tpm_ppi_op;
+
 /********************************************************
   Extensions for TCG-enabled BIOS
  *******************************************************/
@@ -546,3 +548,204 @@ uint32_t tpm_measure_bcv_mbr(uint32_t bootdrv, const uint8_t *addr,
 					  string, strlen(string),
 					  addr + 0x1b8, 0x48);
 }
+
+/****************************************************************
+ * TPM Configuration Menu
+ ****************************************************************/
+
+static int tpm12_read_has_owner(bool *has_owner)
+{
+	struct tpm_rsp_getcap_ownerauth oauth;
+	int ret = tpm12_get_capability(TPM_CAP_PROPERTY, TPM_CAP_PROP_OWNER,
+				       &oauth.hdr, sizeof(oauth));
+	if (ret)
+		return -1;
+
+	*has_owner = oauth.flag;
+
+	return 0;
+}
+
+static int tpm12_enable_tpm(bool enable, bool verbose)
+{
+	struct tpm_permanent_flags pf;
+	int ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf));
+	if (ret)
+		return -1;
+
+	if (pf.flags[PERM_FLAG_IDX_DISABLE] && !enable)
+		return 0;
+
+	ret = tpm_simple_cmd(0, enable ? TPM_ORD_PHYSICAL_ENABLE
+				       : TPM_ORD_PHYSICAL_DISABLE,
+			     0, 0, TPM_DURATION_TYPE_SHORT);
+	if (ret) {
+		if (enable) {
+			dprintf("TCGBIOS: Enabling the TPM failed.\n");
+		} else {
+			dprintf("TCGBIOS: Disabling the TPM failed.\n");
+		}
+	}
+	return ret;
+}
+
+static int tpm12_activate_tpm(bool activate, bool allow_reset, bool verbose)
+{
+	struct tpm_permanent_flags pf;
+	int ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf));
+	if (ret)
+		return -1;
+
+	if (pf.flags[PERM_FLAG_IDX_DEACTIVATED] && !activate)
+		return 0;
+
+	if (pf.flags[PERM_FLAG_IDX_DISABLE])
+		return 0;
+
+	ret = tpm_simple_cmd(0, TPM_ORD_PHYSICAL_SET_DEACTIVATED,
+			     1, activate ? 0 : 1,
+			     TPM_DURATION_TYPE_SHORT);
+	if (ret)
+		return ret;
+
+	if (activate && allow_reset) {
+		if (verbose)
+			printf("Requiring a reboot to activate the TPM.\n");
+	}
+
+	return 0;
+}
+
+static int tpm12_enable_activate(int allow_reset, bool verbose)
+{
+	int ret = tpm12_enable_tpm(true, verbose);
+	if (ret)
+		return ret;
+
+	return tpm12_activate_tpm(true, allow_reset, verbose);
+}
+
+static int tpm12_force_clear(bool enable_activate_before,
+			     bool enable_activate_after,
+			     bool verbose)
+{
+	bool has_owner;
+	int ret = tpm12_read_has_owner(&has_owner);
+	if (ret)
+		return -1;
+	if (!has_owner) {
+		if (verbose)
+			printf("TPM does not have an owner.\n");
+		return 0;
+	}
+
+	if (enable_activate_before) {
+		ret = tpm12_enable_activate(false, verbose);
+		if (ret) {
+			dprintf("TCGBIOS: Enabling/activating the TPM failed.\n");
+			return ret;
+		}
+	}
+
+	ret = tpm_simple_cmd(0, TPM_ORD_FORCE_CLEAR,
+			     0, 0, TPM_DURATION_TYPE_SHORT);
+	if (ret)
+		return ret;
+
+	if (!enable_activate_after) {
+		if (verbose)
+			printf("Owner successfully cleared.\n"
+			       "You will need to enable/activate the TPM again.\n\n");
+		return 0;
+	}
+
+	return tpm12_enable_activate(true, verbose);
+}
+
+static int tpm12_set_owner_install(bool allow, bool verbose)
+{
+	bool has_owner;
+	struct tpm_permanent_flags pf;
+	int ret = tpm12_read_has_owner(&has_owner);
+	if (ret)
+		return -1;
+
+	if (has_owner) {
+		if (verbose)
+			printf("Must first remove owner.\n");
+		return 0;
+	}
+
+	ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf));
+	if (ret)
+		return -1;
+
+	if (pf.flags[PERM_FLAG_IDX_DISABLE]) {
+		if (verbose)
+			printf("TPM must first be enable.\n");
+		return 0;
+	}
+
+	ret = tpm_simple_cmd(0, TPM_ORD_SET_OWNER_INSTALL,
+			     1, allow ? 1 : 0, TPM_DURATION_TYPE_SHORT);
+	if (ret)
+		return ret;
+
+	if (verbose)
+		printf("Installation of owner %s.\n",
+		      allow ? "enabled" : "disabled");
+
+	return 0;
+}
+
+static int tpm12_process_cfg(tpm_ppi_op ppi_op, bool verbose)
+{
+	int ret = 0;
+
+	switch (ppi_op) {
+	case TPM_PPI_OP_NOOP: /* no-op */
+		break;
+
+	case TPM_PPI_OP_ENABLE:
+		ret = tpm12_enable_tpm(true, verbose);
+		break;
+
+	case TPM_PPI_OP_DISABLE:
+		ret = tpm12_enable_tpm(false, verbose);
+		break;
+
+	case TPM_PPI_OP_ACTIVATE:
+		ret = tpm12_activate_tpm(true, true, verbose);
+		break;
+
+	case TPM_PPI_OP_DEACTIVATE:
+		ret = tpm12_activate_tpm(false, true, verbose);
+		break;
+
+	case TPM_PPI_OP_CLEAR:
+		ret = tpm12_force_clear(true, false, verbose);
+		break;
+
+	case TPM_PPI_OP_SET_OWNERINSTALL_TRUE:
+		ret = tpm12_set_owner_install(true, verbose);
+		break;
+
+	case TPM_PPI_OP_SET_OWNERINSTALL_FALSE:
+		ret = tpm12_set_owner_install(false, verbose);
+		break;
+
+	default:
+		break;
+	}
+
+	if (ret)
+		printf("Op %d: An error occurred: 0x%x TPM\n",
+		       ppi_op, ret);
+
+	return ret;
+}
+
+uint32_t tpm_process_opcode(uint8_t op, bool verbose)
+{
+	return tpm12_process_cfg(op, verbose);
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 3ccfca5..b288778 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -32,5 +32,6 @@ uint32_t tpm_hash_all(const void *data, uint32_t datalen, void *hashptr);
 uint32_t tpm_measure_bcv_mbr(uint32_t bootdrv, const uint8_t *addr,
                              uint32_t length);
 uint32_t tpm_add_event_separators(uint32_t start_pcr, uint32_t end_pcr);
+uint32_t tpm_process_opcode(uint8_t op, bool verbose);
 
 #endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
index b3ab0ad..1893ab2 100644
--- a/lib/libtpm/tcgbios_int.h
+++ b/lib/libtpm/tcgbios_int.h
@@ -14,6 +14,7 @@
 #define TCGBIOS_INT_H
 
 #include <stdint.h>
+#include <stdbool.h>
 
 #include "tpm_drivers.h"
 
@@ -111,6 +112,7 @@ struct tpm_req_getcap {
 #define TPM_CAP_FLAG      0x04
 #define TPM_CAP_PROPERTY  0x05
 #define TPM_CAP_FLAG_PERMANENT  0x108
+#define TPM_CAP_PROP_OWNER      0x111
 #define TPM_CAP_PROP_DURATION   0x120
 
 struct tpm_req_getcap_perm_flags {
@@ -139,6 +141,30 @@ struct tpm_rsp_getcap_perm_flags {
 	struct tpm_permanent_flags perm_flags;
 } __attribute__((packed));
 
+struct tpm_req_getcap_stclear_flags {
+	struct tpm_req_header hdr;
+	uint32_t cap_area;
+	uint32_t sub_cap_size;
+	uint32_t sub_cap;
+} __attribute__((packed));
+
+struct tpm_stclear_flags {
+	uint16_t tag;
+	uint8_t  flags[5];
+} __attribute__((packed));
+
+#define STCLEAR_FLAG_IDX_DEACTIVATED 0
+#define STCLEAR_FLAG_IDX_DISABLE_FORCE_CLEAR 1
+#define STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE 2
+#define STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE_LOCK 3
+#define STCLEAR_FLAG_IDX_GLOBAL_LOCK 4
+
+struct tpm_rsp_getcap_stclear_flags {
+	struct tpm_rsp_header hdr;
+	uint32_t size;
+	struct tpm_stclear_flags stclear_flags;
+} __attribute__((packed));
+
 struct tpm_rsp_getcap_ownerauth {
 	struct tpm_rsp_header hdr;
 	uint32_t size;
@@ -151,4 +177,13 @@ struct tpm_rsp_getcap_durations {
 	uint32_t durations[TPM_NUM_DURATIONS];
 } __attribute__((packed));
 
+#define TPM_PPI_OP_NOOP 0
+#define TPM_PPI_OP_ENABLE 1
+#define TPM_PPI_OP_DISABLE 2
+#define TPM_PPI_OP_ACTIVATE 3
+#define TPM_PPI_OP_DEACTIVATE 4
+#define TPM_PPI_OP_CLEAR 5
+#define TPM_PPI_OP_SET_OWNERINSTALL_TRUE 8
+#define TPM_PPI_OP_SET_OWNERINSTALL_FALSE 9
+
 #endif /* TCGBIOS_INT_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index d4a1a72..1a5273f 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -14,6 +14,7 @@
  */
 
 #include <tcgbios.h>
+#include <stdbool.h>
 
 
 /************************************************/
@@ -120,3 +121,14 @@ PRIM(tpm_X2d_measure_X2d_bcv_X2d_mbr)
 	int bootdrv = TOS.u;
 	TOS.n = tpm_measure_bcv_mbr(bootdrv, addr, length);
 MIRP
+
+/*************************************************************/
+/* Process an opcode to change state of the TPM              */
+/* SLOF:   tpm-process-opcode  ( opcode verbose -- errcode)  */
+/* LIBTPM: tpm_process_opcode(opcode, verbose)               */
+/*************************************************************/
+PRIM(tpm_X2d_process_X2d_opcode)
+	int opcode = TOS.u; POP;
+	bool verbose = TOS.u;
+	TOS.n = tpm_process_opcode(opcode, verbose);
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 2d3d75e..9fb30bb 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -23,3 +23,4 @@ cod(tpm-hash-log-extend-event)
 cod(tpm-hash-all)
 cod(tpm-add-event-separators)
 cod(tpm-measure-bcv-mbr)
+cod(tpm-process-opcode)
-- 
2.17.1



More information about the SLOF mailing list