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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.