aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_crypto.c
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2009-02-04 09:06:58 -0500
committerJames Morris <jmorris@namei.org>2009-02-05 17:05:30 -0500
commit3323eec921efd815178a23107ab63588c605c0b2 (patch)
treebc9e9714ac4881ebc515c1bd155674c52c356d6a /security/integrity/ima/ima_crypto.c
parent6146f0d5e47ca4047ffded0fb79b6c25359b386c (diff)
integrity: IMA as an integrity service provider
IMA provides hardware (TPM) based measurement and attestation for file measurements. As the Trusted Computing (TPM) model requires, IMA measures all files before they are accessed in any way (on the integrity_bprm_check, integrity_path_check and integrity_file_mmap hooks), and commits the measurements to the TPM. Once added to the TPM, measurements can not be removed. In addition, IMA maintains a list of these file measurements, which can be used to validate the aggregate value stored in the TPM. The TPM can sign these measurements, and thus the system can prove, to itself and to a third party, the system's integrity in a way that cannot be circumvented by malicious or compromised software. - alloc ima_template_entry before calling ima_store_template() - log ima_add_boot_aggregate() failure - removed unused IMA_TEMPLATE_NAME_LEN - replaced hard coded string length with #define name Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/integrity/ima/ima_crypto.c')
-rw-r--r--security/integrity/ima/ima_crypto.c140
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 00000000000..c2a46e40999
--- /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
23static 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 */
44int 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_set_buf(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);
80out:
81 crypto_free_hash(desc.tfm);
82 return rc;
83}
84
85/*
86 * Calculate the hash of a given template
87 */
88int 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_set_buf(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
106static 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 */
118int 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}