From: Matthew Garrett <matthewg@nvidia.com>
To: mjg59@srcf.ucam.org
Cc: keyrings@vger.kernel.org, James.Bottomley@HansenPartnership.com,
linux-integrity@vger.kernel.org, rafael@kernel.org,
linux-pm@vger.kernel.org, linux-efi@vger.kernel.org,
Matthew Garrett <matthewg@nvidia.com>
Subject: [PATCH 11/17] tpm: Add kernel signing key creation with audited provenance
Date: Thu, 8 Oct 2026 06:20:27 -0700 [thread overview]
Message-ID: <20261008132532.1155166-12-matthewg@nvidia.com> (raw)
In-Reply-To: <20261008132532.1155166-1-matthewg@nvidia.com>
Add tpm2_kernel_key_create(), which creates an ECDSA P-256 signing key
for the kernel along with evidence that the kernel, rather than
userspace, created it. The key is created with TPM2_CreateLoaded under
the null hierarchy primary, with a random auth value that is sent
encrypted and never leaves the kernel. Its private part comes from the
TPM's RNG and the null seed changes on every TPM reset, so it can
neither be recreated nor used after a reboot.
The key is created inside an audit session while the kernel NV index
holds its magic value. Inside that audit session we:
* Read PCR 5. This will be used to bind the key to a kernel that
implements the restricted NV index feature.
* Read the kernel NV index. This will prove that the session was owned
by the kernel - userland will never be able to set this index to the
magic value.
* Generate the key. The above information proves (1) that the kernel
blocks userland from modifying the NV index, and (2) that the NV index
indicated that the session was in-kernel, which means that the key must
have been generated by the kernel.
Once this is done the NV index is set back to 0. The audit log can then
be later used to validate the key identity.
Signed-off-by: Matthew Garrett <matthewg@nvidia.com>
---
drivers/char/tpm/Kconfig | 10 +
drivers/char/tpm/Makefile | 1 +
drivers/char/tpm/tpm.h | 1 +
drivers/char/tpm/tpm2-kernel-key.c | 404 +++++++++++++++++++++++++++++
drivers/char/tpm/tpm2-sessions.c | 2 +-
include/linux/tpm.h | 39 +++
6 files changed, 456 insertions(+), 1 deletion(-)
create mode 100644 drivers/char/tpm/tpm2-kernel-key.c
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index a454b63edca5..15d204f8fa6d 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -42,6 +42,16 @@ config TCG_TPM2_HMAC
here adds some encryption overhead to all kernel to TPM
transactions.
+config TCG_TPM2_KERNEL_KEY
+ bool "Kernel-generated TPM signing keys with provenance"
+ depends on TCG_TPM2_HMAC
+ help
+ Allow the kernel to create TPM signing keys along with evidence,
+ signed by the kernel attestation key, that the key was created
+ by the kernel rather than by userspace. This is used to sign
+ data that must later be shown to have been produced by the
+ kernel, such as hibernation images.
+
config HW_RANDOM_TPM
bool "TPM HW Random Number Generator support"
depends on TCG_TPM && HW_RANDOM && !(TCG_TPM=y && HW_RANDOM=m)
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 88a96fee0934..66e5b27ad7c6 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -19,6 +19,7 @@ tpm-y += tpm-buf.o
tpm-y += tpm2-sessions.o
tpm-$(CONFIG_TCG_TPM2_HMAC) += tpm2-ak.o
tpm-$(CONFIG_TCG_TPM2_HMAC) += tpm2-kernel-nv.o
+tpm-$(CONFIG_TCG_TPM2_KERNEL_KEY) += tpm2-kernel-key.o
tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o
tpm-$(CONFIG_EFI) += eventlog/efi.o
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 54e8d5820b6d..228230b2d5bb 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -152,6 +152,7 @@ void tpm_dev_common_exit(void);
int tpm2_sessions_init(struct tpm_chip *chip);
void tpm2_free_auth(struct tpm2_auth *auth);
int tpm2_audit_session_handle(struct tpm_chip *chip, u32 *handle);
+int tpm2_load_null(struct tpm_chip *chip, u32 *null_key);
extern const u8 tpm2_kernel_nv_magic[TPM2_KERNEL_NV_SIZE];
void tpm2_kernel_nv_name(bool written, u8 name[TPM2_NULL_NAME_SIZE]);
diff --git a/drivers/char/tpm/tpm2-kernel-key.c b/drivers/char/tpm/tpm2-kernel-key.c
new file mode 100644
index 000000000000..27815525bc3f
--- /dev/null
+++ b/drivers/char/tpm/tpm2-kernel-key.c
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Kernel-generated TPM signing keys with provenance.
+ *
+ * A kernel signing key is an ECDSA P-256 key created by the TPM under the
+ * null hierarchy primary, with a random auth value known only to the
+ * kernel. Its private part is generated by the TPM's RNG and cannot be
+ * recreated, and the null seed changes on every TPM reset, so the key
+ * cannot be used once the system has rebooted.
+ *
+ * To show that the key was created by the kernel and not by userspace,
+ * it is created inside an audit session while the kernel NV index holds
+ * its magic value, which userspace is unable to store there:
+ *
+ * set kernel NV index to magic
+ * start audit session
+ * TPM2_PCR_Read(PCR 5, SHA-1 and SHA-256 banks)
+ * TPM2_NV_Read(kernel NV index)
+ * TPM2_CreateLoaded(signing key)
+ * TPM2_GetSessionAuditDigest, signed by the kernel AK
+ * end audit session
+ * reset kernel NV index to zero
+ *
+ * The signed audit digest, the audit log and the parameters of each
+ * response form the key's provenance. A verifier can recompute the
+ * audit digest from the log, check that each logged response matches the
+ * recorded parameters, and so learn that the NV read returned the magic
+ * value, what PCR 5 held, and the public key that was created.
+ */
+
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/unaligned.h>
+#include "tpm.h"
+#include "tpm2-rsp.h"
+
+#define TPM2_KKEY_PROV_MAGIC 0x544b5056 /* "TKPV" */
+#define TPM2_KKEY_PROV_VERSION 1
+#define TPM2_KKEY_NR_CMDS 3
+#define TPM2_KKEY_RSP_MAX 512
+
+/* Kernel signing keys may sign arbitrary digests */
+#define TPM2_OA_KERNEL_KEY ( \
+ TPM2_OA_FIXED_TPM | \
+ TPM2_OA_FIXED_PARENT | \
+ TPM2_OA_SENSITIVE_DATA_ORIGIN | \
+ TPM2_OA_USER_WITH_AUTH | \
+ TPM2_OA_NO_DA | \
+ TPM2_OA_SIGN)
+
+/* TPML_PCR_SELECTION for PCR 5 in the SHA-1 and SHA-256 banks */
+static const u8 tpm2_kkey_pcr5_select[] = {
+ 0x00, 0x00, 0x00, 0x02, /* count */
+ 0x00, 0x04, /* TPM_ALG_SHA1 */
+ 0x03, /* sizeofSelect */
+ 0x20, 0x00, 0x00, /* PCR 5 */
+ 0x00, 0x0b, /* TPM_ALG_SHA256 */
+ 0x03, /* sizeofSelect */
+ 0x20, 0x00, 0x00, /* PCR 5 */
+};
+
+/* The parameters of a response, as covered by the logged rpHash */
+struct tpm2_kkey_rsp {
+ u32 cc;
+ u16 len;
+ u8 data[TPM2_KKEY_RSP_MAX];
+};
+
+/*
+ * Send a command in the audit session and save its response parameters.
+ * If the response has a handle it is returned in @handle.
+ */
+static int tpm2_kkey_transmit(struct tpm_chip *chip, struct tpm_buf *buf,
+ u32 *handle, struct tpm2_kkey_rsp *rsp,
+ const char *desc)
+{
+ struct tpm_header *head = (struct tpm_header *)buf->data;
+ struct tpm2_rsp r;
+ const u8 *params;
+ u32 len;
+ int rc;
+
+ rsp->cc = be32_to_cpu(head->ordinal);
+
+ rc = tpm_buf_fill_hmac_session(chip, buf);
+ if (rc)
+ return rc;
+
+ rc = tpm_transmit_cmd(chip, buf, 0, desc);
+ rc = tpm_buf_check_hmac_response(chip, buf, rc);
+ if (rc)
+ return rc;
+
+ tpm2_rsp_init(&r, buf);
+ if (handle)
+ *handle = tpm2_rsp_u32(&r);
+ len = tpm2_rsp_u32(&r);
+ params = tpm2_rsp_bytes(&r, len);
+ if (!params || len > sizeof(rsp->data))
+ return -EIO;
+
+ memcpy(rsp->data, params, len);
+ rsp->len = len;
+ return 0;
+}
+
+static int tpm2_kkey_pcr_read(struct tpm_chip *chip, struct tpm_buf *buf,
+ struct tpm2_kkey_rsp *rsp)
+{
+ tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_READ);
+ /* the session is used only for audit */
+ tpm_buf_append_hmac_session(chip, buf, TPM2_SA_CONTINUE_SESSION,
+ NULL, 0);
+ tpm_buf_append(buf, tpm2_kkey_pcr5_select,
+ sizeof(tpm2_kkey_pcr5_select));
+
+ return tpm2_kkey_transmit(chip, buf, NULL, rsp, "reading PCR 5");
+}
+
+static int tpm2_kkey_nv_read(struct tpm_chip *chip, struct tpm_buf *buf,
+ struct tpm2_kkey_rsp *rsp)
+{
+ int rc;
+
+ tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_NV_READ);
+ rc = tpm_buf_append_name(chip, buf, TPM2_KERNEL_NV_INDEX, NULL);
+ if (rc)
+ return rc;
+ rc = tpm_buf_append_name(chip, buf, TPM2_KERNEL_NV_INDEX, NULL);
+ if (rc)
+ return rc;
+
+ /* no response encryption, so the logged rpHash covers the value */
+ tpm_buf_append_hmac_session(chip, buf, TPM2_SA_CONTINUE_SESSION,
+ NULL, 0);
+ tpm_buf_append_u16(buf, TPM2_KERNEL_NV_SIZE);
+ tpm_buf_append_u16(buf, 0);
+
+ rc = tpm2_kkey_transmit(chip, buf, NULL, rsp,
+ "reading kernel NV index");
+ if (rc)
+ return rc;
+
+ /* the TPM2B_MAX_NV_BUFFER must hold the magic value */
+ if (rsp->len != sizeof(u16) + TPM2_KERNEL_NV_SIZE ||
+ get_unaligned_be16(rsp->data) != TPM2_KERNEL_NV_SIZE ||
+ memcmp(rsp->data + sizeof(u16), tpm2_kernel_nv_magic,
+ TPM2_KERNEL_NV_SIZE))
+ return -EIO;
+
+ return 0;
+}
+
+static int tpm2_kkey_create_loaded(struct tpm_chip *chip,
+ struct tpm_buf *buf, u32 parent,
+ struct tpm2_kernel_key *key,
+ struct tpm2_kkey_rsp *rsp)
+{
+ struct tpm_buf *template __free(kfree) = NULL;
+ struct tpm2_rsp r;
+ u16 len;
+ int rc;
+
+ template = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
+ if (!template)
+ return -ENOMEM;
+
+ tpm_buf_init_sized(template, TPM_BUFSIZE);
+ tpm_buf_append_u16(template, TPM_ALG_ECC);
+ tpm_buf_append_u16(template, TPM_ALG_SHA256);
+ tpm_buf_append_u32(template, TPM2_OA_KERNEL_KEY);
+ /* auth policy (empty) */
+ tpm_buf_append_u16(template, 0);
+ /* symmetric algorithm (none for a signing key) */
+ tpm_buf_append_u16(template, TPM_ALG_NULL);
+ /* signing scheme */
+ tpm_buf_append_u16(template, TPM_ALG_ECDSA);
+ tpm_buf_append_u16(template, TPM_ALG_SHA256);
+ tpm_buf_append_u16(template, TPM2_ECC_NIST_P256);
+ /* KDF scheme */
+ tpm_buf_append_u16(template, TPM_ALG_NULL);
+ /* unique (empty points) */
+ tpm_buf_append_u16(template, 0);
+ tpm_buf_append_u16(template, 0);
+
+ tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_LOADED);
+ rc = tpm_buf_append_name(chip, buf, parent, chip->null_key_name);
+ if (rc)
+ return rc;
+
+ /* encrypt inSensitive so the key's auth value is not exposed */
+ tpm_buf_append_hmac_session(chip, buf, TPM2_SA_DECRYPT |
+ TPM2_SA_CONTINUE_SESSION, NULL, 0);
+
+ /* inSensitive: the auth value and no data */
+ tpm_buf_append_u16(buf, sizeof(u16) + sizeof(key->auth) + sizeof(u16));
+ tpm_buf_append_u16(buf, sizeof(key->auth));
+ tpm_buf_append(buf, key->auth, sizeof(key->auth));
+ tpm_buf_append_u16(buf, 0);
+
+ /* inPublic */
+ tpm_buf_append(buf, template->data, template->length);
+
+ if (buf->flags & TPM_BUF_INVALID || template->flags & TPM_BUF_INVALID)
+ return -EINVAL;
+
+ rc = tpm2_kkey_transmit(chip, buf, &key->handle, rsp,
+ "creating kernel signing key");
+ if (rc)
+ return rc;
+
+ /* outPrivate, then outPublic */
+ tpm2_rsp_init_data(&r, rsp->data, rsp->len);
+ tpm2_rsp_tpm2b(&r, &len);
+
+ return tpm2_rsp_ecdsa_public(&r, TPM2_OA_KERNEL_KEY, key->x, key->y);
+}
+
+/* Bounds-checked writer for the serialized provenance */
+struct tpm2_kkey_writer {
+ struct tpm2_key_provenance *prov;
+ bool err;
+};
+
+static void tpm2_kkey_put(struct tpm2_kkey_writer *w, const void *data,
+ u16 len)
+{
+ struct tpm2_key_provenance *prov = w->prov;
+
+ if (w->err || sizeof(prov->data) - prov->len < len) {
+ w->err = true;
+ return;
+ }
+
+ memcpy(&prov->data[prov->len], data, len);
+ prov->len += len;
+}
+
+static void tpm2_kkey_put_u8(struct tpm2_kkey_writer *w, u8 val)
+{
+ tpm2_kkey_put(w, &val, sizeof(val));
+}
+
+static void tpm2_kkey_put_u16(struct tpm2_kkey_writer *w, u16 val)
+{
+ __be16 v = cpu_to_be16(val);
+
+ tpm2_kkey_put(w, &v, sizeof(v));
+}
+
+static void tpm2_kkey_put_u32(struct tpm2_kkey_writer *w, u32 val)
+{
+ __be32 v = cpu_to_be32(val);
+
+ tpm2_kkey_put(w, &v, sizeof(v));
+}
+
+/*
+ * Serialized provenance, all integers big-endian:
+ *
+ * u32 magic ("TKPV")
+ * u16 version (1)
+ * u16 attestation length, then the TPMS_ATTEST
+ * u8[32] AK signature R
+ * u8[32] AK signature S
+ * u8 number of commands, then for each command:
+ * u32 command code
+ * u8[32] cpHash
+ * u8[32] rpHash
+ * u16 response parameter length, then the parameters
+ */
+static int tpm2_kkey_serialize(struct tpm2_key_provenance *prov,
+ const struct tpm2_signed_audit *audit,
+ const struct tpm2_audit_entry *log,
+ const struct tpm2_kkey_rsp *rsp)
+{
+ struct tpm2_kkey_writer w = { .prov = prov };
+ int i;
+
+ prov->len = 0;
+ tpm2_kkey_put_u32(&w, TPM2_KKEY_PROV_MAGIC);
+ tpm2_kkey_put_u16(&w, TPM2_KKEY_PROV_VERSION);
+ tpm2_kkey_put_u16(&w, audit->attest_len);
+ tpm2_kkey_put(&w, audit->attest, audit->attest_len);
+ tpm2_kkey_put(&w, audit->sig_r, sizeof(audit->sig_r));
+ tpm2_kkey_put(&w, audit->sig_s, sizeof(audit->sig_s));
+ tpm2_kkey_put_u8(&w, TPM2_KKEY_NR_CMDS);
+
+ for (i = 0; i < TPM2_KKEY_NR_CMDS; i++) {
+ tpm2_kkey_put_u32(&w, rsp[i].cc);
+ tpm2_kkey_put(&w, log[i].cphash, sizeof(log[i].cphash));
+ tpm2_kkey_put(&w, log[i].rphash, sizeof(log[i].rphash));
+ tpm2_kkey_put_u16(&w, rsp[i].len);
+ tpm2_kkey_put(&w, rsp[i].data, rsp[i].len);
+ }
+
+ return w.err ? -E2BIG : 0;
+}
+
+/**
+ * tpm2_kernel_key_create() - create a kernel signing key with provenance
+ * @chip: the TPM chip
+ * @key: filled with the new key, which remains loaded in the TPM
+ * @prov: filled with evidence that the key was created by the kernel
+ *
+ * Creates an ECDSA P-256 signing key as described at the top of this
+ * file. The kernel NV index must be usable and the owner and endorsement
+ * hierarchies must have empty auth values. Any existing auth session is
+ * ended. The caller must hold the chip's ops lock, and must release the
+ * key with tpm2_kernel_key_destroy().
+ *
+ * Return:
+ * * 0 - OK
+ * * -errno - A system error
+ * * TPM_RC - A TPM error
+ */
+int tpm2_kernel_key_create(struct tpm_chip *chip, struct tpm2_kernel_key *key,
+ struct tpm2_key_provenance *prov)
+{
+ struct tpm2_kkey_rsp *rsp __free(kfree) = NULL;
+ struct tpm_buf *buf __free(kfree_sensitive) = NULL;
+ struct tpm2_signed_audit audit = { };
+ const struct tpm2_audit_entry *log;
+ bool magic = false;
+ u32 null_key = 0;
+ int rc, rc2;
+
+ memset(key, 0, sizeof(*key));
+ prov->len = 0;
+
+ rsp = kcalloc(TPM2_KKEY_NR_CMDS, sizeof(*rsp), GFP_KERNEL);
+ buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
+ if (!rsp || !buf)
+ return -ENOMEM;
+ tpm_buf_init(buf, TPM_BUFSIZE);
+
+ get_random_bytes(key->auth, sizeof(key->auth));
+
+ /* the index may have been removed by TPM2_Clear since boot */
+ rc = tpm2_kernel_nv_provision(chip);
+ if (rc)
+ goto out;
+
+ tpm2_end_auth_session(chip);
+
+ rc = tpm2_load_null(chip, &null_key);
+ if (rc)
+ goto out;
+
+ magic = true;
+ rc = tpm2_kernel_nv_set_magic(chip);
+ if (rc)
+ goto out;
+
+ /* setting the index used an ordinary session */
+ tpm2_end_auth_session(chip);
+ rc = tpm2_start_auth_session(chip, true);
+ if (rc)
+ goto out;
+
+ rc = tpm2_kkey_pcr_read(chip, buf, &rsp[0]);
+ if (!rc)
+ rc = tpm2_kkey_nv_read(chip, buf, &rsp[1]);
+ if (!rc)
+ rc = tpm2_kkey_create_loaded(chip, buf, null_key, key, &rsp[2]);
+ if (rc)
+ goto out;
+
+ rc = tpm2_get_signed_audit_digest(chip, NULL, 0, &audit);
+ if (rc)
+ goto out;
+
+ if (tpm2_get_audit_log(chip, &log) != TPM2_KKEY_NR_CMDS) {
+ rc = -EIO;
+ goto out;
+ }
+
+ rc = tpm2_kkey_serialize(prov, &audit, log, rsp);
+
+out:
+ tpm2_free_signed_audit(&audit);
+ tpm2_end_auth_session(chip);
+
+ if (magic) {
+ rc2 = tpm2_kernel_nv_clear(chip);
+ if (!rc)
+ rc = rc2;
+ }
+
+ if (null_key)
+ tpm2_flush_context(chip, null_key);
+
+ if (rc) {
+ if (key->handle)
+ tpm2_flush_context(chip, key->handle);
+ memzero_explicit(key, sizeof(*key));
+ prov->len = 0;
+ dev_err(&chip->dev, "failed to create kernel signing key: %d\n",
+ rc);
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm2_kernel_key_create);
diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
index e5ef30238fbe..78457843084e 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -1073,7 +1073,7 @@ static int tpm2_parse_start_auth_session(struct tpm2_auth *auth,
return 0;
}
-static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
+int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
{
unsigned int offset = 0; /* dummy offset for null seed context */
u8 name[SHA256_DIGEST_SIZE + 2];
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 35ba30a2674d..7ee553688906 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -358,6 +358,45 @@ struct tpm2_signed_audit {
u8 sig_s[EC_PT_SZ];
};
+/**
+ * struct tpm2_kernel_key - a signing key created by the kernel
+ * @handle: transient handle of the loaded key
+ * @auth: the key's random auth value, which never leaves the kernel
+ * @x: X coordinate of the P-256 public key
+ * @y: Y coordinate of the P-256 public key
+ */
+struct tpm2_kernel_key {
+ u32 handle;
+ u8 auth[SHA256_DIGEST_SIZE];
+ u8 x[EC_PT_SZ];
+ u8 y[EC_PT_SZ];
+};
+
+#define TPM2_KEY_PROVENANCE_MAX 2048
+
+/**
+ * struct tpm2_key_provenance - evidence that a key was created by the kernel
+ * @len: length of @data
+ * @data: serialized AK-signed audit session attestation and log, in a
+ * format private to the TPM driver
+ */
+struct tpm2_key_provenance {
+ u16 len;
+ u8 data[TPM2_KEY_PROVENANCE_MAX];
+};
+
+#ifdef CONFIG_TCG_TPM2_KERNEL_KEY
+int tpm2_kernel_key_create(struct tpm_chip *chip, struct tpm2_kernel_key *key,
+ struct tpm2_key_provenance *prov);
+#else
+static inline int tpm2_kernel_key_create(struct tpm_chip *chip,
+ struct tpm2_kernel_key *key,
+ struct tpm2_key_provenance *prov)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
#ifdef CONFIG_TCG_TPM2_HMAC
int tpm2_start_auth_session(struct tpm_chip *chip, bool audit);
--
2.43.0
next prev parent reply other threads:[~2026-10-08 13:26 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-08 13:20 [RFC] Make hibernation work with lockdown Matthew Garrett
2026-10-08 13:20 ` [PATCH 01/17] tpm: Define a kernel-owned TPM NV index that can't be modified by userland Matthew Garrett
2026-10-08 13:41 ` Matthew Garrett
2026-10-08 16:24 ` Jarkko Sakkinen
2026-10-08 16:23 ` Jarkko Sakkinen
2026-10-09 8:33 ` Matthew Garrett
2026-10-08 17:06 ` Ilias Apalodimas
2026-10-08 13:20 ` [PATCH 02/17] efi: Add a mechanism to modify TPM state depending on kernel security features Matthew Garrett
2026-10-08 16:38 ` Jarkko Sakkinen
2026-10-08 13:20 ` [PATCH 03/17] tpm: Allow tpm2_start_auth_session() to start an audit session Matthew Garrett
2026-10-08 13:20 ` [PATCH 04/17] tpm: Log commands executed in " Matthew Garrett
2026-10-08 13:20 ` [PATCH 05/17] tpm: Add a kernel attestation key and signed audit digest retrieval Matthew Garrett
2026-10-08 16:45 ` James Bottomley
2026-10-09 8:29 ` Matthew Garrett
2026-10-08 13:20 ` [PATCH 06/17] tpm: Use TPM2_NV_ReadPublic to read NV index names Matthew Garrett
2026-10-08 13:20 ` [PATCH 07/17] tpm: Add in-kernel support for reading NV indices Matthew Garrett
2026-10-08 13:20 ` [PATCH 08/17] tpm: Add NV define, undefine and write helpers Matthew Garrett
2026-10-08 13:20 ` [PATCH 09/17] tpm: Provision the kernel NV index at registration Matthew Garrett
2026-10-08 13:20 ` [PATCH 10/17] tpm: Move the bounds-checked response reader to a header Matthew Garrett
2026-10-08 13:20 ` Matthew Garrett [this message]
2026-10-08 17:00 ` [PATCH 11/17] tpm: Add kernel signing key creation with audited provenance James Bottomley
2026-10-09 8:31 ` Matthew Garrett
2026-10-08 13:20 ` [PATCH 12/17] tpm: Add signing with the kernel signing key Matthew Garrett
2026-10-08 13:20 ` [PATCH 13/17] tpm: Add verification of kernel signing key provenance Matthew Garrett
2026-10-08 13:20 ` [PATCH 14/17] PM: hibernate: Add image digest and signature page infrastructure Matthew Garrett
2026-10-08 13:20 ` [PATCH 15/17] PM: hibernate: Sign and verify images with a kernel-generated TPM key Matthew Garrett
2026-10-08 13:20 ` [PATCH 16/17] PM: hibernate: Refuse to verify images with a virtual TPM Matthew Garrett
2026-10-08 13:20 ` [PATCH 17/17] PM: hibernate: Allow hibernation under lockdown with signed images Matthew Garrett
2026-10-08 16:53 ` Jarkko Sakkinen
2026-10-09 8:31 ` Matthew Garrett
2026-10-08 15:56 ` [RFC] Make hibernation work with lockdown Jarkko Sakkinen
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=20261008132532.1155166-12-matthewg@nvidia.com \
--to=matthewg@nvidia.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=keyrings@vger.kernel.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=mjg59@srcf.ucam.org \
--cc=rafael@kernel.org \
/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