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_init_one(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_init_one(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 } 141