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, offset = 0; 49 char *rbuf; 50 int rc; 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 if (rbuf_len == 0) 71 break; 72 offset += rbuf_len; 73 sg_init_one(sg, rbuf, rbuf_len); 74 75 rc = crypto_hash_update(&desc, sg, rbuf_len); 76 if (rc) 77 break; 78 } 79 kfree(rbuf); 80 if (!rc) 81 rc = crypto_hash_final(&desc, digest); 82 out: 83 crypto_free_hash(desc.tfm); 84 return rc; 85 } 86 87 /* 88 * Calculate the hash of a given template 89 */ 90 int ima_calc_template_hash(int template_len, void *template, char *digest) 91 { 92 struct hash_desc desc; 93 struct scatterlist sg[1]; 94 int rc; 95 96 rc = init_desc(&desc); 97 if (rc != 0) 98 return rc; 99 100 sg_init_one(sg, template, template_len); 101 rc = crypto_hash_update(&desc, sg, template_len); 102 if (!rc) 103 rc = crypto_hash_final(&desc, digest); 104 crypto_free_hash(desc.tfm); 105 return rc; 106 } 107 108 static void __init ima_pcrread(int idx, u8 *pcr) 109 { 110 if (!ima_used_chip) 111 return; 112 113 if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) 114 pr_err("Error Communicating to TPM chip\n"); 115 } 116 117 /* 118 * Calculate the boot aggregate hash 119 */ 120 int __init ima_calc_boot_aggregate(char *digest) 121 { 122 struct hash_desc desc; 123 struct scatterlist sg; 124 u8 pcr_i[IMA_DIGEST_SIZE]; 125 int rc, i; 126 127 rc = init_desc(&desc); 128 if (rc != 0) 129 return rc; 130 131 /* cumulative sha1 over tpm registers 0-7 */ 132 for (i = TPM_PCR0; i < TPM_PCR8; i++) { 133 ima_pcrread(i, pcr_i); 134 /* now accumulate with current aggregate */ 135 sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE); 136 rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE); 137 } 138 if (!rc) 139 crypto_hash_final(&desc, digest); 140 crypto_free_hash(desc.tfm); 141 return rc; 142 } 143