All of lore.kernel.org
 help / color / mirror / Atom feed
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	[thread overview]
Message-ID: <20230812002823.82576-3-seanedmond@linux.microsoft.com> (raw)
In-Reply-To: <20230812002823.82576-1-seanedmond@linux.microsoft.com>

From: Stephen Carlson <stcarlso@linux.microsoft.com>

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 <stcarlso@linux.microsoft.com>
---
 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 <stcarlso@microsoft.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <dm-security.h>
+#include <tpm-v2.h>
+
+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


  parent reply	other threads:[~2023-08-12  0:29 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-12  0:28 [PATCH 0/5] Add anti-rollback validation feature seanedmond
2023-08-12  0:28 ` [PATCH 1/5] drivers: security: Add security devices to driver model seanedmond
2023-08-16 13:14   ` Ilias Apalodimas
2023-08-17 13:41   ` Simon Glass
2023-08-12  0:28 ` seanedmond [this message]
2023-08-14  8:39   ` [PATCH 2/5] drivers: security: Add TPM2 implementation of security devices Ilias Apalodimas
2023-08-14 21:23     ` Sean Edmond
2023-08-16 13:55       ` Ilias Apalodimas
2023-08-17 13:41   ` Simon Glass
2023-08-17 23:29     ` Sean Edmond
2023-08-18  3:10       ` Simon Glass
2023-08-12  0:28 ` [PATCH 3/5] common: Add OS anti-rollback validation using " seanedmond
2023-08-17 13:41   ` Simon Glass
2023-08-12  0:28 ` [PATCH 4/5] common: Add OS anti-rollback grace period seanedmond
2023-08-17 13:41   ` Simon Glass
2023-08-12  0:28 ` [PATCH 5/5] dm: test: Add a test for security driver seanedmond
2023-08-17 13:41   ` Simon Glass
2023-08-17 13:41 ` [PATCH 0/5] Add anti-rollback validation feature Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230812002823.82576-3-seanedmond@linux.microsoft.com \
    --to=seanedmond@linux.microsoft.com \
    --cc=abdellatif.elkhlifi@arm.com \
    --cc=ilias.apalodimas@linaro.org \
    --cc=sjg@chromium.org \
    --cc=stcarlso@linux.microsoft.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.