ima: introduce ima_kernel_read()
[profile/ivi/kernel-x86-ivi.git] / security / integrity / ima / ima_crypto.c
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 <linux/slab.h>
22 #include <crypto/hash.h>
23 #include <crypto/hash_info.h>
24 #include "ima.h"
25
26 static struct crypto_shash *ima_shash_tfm;
27
28 /**
29  * ima_kernel_read - read file content
30  *
31  * This is a function for reading file content instead of kernel_read().
32  * It does not perform locking checks to ensure it cannot be blocked.
33  * It does not perform security checks because it is irrelevant for IMA.
34  *
35  */
36 static int ima_kernel_read(struct file *file, loff_t offset,
37                            char *addr, unsigned long count)
38 {
39         mm_segment_t old_fs;
40         char __user *buf = addr;
41         ssize_t ret;
42
43         if (!(file->f_mode & FMODE_READ))
44                 return -EBADF;
45         if (!file->f_op->read && !file->f_op->aio_read)
46                 return -EINVAL;
47
48         old_fs = get_fs();
49         set_fs(get_ds());
50         if (file->f_op->read)
51                 ret = file->f_op->read(file, buf, count, &offset);
52         else
53                 ret = do_sync_read(file, buf, count, &offset);
54         set_fs(old_fs);
55         return ret;
56 }
57
58 int ima_init_crypto(void)
59 {
60         long rc;
61
62         ima_shash_tfm = crypto_alloc_shash(hash_algo_name[ima_hash_algo], 0, 0);
63         if (IS_ERR(ima_shash_tfm)) {
64                 rc = PTR_ERR(ima_shash_tfm);
65                 pr_err("Can not allocate %s (reason: %ld)\n",
66                        hash_algo_name[ima_hash_algo], rc);
67                 return rc;
68         }
69         return 0;
70 }
71
72 static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo)
73 {
74         struct crypto_shash *tfm = ima_shash_tfm;
75         int rc;
76
77         if (algo != ima_hash_algo && algo < HASH_ALGO__LAST) {
78                 tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0);
79                 if (IS_ERR(tfm)) {
80                         rc = PTR_ERR(tfm);
81                         pr_err("Can not allocate %s (reason: %d)\n",
82                                hash_algo_name[algo], rc);
83                 }
84         }
85         return tfm;
86 }
87
88 static void ima_free_tfm(struct crypto_shash *tfm)
89 {
90         if (tfm != ima_shash_tfm)
91                 crypto_free_shash(tfm);
92 }
93
94 /*
95  * Calculate the MD5/SHA1 file digest
96  */
97 static int ima_calc_file_hash_tfm(struct file *file,
98                                   struct ima_digest_data *hash,
99                                   struct crypto_shash *tfm)
100 {
101         loff_t i_size, offset = 0;
102         char *rbuf;
103         int rc, read = 0;
104         struct {
105                 struct shash_desc shash;
106                 char ctx[crypto_shash_descsize(tfm)];
107         } desc;
108
109         desc.shash.tfm = tfm;
110         desc.shash.flags = 0;
111
112         hash->length = crypto_shash_digestsize(tfm);
113
114         rc = crypto_shash_init(&desc.shash);
115         if (rc != 0)
116                 return rc;
117
118         rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
119         if (!rbuf) {
120                 rc = -ENOMEM;
121                 goto out;
122         }
123         if (!(file->f_mode & FMODE_READ)) {
124                 file->f_mode |= FMODE_READ;
125                 read = 1;
126         }
127         i_size = i_size_read(file_inode(file));
128         while (offset < i_size) {
129                 int rbuf_len;
130
131                 rbuf_len = ima_kernel_read(file, offset, rbuf, PAGE_SIZE);
132                 if (rbuf_len < 0) {
133                         rc = rbuf_len;
134                         break;
135                 }
136                 if (rbuf_len == 0)
137                         break;
138                 offset += rbuf_len;
139
140                 rc = crypto_shash_update(&desc.shash, rbuf, rbuf_len);
141                 if (rc)
142                         break;
143         }
144         kfree(rbuf);
145         if (!rc)
146                 rc = crypto_shash_final(&desc.shash, hash->digest);
147         if (read)
148                 file->f_mode &= ~FMODE_READ;
149 out:
150         return rc;
151 }
152
153 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
154 {
155         struct crypto_shash *tfm;
156         int rc;
157
158         tfm = ima_alloc_tfm(hash->algo);
159         if (IS_ERR(tfm))
160                 return PTR_ERR(tfm);
161
162         rc = ima_calc_file_hash_tfm(file, hash, tfm);
163
164         ima_free_tfm(tfm);
165
166         return rc;
167 }
168
169 /*
170  * Calculate the hash of template data
171  */
172 static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
173                                          struct ima_template_desc *td,
174                                          int num_fields,
175                                          struct ima_digest_data *hash,
176                                          struct crypto_shash *tfm)
177 {
178         struct {
179                 struct shash_desc shash;
180                 char ctx[crypto_shash_descsize(tfm)];
181         } desc;
182         int rc, i;
183
184         desc.shash.tfm = tfm;
185         desc.shash.flags = 0;
186
187         hash->length = crypto_shash_digestsize(tfm);
188
189         rc = crypto_shash_init(&desc.shash);
190         if (rc != 0)
191                 return rc;
192
193         for (i = 0; i < num_fields; i++) {
194                 if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
195                         rc = crypto_shash_update(&desc.shash,
196                                                 (const u8 *) &field_data[i].len,
197                                                 sizeof(field_data[i].len));
198                         if (rc)
199                                 break;
200                 }
201                 rc = crypto_shash_update(&desc.shash, field_data[i].data,
202                                          field_data[i].len);
203                 if (rc)
204                         break;
205         }
206
207         if (!rc)
208                 rc = crypto_shash_final(&desc.shash, hash->digest);
209
210         return rc;
211 }
212
213 int ima_calc_field_array_hash(struct ima_field_data *field_data,
214                               struct ima_template_desc *desc, int num_fields,
215                               struct ima_digest_data *hash)
216 {
217         struct crypto_shash *tfm;
218         int rc;
219
220         tfm = ima_alloc_tfm(hash->algo);
221         if (IS_ERR(tfm))
222                 return PTR_ERR(tfm);
223
224         rc = ima_calc_field_array_hash_tfm(field_data, desc, num_fields,
225                                            hash, tfm);
226
227         ima_free_tfm(tfm);
228
229         return rc;
230 }
231
232 static void __init ima_pcrread(int idx, u8 *pcr)
233 {
234         if (!ima_used_chip)
235                 return;
236
237         if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
238                 pr_err("IMA: Error Communicating to TPM chip\n");
239 }
240
241 /*
242  * Calculate the boot aggregate hash
243  */
244 static int __init ima_calc_boot_aggregate_tfm(char *digest,
245                                               struct crypto_shash *tfm)
246 {
247         u8 pcr_i[TPM_DIGEST_SIZE];
248         int rc, i;
249         struct {
250                 struct shash_desc shash;
251                 char ctx[crypto_shash_descsize(tfm)];
252         } desc;
253
254         desc.shash.tfm = tfm;
255         desc.shash.flags = 0;
256
257         rc = crypto_shash_init(&desc.shash);
258         if (rc != 0)
259                 return rc;
260
261         /* cumulative sha1 over tpm registers 0-7 */
262         for (i = TPM_PCR0; i < TPM_PCR8; i++) {
263                 ima_pcrread(i, pcr_i);
264                 /* now accumulate with current aggregate */
265                 rc = crypto_shash_update(&desc.shash, pcr_i, TPM_DIGEST_SIZE);
266         }
267         if (!rc)
268                 crypto_shash_final(&desc.shash, digest);
269         return rc;
270 }
271
272 int __init ima_calc_boot_aggregate(struct ima_digest_data *hash)
273 {
274         struct crypto_shash *tfm;
275         int rc;
276
277         tfm = ima_alloc_tfm(hash->algo);
278         if (IS_ERR(tfm))
279                 return PTR_ERR(tfm);
280
281         hash->length = crypto_shash_digestsize(tfm);
282         rc = ima_calc_boot_aggregate_tfm(hash->digest, tfm);
283
284         ima_free_tfm(tfm);
285
286         return rc;
287 }