From nobody Wed Oct 8 09:28:27 2025 Received: from szxga06-in.huawei.com (szxga06-in.huawei.com [45.249.212.32]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC61F28A3E0; Mon, 30 Jun 2025 12:47:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.32 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751287664; cv=none; b=e8h32XkXr0Pc0/hifF/Qp01yLYi9IhF5KVKNdzgSpGBtY2NCHuw5GyvEHUns2W6hfC+VvoVgrfuzess7k1whmK70iFQCGAFDNvzVMHIxg8Lhv7wxOpUC0Z5Ex9TsY8PGqtTFazVSXVxAQihg7tacd7E9O+aICt0ZU7rE8ojzh4k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751287664; c=relaxed/simple; bh=ngCFuKMbAEbWcXu/NVfD5NO+et+4GZUuEmEASqwacz8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=igNTvACt8yAxv/RsC1nsFEX+bi0VSQZ9+HYUXSsGp86VgeRPu+C4lwUK21QvnSrNrxmtIvHU2j8YzwxgzPhyWfa8I8FXSM+B94ay4jfPohhA4vU6NkuPXYm03O1QRpzdbFeYfQ/aGvxQbE8aIpnitjz8mX0X7D40QflC6TziFTc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.32 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.214]) by szxga06-in.huawei.com (SkyGuard) with ESMTP id 4bW5Yp2KvMz16TJW; Mon, 30 Jun 2025 20:48:30 +0800 (CST) Received: from kwepemg100016.china.huawei.com (unknown [7.202.181.57]) by mail.maildlp.com (Postfix) with ESMTPS id 388B61A016C; Mon, 30 Jun 2025 20:47:34 +0800 (CST) Received: from huawei.com (10.67.174.33) by kwepemg100016.china.huawei.com (7.202.181.57) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Mon, 30 Jun 2025 20:47:33 +0800 From: GONG Ruiqi To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin CC: Eric Snowberg , Paul Moore , James Morris , "Serge E . Hallyn" , , , , Lu Jialin , Subject: [PATCH -next RFC 1/4] ima: rot: Introduce basic framework Date: Mon, 30 Jun 2025 20:59:25 +0800 Message-ID: <20250630125928.765285-2-gongruiqi1@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250630125928.765285-1-gongruiqi1@huawei.com> References: <20250630125928.765285-1-gongruiqi1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To kwepemg100016.china.huawei.com (7.202.181.57) Content-Type: text/plain; charset="utf-8" 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=3D` 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=3D`, 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 --- 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/Makef= ile index b376d38b4ee6..b3c8436d941c 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_IMA) +=3D ima.o ima_iint.o =20 ima-y :=3D 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) +=3D ima_appraise.o ima-$(CONFIG_IMA_APPRAISE_MODSIG) +=3D ima_modsig.o ima-$(CONFIG_HAVE_IMA_KEXEC) +=3D 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 =20 #include "../integrity.h" +#include "ima_rot.h" =20 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_in= it; =20 extern int ima_appraise; extern struct tpm_chip *ima_tpm_chip; +extern struct ima_rot *ima_rot_inst; extern const char boot_aggregate_name[]; =20 /* 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[] =3D "boot_aggregate"; struct tpm_chip *ima_tpm_chip; +struct ima_rot *ima_rot_inst; =20 /* 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 + * + * File: ima_rot.c + * IMA rot layer + */ + +#include +#include +#include + +#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=3D`. + */ +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[] =3D { +}; + +/** + * ima_rot_name() - Process RoT device name that user provides. + * @str: Name of RoT device. + * + * The back-end handler of `ima_rot=3D` kernel cmdline, by which users can= specify + * the Root of Trust (RoT) device for IMA. How system will react to each c= ase 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 wi= thout + * an RoT device. + * + * - Valid RoT name: Try to initialize this RoT device and give up if it f= ails. + * + * Return: Always return 1. + */ +static int __init ima_rot_name(char *str) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(ima_rots); i++) { + if (!strcmp(str, ima_rots[i].name)) { + preferred_rot_name =3D str; + break; + } + } + + if (!preferred_rot_name) { + pr_info("%s is NOT implemented as an IMA RoT\n", str); + preferred_rot_name =3D NAME_UNKNOWN; + } + + return 1; +} +__setup("ima_rot=3D", 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 =3D 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 =3D 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 + * + * File: ima_rot.h + * IMA rot layer + */ + +#ifndef __LINUX_IMA_ROT_H +#define __LINUX_IMA_ROT_H + +#include + +/** + * 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 */ --=20 2.25.1 From nobody Wed Oct 8 09:28:27 2025 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 24DA82853E9; Mon, 30 Jun 2025 12:47:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751287661; cv=none; b=JGl3rbkD+1Zv8Ig6RILxny6Eg2l8LfDAFOKtYOkNrjGq+a6MlHdl27W1pco/9TQAvU8HUC1wuE92+SASXt011b2qu6DnjgGZgoNYIeykphjlKa7He623L4I4XOo7+4QqtetUD2SGDC0t3GY4wNiUTXSSj5B6grWUxjPoDDfRvX8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751287661; c=relaxed/simple; bh=fcznj8YsQE0z4pBvxWodQlSbyp5XLZvc0hSVIZs44us=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uut6xZS/D2XZ7aX65FSqNTri4vseRkVuKd7zfy8ZmPR0QaL14ZaxU4m60kd9CmnFP1wPGiHAotswAuVRKQk/qD76Iw7UFtzOJemsN4ZbAz3FOBHTPUjNsyy9mSFs1tZrscHAL/v2kTWeVdb25pg4JZbAhdZ1EMRqiixGVXIU72w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.194]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4bW5Rh6gfYzCsMc; Mon, 30 Jun 2025 20:43:12 +0800 (CST) Received: from kwepemg100016.china.huawei.com (unknown [7.202.181.57]) by mail.maildlp.com (Postfix) with ESMTPS id B00E5140156; Mon, 30 Jun 2025 20:47:34 +0800 (CST) Received: from huawei.com (10.67.174.33) by kwepemg100016.china.huawei.com (7.202.181.57) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Mon, 30 Jun 2025 20:47:33 +0800 From: GONG Ruiqi To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin CC: Eric Snowberg , Paul Moore , James Morris , "Serge E . Hallyn" , , , , Lu Jialin , Subject: [PATCH -next RFC 2/4] ima: rot: Prepare TPM as an RoT Date: Mon, 30 Jun 2025 20:59:26 +0800 Message-ID: <20250630125928.765285-3-gongruiqi1@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250630125928.765285-1-gongruiqi1@huawei.com> References: <20250630125928.765285-1-gongruiqi1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To kwepemg100016.china.huawei.com (7.202.181.57) Content-Type: text/plain; charset="utf-8" Adapt TPM devices into the RoT framework, mostly by separating TPM-specific logic from the IMA code into the new ima_tpm.c file. Note that although TPM has been set up for the RoT framework, at this moment the framework doesn't start working yet, and in practice IMA still runs the same way as before. No functional change intended for this patch. Co-developed-by: Zhao Yipeng Signed-off-by: Zhao Yipeng Signed-off-by: GONG Ruiqi --- security/integrity/ima/Makefile | 1 + security/integrity/ima/ima.h | 3 +- security/integrity/ima/ima_crypto.c | 109 +-------------- security/integrity/ima/ima_init.c | 4 +- security/integrity/ima/ima_queue.c | 14 +- security/integrity/ima/ima_rot.c | 10 ++ security/integrity/ima/ima_template_lib.c | 3 +- security/integrity/ima/ima_tpm.c | 154 ++++++++++++++++++++++ security/integrity/ima/ima_tpm.h | 21 +++ 9 files changed, 196 insertions(+), 123 deletions(-) create mode 100644 security/integrity/ima/ima_tpm.c create mode 100644 security/integrity/ima/ima_tpm.h diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makef= ile index b3c8436d941c..1237847f2e60 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -14,6 +14,7 @@ ima-$(CONFIG_HAVE_IMA_KEXEC) +=3D ima_kexec.o ima-$(CONFIG_IMA_BLACKLIST_KEYRING) +=3D ima_mok.o ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) +=3D ima_asymmetric_keys.o ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) +=3D ima_queue_keys.o +ima-$(CONFIG_TCG_TPM) +=3D ima_tpm.o =20 ifeq ($(CONFIG_EFI),y) ima-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) +=3D ima_efi.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index d3375427dc24..07752e7227b6 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -269,7 +269,8 @@ int ima_calc_buffer_hash(const void *buf, loff_t len, struct ima_digest_data *hash); int ima_calc_field_array_hash(struct ima_field_data *field_data, struct ima_template_entry *entry); -int ima_calc_boot_aggregate(struct ima_digest_data *hash); +struct crypto_shash *ima_alloc_tfm(enum hash_algo algo); +void ima_free_tfm(struct crypto_shash *tfm); void ima_add_violation(struct file *file, const unsigned char *filename, struct ima_iint_cache *iint, const char *op, const char *cause); diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/i= ma_crypto.c index 6f5696d999d0..492d7bc56510 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -21,6 +21,7 @@ #include =20 #include "ima.h" +#include "ima_tpm.h" =20 /* minimum file size for ahash use */ static unsigned long ima_ahash_minsize; @@ -83,7 +84,7 @@ static int __init ima_init_ima_crypto(void) return 0; } =20 -static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo) +struct crypto_shash *ima_alloc_tfm(enum hash_algo algo) { struct crypto_shash *tfm =3D ima_shash_tfm; int rc, i; @@ -206,7 +207,7 @@ int __init ima_init_crypto(void) return rc; } =20 -static void ima_free_tfm(struct crypto_shash *tfm) +void ima_free_tfm(struct crypto_shash *tfm) { int i; =20 @@ -771,107 +772,3 @@ int ima_calc_buffer_hash(const void *buf, loff_t len, =20 return calc_buffer_shash(buf, len, hash); } - -static void ima_pcrread(u32 idx, struct tpm_digest *d) -{ - if (!ima_tpm_chip) - return; - - if (tpm_pcr_read(ima_tpm_chip, idx, d) !=3D 0) - pr_err("Error Communicating to TPM chip\n"); -} - -/* - * The boot_aggregate is a cumulative hash over TPM registers 0 - 7. With - * TPM 1.2 the boot_aggregate was based on reading the SHA1 PCRs, but with - * TPM 2.0 hash agility, TPM chips could support multiple TPM PCR banks, - * allowing firmware to configure and enable different banks. - * - * Knowing which TPM bank is read to calculate the boot_aggregate digest - * needs to be conveyed to a verifier. For this reason, use the same - * hash algorithm for reading the TPM PCRs as for calculating the boot - * aggregate digest as stored in the measurement list. - */ -static int ima_calc_boot_aggregate_tfm(char *digest, u16 alg_id, - struct crypto_shash *tfm) -{ - struct tpm_digest d =3D { .alg_id =3D alg_id, .digest =3D {0} }; - int rc; - u32 i; - SHASH_DESC_ON_STACK(shash, tfm); - - shash->tfm =3D tfm; - - pr_devel("calculating the boot-aggregate based on TPM bank: %04x\n", - d.alg_id); - - rc =3D crypto_shash_init(shash); - if (rc !=3D 0) - return rc; - - /* cumulative digest over TPM registers 0-7 */ - for (i =3D TPM_PCR0; i < TPM_PCR8; i++) { - ima_pcrread(i, &d); - /* now accumulate with current aggregate */ - rc =3D crypto_shash_update(shash, d.digest, - crypto_shash_digestsize(tfm)); - if (rc !=3D 0) - return rc; - } - /* - * Extend cumulative digest over TPM registers 8-9, which contain - * measurement for the kernel command line (reg. 8) and image (reg. 9) - * in a typical PCR allocation. Registers 8-9 are only included in - * non-SHA1 boot_aggregate digests to avoid ambiguity. - */ - if (alg_id !=3D TPM_ALG_SHA1) { - for (i =3D TPM_PCR8; i < TPM_PCR10; i++) { - ima_pcrread(i, &d); - rc =3D crypto_shash_update(shash, d.digest, - crypto_shash_digestsize(tfm)); - } - } - if (!rc) - crypto_shash_final(shash, digest); - return rc; -} - -int ima_calc_boot_aggregate(struct ima_digest_data *hash) -{ - struct crypto_shash *tfm; - u16 crypto_id, alg_id; - int rc, i, bank_idx =3D -1; - - for (i =3D 0; i < ima_tpm_chip->nr_allocated_banks; i++) { - crypto_id =3D ima_tpm_chip->allocated_banks[i].crypto_id; - if (crypto_id =3D=3D hash->algo) { - bank_idx =3D i; - break; - } - - if (crypto_id =3D=3D HASH_ALGO_SHA256) - bank_idx =3D i; - - if (bank_idx =3D=3D -1 && crypto_id =3D=3D HASH_ALGO_SHA1) - bank_idx =3D i; - } - - if (bank_idx =3D=3D -1) { - pr_err("No suitable TPM algorithm for boot aggregate\n"); - return 0; - } - - hash->algo =3D ima_tpm_chip->allocated_banks[bank_idx].crypto_id; - - tfm =3D ima_alloc_tfm(hash->algo); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - hash->length =3D crypto_shash_digestsize(tfm); - alg_id =3D ima_tpm_chip->allocated_banks[bank_idx].alg_id; - rc =3D ima_calc_boot_aggregate_tfm(hash->digest, alg_id, tfm); - - ima_free_tfm(tfm); - - return rc; -} diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima= _init.c index 15c51e1b369c..8651b11c1edf 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -19,10 +19,10 @@ #include =20 #include "ima.h" +#include "ima_tpm.h" =20 /* name for boot aggregate entry */ const char boot_aggregate_name[] =3D "boot_aggregate"; -struct tpm_chip *ima_tpm_chip; struct ima_rot *ima_rot_inst; =20 /* Add the boot aggregate to the IMA measurement list and extend @@ -73,7 +73,7 @@ static int __init ima_add_boot_aggregate(void) * is not found. */ if (ima_tpm_chip) { - result =3D ima_calc_boot_aggregate(hash_hdr); + result =3D ima_tpm_calc_boot_aggregate(hash_hdr); if (result < 0) { audit_cause =3D "hashing_error"; goto err_out; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index 590637e81ad1..b91167ef27dc 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -19,6 +19,7 @@ #include #include #include "ima.h" +#include "ima_tpm.h" =20 #define AUDIT_CAUSE_LEN_MAX 32 =20 @@ -142,19 +143,6 @@ unsigned long ima_get_binary_runtime_size(void) return binary_runtime_size + sizeof(struct ima_kexec_hdr); } =20 -static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) -{ - int result =3D 0; - - if (!ima_tpm_chip) - return result; - - result =3D tpm_pcr_extend(ima_tpm_chip, pcr, digests_arg); - if (result !=3D 0) - pr_err("Error Communicating to TPM chip, result: %d\n", result); - return result; -} - /* * Add template entry to the measurement list and hash table, and * extend the pcr. diff --git a/security/integrity/ima/ima_rot.c b/security/integrity/ima/ima_= rot.c index 7a1ae056ea5d..0083d9c4e64e 100644 --- a/security/integrity/ima/ima_rot.c +++ b/security/integrity/ima/ima_rot.c @@ -14,6 +14,7 @@ #include =20 #include "ima.h" +#include "ima_tpm.h" =20 /* * Meaning of preferred_rot_name's value: @@ -34,6 +35,15 @@ static const char *preferred_rot_name; * IOW, RoT device that owns higher priority should be placed at the front. */ static struct ima_rot ima_rots[] =3D { +#ifdef CONFIG_TCG_TPM + { + .name =3D "tpm", + .default_pcr =3D CONFIG_IMA_MEASURE_PCR_IDX, + .init =3D ima_tpm_init, + .extend =3D ima_tpm_extend, + .calc_boot_aggregate =3D ima_tpm_calc_boot_aggregate, + }, +#endif }; =20 /** diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity= /ima/ima_template_lib.c index 0e627eac9c33..67b43e4e4222 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -10,6 +10,7 @@ */ =20 #include "ima_template_lib.h" +#include "ima_tpm.h" #include #include =20 @@ -366,7 +367,7 @@ int ima_eventdigest_init(struct ima_event_data *event_d= ata, if ((const char *)event_data->filename =3D=3D boot_aggregate_name) { if (ima_tpm_chip) { hash.hdr.algo =3D HASH_ALGO_SHA1; - result =3D ima_calc_boot_aggregate(hash_hdr); + result =3D ima_tpm_calc_boot_aggregate(hash_hdr); =20 /* algo can change depending on available PCR banks */ if (!result && hash.hdr.algo !=3D HASH_ALGO_SHA1) diff --git a/security/integrity/ima/ima_tpm.c b/security/integrity/ima/ima_= tpm.c new file mode 100644 index 000000000000..6ff7ed8ef322 --- /dev/null +++ b/security/integrity/ima/ima_tpm.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 Huawei Technologies Co., Ltd. + * + * Authors: + * GONG Ruiqi + * + * File: ima_rot_tpm.c + * TPM implementation of IMA RoT + */ + +#include +#include + +#include "ima.h" +#include "ima_tpm.h" + +struct tpm_chip *ima_tpm_chip; + +int ima_tpm_init(struct ima_rot *rot) +{ + ima_tpm_chip =3D tpm_default_chip(); + if (!ima_tpm_chip) + return -ENODEV; + + rot->nr_allocated_banks =3D ima_tpm_chip->nr_allocated_banks; + rot->allocated_banks =3D ima_tpm_chip->allocated_banks; + + return 0; +} + +int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) +{ + int result =3D 0; + + if (!ima_tpm_chip) + return result; + + result =3D tpm_pcr_extend(ima_tpm_chip, pcr, digests_arg); + if (result !=3D 0) + pr_err("Error Communicating to TPM chip, result: %d\n", result); + return result; +} + +int ima_tpm_extend(struct tpm_digest *digests_arg, const void *args) +{ + const int pcr =3D *(const int *)args; + + return ima_pcr_extend(digests_arg, pcr); +} + +static void ima_pcrread(u32 idx, struct tpm_digest *d) +{ + if (!ima_tpm_chip) + return; + + if (tpm_pcr_read(ima_tpm_chip, idx, d) !=3D 0) + pr_err("Error Communicating to TPM chip\n"); +} + +/* + * The boot_aggregate is a cumulative hash over TPM registers 0 - 7. With + * TPM 1.2 the boot_aggregate was based on reading the SHA1 PCRs, but with + * TPM 2.0 hash agility, TPM chips could support multiple TPM PCR banks, + * allowing firmware to configure and enable different banks. + * + * Knowing which TPM bank is read to calculate the boot_aggregate digest + * needs to be conveyed to a verifier. For this reason, use the same + * hash algorithm for reading the TPM PCRs as for calculating the boot + * aggregate digest as stored in the measurement list. + */ +static int ima_calc_boot_aggregate_tfm(char *digest, u16 alg_id, + struct crypto_shash *tfm) +{ + struct tpm_digest d =3D { .alg_id =3D alg_id, .digest =3D {0} }; + int rc; + u32 i; + SHASH_DESC_ON_STACK(shash, tfm); + + shash->tfm =3D tfm; + + pr_devel("calculating the boot-aggregate based on TPM bank: %04x\n", + d.alg_id); + + rc =3D crypto_shash_init(shash); + if (rc !=3D 0) + return rc; + + /* cumulative digest over TPM registers 0-7 */ + for (i =3D TPM_PCR0; i < TPM_PCR8; i++) { + ima_pcrread(i, &d); + /* now accumulate with current aggregate */ + rc =3D crypto_shash_update(shash, d.digest, + crypto_shash_digestsize(tfm)); + if (rc !=3D 0) + return rc; + } + /* + * Extend cumulative digest over TPM registers 8-9, which contain + * measurement for the kernel command line (reg. 8) and image (reg. 9) + * in a typical PCR allocation. Registers 8-9 are only included in + * non-SHA1 boot_aggregate digests to avoid ambiguity. + */ + if (alg_id !=3D TPM_ALG_SHA1) { + for (i =3D TPM_PCR8; i < TPM_PCR10; i++) { + ima_pcrread(i, &d); + rc =3D crypto_shash_update(shash, d.digest, + crypto_shash_digestsize(tfm)); + } + } + if (!rc) + crypto_shash_final(shash, digest); + return rc; +} + +int ima_tpm_calc_boot_aggregate(struct ima_digest_data *hash) +{ + struct crypto_shash *tfm; + u16 crypto_id, alg_id; + int rc, i, bank_idx =3D -1; + + for (i =3D 0; i < ima_tpm_chip->nr_allocated_banks; i++) { + crypto_id =3D ima_tpm_chip->allocated_banks[i].crypto_id; + if (crypto_id =3D=3D hash->algo) { + bank_idx =3D i; + break; + } + + if (crypto_id =3D=3D HASH_ALGO_SHA256) + bank_idx =3D i; + + if (bank_idx =3D=3D -1 && crypto_id =3D=3D HASH_ALGO_SHA1) + bank_idx =3D i; + } + + if (bank_idx =3D=3D -1) { + pr_err("No suitable TPM algorithm for boot aggregate\n"); + return 0; + } + + hash->algo =3D ima_tpm_chip->allocated_banks[bank_idx].crypto_id; + + tfm =3D ima_alloc_tfm(hash->algo); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + hash->length =3D crypto_shash_digestsize(tfm); + alg_id =3D ima_tpm_chip->allocated_banks[bank_idx].alg_id; + rc =3D ima_calc_boot_aggregate_tfm(hash->digest, alg_id, tfm); + + ima_free_tfm(tfm); + + return rc; +} diff --git a/security/integrity/ima/ima_tpm.h b/security/integrity/ima/ima_= tpm.h new file mode 100644 index 000000000000..fa2946073ceb --- /dev/null +++ b/security/integrity/ima/ima_tpm.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2025 Huawei Technologies Co., Ltd. + * + * Authors: + * GONG Ruiqi + * + * File: ima_tpm.h + * Hooks of TPM for IMA RoT + */ + +#ifndef __IMA_IMA_TPM_H +#define __IMA_IMA_TPM_H + +int ima_tpm_init(struct ima_rot *rot); +int ima_tpm_extend(struct tpm_digest *digests_arg, const void *args); +int ima_tpm_calc_boot_aggregate(struct ima_digest_data *hash); + +int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr); + +#endif /* __IMA_IMA_TPM_H */ --=20 2.25.1 From nobody Wed Oct 8 09:28:27 2025 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C5B8D2701DF; Mon, 30 Jun 2025 12:47:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.187 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751287660; cv=none; b=FmYQ1wQVMYZSF/FKc2riRpT7T2W3VyO6bXqDbxH3X1bUIp3qM+wp8uhlSsDEGMP6l61WPJcETWK5jwwlCyoP8FD8KR4YUJysZgRYPOwp42h//iKHE0v1qchaqC2swAvkAHQ8SrecfcYu22v40uPAnedeFzb1iHCrxzhKfFJKk54= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751287660; c=relaxed/simple; bh=i6/164pcR4NLefGrudZewZCUwIEFmxRK5pIjFusqjK4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=I0UjzY5MbMYB2CtcnzmzcIo/LmVQ5Iukw0pXrsoQDZXWaC9sZexdJ1QixIhwYHpCwVXMFx0JI8V3CQgseJHWY9ALhWxT09a7RPUpszZGp19VKSSO8btzET04I7OD7t5OXfncXMuuMgxE+pes8gTr3WZPec8A+NB152dZsYnTGyA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.187 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.162.254]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4bW5RM4FgRz14Lqf; Mon, 30 Jun 2025 20:42:55 +0800 (CST) Received: from kwepemg100016.china.huawei.com (unknown [7.202.181.57]) by mail.maildlp.com (Postfix) with ESMTPS id 38329180486; Mon, 30 Jun 2025 20:47:35 +0800 (CST) Received: from huawei.com (10.67.174.33) by kwepemg100016.china.huawei.com (7.202.181.57) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Mon, 30 Jun 2025 20:47:34 +0800 From: GONG Ruiqi To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin CC: Eric Snowberg , Paul Moore , James Morris , "Serge E . Hallyn" , , , , Lu Jialin , Subject: [PATCH -next RFC 3/4] ima: rot: Make RoT kick in Date: Mon, 30 Jun 2025 20:59:27 +0800 Message-ID: <20250630125928.765285-4-gongruiqi1@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250630125928.765285-1-gongruiqi1@huawei.com> References: <20250630125928.765285-1-gongruiqi1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To kwepemg100016.china.huawei.com (7.202.181.57) Content-Type: text/plain; charset="utf-8" From now on the RoT framework starts to work, achieved by replacing multiple variables and function calls to their RoT counterparts. Specifically, - Replace ima_tpm_chip with ima_rot_inst at all places related to ->{nr_,}allocated_banks, and use the latter to indicate RoT's availability; - Make ima_tpm_chip static in ima_tpm.c; - Replace ima_pcr_extend() & ima_calc_boot_aggregate() with corresponding RoT hooks; - Initialize RoT with ima_rot_init() instead of tpm_default_chip() in ima_init(); Co-developed-by: Zhao Yipeng Signed-off-by: Zhao Yipeng Signed-off-by: GONG Ruiqi --- security/integrity/ima/ima.h | 3 +-- security/integrity/ima/ima_api.c | 2 +- security/integrity/ima/ima_crypto.c | 30 +++++++++++------------ security/integrity/ima/ima_fs.c | 4 +-- security/integrity/ima/ima_init.c | 11 ++++----- security/integrity/ima/ima_queue.c | 27 ++++++++++---------- security/integrity/ima/ima_template.c | 2 +- security/integrity/ima/ima_template_lib.c | 5 ++-- security/integrity/ima/ima_tpm.c | 4 +-- security/integrity/ima/ima_tpm.h | 2 -- 10 files changed, 42 insertions(+), 48 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 07752e7227b6..31e3f76cdda6 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -42,7 +42,7 @@ enum tpm_pcrs { TPM_PCR0 =3D 0, TPM_PCR8 =3D 8, TPM_PCR10= =3D 10 }; #define IMA_TEMPLATE_IMA_NAME "ima" #define IMA_TEMPLATE_IMA_FMT "d|n" =20 -#define NR_BANKS(chip) ((chip !=3D NULL) ? chip->nr_allocated_banks : 0) +#define NR_BANKS(rot) ((rot !=3D NULL) ? rot->nr_allocated_banks : 0) =20 /* current content of the policy */ extern int ima_policy_flag; @@ -64,7 +64,6 @@ extern int ima_extra_slots __ro_after_init; extern struct ima_algo_desc *ima_algo_array __ro_after_init; =20 extern int ima_appraise; -extern struct tpm_chip *ima_tpm_chip; extern struct ima_rot *ima_rot_inst; extern const char boot_aggregate_name[]; =20 diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_= api.c index c35ea613c9f8..65cf5b2400f2 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -52,7 +52,7 @@ int ima_alloc_init_template(struct ima_event_data *event_= data, if (!*entry) return -ENOMEM; =20 - digests =3D kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots, + digests =3D kcalloc(NR_BANKS(ima_rot_inst) + ima_extra_slots, sizeof(*digests), GFP_NOFS); if (!digests) { kfree(*entry); diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/i= ma_crypto.c index 492d7bc56510..ee53f44b1a30 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -95,7 +95,7 @@ struct crypto_shash *ima_alloc_tfm(enum hash_algo algo) if (algo =3D=3D ima_hash_algo) return tfm; =20 - for (i =3D 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) + for (i =3D 0; i < NR_BANKS(ima_rot_inst) + ima_extra_slots; i++) if (ima_algo_array[i].tfm && ima_algo_array[i].algo =3D=3D algo) return ima_algo_array[i].tfm; =20 @@ -121,8 +121,8 @@ int __init ima_init_crypto(void) ima_sha1_idx =3D -1; ima_hash_algo_idx =3D -1; =20 - for (i =3D 0; i < NR_BANKS(ima_tpm_chip); i++) { - algo =3D ima_tpm_chip->allocated_banks[i].crypto_id; + for (i =3D 0; i < NR_BANKS(ima_rot_inst); i++) { + algo =3D ima_rot_inst->allocated_banks[i].crypto_id; if (algo =3D=3D HASH_ALGO_SHA1) ima_sha1_idx =3D i; =20 @@ -131,23 +131,23 @@ int __init ima_init_crypto(void) } =20 if (ima_sha1_idx < 0) { - ima_sha1_idx =3D NR_BANKS(ima_tpm_chip) + ima_extra_slots++; + ima_sha1_idx =3D NR_BANKS(ima_rot_inst) + ima_extra_slots++; if (ima_hash_algo =3D=3D HASH_ALGO_SHA1) ima_hash_algo_idx =3D ima_sha1_idx; } =20 if (ima_hash_algo_idx < 0) - ima_hash_algo_idx =3D NR_BANKS(ima_tpm_chip) + ima_extra_slots++; + ima_hash_algo_idx =3D NR_BANKS(ima_rot_inst) + ima_extra_slots++; =20 - ima_algo_array =3D kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots, + ima_algo_array =3D kcalloc(NR_BANKS(ima_rot_inst) + ima_extra_slots, sizeof(*ima_algo_array), GFP_KERNEL); if (!ima_algo_array) { rc =3D -ENOMEM; goto out; } =20 - for (i =3D 0; i < NR_BANKS(ima_tpm_chip); i++) { - algo =3D ima_tpm_chip->allocated_banks[i].crypto_id; + for (i =3D 0; i < NR_BANKS(ima_rot_inst); i++) { + algo =3D ima_rot_inst->allocated_banks[i].crypto_id; ima_algo_array[i].algo =3D algo; =20 /* unknown TPM algorithm */ @@ -171,7 +171,7 @@ int __init ima_init_crypto(void) } } =20 - if (ima_sha1_idx >=3D NR_BANKS(ima_tpm_chip)) { + if (ima_sha1_idx >=3D NR_BANKS(ima_rot_inst)) { if (ima_hash_algo =3D=3D HASH_ALGO_SHA1) { ima_algo_array[ima_sha1_idx].tfm =3D ima_shash_tfm; } else { @@ -186,7 +186,7 @@ int __init ima_init_crypto(void) ima_algo_array[ima_sha1_idx].algo =3D HASH_ALGO_SHA1; } =20 - if (ima_hash_algo_idx >=3D NR_BANKS(ima_tpm_chip) && + if (ima_hash_algo_idx >=3D NR_BANKS(ima_rot_inst) && ima_hash_algo_idx !=3D ima_sha1_idx) { ima_algo_array[ima_hash_algo_idx].tfm =3D ima_shash_tfm; ima_algo_array[ima_hash_algo_idx].algo =3D ima_hash_algo; @@ -194,7 +194,7 @@ int __init ima_init_crypto(void) =20 return 0; out_array: - for (i =3D 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) { + for (i =3D 0; i < NR_BANKS(ima_rot_inst) + ima_extra_slots; i++) { if (!ima_algo_array[i].tfm || ima_algo_array[i].tfm =3D=3D ima_shash_tfm) continue; @@ -214,7 +214,7 @@ void ima_free_tfm(struct crypto_shash *tfm) if (tfm =3D=3D ima_shash_tfm) return; =20 - for (i =3D 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) + for (i =3D 0; i < NR_BANKS(ima_rot_inst) + ima_extra_slots; i++) if (ima_algo_array[i].tfm =3D=3D tfm) return; =20 @@ -632,12 +632,12 @@ int ima_calc_field_array_hash(struct ima_field_data *= field_data, =20 entry->digests[ima_sha1_idx].alg_id =3D TPM_ALG_SHA1; =20 - for (i =3D 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) { + for (i =3D 0; i < NR_BANKS(ima_rot_inst) + ima_extra_slots; i++) { if (i =3D=3D ima_sha1_idx) continue; =20 - if (i < NR_BANKS(ima_tpm_chip)) { - alg_id =3D ima_tpm_chip->allocated_banks[i].alg_id; + if (i < NR_BANKS(ima_rot_inst)) { + alg_id =3D ima_rot_inst->allocated_banks[i].alg_id; entry->digests[i].alg_id =3D alg_id; } =20 diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_f= s.c index 87045b09f120..b4a9bb5468be 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -394,9 +394,9 @@ static const struct seq_operations ima_policy_seqops = =3D { =20 static int __init create_securityfs_measurement_lists(void) { - int count =3D NR_BANKS(ima_tpm_chip); + int count =3D NR_BANKS(ima_rot_inst); =20 - if (ima_sha1_idx >=3D NR_BANKS(ima_tpm_chip)) + if (ima_sha1_idx >=3D NR_BANKS(ima_rot_inst)) count++; =20 for (int i =3D 0; i < count; i++) { diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima= _init.c index 8651b11c1edf..096eaa7a7666 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -19,7 +19,6 @@ #include =20 #include "ima.h" -#include "ima_tpm.h" =20 /* name for boot aggregate entry */ const char boot_aggregate_name[] =3D "boot_aggregate"; @@ -72,8 +71,8 @@ static int __init ima_add_boot_aggregate(void) * Ultimately select SHA1 also for TPM 2.0 if the SHA256 PCR bank * is not found. */ - if (ima_tpm_chip) { - result =3D ima_tpm_calc_boot_aggregate(hash_hdr); + if (ima_rot_inst) { + result =3D ima_rot_inst->calc_boot_aggregate(hash_hdr); if (result < 0) { audit_cause =3D "hashing_error"; goto err_out; @@ -120,9 +119,9 @@ int __init ima_init(void) { int rc; =20 - ima_tpm_chip =3D tpm_default_chip(); - if (!ima_tpm_chip) - pr_info("No TPM chip found, activating TPM-bypass!\n"); + ima_rot_inst =3D ima_rot_init(); + if (!ima_rot_inst) + pr_info("No RoT found, activating RoT-bypass!\n"); =20 rc =3D integrity_init_keyring(INTEGRITY_KEYRING_IMA); if (rc) diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/im= a_queue.c index b91167ef27dc..05ed90d6a608 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -19,7 +19,6 @@ #include #include #include "ima.h" -#include "ima_tpm.h" =20 #define AUDIT_CAUSE_LEN_MAX 32 =20 @@ -158,9 +157,9 @@ int ima_add_template_entry(struct ima_template_entry *e= ntry, int violation, u8 *digest =3D entry->digests[ima_hash_algo_idx].digest; struct tpm_digest *digests_arg =3D entry->digests; const char *audit_cause =3D "hash_added"; - char tpm_audit_cause[AUDIT_CAUSE_LEN_MAX]; + char rot_audit_cause[AUDIT_CAUSE_LEN_MAX]; int audit_info =3D 1; - int result =3D 0, tpmresult =3D 0; + int result =3D 0, rotresult =3D 0; =20 mutex_lock(&ima_extend_list_mutex); =20 @@ -194,11 +193,11 @@ int ima_add_template_entry(struct ima_template_entry = *entry, int violation, if (violation) /* invalidate pcr */ digests_arg =3D digests; =20 - tpmresult =3D ima_pcr_extend(digests_arg, entry->pcr); - if (tpmresult !=3D 0) { - snprintf(tpm_audit_cause, AUDIT_CAUSE_LEN_MAX, "TPM_error(%d)", - tpmresult); - audit_cause =3D tpm_audit_cause; + rotresult =3D ima_rot_inst->extend(digests_arg, &entry->pcr); + if (rotresult !=3D 0) { + snprintf(rot_audit_cause, AUDIT_CAUSE_LEN_MAX, "%s_error(%d)", + ima_rot_inst->name, rotresult); + audit_cause =3D rot_audit_cause; audit_info =3D 0; } out: @@ -254,18 +253,18 @@ int __init ima_init_digests(void) u16 crypto_id; int i; =20 - if (!ima_tpm_chip) + if (!ima_rot_inst) return 0; =20 - digests =3D kcalloc(ima_tpm_chip->nr_allocated_banks, sizeof(*digests), + digests =3D kcalloc(ima_rot_inst->nr_allocated_banks, sizeof(*digests), GFP_NOFS); if (!digests) return -ENOMEM; =20 - for (i =3D 0; i < ima_tpm_chip->nr_allocated_banks; i++) { - digests[i].alg_id =3D ima_tpm_chip->allocated_banks[i].alg_id; - digest_size =3D ima_tpm_chip->allocated_banks[i].digest_size; - crypto_id =3D ima_tpm_chip->allocated_banks[i].crypto_id; + for (i =3D 0; i < ima_rot_inst->nr_allocated_banks; i++) { + digests[i].alg_id =3D ima_rot_inst->allocated_banks[i].alg_id; + digest_size =3D ima_rot_inst->allocated_banks[i].digest_size; + crypto_id =3D ima_rot_inst->allocated_banks[i].crypto_id; =20 /* for unmapped TPM algorithms digest is still a padded SHA1 */ if (crypto_id =3D=3D HASH_ALGO__LAST) diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima= /ima_template.c index 04c49f05cb74..a6ece3557267 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -367,7 +367,7 @@ static int ima_restore_template_data(struct ima_templat= e_desc *template_desc, if (!*entry) return -ENOMEM; =20 - digests =3D kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots, + digests =3D kcalloc(NR_BANKS(ima_rot_inst) + ima_extra_slots, sizeof(*digests), GFP_NOFS); if (!digests) { kfree(*entry); diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity= /ima/ima_template_lib.c index 67b43e4e4222..e5581bf47601 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -10,7 +10,6 @@ */ =20 #include "ima_template_lib.h" -#include "ima_tpm.h" #include #include =20 @@ -365,9 +364,9 @@ int ima_eventdigest_init(struct ima_event_data *event_d= ata, } =20 if ((const char *)event_data->filename =3D=3D boot_aggregate_name) { - if (ima_tpm_chip) { + if (ima_rot_inst) { hash.hdr.algo =3D HASH_ALGO_SHA1; - result =3D ima_tpm_calc_boot_aggregate(hash_hdr); + result =3D ima_rot_inst->calc_boot_aggregate(hash_hdr); =20 /* algo can change depending on available PCR banks */ if (!result && hash.hdr.algo !=3D HASH_ALGO_SHA1) diff --git a/security/integrity/ima/ima_tpm.c b/security/integrity/ima/ima_= tpm.c index 6ff7ed8ef322..836b7832e2eb 100644 --- a/security/integrity/ima/ima_tpm.c +++ b/security/integrity/ima/ima_tpm.c @@ -15,7 +15,7 @@ #include "ima.h" #include "ima_tpm.h" =20 -struct tpm_chip *ima_tpm_chip; +static struct tpm_chip *ima_tpm_chip; =20 int ima_tpm_init(struct ima_rot *rot) { @@ -29,7 +29,7 @@ int ima_tpm_init(struct ima_rot *rot) return 0; } =20 -int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) +static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) { int result =3D 0; =20 diff --git a/security/integrity/ima/ima_tpm.h b/security/integrity/ima/ima_= tpm.h index fa2946073ceb..0fb0e80ea1e7 100644 --- a/security/integrity/ima/ima_tpm.h +++ b/security/integrity/ima/ima_tpm.h @@ -16,6 +16,4 @@ int ima_tpm_init(struct ima_rot *rot); int ima_tpm_extend(struct tpm_digest *digests_arg, const void *args); int ima_tpm_calc_boot_aggregate(struct ima_digest_data *hash); =20 -int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr); - #endif /* __IMA_IMA_TPM_H */ --=20 2.25.1 From nobody Wed Oct 8 09:28:27 2025 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 24D3826F463; Mon, 30 Jun 2025 12:47:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751287660; cv=none; b=ml+Wen7MGUKX/9wlDdEXywWwVpEiZyYyGdje9VIiIC7WMllrvkcHU/QNeS+FzN2Qrx8c3zESlK8UqzK5b9+MuVj+90XH9NJ6SdTrVODdI1Y4CapVfs4Og5W9OZ67TQJ+bZDM27a0NTQRxNTW1wcsbWbFccLSpr4E4blJ+XwbNiU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751287660; c=relaxed/simple; bh=2j7p5gpf+8wtNYLLVp46XrGSopcKtlZ1X8i8OTr8ApA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Xc4Y65PRYvWrQ0qpRv8xANzygPApa00xbGxUMm+90waz5YU9a6R4hN9w6q2XB2xVC+97J1ifLqibvLJODXfIhGghWoFzuCiJBkD3+HtWeOwnXgRS4/Ov8XDPJnr4dPmDXiw5aHyZV40PvIO9WCXoXt4UY5TBnFFWVF0EqBhS7I8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.252]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4bW5Rj6qMjzCsMV; Mon, 30 Jun 2025 20:43:13 +0800 (CST) Received: from kwepemg100016.china.huawei.com (unknown [7.202.181.57]) by mail.maildlp.com (Postfix) with ESMTPS id BB175180237; Mon, 30 Jun 2025 20:47:35 +0800 (CST) Received: from huawei.com (10.67.174.33) by kwepemg100016.china.huawei.com (7.202.181.57) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Mon, 30 Jun 2025 20:47:35 +0800 From: GONG Ruiqi To: Mimi Zohar , Roberto Sassu , Dmitry Kasatkin CC: Eric Snowberg , Paul Moore , James Morris , "Serge E . Hallyn" , , , , Lu Jialin , Subject: [PATCH -next RFC 4/4] ima: rot: Involve per-RoT default PCR index Date: Mon, 30 Jun 2025 20:59:28 +0800 Message-ID: <20250630125928.765285-5-gongruiqi1@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250630125928.765285-1-gongruiqi1@huawei.com> References: <20250630125928.765285-1-gongruiqi1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To kwepemg100016.china.huawei.com (7.202.181.57) Content-Type: text/plain; charset="utf-8" As both the extend operation and the measurement list require a PCR index, the concept of PCR needs to be somehow applied to RoTs besides TPM as well, and each type of RoT device should have its own PCR index, no matter it's actually used or not. The original CONFIG_IMA_MEASURE_PCR_IDX in fact has two roles: 1. It specifies the default index of TPM's PCR that IMA will use. 2. It provides a dummy PCR index (as a placeholder in the measurement list) when TPM (now generalized to RoT) is unavailable. Now rename this config to emphasize its first role, and create another macro, IMA_DEFAULT_PCR_IDX, to take up the second role. Signed-off-by: GONG Ruiqi --- security/integrity/ima/Kconfig | 12 ++++++++---- security/integrity/ima/ima.h | 3 +++ security/integrity/ima/ima_api.c | 2 +- security/integrity/ima/ima_init.c | 2 +- security/integrity/ima/ima_main.c | 4 ++-- security/integrity/ima/ima_rot.c | 2 +- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 976e75f9b9ba..5e3b4ddea9ab 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -44,14 +44,18 @@ config IMA_KEXEC Depending on the IMA policy, the measurement list can grow to be very large. =20 -config IMA_MEASURE_PCR_IDX +config IMA_ROT_TPM_PCR_IDX int range 8 14 default 10 help - IMA_MEASURE_PCR_IDX determines the TPM PCR register index - that IMA uses to maintain the integrity aggregate of the - measurement list. If unsure, use the default 10. + IMA_ROT_TPM_PCR_IDX determines the index of PCR that IMA, when + choosing TPM as the Root of Trust (RoT), would use to maintain + the integrity aggregate of the measurement list. Its value is + also used as a dummy PCR index IMA would use in the absence of + RoT. + + If unsure, use the default 10. =20 config IMA_LSM_RULES bool diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 31e3f76cdda6..f64fde127006 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -42,6 +42,9 @@ enum tpm_pcrs { TPM_PCR0 =3D 0, TPM_PCR8 =3D 8, TPM_PCR10= =3D 10 }; #define IMA_TEMPLATE_IMA_NAME "ima" #define IMA_TEMPLATE_IMA_FMT "d|n" =20 +#define IMA_DEFAULT_PCR_IDX CONFIG_IMA_ROT_TPM_PCR_IDX +#define IMA_MEASURE_PCR_IDX (ima_rot_inst ? ima_rot_inst->default_pcr : IM= A_DEFAULT_PCR_IDX) + #define NR_BANKS(rot) ((rot !=3D NULL) ? rot->nr_allocated_banks : 0) =20 /* current content of the policy */ diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_= api.c index 65cf5b2400f2..94201216225d 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -152,7 +152,7 @@ void ima_add_violation(struct file *file, const unsigne= d char *filename, goto err_out; } result =3D ima_store_template(entry, violation, inode, - filename, CONFIG_IMA_MEASURE_PCR_IDX); + filename, IMA_MEASURE_PCR_IDX); if (result < 0) ima_free_template_entry(entry); err_out: diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima= _init.c index 096eaa7a7666..a63a5d8355df 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -87,7 +87,7 @@ static int __init ima_add_boot_aggregate(void) =20 result =3D ima_store_template(entry, violation, NULL, boot_aggregate_name, - CONFIG_IMA_MEASURE_PCR_IDX); + IMA_MEASURE_PCR_IDX); if (result < 0) { ima_free_template_entry(entry); audit_cause =3D "store_entry"; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima= _main.c index cdd225f65a62..ed13966dc562 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -245,7 +245,7 @@ static int process_measurement(struct file *file, const= struct cred *cred, char filename[NAME_MAX]; const char *pathname =3D NULL; int rc =3D 0, action, must_appraise =3D 0; - int pcr =3D CONFIG_IMA_MEASURE_PCR_IDX; + int pcr =3D IMA_MEASURE_PCR_IDX; struct evm_ima_xattr_data *xattr_value =3D NULL; struct modsig *modsig =3D NULL; int xattr_len =3D 0; @@ -1060,7 +1060,7 @@ int process_buffer_measurement(struct mnt_idmap *idma= p, } =20 if (!pcr) - pcr =3D CONFIG_IMA_MEASURE_PCR_IDX; + pcr =3D IMA_MEASURE_PCR_IDX; =20 iint.ima_hash =3D hash_hdr; iint.ima_hash->algo =3D ima_hash_algo; diff --git a/security/integrity/ima/ima_rot.c b/security/integrity/ima/ima_= rot.c index 0083d9c4e64e..ed32a48bef8d 100644 --- a/security/integrity/ima/ima_rot.c +++ b/security/integrity/ima/ima_rot.c @@ -38,7 +38,7 @@ static struct ima_rot ima_rots[] =3D { #ifdef CONFIG_TCG_TPM { .name =3D "tpm", - .default_pcr =3D CONFIG_IMA_MEASURE_PCR_IDX, + .default_pcr =3D CONFIG_IMA_ROT_TPM_PCR_IDX, .init =3D ima_tpm_init, .extend =3D ima_tpm_extend, .calc_boot_aggregate =3D ima_tpm_calc_boot_aggregate, --=20 2.25.1