@@ -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);
+}
@@ -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 */
@@ -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 */
@@ -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
@@ -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)
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@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(+)