xref: /openbmc/linux/security/integrity/ima/ima_crypto.c (revision b8bb76713ec50df2f11efee386e16f93d51e1076)
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