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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox