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 "ima.h" 24 25 static struct crypto_shash *ima_shash_tfm; 26 27 int ima_init_crypto(void) 28 { 29 long rc; 30 31 ima_shash_tfm = crypto_alloc_shash(ima_hash, 0, 0); 32 if (IS_ERR(ima_shash_tfm)) { 33 rc = PTR_ERR(ima_shash_tfm); 34 pr_err("Can not allocate %s (reason: %ld)\n", ima_hash, rc); 35 return rc; 36 } 37 return 0; 38 } 39 40 /* 41 * Calculate the MD5/SHA1 file digest 42 */ 43 int ima_calc_file_hash(struct file *file, char *digest) 44 { 45 loff_t i_size, offset = 0; 46 char *rbuf; 47 int rc, read = 0; 48 struct { 49 struct shash_desc shash; 50 char ctx[crypto_shash_descsize(ima_shash_tfm)]; 51 } desc; 52 53 desc.shash.tfm = ima_shash_tfm; 54 desc.shash.flags = 0; 55 56 rc = crypto_shash_init(&desc.shash); 57 if (rc != 0) 58 return rc; 59 60 rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); 61 if (!rbuf) { 62 rc = -ENOMEM; 63 goto out; 64 } 65 if (!(file->f_mode & FMODE_READ)) { 66 file->f_mode |= FMODE_READ; 67 read = 1; 68 } 69 i_size = i_size_read(file_inode(file)); 70 while (offset < i_size) { 71 int rbuf_len; 72 73 rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE); 74 if (rbuf_len < 0) { 75 rc = rbuf_len; 76 break; 77 } 78 if (rbuf_len == 0) 79 break; 80 offset += rbuf_len; 81 82 rc = crypto_shash_update(&desc.shash, rbuf, rbuf_len); 83 if (rc) 84 break; 85 } 86 kfree(rbuf); 87 if (!rc) 88 rc = crypto_shash_final(&desc.shash, digest); 89 if (read) 90 file->f_mode &= ~FMODE_READ; 91 out: 92 return rc; 93 } 94 95 /* 96 * Calculate the hash of a given buffer 97 */ 98 int ima_calc_buffer_hash(const void *data, int len, char *digest) 99 { 100 struct { 101 struct shash_desc shash; 102 char ctx[crypto_shash_descsize(ima_shash_tfm)]; 103 } desc; 104 105 desc.shash.tfm = ima_shash_tfm; 106 desc.shash.flags = 0; 107 108 return crypto_shash_digest(&desc.shash, data, len, digest); 109 } 110 111 static void __init ima_pcrread(int idx, u8 *pcr) 112 { 113 if (!ima_used_chip) 114 return; 115 116 if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) 117 pr_err("IMA: Error Communicating to TPM chip\n"); 118 } 119 120 /* 121 * Calculate the boot aggregate hash 122 */ 123 int __init ima_calc_boot_aggregate(char *digest) 124 { 125 u8 pcr_i[IMA_DIGEST_SIZE]; 126 int rc, i; 127 struct { 128 struct shash_desc shash; 129 char ctx[crypto_shash_descsize(ima_shash_tfm)]; 130 } desc; 131 132 desc.shash.tfm = ima_shash_tfm; 133 desc.shash.flags = 0; 134 135 rc = crypto_shash_init(&desc.shash); 136 if (rc != 0) 137 return rc; 138 139 /* cumulative sha1 over tpm registers 0-7 */ 140 for (i = TPM_PCR0; i < TPM_PCR8; i++) { 141 ima_pcrread(i, pcr_i); 142 /* now accumulate with current aggregate */ 143 rc = crypto_shash_update(&desc.shash, pcr_i, IMA_DIGEST_SIZE); 144 } 145 if (!rc) 146 crypto_shash_final(&desc.shash, digest); 147 return rc; 148 } 149