VirtCCA is now fit into the RoT framework, with a lower priority against TPM, which means that the framework will always try to initialize and use TPM first. Nevertheless, users can select VirtCCA to be the IMA RoT with `ima_rot=virtcca` cmdline.
Co-developed-by: Lu Huaxin luhuaxin1@huawei.com Signed-off-by: Lu Huaxin luhuaxin1@huawei.com Signed-off-by: GONG Ruiqi gongruiqi1@huawei.com --- security/integrity/ima/ima_init.c | 19 ------- security/integrity/ima/ima_queue.c | 20 ++----- security/integrity/ima/ima_rot.c | 9 ++++ security/integrity/ima/ima_virtcca.c | 80 +++++++++++++++++----------- security/integrity/ima/ima_virtcca.h | 27 +--------- 5 files changed, 64 insertions(+), 91 deletions(-)
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 8889d42448da..8909b358fcde 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -19,7 +19,6 @@ #include <generated/utsrelease.h>
#include "ima.h" -#include "ima_virtcca.h"
/* name for boot aggregate entry */ const char boot_aggregate_name[] = "boot_aggregate"; @@ -58,16 +57,6 @@ static int __init ima_add_boot_aggregate(void) iint->ima_hash->algo = ima_hash_algo; iint->ima_hash->length = hash_digest_size[ima_hash_algo];
-#ifdef CONFIG_HISI_VIRTCCA_GUEST - if (ima_virtcca_available()) { - result = ima_calc_virtcca_boot_aggregate(&hash.hdr); - if (result < 0) { - audit_cause = "hashing_error"; - goto err_out; - } - } -#endif - /* * With TPM 2.0 hash agility, TPM chips could support multiple TPM * PCR banks, allowing firmware to configure and enable different @@ -132,15 +121,7 @@ int __init ima_init(void) { int rc;
-#ifdef CONFIG_HISI_VIRTCCA_GUEST - rc = ima_virtcca_init(); - if (rc) { - pr_info("No CVM found, activating CVM-bypass!\n"); - ima_rot_inst = ima_rot_init(); - } -#else ima_rot_inst = ima_rot_init(); -#endif if (!ima_rot_inst) pr_info("No RoT found, activating RoT-bypass!\n");
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index fba549d2d0d8..296ad15fd520 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -18,7 +18,6 @@ #include <linux/rculist.h> #include <linux/slab.h> #include "ima.h" -#include "ima_virtcca.h"
#define AUDIT_CAUSE_LEN_MAX 32
@@ -175,25 +174,14 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, if (violation) /* invalidate pcr */ digests_arg = digests;
-#ifdef CONFIG_HISI_VIRTCCA_GUEST - rotresult = ima_virtcca_extend(digests_arg); + if (ima_rot_inst) + rotresult = ima_rot_inst->extend(digests_arg, &entry->pcr); if (rotresult != 0) { - snprintf(rot_audit_cause, AUDIT_CAUSE_LEN_MAX, "TSI_error(%d)", - rotresult); + snprintf(rot_audit_cause, AUDIT_CAUSE_LEN_MAX, "%s_error(%d)", + ima_rot_inst->name, rotresult); audit_cause = rot_audit_cause; audit_info = 0; } -#endif - - if (ima_rot_inst) { - rotresult = ima_rot_inst->extend(digests_arg, &entry->pcr); - if (rotresult != 0) { - snprintf(rot_audit_cause, AUDIT_CAUSE_LEN_MAX, "%s_error(%d)", - ima_rot_inst->name, rotresult); - audit_cause = rot_audit_cause; - audit_info = 0; - } - } out: mutex_unlock(&ima_extend_list_mutex); integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, diff --git a/security/integrity/ima/ima_rot.c b/security/integrity/ima/ima_rot.c index ca48c8a02390..45d2ea314790 100644 --- a/security/integrity/ima/ima_rot.c +++ b/security/integrity/ima/ima_rot.c @@ -15,6 +15,7 @@
#include "ima.h" #include "ima_tpm.h" +#include "ima_virtcca.h"
static const char *name_rot_prefered;
@@ -33,6 +34,14 @@ static struct ima_rot ima_rots[] = { .calc_boot_aggregate = ima_tpm_calc_boot_aggregate, }, #endif +#ifdef CONFIG_HISI_VIRTCCA_GUEST + { + .name = "virtcca", + .init = ima_virtcca_init, + .extend = ima_virtcca_extend, + .calc_boot_aggregate = ima_calc_virtcca_boot_aggregate, + }, +#endif };
static int __init ima_rot_name(char *str) diff --git a/security/integrity/ima/ima_virtcca.c b/security/integrity/ima/ima_virtcca.c index 318c547b0d59..15f7338564b3 100644 --- a/security/integrity/ima/ima_virtcca.c +++ b/security/integrity/ima/ima_virtcca.c @@ -4,43 +4,65 @@ */ #include <asm/virtcca_cvm_smc.h> #include <asm/virtcca_cvm_guest.h> -#include "ima_virtcca.h" +#include "ima.h"
-static bool ima_tsi_cvm; +#define CVM_IMA_SLOT_IDX 1
-bool ima_virtcca_available(void) +static enum hash_algo virtcca_algo; + +static int ima_virtcca_init_algo(void) { - return ima_tsi_cvm; + unsigned long result; + struct virtcca_cvm_config cfg = { 0 }; + + result = tsi_get_cvm_config(&cfg); + if (result != TSI_SUCCESS) { + pr_info("Error reading cvm config\n"); + return -EFAULT; + } + + /* 0: SHA256, 1: SHA512 */ + virtcca_algo = cfg.algorithm ? HASH_ALGO_SHA512 : HASH_ALGO_SHA256; + + return 0; }
-int __init ima_virtcca_init(void) +int ima_virtcca_init(struct ima_rot *rot) { - int rc = -ENODEV; + int rc; + + if (!is_virtcca_cvm_world() || tsi_get_version() == SMCCC_RET_NOT_SUPPORTED) + return -ENODEV;
- if (is_virtcca_cvm_world() && tsi_get_version() != SMCCC_RET_NOT_SUPPORTED) { - ima_tsi_cvm = true; - rc = 0; + rc = ima_virtcca_init_algo(); + if (rc) + return rc; + + if (virtcca_algo != ima_hash_algo) { + pr_info("VirtCCA's algo (%s) is different from ima_hash_algo (%s)\n", + hash_algo_name[virtcca_algo], hash_algo_name[ima_hash_algo]); + + rot->allocated_banks = kcalloc(1, sizeof(*rot->allocated_banks), GFP_KERNEL); + if (!rot->allocated_banks) + return -ENOMEM; + + rot->nr_allocated_banks = 1; + rot->allocated_banks[0].alg_id = (virtcca_algo == HASH_ALGO_SHA512) ? + TPM_ALG_SHA512 : TPM_ALG_SHA256; + rot->allocated_banks[0].digest_size = hash_digest_size[virtcca_algo]; + rot->allocated_banks[0].crypto_id = virtcca_algo; }
- return rc; + return 0; }
int ima_calc_virtcca_boot_aggregate(struct ima_digest_data *hash) { unsigned long result; - int hash_len; - struct virtcca_cvm_config cfg = { 0 }; struct virtcca_cvm_measurement cm = { 0 };
- result = tsi_get_cvm_config(&cfg); - if (result != TSI_SUCCESS) { - pr_err("Error reading cvm config for boot aggregate\n"); - return -EFAULT; - } - - /* 0: SHA256, 1: SHA512 */ - hash->algo = cfg.algorithm ? HASH_ALGO_SHA512 : HASH_ALGO_SHA256; - hash_len = hash_digest_size[hash->algo]; + hash->algo = virtcca_algo; + hash->length = hash_digest_size[virtcca_algo];
/* Read the measurement result of RIM as the boot aggregate */ cm.index = RIM_MEASUREMENT_SLOT; @@ -51,25 +73,21 @@ int ima_calc_virtcca_boot_aggregate(struct ima_digest_data *hash) return -EFAULT; }
- memcpy(hash->digest, cm.value, hash_len); + memcpy(hash->digest, cm.value, hash->length);
return 0; }
-int ima_virtcca_extend(struct tpm_digest *digests_arg) +int ima_virtcca_extend(struct tpm_digest *digests_arg, const void *args) { struct virtcca_cvm_measurement_extend cme; + int algo_idx = (virtcca_algo != ima_hash_algo) ? 0 : ima_hash_algo_idx;
- if (!ima_tsi_cvm) - return 0; - - /* Use index 1 as CVM IMA slot */ - cme.index = 1; - cme.size = hash_digest_size[ima_hash_algo]; + cme.index = CVM_IMA_SLOT_IDX; + cme.size = hash_digest_size[virtcca_algo];
if (digests_arg) - memcpy(cme.value, digests_arg[ima_hash_algo_idx].digest, - cme.size); + memcpy(cme.value, digests_arg[algo_idx].digest, cme.size); else memset(cme.value, 0xff, cme.size);
diff --git a/security/integrity/ima/ima_virtcca.h b/security/integrity/ima/ima_virtcca.h index 8e00c9b6a996..cffb9bdf3013 100644 --- a/security/integrity/ima/ima_virtcca.h +++ b/security/integrity/ima/ima_virtcca.h @@ -7,30 +7,7 @@
#include "ima.h"
-#ifdef CONFIG_HISI_VIRTCCA_GUEST -int __init ima_virtcca_init(void); -bool ima_virtcca_available(void); -int ima_virtcca_extend(struct tpm_digest *digests_arg); +int ima_virtcca_init(struct ima_rot *rot); int ima_calc_virtcca_boot_aggregate(struct ima_digest_data *hash); -#else -static inline int __init ima_virtcca_init(void) -{ - return -ENODEV; -} - -static inline bool ima_virtcca_available(void) -{ - return false; -} - -static inline int ima_virtcca_extend(struct tpm_digest *digests_arg) -{ - return -ENODEV; -} - -static inline int ima_calc_virtcca_boot_aggregate(struct ima_digest_data *hash) -{ - return -ENODEV; -} -#endif +int ima_virtcca_extend(struct tpm_digest *digests_arg, const void *args); #endif