~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/security/integrity/ima/ima_crypto.c

Version: ~ [ linux-5.12-rc1 ] ~ [ linux-5.11.2 ] ~ [ linux-5.10.19 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.101 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.177 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.222 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.258 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.258 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 }
288 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp