diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-04-05 19:41:22 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-04-05 19:41:22 -0400 |
| commit | 9efe21cb82b5dbe3b0b2ae4de4eccc64ecb94e95 (patch) | |
| tree | 7ff8833745d2f268f897f6fa4a27263b4a572245 /security/integrity/ima/ima_crypto.c | |
| parent | de18836e447c2dc30120c0919b8db8ddc0401cc4 (diff) | |
| parent | 0221c81b1b8eb0cbb6b30a0ced52ead32d2b4e4c (diff) | |
Merge branch 'linus' into irq/threaded
Conflicts:
include/linux/irq.h
kernel/irq/handle.c
Diffstat (limited to 'security/integrity/ima/ima_crypto.c')
| -rw-r--r-- | security/integrity/ima/ima_crypto.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c new file mode 100644 index 000000000000..50d572b74caf --- /dev/null +++ b/security/integrity/ima/ima_crypto.c | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005,2006,2007,2008 IBM Corporation | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Mimi Zohar <zohar@us.ibm.com> | ||
| 6 | * Kylene Hall <kjhall@us.ibm.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation, version 2 of the License. | ||
| 11 | * | ||
| 12 | * File: ima_crypto.c | ||
| 13 | * Calculates md5/sha1 file hash, template hash, boot-aggreate hash | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/file.h> | ||
| 18 | #include <linux/crypto.h> | ||
| 19 | #include <linux/scatterlist.h> | ||
| 20 | #include <linux/err.h> | ||
| 21 | #include "ima.h" | ||
| 22 | |||
| 23 | static int init_desc(struct hash_desc *desc) | ||
| 24 | { | ||
| 25 | int rc; | ||
| 26 | |||
| 27 | desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC); | ||
| 28 | if (IS_ERR(desc->tfm)) { | ||
| 29 | pr_info("failed to load %s transform: %ld\n", | ||
| 30 | ima_hash, PTR_ERR(desc->tfm)); | ||
| 31 | rc = PTR_ERR(desc->tfm); | ||
| 32 | return rc; | ||
| 33 | } | ||
| 34 | desc->flags = 0; | ||
| 35 | rc = crypto_hash_init(desc); | ||
| 36 | if (rc) | ||
| 37 | crypto_free_hash(desc->tfm); | ||
| 38 | return rc; | ||
| 39 | } | ||
| 40 | |||
| 41 | /* | ||
| 42 | * Calculate the MD5/SHA1 file digest | ||
| 43 | */ | ||
| 44 | int ima_calc_hash(struct file *file, char *digest) | ||
| 45 | { | ||
| 46 | struct hash_desc desc; | ||
| 47 | struct scatterlist sg[1]; | ||
| 48 | loff_t i_size; | ||
| 49 | char *rbuf; | ||
| 50 | int rc, offset = 0; | ||
| 51 | |||
| 52 | rc = init_desc(&desc); | ||
| 53 | if (rc != 0) | ||
| 54 | return rc; | ||
| 55 | |||
| 56 | rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 57 | if (!rbuf) { | ||
| 58 | rc = -ENOMEM; | ||
| 59 | goto out; | ||
| 60 | } | ||
| 61 | i_size = i_size_read(file->f_dentry->d_inode); | ||
| 62 | while (offset < i_size) { | ||
| 63 | int rbuf_len; | ||
| 64 | |||
| 65 | rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE); | ||
| 66 | if (rbuf_len < 0) { | ||
| 67 | rc = rbuf_len; | ||
| 68 | break; | ||
| 69 | } | ||
| 70 | offset += rbuf_len; | ||
| 71 | sg_init_one(sg, rbuf, rbuf_len); | ||
| 72 | |||
| 73 | rc = crypto_hash_update(&desc, sg, rbuf_len); | ||
| 74 | if (rc) | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | kfree(rbuf); | ||
| 78 | if (!rc) | ||
| 79 | rc = crypto_hash_final(&desc, digest); | ||
| 80 | out: | ||
| 81 | crypto_free_hash(desc.tfm); | ||
| 82 | return rc; | ||
| 83 | } | ||
| 84 | |||
| 85 | /* | ||
| 86 | * Calculate the hash of a given template | ||
| 87 | */ | ||
| 88 | int ima_calc_template_hash(int template_len, void *template, char *digest) | ||
| 89 | { | ||
| 90 | struct hash_desc desc; | ||
| 91 | struct scatterlist sg[1]; | ||
| 92 | int rc; | ||
| 93 | |||
| 94 | rc = init_desc(&desc); | ||
| 95 | if (rc != 0) | ||
| 96 | return rc; | ||
| 97 | |||
| 98 | sg_init_one(sg, template, template_len); | ||
| 99 | rc = crypto_hash_update(&desc, sg, template_len); | ||
| 100 | if (!rc) | ||
| 101 | rc = crypto_hash_final(&desc, digest); | ||
| 102 | crypto_free_hash(desc.tfm); | ||
| 103 | return rc; | ||
| 104 | } | ||
| 105 | |||
| 106 | static void ima_pcrread(int idx, u8 *pcr) | ||
| 107 | { | ||
| 108 | if (!ima_used_chip) | ||
| 109 | return; | ||
| 110 | |||
| 111 | if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) | ||
| 112 | pr_err("Error Communicating to TPM chip\n"); | ||
| 113 | } | ||
| 114 | |||
| 115 | /* | ||
| 116 | * Calculate the boot aggregate hash | ||
| 117 | */ | ||
| 118 | int ima_calc_boot_aggregate(char *digest) | ||
| 119 | { | ||
| 120 | struct hash_desc desc; | ||
| 121 | struct scatterlist sg; | ||
| 122 | u8 pcr_i[IMA_DIGEST_SIZE]; | ||
| 123 | int rc, i; | ||
| 124 | |||
| 125 | rc = init_desc(&desc); | ||
| 126 | if (rc != 0) | ||
| 127 | return rc; | ||
| 128 | |||
| 129 | /* cumulative sha1 over tpm registers 0-7 */ | ||
| 130 | for (i = TPM_PCR0; i < TPM_PCR8; i++) { | ||
| 131 | ima_pcrread(i, pcr_i); | ||
| 132 | /* now accumulate with current aggregate */ | ||
| 133 | sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE); | ||
| 134 | rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE); | ||
| 135 | } | ||
| 136 | if (!rc) | ||
| 137 | crypto_hash_final(&desc, digest); | ||
| 138 | crypto_free_hash(desc.tfm); | ||
| 139 | return rc; | ||
| 140 | } | ||
