From patchwork Wed Dec 11 20:27:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 1207911 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47Y7pS4vrdz9sR8 for ; Thu, 12 Dec 2019 07:30:08 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.vnet.ibm.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 47Y7pS3c68zDqsM for ; Thu, 12 Dec 2019 07:30:08 +1100 (AEDT) X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=stefanb@linux.vnet.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.vnet.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 47Y7ll6Y8NzDqWh for ; Thu, 12 Dec 2019 07:27:44 +1100 (AEDT) Received: from pps.filterd (m0187473.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id xBBKGXX0133896; Wed, 11 Dec 2019 15:27:42 -0500 Received: from ppma01dal.us.ibm.com (83.d6.3fa9.ip4.static.sl-reverse.com [169.63.214.131]) by mx0a-001b2d01.pphosted.com with ESMTP id 2wr8m09rma-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 15:27:41 -0500 Received: from pps.filterd (ppma01dal.us.ibm.com [127.0.0.1]) by ppma01dal.us.ibm.com (8.16.0.27/8.16.0.27) with SMTP id xBBKQ0XD000622; Wed, 11 Dec 2019 20:27:40 GMT Received: from b01cxnp22033.gho.pok.ibm.com (b01cxnp22033.gho.pok.ibm.com [9.57.198.23]) by ppma01dal.us.ibm.com with ESMTP id 2wr3q7a2t3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 20:27:40 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id xBBKReMv51053022 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 11 Dec 2019 20:27:40 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 11F54B2064; Wed, 11 Dec 2019 20:27:40 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EDF78B2066; Wed, 11 Dec 2019 20:27:39 +0000 (GMT) Received: from newfield.pok.ibm.com (unknown [9.47.158.66]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Wed, 11 Dec 2019 20:27:39 +0000 (GMT) From: Stefan Berger To: slof@lists.ozlabs.org Date: Wed, 11 Dec 2019 15:27:04 -0500 Message-Id: <20191211202728.127996-10-stefanb@linux.vnet.ibm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191211202728.127996-1-stefanb@linux.vnet.ibm.com> References: <20191211202728.127996-1-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.95, 18.0.572 definitions=2019-12-11_06:2019-12-11, 2019-12-11 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 mlxlogscore=999 lowpriorityscore=0 priorityscore=1501 impostorscore=0 malwarescore=0 phishscore=0 bulkscore=0 clxscore=1015 adultscore=0 spamscore=0 suspectscore=15 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-1910280000 definitions=main-1912110168 Subject: [SLOF] [PATCH v4 09/33] tpm: Add support for controlling the states of the TPM X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin@koconnor.net MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" 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 --- 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 +#include #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 +#include /************************************************/ @@ -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)