Commit b1410546 authored by Huaxin Lu's avatar Huaxin Lu
Browse files

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: default avatarHuaxin Lu <luhuaxin1@huawei.com>
parent fb5d5e56
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -15,3 +15,4 @@ ima-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o
ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o
ima-$(CONFIG_IMA_DIGEST_LIST) += ima_digest_list.o
ima-$(CONFIG_CVM_GUEST) += ima_cvm.o
 No newline at end of file
+71 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2024. Huawei Technologies Co., Ltd. All rights reserved.
 */
#include <asm/cvm_smc.h>
#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 (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 cvm_config cfg = { 0 };
	struct 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 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];
	memcpy(cme.value, digests_arg[ima_hash_algo_idx].digest, cme.size);

	return tsi_measurement_extend(&cme) == TSI_SUCCESS ? 0 : -EFAULT;
}
+36 −0
Original line number Diff line number Diff line
/* 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_CVM_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
+19 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/err.h>

#include "ima.h"
#include "ima_cvm.h"

/* name for boot aggregate entry */
const char boot_aggregate_name[] = "boot_aggregate";
@@ -58,6 +59,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_CVM_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
@@ -124,7 +135,15 @@ int __init ima_init(void)
{
	int rc;

#ifdef CONFIG_CVM_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");

+11 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/rculist.h>
#include <linux/slab.h>
#include "ima.h"
#include "ima_cvm.h"

#define AUDIT_CAUSE_LEN_MAX 32

@@ -186,6 +187,16 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
	if (violation)		/* invalidate pcr */
		digests_arg = digests;

#ifdef CONFIG_CVM_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)",