aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/ima_crypto.c187
1 files changed, 183 insertions, 4 deletions
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index ccd0ac8fa9a0..b9e5120559d4 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -16,6 +16,8 @@
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17 17
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/moduleparam.h>
20#include <linux/ratelimit.h>
19#include <linux/file.h> 21#include <linux/file.h>
20#include <linux/crypto.h> 22#include <linux/crypto.h>
21#include <linux/scatterlist.h> 23#include <linux/scatterlist.h>
@@ -25,7 +27,18 @@
25#include <crypto/hash_info.h> 27#include <crypto/hash_info.h>
26#include "ima.h" 28#include "ima.h"
27 29
30struct ahash_completion {
31 struct completion completion;
32 int err;
33};
34
35/* minimum file size for ahash use */
36static unsigned long ima_ahash_minsize;
37module_param_named(ahash_minsize, ima_ahash_minsize, ulong, 0644);
38MODULE_PARM_DESC(ahash_minsize, "Minimum file size for ahash use");
39
28static struct crypto_shash *ima_shash_tfm; 40static struct crypto_shash *ima_shash_tfm;
41static struct crypto_ahash *ima_ahash_tfm;
29 42
30/** 43/**
31 * ima_kernel_read - read file content 44 * ima_kernel_read - read file content
@@ -93,9 +106,146 @@ static void ima_free_tfm(struct crypto_shash *tfm)
93 crypto_free_shash(tfm); 106 crypto_free_shash(tfm);
94} 107}
95 108
96/* 109static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo)
97 * Calculate the MD5/SHA1 file digest 110{
98 */ 111 struct crypto_ahash *tfm = ima_ahash_tfm;
112 int rc;
113
114 if ((algo != ima_hash_algo && algo < HASH_ALGO__LAST) || !tfm) {
115 tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0);
116 if (!IS_ERR(tfm)) {
117 if (algo == ima_hash_algo)
118 ima_ahash_tfm = tfm;
119 } else {
120 rc = PTR_ERR(tfm);
121 pr_err("Can not allocate %s (reason: %d)\n",
122 hash_algo_name[algo], rc);
123 }
124 }
125 return tfm;
126}
127
128static void ima_free_atfm(struct crypto_ahash *tfm)
129{
130 if (tfm != ima_ahash_tfm)
131 crypto_free_ahash(tfm);
132}
133
134static void ahash_complete(struct crypto_async_request *req, int err)
135{
136 struct ahash_completion *res = req->data;
137
138 if (err == -EINPROGRESS)
139 return;
140 res->err = err;
141 complete(&res->completion);
142}
143
144static int ahash_wait(int err, struct ahash_completion *res)
145{
146 switch (err) {
147 case 0:
148 break;
149 case -EINPROGRESS:
150 case -EBUSY:
151 wait_for_completion(&res->completion);
152 reinit_completion(&res->completion);
153 err = res->err;
154 /* fall through */
155 default:
156 pr_crit_ratelimited("ahash calculation failed: err: %d\n", err);
157 }
158
159 return err;
160}
161
162static int ima_calc_file_hash_atfm(struct file *file,
163 struct ima_digest_data *hash,
164 struct crypto_ahash *tfm)
165{
166 loff_t i_size, offset;
167 char *rbuf;
168 int rc, read = 0, rbuf_len;
169 struct ahash_request *req;
170 struct scatterlist sg[1];
171 struct ahash_completion res;
172
173 hash->length = crypto_ahash_digestsize(tfm);
174
175 req = ahash_request_alloc(tfm, GFP_KERNEL);
176 if (!req)
177 return -ENOMEM;
178
179 init_completion(&res.completion);
180 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
181 CRYPTO_TFM_REQ_MAY_SLEEP,
182 ahash_complete, &res);
183
184 rc = ahash_wait(crypto_ahash_init(req), &res);
185 if (rc)
186 goto out1;
187
188 i_size = i_size_read(file_inode(file));
189
190 if (i_size == 0)
191 goto out2;
192
193 rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
194 if (!rbuf) {
195 rc = -ENOMEM;
196 goto out1;
197 }
198
199 if (!(file->f_mode & FMODE_READ)) {
200 file->f_mode |= FMODE_READ;
201 read = 1;
202 }
203
204 for (offset = 0; offset < i_size; offset += rbuf_len) {
205 rbuf_len = ima_kernel_read(file, offset, rbuf, PAGE_SIZE);
206 if (rbuf_len < 0) {
207 rc = rbuf_len;
208 break;
209 }
210 if (rbuf_len == 0)
211 break;
212
213 sg_init_one(&sg[0], rbuf, rbuf_len);
214 ahash_request_set_crypt(req, sg, NULL, rbuf_len);
215
216 rc = ahash_wait(crypto_ahash_update(req), &res);
217 if (rc)
218 break;
219 }
220 if (read)
221 file->f_mode &= ~FMODE_READ;
222 kfree(rbuf);
223out2:
224 if (!rc) {
225 ahash_request_set_crypt(req, NULL, hash->digest, 0);
226 rc = ahash_wait(crypto_ahash_final(req), &res);
227 }
228out1:
229 ahash_request_free(req);
230 return rc;
231}
232
233static int ima_calc_file_ahash(struct file *file, struct ima_digest_data *hash)
234{
235 struct crypto_ahash *tfm;
236 int rc;
237
238 tfm = ima_alloc_atfm(hash->algo);
239 if (IS_ERR(tfm))
240 return PTR_ERR(tfm);
241
242 rc = ima_calc_file_hash_atfm(file, hash, tfm);
243
244 ima_free_atfm(tfm);
245
246 return rc;
247}
248
99static int ima_calc_file_hash_tfm(struct file *file, 249static int ima_calc_file_hash_tfm(struct file *file,
100 struct ima_digest_data *hash, 250 struct ima_digest_data *hash,
101 struct crypto_shash *tfm) 251 struct crypto_shash *tfm)
@@ -156,7 +306,7 @@ out:
156 return rc; 306 return rc;
157} 307}
158 308
159int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) 309static int ima_calc_file_shash(struct file *file, struct ima_digest_data *hash)
160{ 310{
161 struct crypto_shash *tfm; 311 struct crypto_shash *tfm;
162 int rc; 312 int rc;
@@ -173,6 +323,35 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
173} 323}
174 324
175/* 325/*
326 * ima_calc_file_hash - calculate file hash
327 *
328 * Asynchronous hash (ahash) allows using HW acceleration for calculating
329 * a hash. ahash performance varies for different data sizes on different
330 * crypto accelerators. shash performance might be better for smaller files.
331 * The 'ima.ahash_minsize' module parameter allows specifying the best
332 * minimum file size for using ahash on the system.
333 *
334 * If the ima.ahash_minsize parameter is not specified, this function uses
335 * shash for the hash calculation. If ahash fails, it falls back to using
336 * shash.
337 */
338int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
339{
340 loff_t i_size;
341 int rc;
342
343 i_size = i_size_read(file_inode(file));
344
345 if (ima_ahash_minsize && i_size >= ima_ahash_minsize) {
346 rc = ima_calc_file_ahash(file, hash);
347 if (!rc)
348 return 0;
349 }
350
351 return ima_calc_file_shash(file, hash);
352}
353
354/*
176 * Calculate the hash of template data 355 * Calculate the hash of template data
177 */ 356 */
178static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, 357static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,