forked from Minki/linux
0b6cf6b97b
Currently, tpm_pcr_extend() accepts as an input only a SHA1 digest. This patch replaces the hash parameter of tpm_pcr_extend() with an array of tpm_digest structures, so that the caller can provide a digest for each PCR bank currently allocated in the TPM. tpm_pcr_extend() will not extend banks for which no digest was provided, as it happened before this patch, but instead it requires that callers provide the full set of digests. Since the number of digests will always be chip->nr_allocated_banks, the count parameter has been removed. Due to the API change, ima_pcr_extend() and pcrlock() have been modified. Since the number of allocated banks is not known in advance, the memory for the digests must be dynamically allocated. To avoid performance degradation and to avoid that a PCR extend is not done due to lack of memory, the array of tpm_digest structures is allocated by the users of the TPM driver at initialization time. Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Mimi Zohar <zohar@linux.ibm.com> (on x86 for TPM 1.2 & PTT TPM 2.0) Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
140 lines
3.6 KiB
C
140 lines
3.6 KiB
C
/*
|
|
* Copyright (C) 2005,2006,2007,2008 IBM Corporation
|
|
*
|
|
* Authors:
|
|
* Reiner Sailer <sailer@watson.ibm.com>
|
|
* Leendert van Doorn <leendert@watson.ibm.com>
|
|
* Mimi Zohar <zohar@us.ibm.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation, version 2 of the
|
|
* License.
|
|
*
|
|
* File: ima_init.c
|
|
* initialization and cleanup functions
|
|
*/
|
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/err.h>
|
|
|
|
#include "ima.h"
|
|
|
|
/* name for boot aggregate entry */
|
|
static const char boot_aggregate_name[] = "boot_aggregate";
|
|
struct tpm_chip *ima_tpm_chip;
|
|
|
|
/* Add the boot aggregate to the IMA measurement list and extend
|
|
* the PCR register.
|
|
*
|
|
* Calculate the boot aggregate, a SHA1 over tpm registers 0-7,
|
|
* assuming a TPM chip exists, and zeroes if the TPM chip does not
|
|
* exist. Add the boot aggregate measurement to the measurement
|
|
* list and extend the PCR register.
|
|
*
|
|
* If a tpm chip does not exist, indicate the core root of trust is
|
|
* not hardware based by invalidating the aggregate PCR value.
|
|
* (The aggregate PCR value is invalidated by adding one value to
|
|
* the measurement list and extending the aggregate PCR value with
|
|
* a different value.) Violations add a zero entry to the measurement
|
|
* list and extend the aggregate PCR value with ff...ff's.
|
|
*/
|
|
static int __init ima_add_boot_aggregate(void)
|
|
{
|
|
static const char op[] = "add_boot_aggregate";
|
|
const char *audit_cause = "ENOMEM";
|
|
struct ima_template_entry *entry;
|
|
struct integrity_iint_cache tmp_iint, *iint = &tmp_iint;
|
|
struct ima_event_data event_data = {iint, NULL, boot_aggregate_name,
|
|
NULL, 0, NULL};
|
|
int result = -ENOMEM;
|
|
int violation = 0;
|
|
struct {
|
|
struct ima_digest_data hdr;
|
|
char digest[TPM_DIGEST_SIZE];
|
|
} hash;
|
|
|
|
memset(iint, 0, sizeof(*iint));
|
|
memset(&hash, 0, sizeof(hash));
|
|
iint->ima_hash = &hash.hdr;
|
|
iint->ima_hash->algo = HASH_ALGO_SHA1;
|
|
iint->ima_hash->length = SHA1_DIGEST_SIZE;
|
|
|
|
if (ima_tpm_chip) {
|
|
result = ima_calc_boot_aggregate(&hash.hdr);
|
|
if (result < 0) {
|
|
audit_cause = "hashing_error";
|
|
goto err_out;
|
|
}
|
|
}
|
|
|
|
result = ima_alloc_init_template(&event_data, &entry);
|
|
if (result < 0) {
|
|
audit_cause = "alloc_entry";
|
|
goto err_out;
|
|
}
|
|
|
|
result = ima_store_template(entry, violation, NULL,
|
|
boot_aggregate_name,
|
|
CONFIG_IMA_MEASURE_PCR_IDX);
|
|
if (result < 0) {
|
|
ima_free_template_entry(entry);
|
|
audit_cause = "store_entry";
|
|
goto err_out;
|
|
}
|
|
return 0;
|
|
err_out:
|
|
integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op,
|
|
audit_cause, result, 0);
|
|
return result;
|
|
}
|
|
|
|
#ifdef CONFIG_IMA_LOAD_X509
|
|
void __init ima_load_x509(void)
|
|
{
|
|
int unset_flags = ima_policy_flag & IMA_APPRAISE;
|
|
|
|
ima_policy_flag &= ~unset_flags;
|
|
integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
|
|
ima_policy_flag |= unset_flags;
|
|
}
|
|
#endif
|
|
|
|
int __init ima_init(void)
|
|
{
|
|
int rc;
|
|
|
|
ima_tpm_chip = tpm_default_chip();
|
|
if (!ima_tpm_chip)
|
|
pr_info("No TPM chip found, activating TPM-bypass!\n");
|
|
|
|
rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
|
|
if (rc)
|
|
return rc;
|
|
|
|
rc = ima_init_crypto();
|
|
if (rc)
|
|
return rc;
|
|
rc = ima_init_template();
|
|
if (rc != 0)
|
|
return rc;
|
|
|
|
/* It can be called before ima_init_digests(), it does not use TPM. */
|
|
ima_load_kexec_buffer();
|
|
|
|
rc = ima_init_digests();
|
|
if (rc != 0)
|
|
return rc;
|
|
rc = ima_add_boot_aggregate(); /* boot aggregate must be first entry */
|
|
if (rc != 0)
|
|
return rc;
|
|
|
|
ima_init_policy();
|
|
|
|
return ima_fs_init();
|
|
}
|