Each type of RoT devices should have a corresponding entry in ima_rots, a static array that represents entries' priority with their order. In case that `ima_rot=` is absent, the first device (which means with higher 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@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 | 68 +++++++++++++++++++++++++++++++ security/integrity/ima/ima_rot.h | 28 +++++++++++++ 5 files changed, 100 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 d823ac70ddc2..2b6467ea3f24 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_IMA) += ima.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 ceaae0e2c52a..80b4e13452a7 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 }; @@ -56,6 +57,7 @@ extern int ima_hash_algo_idx __ro_after_init; extern int ima_extra_slots __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[]; #ifdef CONFIG_IMA_DIGEST_LIST extern int ima_digest_list_pcr; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index aa750942e422..80de396e8c07 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -24,6 +24,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..bff7b57cf10d --- /dev/null +++ b/security/integrity/ima/ima_rot.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * Authors: + * GONG Ruiqi gongruiqi1@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" + +static const char *name_rot_prefered; + +/* + * 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[] = { +}; + +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)) { + name_rot_prefered = str; + break; + } + } + + if (!name_rot_prefered) + pr_info("%s is NOT implemented as an IMA RoT\n", str); + + 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 (name_rot_prefered && strcmp(name_rot_prefered, 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_info("%s failed to self-initialize\n", ima_rots[i].name); + } + + return NULL; +} diff --git a/security/integrity/ima/ima_rot.h b/security/integrity/ima/ima_rot.h new file mode 100644 index 000000000000..ba6bec380ed4 --- /dev/null +++ b/security/integrity/ima/ima_rot.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * Authors: + * GONG Ruiqi gongruiqi1@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 { + const char *name; + 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 */