diff options
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 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 | |||
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_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); | ||
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_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 | |||
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 | } | ||