diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/integrity/ima/ima.h | 1 | ||||
-rw-r--r-- | security/integrity/ima/ima_init.c | 4 | ||||
-rw-r--r-- | security/integrity/ima/ima_queue.c | 27 | ||||
-rw-r--r-- | security/keys/trusted.c | 41 |
4 files changed, 64 insertions, 9 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index cc12f3449a72..89d65cf8053d 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -153,6 +153,7 @@ int ima_measurements_show(struct seq_file *m, void *v); unsigned long ima_get_binary_runtime_size(void); int ima_init_template(void); void ima_init_template_list(void); +int __init ima_init_digests(void); /* * used to protect h_table and sha_table diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 6bb42a9c5e47..6c9295449751 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -123,8 +123,12 @@ int __init ima_init(void) 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; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 0e41dc1df1d4..6b6d044e0440 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -27,6 +27,9 @@ #define AUDIT_CAUSE_LEN_MAX 32 +/* pre-allocated array of tpm_digest structures to extend a PCR */ +static struct tpm_digest *digests; + LIST_HEAD(ima_measurements); /* list of all measurements */ #ifdef CONFIG_IMA_KEXEC static unsigned long binary_runtime_size; @@ -140,11 +143,15 @@ unsigned long ima_get_binary_runtime_size(void) static int ima_pcr_extend(const u8 *hash, int pcr) { int result = 0; + int i; if (!ima_tpm_chip) return result; - result = tpm_pcr_extend(ima_tpm_chip, pcr, hash); + for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) + memcpy(digests[i].digest, hash, TPM_DIGEST_SIZE); + + result = tpm_pcr_extend(ima_tpm_chip, pcr, digests); if (result != 0) pr_err("Error Communicating to TPM chip, result: %d\n", result); return result; @@ -211,3 +218,21 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry) mutex_unlock(&ima_extend_list_mutex); return result; } + +int __init ima_init_digests(void) +{ + int i; + + if (!ima_tpm_chip) + return 0; + + digests = kcalloc(ima_tpm_chip->nr_allocated_banks, sizeof(*digests), + GFP_NOFS); + if (!digests) + return -ENOMEM; + + for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) + digests[i].alg_id = ima_tpm_chip->allocated_banks[i].alg_id; + + return 0; +} diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 5b852263eae1..bcc9c6ead7fd 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -35,6 +35,7 @@ static const char hmac_alg[] = "hmac(sha1)"; static const char hash_alg[] = "sha1"; static struct tpm_chip *chip; +static struct tpm_digest *digests; struct sdesc { struct shash_desc shash; @@ -380,15 +381,10 @@ EXPORT_SYMBOL_GPL(trusted_tpm_send); */ static int pcrlock(const int pcrnum) { - unsigned char hash[SHA1_DIGEST_SIZE]; - int ret; - if (!capable(CAP_SYS_ADMIN)) return -EPERM; - ret = tpm_get_random(chip, hash, SHA1_DIGEST_SIZE); - if (ret != SHA1_DIGEST_SIZE) - return ret; - return tpm_pcr_extend(chip, pcrnum, hash) ? -EINVAL : 0; + + return tpm_pcr_extend(chip, pcrnum, digests) ? -EINVAL : 0; } /* @@ -1222,6 +1218,29 @@ hashalg_fail: return ret; } +static int __init init_digests(void) +{ + u8 digest[TPM_MAX_DIGEST_SIZE]; + int ret; + int i; + + ret = tpm_get_random(chip, digest, TPM_MAX_DIGEST_SIZE); + if (ret < 0) + return ret; + if (ret < TPM_MAX_DIGEST_SIZE) + return -EFAULT; + + digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests), + GFP_KERNEL); + if (!digests) + return -ENOMEM; + + for (i = 0; i < chip->nr_allocated_banks; i++) + memcpy(digests[i].digest, digest, TPM_MAX_DIGEST_SIZE); + + return 0; +} + static int __init init_trusted(void) { int ret; @@ -1229,15 +1248,20 @@ static int __init init_trusted(void) chip = tpm_default_chip(); if (!chip) return -ENOENT; - ret = trusted_shash_alloc(); + ret = init_digests(); if (ret < 0) goto err_put; + ret = trusted_shash_alloc(); + if (ret < 0) + goto err_free; ret = register_key_type(&key_type_trusted); if (ret < 0) goto err_release; return 0; err_release: trusted_shash_release(); +err_free: + kfree(digests); err_put: put_device(&chip->dev); return ret; @@ -1246,6 +1270,7 @@ err_put: static void __exit cleanup_trusted(void) { put_device(&chip->dev); + kfree(digests); trusted_shash_release(); unregister_key_type(&key_type_trusted); } |