[PATCH -next RFC 1/4] ima: rot: Introduce basic framework
GONG Ruiqi
gongruiqi1 at huawei.com
Mon Jun 30 12:59:25 UTC 2025
Each type of RoT devices should have a corresponding entry in ima_rots,
a static array that represents entries' priority via their order. In
case that `ima_rot=` is absent, the first device (which means with
highest priority) that gets successfully initialized will be the RoT.
Otherwise, the framework will only try to initialize the one specified
by `ima_rot=`, and there will be no RoT if the initialization fails.
All necessary hooks and variables of the RoT entry should be set at
least when .init() is finished.
Signed-off-by: GONG Ruiqi <gongruiqi1 at huawei.com>
---
security/integrity/ima/Makefile | 2 +-
security/integrity/ima/ima.h | 2 +
security/integrity/ima/ima_init.c | 1 +
security/integrity/ima/ima_rot.c | 98 +++++++++++++++++++++++++++++++
security/integrity/ima/ima_rot.h | 42 +++++++++++++
5 files changed, 144 insertions(+), 1 deletion(-)
create mode 100644 security/integrity/ima/ima_rot.c
create mode 100644 security/integrity/ima/ima_rot.h
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index b376d38b4ee6..b3c8436d941c 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -7,7 +7,7 @@
obj-$(CONFIG_IMA) += ima.o ima_iint.o
ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
- ima_policy.o ima_template.o ima_template_lib.o
+ ima_policy.o ima_template.o ima_template_lib.o ima_rot.o
ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o
ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index e3d71d8d56e3..d3375427dc24 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -23,6 +23,7 @@
#include <crypto/hash_info.h>
#include "../integrity.h"
+#include "ima_rot.h"
enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII };
@@ -64,6 +65,7 @@ extern struct ima_algo_desc *ima_algo_array __ro_after_init;
extern int ima_appraise;
extern struct tpm_chip *ima_tpm_chip;
+extern struct ima_rot *ima_rot_inst;
extern const char boot_aggregate_name[];
/* IMA event related data */
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index a2f34f2d8ad7..15c51e1b369c 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -23,6 +23,7 @@
/* name for boot aggregate entry */
const char boot_aggregate_name[] = "boot_aggregate";
struct tpm_chip *ima_tpm_chip;
+struct ima_rot *ima_rot_inst;
/* Add the boot aggregate to the IMA measurement list and extend
* the PCR register.
diff --git a/security/integrity/ima/ima_rot.c b/security/integrity/ima/ima_rot.c
new file mode 100644
index 000000000000..7a1ae056ea5d
--- /dev/null
+++ b/security/integrity/ima/ima_rot.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Huawei Technologies Co., Ltd.
+ *
+ * Authors:
+ * GONG Ruiqi <gongruiqi1 at huawei.com>
+ *
+ * File: ima_rot.c
+ * IMA rot layer
+ */
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/gfp_types.h>
+
+#include "ima.h"
+
+/*
+ * Meaning of preferred_rot_name's value:
+ *
+ * - NULL: User doesn't specify one.
+ * - NAME_UNKNOWN: User specifies an unknown RoT name.
+ * - (Valid RoT name): User specifies a valid name.
+ *
+ * Which corresponds to cases of `ima_rot=`.
+ */
+static const char *preferred_rot_name;
+#define NAME_UNKNOWN "UNKNOWN"
+
+/*
+ * The list containing all possible RoT devices.
+ *
+ * The order of RoTs inside the list implies priority.
+ * IOW, RoT device that owns higher priority should be placed at the front.
+ */
+static struct ima_rot ima_rots[] = {
+};
+
+/**
+ * ima_rot_name() - Process RoT device name that user provides.
+ * @str: Name of RoT device.
+ *
+ * The back-end handler of `ima_rot=` kernel cmdline, by which users can specify
+ * the Root of Trust (RoT) device for IMA. How system will react to each case of
+ * this cmdline's value is explained as follows:
+ *
+ * - Absent: Choose an RoT device based on priority, try to initialize it and
+ * give up if it fails.
+ *
+ * - Invalid/Unknown RoT name: Give up RoT initialization. IMA will run without
+ * an RoT device.
+ *
+ * - Valid RoT name: Try to initialize this RoT device and give up if it fails.
+ *
+ * Return: Always return 1.
+ */
+static int __init ima_rot_name(char *str)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ima_rots); i++) {
+ if (!strcmp(str, ima_rots[i].name)) {
+ preferred_rot_name = str;
+ break;
+ }
+ }
+
+ if (!preferred_rot_name) {
+ pr_info("%s is NOT implemented as an IMA RoT\n", str);
+ preferred_rot_name = NAME_UNKNOWN;
+ }
+
+ return 1;
+}
+__setup("ima_rot=", ima_rot_name);
+
+/*
+ * Pick the most prioritized RoT that can be initialized successfully.
+ */
+struct ima_rot * __init ima_rot_init(void)
+{
+ int rc, i;
+
+ for (i = 0; i < ARRAY_SIZE(ima_rots); i++) {
+ if (preferred_rot_name && strcmp(preferred_rot_name, ima_rots[i].name))
+ continue;
+
+ pr_info("IMA RoT initializing %s\n", ima_rots[i].name);
+ rc = ima_rots[i].init(&ima_rots[i]);
+ if (!rc) {
+ pr_info("%s initialized and taken as IMA RoT\n", ima_rots[i].name);
+ return &ima_rots[i];
+ }
+ pr_debug("%s failed to self-initialize (%d)\n", ima_rots[i].name, rc);
+ }
+
+ return NULL;
+}
diff --git a/security/integrity/ima/ima_rot.h b/security/integrity/ima/ima_rot.h
new file mode 100644
index 000000000000..f88f8162d6c8
--- /dev/null
+++ b/security/integrity/ima/ima_rot.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2025 Huawei Technologies Co., Ltd.
+ *
+ * Authors:
+ * GONG Ruiqi <gongruiqi1 at huawei.com>
+ *
+ * File: ima_rot.h
+ * IMA rot layer
+ */
+
+#ifndef __LINUX_IMA_ROT_H
+#define __LINUX_IMA_ROT_H
+
+#include <linux/tpm.h>
+
+/**
+ * struct ima_rot - Root of Trust (RoT) device instance.
+ * @name: Name of the device.
+ * @default_pcr: Index of default (virtual) PCR.
+ * @nr_allocated_banks: Number of (virtual) TPM banks.
+ * @allocated_banks: Info of (virtual) TPM bank.
+ * @init: Initializes this device to be an IMA RoT.
+ * @extend: Performs a hash extend operation to the device's (virtual) PCR.
+ * @calc_boot_aggregate: Generate the initial value of IMA measurement list
+ * (i.e. boot aggregate).
+ *
+ * Attributes and methods necessary for a device working as an RoT for IMA.
+ */
+struct ima_rot {
+ const char *name;
+ int default_pcr;
+ int nr_allocated_banks;
+ struct tpm_bank_info *allocated_banks;
+
+ int (*init)(struct ima_rot *rot);
+ int (*extend)(struct tpm_digest *digests_arg, const void *args);
+ int (*calc_boot_aggregate)(struct ima_digest_data *hash);
+};
+
+struct ima_rot *ima_rot_init(void);
+#endif /* __LINUX_IMA_ROT_H */
--
2.25.1
More information about the Linux-security-module-archive
mailing list