Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp50748pxb; Fri, 19 Feb 2021 17:37:03 -0800 (PST) X-Google-Smtp-Source: ABdhPJx0VDQ0RKE2uxPRhjORZj4mMxvMTUpM8Bxbv50fXPfDVaUpOgBPtds4HAoxSU5ic2PSU1S6 X-Received: by 2002:a05:6402:610:: with SMTP id n16mr11509328edv.288.1613785023179; Fri, 19 Feb 2021 17:37:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1613785023; cv=none; d=google.com; s=arc-20160816; b=U0EtkDTKjq53Aaq3KXQrU6lIfCPGzo18rBIv0TmXALhuxzcmljblppl2RBNN2uSC6u mUufl9SOIx+qAfmh2/QLLE+QPG7HWeEzXyGDNAngIlT9RQ/TyQe2PtCKo8O+xys5JF/j nW4jPummBbNwzzz/rUcZr7yn7gB9JTSOoUG9oQmJpjiJOx0uiuUu5viupdGcJrJyX+mK TnQZi8Fn21t8OrAihRDSrNz6MXj3VUQYhsyDXakD2SOH2AcyxwwOTxxlWdkmduCNRhtN 6gne6oGFZLwrF62k3qLKGZXNW3alfeV9XSi9fW+aLxflqJaoB8RpGLXlgY86YRQvnT9p s1Uw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:sender:dkim-signature; bh=y0augfXTryPPckNIjyG37nVNdhig6ZbrGk3G+Se0bhk=; b=basqFb5B9xNkoykArS9E3kiM+GG14PyEh8ncbIfiDpUs+Faw/IOcL2r0lM0nWu9rgS K9Q6u10FRjEkqe5yAEaXuYd+ejGkPxw4wf+w1mE15iw5eB+zm7qpum7TgwZI0vxxUz77 +4zCQaEbCYa3N9FJlTgqisPHvjGHPd8aoVh1VWfK6kEacWQtRDagDh7lowr8H7qhuULu AneZbI0WJMMPdKW+NdHTIL80bFRjA/mREbP5yz72g89FSGjuHGTCZqlylD1sbBgXuFvo 22wWcGbLDNY/CaD+EOovK0ALH6jcXkwTIwJo3+HotfJ8To6s9+YahPTeB1iDK3mGDQ0B DWfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=RAnSVHS6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z1si7116953edp.254.2021.02.19.17.36.02; Fri, 19 Feb 2021 17:37:03 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=RAnSVHS6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229896AbhBTBed (ORCPT + 99 others); Fri, 19 Feb 2021 20:34:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229874AbhBTBe2 (ORCPT ); Fri, 19 Feb 2021 20:34:28 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6B730C0617AA for ; Fri, 19 Feb 2021 17:33:10 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id u17so8909646ybi.10 for ; Fri, 19 Feb 2021 17:33:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=y0augfXTryPPckNIjyG37nVNdhig6ZbrGk3G+Se0bhk=; b=RAnSVHS6Smj0l3LTFE/vx6JcAMiDFRCoCBnWUB8vImivgo1DTitkKgcGHqMjwAJw/O txIgPqjTqa5i4y7plNhFKxAOjXZ8FqAPcnC1jxvxhEqDXMk3kcqnC0fP9TLI25gVJUXK ddHY50qffEoya6LEsxV2vjOe6YrzC22XhdLQxxrKho7+T0KrN7kp1rjJhsyKoU/cKfYb TEn1URRMkGXIyknaMegtLk6tmlOfKyVP5pr7+ftAFXeT0hi4EscWeLB1AHcTBFFNiuzt LWSmztlO4C9ylDtqEpai3Jw11CILCmSXimM0qGQkwtnWxlfXul5qzttJBxAyTWmez48Z zDyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=y0augfXTryPPckNIjyG37nVNdhig6ZbrGk3G+Se0bhk=; b=SMWhrnx9Jk9SkxZdtIGsYVZfgFcYyLfku30HhyDvn54iAVWTsyvMl2/dgCViOa2qCL F7F5Pp53KHz6WFPWbGLjw1eMQiV1S3bPU+CdZEr5jB9Hqt07UExdtD0hleifEVCMzcww EuVci6wNShowdnswaF+UU6z9yHrgE+SQub/bsotjLcMYcY8IHuX80aA4MD1WagisbBZs yXEOhs4eXRmT/LMezDiwd+bDw7Jy+Wy8izinBtQ+Q/vaFwbEB7wLG02dMduw9l9xLa3/ 0VmdU9+ynPVcDGNHmD8FpEpLma9dNfOwSbqEF4fLCbAV8oMr2aOG3GF2KvdnmtURX23V etVQ== X-Gm-Message-State: AOAM533fhV8Gc3frdnXyeCvp2i0fBAprObHjjLjRGHepIgMO1mLhEM6W TGS1Ginj3Xts8k42YTjs9mdlCv8BH1Lfjue3QYeTnq+pTggtSllvs3xdk/pmOgP3uLRoj+0PLfW dmwzFru5goML9dKYyTy1B0FQiRERRsMQoeIna9nwxqao2N3VPZNxsn5+pvHUeiMEA/kflp0nNfO tF5cm8y5w8DFo1UK0= Sender: "matthewgarrett via sendgmr" X-Received: from matthewgarrett-tmp.c.googlers.com ([fda3:e722:ac3:10:7f:e700:c0a8:1081]) (user=matthewgarrett job=sendgmr) by 2002:a25:9383:: with SMTP id a3mr17879351ybm.215.1613784789563; Fri, 19 Feb 2021 17:33:09 -0800 (PST) Date: Sat, 20 Feb 2021 01:32:48 +0000 In-Reply-To: <20210220013255.1083202-1-matthewgarrett@google.com> Message-Id: <20210220013255.1083202-3-matthewgarrett@google.com> Mime-Version: 1.0 References: <20210220013255.1083202-1-matthewgarrett@google.com> X-Mailer: git-send-email 2.30.0.617.g56c4b15f3c-goog Subject: [PATCH 2/9] tpm: Allow PCR 23 to be restricted to kernel-only use From: Matthew Garrett To: linux-kernel@vger.kernel.org Cc: linux-integrity@vger.kernel.org, linux-pm@vger.kernel.org, keyrings@vger.kernel.org, zohar@linux.ibm.com, jejb@linux.ibm.com, jarkko@kernel.org, corbet@lwn.net, rjw@rjwysocki.net, Matthew Garrett , Matthew Garrett Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Under certain circumstances it might be desirable to enable the creation of TPM-backed secrets that are only accessible to the kernel. In an ideal world this could be achieved by using TPM localities, but these don't appear to be available on consumer systems. An alternative is to simply block userland from modifying one of the resettable PCRs, leaving it available to the kernel. If the kernel ensures that no userland can access the TPM while it is carrying out work, it can reset PCR 23, extend it to an arbitrary value, create or load a secret, and then reset the PCR again. Even if userland somehow obtains the sealed material, it will be unable to unseal it since PCR 23 will never be in the appropriate state. Signed-off-by: Matthew Garrett --- drivers/char/tpm/Kconfig | 10 +++++++++ drivers/char/tpm/tpm-dev-common.c | 8 +++++++ drivers/char/tpm/tpm.h | 21 +++++++++++++++++++ drivers/char/tpm/tpm1-cmd.c | 35 +++++++++++++++++++++++++++++++ drivers/char/tpm/tpm2-cmd.c | 22 +++++++++++++++++++ drivers/char/tpm/tpm2-space.c | 2 +- 6 files changed, 97 insertions(+), 1 deletion(-) diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index a18c314da211..bba30fb16a2e 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -190,4 +190,14 @@ config TCG_FTPM_TEE This driver proxies for firmware TPM running in TEE. source "drivers/char/tpm/st33zp24/Kconfig" + +config TCG_TPM_RESTRICT_PCR + bool "Restrict userland access to PCR 23" + depends on TCG_TPM + help + If set, block userland from extending or resetting PCR 23. This + allows it to be restricted to in-kernel use, preventing userland + from being able to make use of data sealed to the TPM by the kernel. + This is required for secure hibernation support, but should be left + disabled if any userland may require access to PCR23. endif # TCG_TPM diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 1784530b8387..d3db4fd76257 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c @@ -193,6 +193,14 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, priv->response_read = false; *off = 0; + if (priv->chip->flags & TPM_CHIP_FLAG_TPM2) + ret = tpm2_cmd_restricted(priv->chip, priv->data_buffer, size); + else + ret = tpm1_cmd_restricted(priv->chip, priv->data_buffer, size); + + if (ret) + goto out; + /* * If in nonblocking mode schedule an async job to send * the command return the size. diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 746f7696bdc0..8eed5016d733 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -232,6 +232,8 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); int tpm2_probe(struct tpm_chip *chip); int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip); +int tpm_find_and_validate_cc(struct tpm_chip *chip, struct tpm_space *space, + const void *buf, size_t bufsiz); int tpm2_find_cc(struct tpm_chip *chip, u32 cc); int tpm2_init_space(struct tpm_space *space, unsigned int buf_size); void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space); @@ -245,4 +247,23 @@ void tpm_bios_log_setup(struct tpm_chip *chip); void tpm_bios_log_teardown(struct tpm_chip *chip); int tpm_dev_common_init(void); void tpm_dev_common_exit(void); + +#ifdef CONFIG_TCG_TPM_RESTRICT_PCR +#define TPM_RESTRICTED_PCR 23 + +int tpm1_cmd_restricted(struct tpm_chip *chip, u8 *buffer, size_t size); +int tpm2_cmd_restricted(struct tpm_chip *chip, u8 *buffer, size_t size); +#else +static inline int tpm1_cmd_restricted(struct tpm_chip *chip, u8 *buffer, + size_t size) +{ + return 0; +} + +static inline int tpm2_cmd_restricted(struct tpm_chip *chip, u8 *buffer, + size_t size) +{ + return 0; +} +#endif #endif diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c index 36990e9d2dc1..2dab1647d89c 100644 --- a/drivers/char/tpm/tpm1-cmd.c +++ b/drivers/char/tpm/tpm1-cmd.c @@ -840,3 +840,38 @@ int tpm1_get_pcr_allocation(struct tpm_chip *chip) return 0; } + +#ifdef CONFIG_TCG_TPM_RESTRICT_PCR +int tpm1_cmd_restricted(struct tpm_chip *chip, u8 *buffer, size_t size) +{ + struct tpm_header *header = (struct tpm_header *)buffer; + char len, offset; + u32 *pcr; + int pos; + + switch (be32_to_cpu(header->ordinal)) { + case TPM_ORD_PCR_EXTEND: + if (size < (TPM_HEADER_SIZE + sizeof(u32))) + return -EINVAL; + pcr = (u32 *)&buffer[TPM_HEADER_SIZE]; + if (be32_to_cpu(*pcr) == TPM_RESTRICTED_PCR) + return -EPERM; + break; + case TPM_ORD_PCR_RESET: + if (size < (TPM_HEADER_SIZE + 1)) + return -EINVAL; + len = buffer[TPM_HEADER_SIZE]; + if (size < (TPM_HEADER_SIZE + 1 + len)) + return -EINVAL; + offset = TPM_RESTRICTED_PCR/3; + if (len < offset) + break; + pos = TPM_HEADER_SIZE + 1 + offset; + if (buffer[pos] & (1 << (TPM_RESTRICTED_PCR - 2 * offset))) + return -EPERM; + break; + } + + return 0; +} +#endif diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 9609ae8086c6..7dbd4590dee8 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -795,3 +795,25 @@ int tpm2_find_cc(struct tpm_chip *chip, u32 cc) return -1; } + +#ifdef CONFIG_TCG_TPM_RESTRICT_PCR +int tpm2_cmd_restricted(struct tpm_chip *chip, u8 *buffer, size_t size) +{ + int cc = tpm_find_and_validate_cc(chip, NULL, buffer, size); + u32 *handle; + + switch (cc) { + case TPM2_CC_PCR_EXTEND: + case TPM2_CC_PCR_RESET: + if (size < (TPM_HEADER_SIZE + sizeof(u32))) + return -EINVAL; + + handle = (u32 *)&buffer[TPM_HEADER_SIZE]; + if (be32_to_cpu(*handle) == TPM_RESTRICTED_PCR) + return -EPERM; + break; + } + + return 0; +} +#endif diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index 784b8b3cb903..76a993492962 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -262,7 +262,7 @@ static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd) return 0; } -static int tpm_find_and_validate_cc(struct tpm_chip *chip, +int tpm_find_and_validate_cc(struct tpm_chip *chip, struct tpm_space *space, const void *cmd, size_t len) { -- 2.30.0.617.g56c4b15f3c-goog