linux-security-module.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Wettstein <greg@enjellic.com>
To: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: jmorris@namei.org
Subject: [PATCH v4 05/14] Add root domain trust implementation.
Date: Mon, 26 Aug 2024 05:37:19 -0500	[thread overview]
Message-ID: <20240826103728.3378-6-greg@enjellic.com> (raw)
In-Reply-To: <20240826103728.3378-1-greg@enjellic.com>

The trust.c contains the support infrastructure for anchoring the
root modeling domain to a Trusted Platform Modul (TPM)
implementation if one is available.

The Platform Configuation Register (PCR) that is selected for the
trust root is extended with the security state coefficients that
each security event maps into.

Also included is functionality that computes the hardware
platform aggregate measurement that is the linear extension sum
over PCR register 0 through 8.  The hardware aggregate
measurement is generated and maintained in multiple cryptographic
digest forms depending on the cryptographic hash functions used
in the security modeling namespaces that request the value of the
hardware aggregate.
---
 security/tsem/trust.c | 261 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 261 insertions(+)
 create mode 100644 security/tsem/trust.c

diff --git a/security/tsem/trust.c b/security/tsem/trust.c
new file mode 100644
index 000000000000..762bca735afc
--- /dev/null
+++ b/security/tsem/trust.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (C) 2024 Enjellic Systems Development, LLC
+ * Author: Dr. Greg Wettstein <greg@enjellic.com>
+ *
+ * On a platform that has access to a TPM device, this file is
+ * responsible for maintaining a root of trust based on that device.
+ *
+ * As with other trusted platform implementations the root of trust is
+ * a linear extension measurement maintained in a Platform
+ * Configuration Register (PCR) on the TPM device.
+ *
+ * The PCR is extended with each unique security state coefficient
+ * that is generated by the model being implemented for the
+ * root security modeling namespace.  As with other trusted systems
+ * the value of the PCR will be variable depending on scheduling
+ * artifacts that are experienced by the root modeling namespace.
+ *
+ * TSEM uses a strategy of executing the TPM extension transactions
+ * using an ordered workqueue rather than doing them at the time the
+ * security event is processed.  This is done both for performance
+ * reasons and the fact that the coefficient extensions may arise from
+ * security events that are being invoked by processes running in
+ * atomic context.
+ *
+ * If the trust_init() function detects the presence of a TPM an
+ * ordered workqueue with the following name is created:
+ *
+ * tsem_tpm
+ *
+ * The tsem_trust_add_event() function places a work request
+ * containing a description of the event on this workqueue that will
+ * then asynchronously extend the security state coefficient of the
+ * event into the PCR being used to measure the trust state of
+ * the root security modeling namespace.
+ *
+ * This file is also responsible for providing the hardware aggregate
+ * measurement for injection into both internally and externally
+ * modeled namespaces.  The hardware aggregate value is the linear
+ * extension sum of PCR registers 0 through 8.
+ *
+ * Since TSEM supports multiple cryptographic digest functions on a
+ * namespace by namespace basis the hardware aggregate value is
+ * maintained in multiple digest forms.  The tsem_trust_aggregate()
+ * function returns a pointer to the digest value for the
+ * cryptographic digest function that is being used by the security
+ * modeling namespace in effect for the calling process.
+ */
+
+#include <linux/tpm.h>
+
+#include "tsem.h"
+
+static struct workqueue_struct *tpm_update_wq;
+
+static u8 zero_aggregate[HASH_MAX_DIGESTSIZE];
+
+static struct tpm_chip *tpm;
+
+static struct tpm_digest *digests;
+
+struct hardware_aggregate {
+	struct list_head list;
+	char *name;
+	u8 value[HASH_MAX_DIGESTSIZE];
+};
+
+DEFINE_MUTEX(hardware_aggregate_mutex);
+LIST_HEAD(hardware_aggregate_list);
+
+static struct hardware_aggregate *find_aggregate(void)
+{
+	struct hardware_aggregate *aggregate;
+
+	list_for_each_entry(aggregate, &hardware_aggregate_list, list) {
+		if (!strcmp(aggregate->name,
+			    tsem_context(current)->digestname))
+			goto done;
+	}
+	aggregate = NULL;
+
+ done:
+	return aggregate;
+}
+
+static struct hardware_aggregate *add_aggregate(u8 *new_aggregate)
+{
+	struct hardware_aggregate *aggregate;
+
+	aggregate = kzalloc(sizeof(*aggregate), GFP_KERNEL);
+	if (!aggregate)
+		return NULL;
+
+	aggregate->name = kstrdup(tsem_context(current)->digestname,
+				  GFP_KERNEL);
+	if (!aggregate->name) {
+		kfree(aggregate);
+		return NULL;
+	}
+	memcpy(aggregate->value, new_aggregate, tsem_digestsize());
+
+	list_add(&aggregate->list, &hardware_aggregate_list);
+
+	return aggregate;
+}
+
+/**
+ * tsem_trust_aggregate() - Return a pointer to the hardware aggregate.
+ *
+ * This function returns a pointer to the hardware aggregate encoded
+ * with the hash function for the current modeling domain.
+ *
+ * Return: A pointer is returned to the hardware aggregate value that
+ *	   has been cached.
+ */
+u8 *tsem_trust_aggregate(void)
+{
+	u8 aggregate[HASH_MAX_DIGESTSIZE], *retn = zero_aggregate;
+	u16 size;
+	unsigned int lp;
+	struct tpm_digest pcr;
+	struct hardware_aggregate *hw_aggregate;
+	SHASH_DESC_ON_STACK(shash, tfm);
+
+	if (!tpm)
+		return retn;
+
+	mutex_lock(&hardware_aggregate_mutex);
+
+	hw_aggregate = find_aggregate();
+	if (hw_aggregate) {
+		retn = hw_aggregate->value;
+		goto done;
+	}
+
+	shash->tfm = tsem_digest();
+	if (crypto_shash_init(shash))
+		goto done;
+
+	if (tpm_is_tpm2(tpm))
+		pcr.alg_id = TPM_ALG_SHA256;
+	else
+		pcr.alg_id = TPM_ALG_SHA1;
+	memset(pcr.digest, '\0', TPM_MAX_DIGEST_SIZE);
+
+	for (lp = 0; lp < tpm->nr_allocated_banks; lp++) {
+		if (pcr.alg_id == tpm->allocated_banks[lp].alg_id) {
+			size = tpm->allocated_banks[lp].digest_size;
+			break;
+		}
+	}
+
+	for (lp = 0; lp < 8; ++lp) {
+		if (tpm_pcr_read(tpm, lp, &pcr))
+			goto done;
+		if (crypto_shash_update(shash, pcr.digest, size))
+			goto done;
+	}
+	if (!crypto_shash_final(shash, aggregate)) {
+		hw_aggregate = add_aggregate(aggregate);
+		if (hw_aggregate)
+			retn = hw_aggregate->value;
+	}
+
+ done:
+	mutex_unlock(&hardware_aggregate_mutex);
+
+	if (retn == zero_aggregate)
+		pr_warn("tsem: Error generating platform aggregate\n");
+
+	return retn;
+}
+
+static void tpm_update_worker(struct work_struct *work)
+{
+	int amt, bank, digestsize;
+	struct tsem_event *ep;
+
+	ep = container_of(work, struct tsem_event, work);
+	digestsize = ep->digestsize;
+
+	for (bank = 0; bank < tpm->nr_allocated_banks; bank++) {
+		if (tpm->allocated_banks[bank].digest_size > digestsize) {
+			amt = digestsize;
+			memset(digests[bank].digest, '\0',
+			       tpm->allocated_banks[bank].digest_size);
+		} else
+			amt = tpm->allocated_banks[bank].digest_size;
+		memcpy(digests[bank].digest, ep->mapping, amt);
+	}
+
+	if (tpm_pcr_extend(tpm, CONFIG_SECURITY_TSEM_ROOT_MODEL_PCR,
+			   digests))
+		pr_warn("tsem: Failed TPM update.\n");
+
+	tsem_event_put(ep);
+}
+
+/**
+ * tsem_trust_add_point() - Add a measurement to the trust root.
+ * @ep: A pointer to the security event description whose measurement
+ *	is to be extended into the TPM.
+ *
+ * This function extends the platform configuration register being
+ * used to document the hardware root of trust for internally modeled
+ * domains with a security event coefficient value.
+ *
+ * Return: If the extension fails the error return value from the
+ *	   TPM command is returned, otherwise a value of zero is
+ *	   returned.
+ */
+int tsem_trust_add_event(struct tsem_event *ep)
+{
+	bool retn;
+
+	if (!tpm)
+		return 0;
+
+	tsem_event_get(ep);
+	ep->digestsize = tsem_digestsize();
+
+	INIT_WORK(&ep->work, tpm_update_worker);
+	retn = queue_work(tpm_update_wq, &ep->work);
+
+	return 0;
+}
+
+static int __init trust_init(void)
+{
+	int retn = -EINVAL, lp;
+
+	tpm = tpm_default_chip();
+	if (!tpm)
+		return retn;
+
+	tpm_update_wq = alloc_ordered_workqueue("tsem_tpm", 0);
+	if (IS_ERR(tpm_update_wq)) {
+		retn = PTR_ERR(tpm_update_wq);
+		goto done;
+	}
+
+	digests = kcalloc(tpm->nr_allocated_banks, sizeof(*digests), GFP_NOFS);
+	if (!digests) {
+		tpm = NULL;
+		return retn;
+	}
+	for (lp = 0; lp < tpm->nr_allocated_banks; lp++)
+		digests[lp].alg_id = tpm->allocated_banks[lp].alg_id;
+	retn = 0;
+
+ done:
+	if (retn) {
+		destroy_workqueue(tpm_update_wq);
+		kfree(digests);
+	}
+
+	return retn;
+}
+
+device_initcall_sync(trust_init);
-- 
2.39.1


  parent reply	other threads:[~2024-08-26 10:50 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-26 10:37 [PATCH v4 00/14] Implement Trusted Security Event Modeling Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 01/14] Update MAINTAINERS file Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 02/14] Add TSEM specific documentation Greg Wettstein
