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 05/17] tpm: Add a kernel attestation key and signed audit digest retrieval
Date: Thu, 8 Oct 2026 06:20:21 -0700 [thread overview]
Message-ID: <20261008132532.1155166-6-matthewg@nvidia.com> (raw)
In-Reply-To: <20261008132532.1155166-1-matthewg@nvidia.com>
Add tpm2_create_kernel_ak(), which creates a restricted ECDSA P-256
signing key as a primary key in the owner hierarchy. The template's
unique field holds a fixed seed, which means that (since the primary
keys are derived from the seed and template) the same AK is generated on
every call until something changes the owner seed (ie, the TPM being
cleared or replaced).
We can use this to get a signed copy of the audit digest from a TPM
audit session. Add tpm2_get_signed_audit_digest(), which uses the AK to
sign the digest of the active audit session and returns the TPMS_ATTEST
structure, the signature and the AK public key.
Both the owner and endorsement hierarchies are assumed to have empty
auth values, which is the default. If this turns out to be a problem in
the real world we can look at providing a mechanism for userland to
provide the values at boot or resume times.
Signed-off-by: Matthew Garrett <matthewg@nvidia.com>
---
drivers/char/tpm/Makefile | 1 +
drivers/char/tpm/tpm.h | 1 +
drivers/char/tpm/tpm2-ak.c | 374 +++++++++++++++++++++++++++++++
drivers/char/tpm/tpm2-sessions.c | 15 ++
include/linux/tpm.h | 38 ++++
include/linux/tpm_command.h | 8 +
6 files changed, 437 insertions(+)
create mode 100644 drivers/char/tpm/tpm2-ak.c
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 5b5cdc0d32e4..10a4ed388dea 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -17,6 +17,7 @@ tpm-y += eventlog/tpm1.o
tpm-y += eventlog/tpm2.o
tpm-y += tpm-buf.o
tpm-y += tpm2-sessions.o
+tpm-$(CONFIG_TCG_TPM2_HMAC) += tpm2-ak.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 e55fa22a13eb..23070bdb2aa4 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -145,6 +145,7 @@ void tpm_dev_common_exit(void);
#ifdef CONFIG_TCG_TPM2_HMAC
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);
#else
static inline int tpm2_sessions_init(struct tpm_chip *chip)
{
diff --git a/drivers/char/tpm/tpm2-ak.c b/drivers/char/tpm/tpm2-ak.c
new file mode 100644
index 000000000000..ad24d36b1728
--- /dev/null
+++ b/drivers/char/tpm/tpm2-ak.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Kernel attestation key (AK) support.
+ *
+ * The kernel AK is a restricted ECDSA P-256 signing key created as a
+ * primary key in the owner hierarchy from a fixed template. Primary keys
+ * are derived from the hierarchy seed and the template, so on a given TPM
+ * the same AK is generated every time until the owner seed changes, which
+ * happens when the TPM is cleared.
+ *
+ * The AK can be used to sign the digest of the kernel's audit session,
+ * allowing the log returned by tpm2_get_audit_log() to be verified.
+ */
+
+#include <linux/slab.h>
+#include <linux/unaligned.h>
+#include "tpm.h"
+
+/*
+ * Restricted signing key whose private part never leaves the TPM. NO_DA
+ * as the key has an empty auth value.
+ */
+#define TPM2_OA_KERNEL_AK ( \
+ TPM2_OA_FIXED_TPM | \
+ TPM2_OA_FIXED_PARENT | \
+ TPM2_OA_SENSITIVE_DATA_ORIGIN | \
+ TPM2_OA_USER_WITH_AUTH | \
+ TPM2_OA_NO_DA | \
+ TPM2_OA_RESTRICTED | \
+ TPM2_OA_SIGN)
+
+/*
+ * Placed in the unique field of the template. Changing it changes the
+ * AK derived from the owner seed.
+ */
+static const u8 tpm2_kernel_ak_seed[EC_PT_SZ] =
+ "Linux kernel attestation key v1";
+
+/* Bounds-checked reader for TPM response data */
+struct tpm2_rsp {
+ const u8 *data;
+ u32 len;
+ u32 off;
+ bool err;
+};
+
+static const u8 *tpm2_rsp_bytes(struct tpm2_rsp *r, u32 count)
+{
+ const u8 *p;
+
+ if (r->err || r->len - r->off < count) {
+ r->err = true;
+ return NULL;
+ }
+
+ p = &r->data[r->off];
+ r->off += count;
+ return p;
+}
+
+static u16 tpm2_rsp_u16(struct tpm2_rsp *r)
+{
+ const u8 *p = tpm2_rsp_bytes(r, sizeof(u16));
+
+ return p ? get_unaligned_be16(p) : 0;
+}
+
+static u32 tpm2_rsp_u32(struct tpm2_rsp *r)
+{
+ const u8 *p = tpm2_rsp_bytes(r, sizeof(u32));
+
+ return p ? get_unaligned_be32(p) : 0;
+}
+
+/* Initialise a reader over the response held in @buf */
+static void tpm2_rsp_init(struct tpm2_rsp *r, struct tpm_buf *buf)
+{
+ struct tpm_header *head = (struct tpm_header *)buf->data;
+
+ r->data = buf->data;
+ r->len = min_t(u32, be32_to_cpu(head->length), TPM_BUFSIZE);
+ r->off = TPM_HEADER_SIZE;
+ r->err = r->len < TPM_HEADER_SIZE;
+}
+
+/* Read a TPM2B_ECC_PARAMETER, left-padding it to EC_PT_SZ bytes */
+static void tpm2_rsp_ecc_param(struct tpm2_rsp *r, u8 *out)
+{
+ u16 len = tpm2_rsp_u16(r);
+ const u8 *p;
+
+ if (len > EC_PT_SZ) {
+ r->err = true;
+ return;
+ }
+
+ p = tpm2_rsp_bytes(r, len);
+ if (!p)
+ return;
+
+ memset(out, 0, EC_PT_SZ - len);
+ memcpy(out + EC_PT_SZ - len, p, len);
+}
+
+/* Parse and validate the TPM2B_PUBLIC of the kernel AK */
+static int tpm2_parse_kernel_ak_public(struct tpm2_rsp *r, u8 *x, u8 *y)
+{
+ u16 size = tpm2_rsp_u16(r);
+ u32 end = r->off + size;
+
+ if (tpm2_rsp_u16(r) != TPM_ALG_ECC ||
+ tpm2_rsp_u16(r) != TPM_ALG_SHA256 ||
+ tpm2_rsp_u32(r) != TPM2_OA_KERNEL_AK ||
+ tpm2_rsp_u16(r) != 0 || /* authPolicy */
+ tpm2_rsp_u16(r) != TPM_ALG_NULL || /* symmetric */
+ tpm2_rsp_u16(r) != TPM_ALG_ECDSA || /* scheme */
+ tpm2_rsp_u16(r) != TPM_ALG_SHA256 || /* scheme hash */
+ tpm2_rsp_u16(r) != TPM2_ECC_NIST_P256 ||
+ tpm2_rsp_u16(r) != TPM_ALG_NULL) /* kdf */
+ return -EINVAL;
+
+ tpm2_rsp_ecc_param(r, x);
+ tpm2_rsp_ecc_param(r, y);
+
+ if (r->err || r->off != end)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * tpm2_create_kernel_ak() - create the kernel attestation key
+ * @chip: the TPM chip
+ * @handle: set to the transient handle of the AK on success
+ * @x: if not NULL, filled with the X coordinate of the AK public key
+ * @y: if not NULL, filled with the Y coordinate of the AK public key
+ *
+ * Creates the kernel AK as a primary key in the owner hierarchy using a
+ * fixed template, so the same key is returned on every call until the
+ * TPM is cleared. The owner hierarchy must have an empty auth value.
+ * The caller must hold the chip's ops lock and is responsible for
+ * flushing @handle with tpm2_flush_context().
+ *
+ * Return:
+ * * 0 - OK
+ * * -errno - A system error
+ * * TPM_RC - A TPM error
+ */
+int tpm2_create_kernel_ak(struct tpm_chip *chip, u32 *handle, u8 *x, u8 *y)
+{
+ struct tpm_buf *template __free(kfree) = NULL;
+ struct tpm_buf *buf __free(kfree) = NULL;
+ u8 ak_x[EC_PT_SZ], ak_y[EC_PT_SZ];
+ struct tpm2_rsp r;
+ u32 ak;
+ int rc;
+
+ buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ template = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
+ if (!template)
+ return -ENOMEM;
+
+ tpm_buf_init(buf, TPM_BUFSIZE);
+ tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_PRIMARY);
+ tpm_buf_init_sized(template, TPM_BUFSIZE);
+
+ /* key type */
+ tpm_buf_append_u16(template, TPM_ALG_ECC);
+ /* name algorithm */
+ tpm_buf_append_u16(template, TPM_ALG_SHA256);
+ /* object properties */
+ tpm_buf_append_u32(template, TPM2_OA_KERNEL_AK);
+ /* 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);
+ /* ECC curve */
+ tpm_buf_append_u16(template, TPM2_ECC_NIST_P256);
+ /* KDF scheme */
+ tpm_buf_append_u16(template, TPM_ALG_NULL);
+ /* unique: the fixed seed as X, empty Y */
+ tpm_buf_append_u16(template, sizeof(tpm2_kernel_ak_seed));
+ tpm_buf_append(template, tpm2_kernel_ak_seed,
+ sizeof(tpm2_kernel_ak_seed));
+ tpm_buf_append_u16(template, 0);
+
+ /* primary handle */
+ tpm_buf_append_handle(buf, TPM2_RH_OWNER);
+ tpm_buf_append_auth(chip, buf, NULL, 0);
+
+ /* sensitive create: empty auth and data */
+ tpm_buf_append_u16(buf, 4);
+ tpm_buf_append_u16(buf, 0);
+ tpm_buf_append_u16(buf, 0);
+
+ /* the public template */
+ tpm_buf_append(buf, template->data, template->length);
+
+ /* outside info (empty) */
+ tpm_buf_append_u16(buf, 0);
+
+ /* creation PCR (none) */
+ tpm_buf_append_u32(buf, 0);
+
+ if (buf->flags & TPM_BUF_INVALID || template->flags & TPM_BUF_INVALID)
+ return -EINVAL;
+
+ rc = tpm_transmit_cmd(chip, buf, 0, "creating kernel AK");
+ if (rc)
+ return rc;
+
+ tpm2_rsp_init(&r, buf);
+ ak = tpm2_rsp_u32(&r);
+ /* parameterSize */
+ tpm2_rsp_u32(&r);
+ if (r.err)
+ return -EINVAL;
+
+ rc = tpm2_parse_kernel_ak_public(&r, ak_x, ak_y);
+ if (rc) {
+ dev_err(&chip->dev, "unexpected kernel AK public area\n");
+ tpm2_flush_context(chip, ak);
+ return rc;
+ }
+
+ if (x)
+ memcpy(x, ak_x, EC_PT_SZ);
+ if (y)
+ memcpy(y, ak_y, EC_PT_SZ);
+ *handle = ak;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tpm2_create_kernel_ak);
+
+/**
+ * tpm2_get_signed_audit_digest() - get the audit session digest signed by the AK
+ * @chip: the TPM chip
+ * @nonce: qualifying data to include in the attestation (may be NULL)
+ * @nonce_len: length of @nonce
+ * @audit: filled with the signed attestation and the AK public key
+ *
+ * Creates the kernel AK and uses TPM2_GetSessionAuditDigest to have it
+ * sign the digest of the active audit session. The session itself is not
+ * used to authorize the command, so the audit digest and the log returned
+ * by tpm2_get_audit_log() are unaffected. The endorsement and owner
+ * hierarchies must have empty auth values. The caller must hold the
+ * chip's ops lock and must release @audit with tpm2_free_signed_audit().
+ *
+ * Return:
+ * * 0 - OK
+ * * -EINVAL - No audit session is active, or the response was malformed
+ * * -errno - A system error
+ * * TPM_RC - A TPM error
+ */
+int tpm2_get_signed_audit_digest(struct tpm_chip *chip, const u8 *nonce,
+ u16 nonce_len,
+ struct tpm2_signed_audit *audit)
+{
+ struct tpm_buf *buf __free(kfree) = NULL;
+ u32 session, ak, param_size, end;
+ const u8 *attest;
+ struct tpm2_rsp r;
+ u16 attest_len;
+ int rc;
+
+ memset(audit, 0, sizeof(*audit));
+
+ if (nonce_len > TPM2_MAX_DIGEST_SIZE)
+ return -EINVAL;
+
+ rc = tpm2_audit_session_handle(chip, &session);
+ if (rc)
+ return rc;
+
+ buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ rc = tpm2_create_kernel_ak(chip, &ak, audit->ak_x, audit->ak_y);
+ if (rc)
+ return rc;
+
+ tpm_buf_init(buf, TPM_BUFSIZE);
+ tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_GET_SESSION_AUDIT_DIGEST);
+
+ /* privacyAdminHandle, signHandle, sessionHandle */
+ tpm_buf_append_handle(buf, TPM2_RH_ENDORSEMENT);
+ tpm_buf_append_handle(buf, ak);
+ tpm_buf_append_handle(buf, session);
+
+ /* empty password authorizations for the endorsement hierarchy and AK */
+ tpm_buf_append_auth(chip, buf, NULL, 0);
+ tpm_buf_append_auth(chip, buf, NULL, 0);
+
+ /* qualifyingData */
+ tpm_buf_append_u16(buf, nonce_len);
+ if (nonce_len)
+ tpm_buf_append(buf, nonce, nonce_len);
+
+ /* inScheme: use the AK's scheme */
+ tpm_buf_append_u16(buf, TPM_ALG_NULL);
+
+ if (buf->flags & TPM_BUF_INVALID) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = tpm_transmit_cmd(chip, buf, 0, "getting session audit digest");
+ if (rc)
+ goto out;
+
+ rc = -EINVAL;
+ tpm2_rsp_init(&r, buf);
+ param_size = tpm2_rsp_u32(&r);
+ end = r.off + param_size;
+
+ /* auditInfo */
+ attest_len = tpm2_rsp_u16(&r);
+ attest = tpm2_rsp_bytes(&r, attest_len);
+ if (!attest)
+ goto out;
+
+ /* TPMS_ATTEST begins with magic and type */
+ if (attest_len < sizeof(u32) + sizeof(u16) ||
+ get_unaligned_be32(attest) != TPM2_GENERATED_VALUE ||
+ get_unaligned_be16(attest + sizeof(u32)) !=
+ TPM2_ST_ATTEST_SESSION_AUDIT)
+ goto out;
+
+ /* signature */
+ if (tpm2_rsp_u16(&r) != TPM_ALG_ECDSA ||
+ tpm2_rsp_u16(&r) != TPM_ALG_SHA256)
+ goto out;
+ tpm2_rsp_ecc_param(&r, audit->sig_r);
+ tpm2_rsp_ecc_param(&r, audit->sig_s);
+
+ if (r.err || r.off != end)
+ goto out;
+
+ audit->attest = kmemdup(attest, attest_len, GFP_KERNEL);
+ if (!audit->attest) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ audit->attest_len = attest_len;
+ rc = 0;
+
+out:
+ if (rc < 0 && rc != -ENOMEM)
+ dev_err(&chip->dev, "failed to get session audit digest: %d\n",
+ rc);
+ tpm2_flush_context(chip, ak);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm2_get_signed_audit_digest);
+
+/**
+ * tpm2_free_signed_audit() - release a signed audit digest
+ * @audit: the structure filled by tpm2_get_signed_audit_digest()
+ */
+void tpm2_free_signed_audit(struct tpm2_signed_audit *audit)
+{
+ kfree(audit->attest);
+ audit->attest = NULL;
+ audit->attest_len = 0;
+}
+EXPORT_SYMBOL_GPL(tpm2_free_signed_audit);
diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
index 56323a9ac87a..badc9bec9caa 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -1023,6 +1023,21 @@ int tpm2_get_audit_log(struct tpm_chip *chip,
}
EXPORT_SYMBOL(tpm2_get_audit_log);
+/*
+ * Return the handle of the active audit session, or -EINVAL if there is
+ * no active audit session.
+ */
+int tpm2_audit_session_handle(struct tpm_chip *chip, u32 *handle)
+{
+ struct tpm2_auth *auth = chip->auth;
+
+ if (!auth || !auth->audit)
+ return -EINVAL;
+
+ *handle = auth->handle;
+ return 0;
+}
+
static int tpm2_parse_start_auth_session(struct tpm2_auth *auth,
struct tpm_buf *buf)
{
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index c1d0617ff8a1..1d828b32847f 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -329,11 +329,35 @@ struct tpm2_audit_entry {
u8 rphash[SHA256_DIGEST_SIZE];
};
+/**
+ * struct tpm2_signed_audit - a session audit digest signed by the kernel AK
+ * @ak_x: X coordinate of the AK's P-256 public key
+ * @ak_y: Y coordinate of the AK's P-256 public key
+ * @attest: the signed TPMS_ATTEST structure, containing the audit digest
+ * @attest_len: length of @attest
+ * @sig_r: R component of the ECDSA-SHA256 signature over @attest
+ * @sig_s: S component of the ECDSA-SHA256 signature over @attest
+ */
+struct tpm2_signed_audit {
+ u8 ak_x[EC_PT_SZ];
+ u8 ak_y[EC_PT_SZ];
+ u8 *attest;
+ u16 attest_len;
+ u8 sig_r[EC_PT_SZ];
+ u8 sig_s[EC_PT_SZ];
+};
+
#ifdef CONFIG_TCG_TPM2_HMAC
int tpm2_start_auth_session(struct tpm_chip *chip, bool audit);
int tpm2_get_audit_log(struct tpm_chip *chip,
const struct tpm2_audit_entry **log);
+int tpm2_create_kernel_ak(struct tpm_chip *chip, u32 *handle,
+ u8 *x, u8 *y);
+int tpm2_get_signed_audit_digest(struct tpm_chip *chip, const u8 *nonce,
+ u16 nonce_len,
+ struct tpm2_signed_audit *audit);
+void tpm2_free_signed_audit(struct tpm2_signed_audit *audit);
int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
int rc);
@@ -354,6 +378,20 @@ static inline int tpm2_get_audit_log(struct tpm_chip *chip,
{
return -EOPNOTSUPP;
}
+static inline int tpm2_create_kernel_ak(struct tpm_chip *chip, u32 *handle,
+ u8 *x, u8 *y)
+{
+ return -EOPNOTSUPP;
+}
+static inline int
+tpm2_get_signed_audit_digest(struct tpm_chip *chip, const u8 *nonce,
+ u16 nonce_len, struct tpm2_signed_audit *audit)
+{
+ return -EOPNOTSUPP;
+}
+static inline void tpm2_free_signed_audit(struct tpm2_signed_audit *audit)
+{
+}
static inline int tpm_buf_fill_hmac_session(struct tpm_chip *chip,
struct tpm_buf *buf)
diff --git a/include/linux/tpm_command.h b/include/linux/tpm_command.h
index 79f547ca6dbf..486493efa759 100644
--- a/include/linux/tpm_command.h
+++ b/include/linux/tpm_command.h
@@ -189,6 +189,7 @@ enum tpm2_timeouts {
enum tpm2_structures {
TPM2_ST_NO_SESSIONS = 0x8001,
TPM2_ST_SESSIONS = 0x8002,
+ TPM2_ST_ATTEST_SESSION_AUDIT = 0x8016,
TPM2_ST_CREATION = 0x8021,
};
@@ -230,6 +231,7 @@ enum tpm2_command_codes {
TPM2_CC_SELF_TEST = 0x0143,
TPM2_CC_STARTUP = 0x0144,
TPM2_CC_SHUTDOWN = 0x0145,
+ TPM2_CC_GET_SESSION_AUDIT_DIGEST = 0x014D,
TPM2_CC_NV_READ = 0x014E,
TPM2_CC_NV_READ_LOCK = 0x014F,
TPM2_CC_CREATE = 0x0153,
@@ -275,10 +277,15 @@ enum tpm2_cc_attrs {
};
enum tpm2_permanent_handles {
+ TPM2_RH_OWNER = 0x40000001,
TPM2_RH_NULL = 0x40000007,
TPM2_RS_PW = 0x40000009,
+ TPM2_RH_ENDORSEMENT = 0x4000000B,
};
+/* TPMS_ATTEST.magic */
+#define TPM2_GENERATED_VALUE 0xff544347
+
/* Most Significant Octet for key types */
enum tpm2_mso_type {
TPM2_MSO_NVRAM = 0x01,
@@ -479,6 +486,7 @@ enum tpm_algorithms {
TPM_ALG_SHA512 = 0x000D,
TPM_ALG_NULL = 0x0010,
TPM_ALG_SM3_256 = 0x0012,
+ TPM_ALG_ECDSA = 0x0018,
TPM_ALG_ECC = 0x0023,
TPM_ALG_CFB = 0x0043,
};
--
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 ` Matthew Garrett [this message]
2026-10-08 16:45 ` [PATCH 05/17] tpm: Add a kernel attestation key and signed audit digest retrieval 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 ` [PATCH 11/17] tpm: Add kernel signing key creation with audited provenance Matthew Garrett
2026-10-08 17:00 ` 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-6-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