Commit 24ac42fb authored by GONG Ruiqi's avatar GONG Ruiqi
Browse files

ima: rot: Adapt VirtCCA into Rot

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IB4I9O



--------------------------------

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: default avatarLu Huaxin <luhuaxin1@huawei.com>
Signed-off-by: default avatarLu Huaxin <luhuaxin1@huawei.com>
Signed-off-by: default avatarGONG Ruiqi <gongruiqi1@huawei.com>
parent 7c8da9dc
Loading
Loading
Loading
Loading
+0 −19
Original line number Diff line number Diff line
@@ -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");

+4 −16
Original line number Diff line number Diff line
@@ -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,17 +174,7 @@ 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 (rotresult != 0) {
		snprintf(rot_audit_cause, AUDIT_CAUSE_LEN_MAX, "TSI_error(%d)",
			 rotresult);
		audit_cause = rot_audit_cause;
		audit_info = 0;
	}
#endif

	if (ima_rot_inst) {
	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)",
@@ -193,7 +182,6 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
		audit_cause = rot_audit_cause;
		audit_info = 0;
	}
	}
out:
	mutex_unlock(&ima_extend_list_mutex);
	integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
+9 −0
Original line number Diff line number Diff line
@@ -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)
+49 −31
Original line number Diff line number Diff line
@@ -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;
	}

int __init ima_virtcca_init(void)
{
	int rc = -ENODEV;
	/* 0: SHA256, 1: SHA512 */
	virtcca_algo = cfg.algorithm ? HASH_ALGO_SHA512 : HASH_ALGO_SHA256;

	if (is_virtcca_cvm_world() && tsi_get_version() != SMCCC_RET_NOT_SUPPORTED) {
		ima_tsi_cvm = true;
		rc = 0;
	return 0;
}

int ima_virtcca_init(struct ima_rot *rot)
{
	int rc;

	if (!is_virtcca_cvm_world() || tsi_get_version() == SMCCC_RET_NOT_SUPPORTED)
		return -ENODEV;

	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 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);

+2 −25
Original line number Diff line number Diff line
@@ -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