2025-01-14  1:29   ` [PATCH v4 2/14] " Paul Moore
2025-01-17  4:47     ` Dr. Greg
2025-01-17 18:10       ` Casey Schaufler
2025-01-18 19:03         ` Dr. Greg
2025-01-21 18:09           ` Casey Schaufler
2025-01-26 18:40             ` Dr. Greg
2025-01-28 22:23       ` Paul Moore
2025-01-31 17:11         ` Dr. Greg
2025-02-25 12:01         ` Dr. Greg
2025-02-25 15:48           ` Casey Schaufler
2025-02-27 12:12             ` Dr. Greg
2025-02-27 16:47               ` Casey Schaufler
2025-03-03 10:14                 ` Dr. Greg
2025-03-03 16:23                   ` Casey Schaufler
2025-02-05 12:00     ` Dr. Greg
2025-02-05 19:58       ` Casey Schaufler
2025-02-06 12:45         ` Dr. Greg
2025-02-06 15:48       ` Paul Moore
2025-02-07 10:20         ` Dr. Greg
2025-02-07 17:42           ` Casey Schaufler
2025-02-08  0:29           ` Paul Moore
2025-02-17 12:53             ` Dr. Greg
2025-02-17 23:09               ` Paul Moore
2024-08-26 10:37 ` [PATCH v4 03/14] TSEM global declarations Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 04/14] Add primary TSEM implementation file Greg Wettstein
2024-08-26 15:53   ` Casey Schaufler
2024-08-27 10:52     ` Dr. Greg
2024-08-27 17:51       ` Casey Schaufler
2024-08-26 10:37 ` Greg Wettstein [this message]
2024-08-26 10:37 ` [PATCH v4 06/14] Implement TSEM control plane Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 07/14] Add namespace implementation Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 08/14] Add security event description export facility Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 09/14] Add event processing implementation Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 10/14] Implement security event mapping Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 11/14] Implement the internal Trusted Modeling Agent Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 12/14] Implement configuration and methods for default model Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 13/14] Implement infrastructure for loadable security models Greg Wettstein
2024-08-26 10:37 ` [PATCH v4 14/14] Activate the configuration and build of the TSEM LSM Greg Wettstein

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=20240826103728.3378-6-greg@enjellic.com \
    --to=greg@enjellic.com \
    --cc=jmorris@namei.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.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;
as well as URLs for NNTP newsgroup(s).