Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | // SPDX-License-Identifier: GPL-2.0-only /* * 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> * * File: ima_init.c * initialization and cleanup functions */ #include <linux/init.h> #include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/err.h> #include <linux/ima.h> #include <generated/utsrelease.h> #include "ima.h" /* name for boot aggregate entry */ 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 hash 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 = iint, .filename = boot_aggregate_name }; struct ima_max_digest_data hash; int result = -ENOMEM; int violation = 0; memset(iint, 0, sizeof(*iint)); memset(&hash, 0, sizeof(hash)); iint->ima_hash = &hash.hdr; iint->ima_hash->algo = ima_hash_algo; iint->ima_hash->length = hash_digest_size[ima_hash_algo]; /* * With TPM 2.0 hash agility, TPM chips could support multiple TPM * PCR banks, allowing firmware to configure and enable different * banks. The SHA1 bank is not necessarily enabled. * * Use the same hash algorithm for reading the TPM PCRs as for * calculating the boot aggregate digest. Preference is given to * the configured IMA default hash algorithm. Otherwise, use the * TCG required banks - SHA256 for TPM 2.0, SHA1 for TPM 1.2. * Ultimately select SHA1 also for TPM 2.0 if the SHA256 PCR bank * is not found. */ 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, NULL); 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); /* load also EVM key to avoid appraisal */ evm_load_x509(); 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(); rc = ima_fs_init(); if (rc != 0) return rc; ima_init_key_queue(); ima_measure_critical_data("kernel_info", "kernel_version", UTS_RELEASE, strlen(UTS_RELEASE), false, NULL, 0); return rc; } |