From b858b2e7f81330dde364732b68159636cc5b51ee Mon Sep 17 00:00:00 2001 From: Huaxin Lu Date: Mon, 20 May 2024 19:41:40 +0800 Subject: [PATCH] IMA: Support the measurement extending of TSI TMM EulerOS inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9RJ09 -------------------------------- This patch support the RoT (Root of Trust) implemented by TSI TMM, which is used in virtCCA CVM feature. This patch includes the three parts: 1. Use a bool flag to determine whether the CVM is enabled. If enabled, bypass TPM. 2. Read the value of slot 0 (RIM) as the boot aggregate value, which is the measurement result of RIM. 3. Extend the IMA measure log hash into slot1 (REM0). Signed-off-by: Huaxin Lu --- security/integrity/ima/Makefile | 2 + security/integrity/ima/ima_cvm.c | 77 ++++++++++++++++++++++++++++++ security/integrity/ima/ima_cvm.h | 36 ++++++++++++++ security/integrity/ima/ima_init.c | 19 ++++++++ security/integrity/ima/ima_queue.c | 11 +++++ 5 files changed, 145 insertions(+) create mode 100644 security/integrity/ima/ima_cvm.c create mode 100644 security/integrity/ima/ima_cvm.h diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index fb9744a1c3d4..d823ac70ddc2 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -19,3 +19,5 @@ ima-$(CONFIG_IMA_DIGEST_LIST) += ima_digest_list.o ifeq ($(CONFIG_EFI),y) ima-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_efi.o endif + +ima-$(CONFIG_HISI_VIRTCCA_GUEST) += ima_cvm.o diff --git a/security/integrity/ima/ima_cvm.c b/security/integrity/ima/ima_cvm.c new file mode 100644 index 000000000000..0fe3c0da63b2 --- /dev/null +++ b/security/integrity/ima/ima_cvm.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024. Huawei Technologies Co., Ltd. All rights reserved. + */ +#include +#include +#include "ima_cvm.h" + +static bool ima_tsi_cvm; + +bool ima_cvm_available(void) +{ + return ima_tsi_cvm; +} + +int __init ima_cvm_init(void) +{ + int rc = -ENODEV; + + if (is_virtcca_cvm_world() && tsi_get_version() != SMCCC_RET_NOT_SUPPORTED) { + ima_tsi_cvm = true; + rc = 0; + } + + return rc; +} + +int ima_calc_cvm_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]; + + /* Read the measurement result of RIM as the boot aggregate */ + cm.index = RIM_MEASUREMENT_SLOT; + + result = tsi_measurement_read(&cm); + if (result != TSI_SUCCESS) { + pr_err("Error reading cvm measurement 0 for boot aggregate\n"); + return -EFAULT; + } + + memcpy(hash->digest, cm.value, hash_len); + + return 0; +} + +int ima_cvm_extend(struct tpm_digest *digests_arg) +{ + struct virtcca_cvm_measurement_extend cme; + + if (!ima_tsi_cvm) + return 0; + + /* Use index 1 as CVM IMA slot */ + cme.index = 1; + cme.size = hash_digest_size[ima_hash_algo]; + + if (digests_arg) + memcpy(cme.value, digests_arg[ima_hash_algo_idx].digest, + cme.size); + else + memset(cme.value, 0xff, cme.size); + + return tsi_measurement_extend(&cme) == TSI_SUCCESS ? 0 : -EFAULT; +} diff --git a/security/integrity/ima/ima_cvm.h b/security/integrity/ima/ima_cvm.h new file mode 100644 index 000000000000..864243bd0844 --- /dev/null +++ b/security/integrity/ima/ima_cvm.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024. Huawei Technologies Co., Ltd. All rights reserved. + */ +#ifndef __LINUX_IMA_CVM_H +#define __LINUX_IMA_CVM_H + +#include "ima.h" + +#ifdef CONFIG_HISI_VIRTCCA_GUEST +int __init ima_cvm_init(void); +bool ima_cvm_available(void); +int ima_cvm_extend(struct tpm_digest *digests_arg); +int ima_calc_cvm_boot_aggregate(struct ima_digest_data *hash); +#else +static inline int __init ima_cvm_init(void) +{ + return -ENODEV; +} + +static inline bool ima_cvm_available(void) +{ + return false; +} + +static inline int ima_cvm_extend(struct tpm_digest *digests_arg) +{ + return -ENODEV; +} + +static inline int ima_calc_cvm_boot_aggregate(struct ima_digest_data *hash) +{ + return -ENODEV; +} +#endif +#endif diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 0a4833daf4da..aa750942e422 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -19,6 +19,7 @@ #include #include "ima.h" +#include "ima_cvm.h" /* name for boot aggregate entry */ const char boot_aggregate_name[] = "boot_aggregate"; @@ -57,6 +58,16 @@ 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_cvm_available()) { + result = ima_calc_cvm_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 @@ -121,7 +132,15 @@ int __init ima_init(void) { int rc; +#ifdef CONFIG_HISI_VIRTCCA_GUEST + rc = ima_cvm_init(); + if (rc) { + pr_info("No CVM found, activating CVM-bypass!\n"); + ima_tpm_chip = tpm_default_chip(); + } +#else ima_tpm_chip = tpm_default_chip(); +#endif if (!ima_tpm_chip) pr_info("No TPM chip found, activating TPM-bypass!\n"); diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 532da87ce519..06653c3f3417 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -18,6 +18,7 @@ #include #include #include "ima.h" +#include "ima_cvm.h" #define AUDIT_CAUSE_LEN_MAX 32 @@ -187,6 +188,16 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, if (violation) /* invalidate pcr */ digests_arg = digests; +#ifdef CONFIG_HISI_VIRTCCA_GUEST + tpmresult = ima_cvm_extend(digests_arg); + if (tpmresult != 0) { + snprintf(tpm_audit_cause, AUDIT_CAUSE_LEN_MAX, "TSI_error(%d)", + tpmresult); + audit_cause = tpm_audit_cause; + audit_info = 0; + } +#endif + tpmresult = ima_pcr_extend(digests_arg, entry->pcr); if (tpmresult != 0) { snprintf(tpm_audit_cause, AUDIT_CAUSE_LEN_MAX, "TPM_error(%d)", -- Gitee