From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7B0DFC0015E for ; Sat, 12 Aug 2023 00:29:26 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B97F986949; Sat, 12 Aug 2023 02:28:39 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="hEqaAIgR"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 850368694E; Sat, 12 Aug 2023 02:28:36 +0200 (CEST) Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by phobos.denx.de (Postfix) with ESMTP id 3BBD386947 for ; Sat, 12 Aug 2023 02:28:31 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanedmond@linux.microsoft.com Received: from ovlvm106.redmond.corp.microsoft.com (unknown [131.107.147.185]) by linux.microsoft.com (Postfix) with ESMTPSA id 3C23220FD0E8; Fri, 11 Aug 2023 17:28:30 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 3C23220FD0E8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1691800110; bh=354JZD4nrAvIha2w7fJ/E4Ah6P0jFDD/5MmA7C5kvh0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hEqaAIgRI4BHfGCR2AgjxjrNSdghC6T/cq5CJN0XbCj0UhlBSSAm3KYlgXP445hqO gCXI1PLmFIXv+W8FyyiOE2DyZBGZzFjzVb2V3N/I02vM7QAPkm3k6lnJJ1r8xUyDKe +Jy89PokgmfQMgjppLiyU7A2mwAdX0woRL4axbWs= From: seanedmond@linux.microsoft.com To: u-boot@lists.denx.de Cc: sjg@chromium.org, stcarlso@linux.microsoft.com, ilias.apalodimas@linaro.org, abdellatif.elkhlifi@arm.com Subject: [PATCH 2/5] drivers: security: Add TPM2 implementation of security devices Date: Fri, 11 Aug 2023 17:28:20 -0700 Message-Id: <20230812002823.82576-3-seanedmond@linux.microsoft.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20230812002823.82576-1-seanedmond@linux.microsoft.com> References: <20230812002823.82576-1-seanedmond@linux.microsoft.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Stephen Carlson This implementation of the security uclass driver allows existing TPM2 devices declared in the device tree to be referenced for storing the OS anti-rollback counter, using the TPM2 non-volatile storage API. Signed-off-by: Stephen Carlson --- MAINTAINERS | 1 + drivers/security/Makefile | 1 + drivers/security/security-tpm.c | 173 ++++++++++++++++++++++++++++++++ include/tpm-v2.h | 1 + 4 files changed, 176 insertions(+) create mode 100644 drivers/security/security-tpm.c diff --git a/MAINTAINERS b/MAINTAINERS index 73b6943e03..257660a847 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1444,6 +1444,7 @@ S: Maintained F: drivers/security/Kconfig F: drivers/security/Makefile F: drivers/security/sandbox_security.c +F: drivers/security/security-tpm.c F: drivers/security/security-uclass.c SEMIHOSTING diff --git a/drivers/security/Makefile b/drivers/security/Makefile index ed10c3f234..e81966bb4a 100644 --- a/drivers/security/Makefile +++ b/drivers/security/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_DM_SECURITY) += security-uclass.o obj-$(CONFIG_SECURITY_SANDBOX) += sandbox_security.o +obj-$(CONFIG_SECURITY_TPM) += security-tpm.o diff --git a/drivers/security/security-tpm.c b/drivers/security/security-tpm.c new file mode 100644 index 0000000000..9070dd49ac --- /dev/null +++ b/drivers/security/security-tpm.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Microsoft, Inc + * Written by Stephen Carlson + */ + +#include +#include +#include +#include +#include + +struct security_state { + u32 index_arbvn; + struct udevice *tpm_dev; +}; + +static int tpm_security_init(struct udevice *tpm_dev) +{ + int res; + + /* Initialize TPM but allow reuse of existing session */ + res = tpm_open(tpm_dev); + if (res == -EBUSY) { + log(UCLASS_SECURITY, LOGL_DEBUG, + "Existing TPM session found, reusing\n"); + } else { + if (res) { + log(UCLASS_SECURITY, LOGL_ERR, + "TPM initialization failed (ret=%d)\n", res); + return res; + } + + res = tpm2_startup(tpm_dev, TPM2_SU_CLEAR); + if (res) { + log(UCLASS_SECURITY, LOGL_ERR, + "TPM startup failed (ret=%d)\n", res); + return res; + } + } + + return 0; +} + +static int tpm_security_arbvn_get(struct udevice *dev, u64 *arbvn) +{ + struct security_state *priv = dev_get_priv(dev); + int ret; + + if (!arbvn) + return -EINVAL; + + ret = tpm2_nv_read_value(priv->tpm_dev, priv->index_arbvn, arbvn, + sizeof(u64)); + if (ret == TPM2_RC_NV_UNINITIALIZED) { + /* Expected if no OS image has been loaded before */ + log(UCLASS_SECURITY, LOGL_INFO, + "No previous OS image, defaulting ARBVN to 0\n"); + *arbvn = 0ULL; + } else if (ret) { + log(UCLASS_SECURITY, LOGL_ERR, + "Unable to read ARBVN from TPM (ret=%d)\n", ret); + return ret; + } + + return 0; +} + +static int tpm_security_arbvn_set(struct udevice *dev, u64 arbvn) +{ + struct security_state *priv = dev_get_priv(dev); + struct udevice *tpm_dev = priv->tpm_dev; + u64 old_arbvn; + int ret; + + ret = tpm_security_arbvn_get(dev, &old_arbvn); + if (ret) + return ret; + + if (arbvn < old_arbvn) + return -EPERM; + + if (arbvn > old_arbvn) { + ret = tpm2_nv_write_value(tpm_dev, priv->index_arbvn, &arbvn, + sizeof(u64)); + if (ret) { + log(UCLASS_SECURITY, LOGL_ERR, + "Unable to write ARBVN to TPM (ret=%d)\n", ret); + return ret; + } + } + + return 0; +} + +static const struct dm_security_ops tpm_security_ops = { + .arbvn_get = tpm_security_arbvn_get, + .arbvn_set = tpm_security_arbvn_set, +}; + +static int tpm_security_probe(struct udevice *dev) +{ + struct security_state *priv = dev_get_priv(dev); + struct udevice *tpm_dev = priv->tpm_dev; + u32 index = priv->index_arbvn; + int ret; + + if (!tpm_dev) { + log(UCLASS_SECURITY, LOGL_ERR, + "TPM device not defined in DTS\n"); + return -EINVAL; + } + + ret = tpm_security_init(tpm_dev); + if (ret) + return ret; + + ret = tpm2_nv_define_space(tpm_dev, index, sizeof(u64), TPMA_NV_PPREAD | + TPMA_NV_PPWRITE | TPMA_NV_PLATFORMCREATE, + NULL, 0); + /* NV_DEFINED is an expected error if ARBVN already initialized */ + if (ret == TPM2_RC_NV_DEFINED) + log(UCLASS_SECURITY, LOGL_DEBUG, + "ARBVN index %u already defined\n", index); + else if (ret) { + log(UCLASS_SECURITY, LOGL_ERR, + "Unable to create ARBVN NV index (ret=%d)\n", ret); + return ret; + } + + return 0; +} + +static int tpm_security_remove(struct udevice *dev) +{ + struct security_state *priv = dev_get_priv(dev); + + return tpm_close(priv->tpm_dev); +} + +static int tpm_security_ofdata_to_platdata(struct udevice *dev) +{ + const u32 phandle = (u32)dev_read_u32_default(dev, "tpm", 0); + struct security_state *priv = dev_get_priv(dev); + struct udevice *tpm_dev; + int ret; + + ret = uclass_get_device_by_phandle_id(UCLASS_TPM, phandle, &tpm_dev); + if (ret) { + log(UCLASS_SECURITY, LOGL_ERR, "TPM node in DTS is invalid\n"); + return ret; + } + + priv->index_arbvn = (u32)dev_read_u32_default(dev, "arbvn-nv-index", 0); + priv->tpm_dev = tpm_dev; + return 0; +} + +static const struct udevice_id tpm_security_ids[] = { + { .compatible = "tpm,security" }, + { } +}; + +U_BOOT_DRIVER(security_tpm) = { + .name = "security_tpm", + .id = UCLASS_SECURITY, + .priv_auto = sizeof(struct security_state), + .of_match = tpm_security_ids, + .of_to_plat = tpm_security_ofdata_to_platdata, + .probe = tpm_security_probe, + .remove = tpm_security_remove, + .ops = &tpm_security_ops, +}; diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 2b6980e441..49bf0f0ba4 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -321,6 +321,7 @@ enum tpm2_return_codes { TPM2_RC_COMMAND_CODE = TPM2_RC_VER1 + 0x0043, TPM2_RC_AUTHSIZE = TPM2_RC_VER1 + 0x0044, TPM2_RC_AUTH_CONTEXT = TPM2_RC_VER1 + 0x0045, + TPM2_RC_NV_UNINITIALIZED = TPM2_RC_VER1 + 0x04a, TPM2_RC_NV_DEFINED = TPM2_RC_VER1 + 0x004c, TPM2_RC_NEEDS_TEST = TPM2_RC_VER1 + 0x0053, TPM2_RC_WARN = 0x0900, -- 2.40.0