Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/security/integrity/ima/ima_crypto.c
10820 views
1
/*
2
* Copyright (C) 2005,2006,2007,2008 IBM Corporation
3
*
4
* Authors:
5
* Mimi Zohar <[email protected]>
6
* Kylene Hall <[email protected]>
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 "ima.h"
23
24
static int init_desc(struct hash_desc *desc)
25
{
26
int rc;
27
28
desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
29
if (IS_ERR(desc->tfm)) {
30
pr_info("IMA: failed to load %s transform: %ld\n",
31
ima_hash, PTR_ERR(desc->tfm));
32
rc = PTR_ERR(desc->tfm);
33
return rc;
34
}
35
desc->flags = 0;
36
rc = crypto_hash_init(desc);
37
if (rc)
38
crypto_free_hash(desc->tfm);
39
return rc;
40
}
41
42
/*
43
* Calculate the MD5/SHA1 file digest
44
*/
45
int ima_calc_hash(struct file *file, char *digest)
46
{
47
struct hash_desc desc;
48
struct scatterlist sg[1];
49
loff_t i_size, offset = 0;
50
char *rbuf;
51
int rc;
52
53
rc = init_desc(&desc);
54
if (rc != 0)
55
return rc;
56
57
rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
58
if (!rbuf) {
59
rc = -ENOMEM;
60
goto out;
61
}
62
i_size = i_size_read(file->f_dentry->d_inode);
63
while (offset < i_size) {
64
int rbuf_len;
65
66
rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE);
67
if (rbuf_len < 0) {
68
rc = rbuf_len;
69
break;
70
}
71
if (rbuf_len == 0)
72
break;
73
offset += rbuf_len;
74
sg_init_one(sg, rbuf, rbuf_len);
75
76
rc = crypto_hash_update(&desc, sg, rbuf_len);
77
if (rc)
78
break;
79
}
80
kfree(rbuf);
81
if (!rc)
82
rc = crypto_hash_final(&desc, digest);
83
out:
84
crypto_free_hash(desc.tfm);
85
return rc;
86
}
87
88
/*
89
* Calculate the hash of a given template
90
*/
91
int ima_calc_template_hash(int template_len, void *template, char *digest)
92
{
93
struct hash_desc desc;
94
struct scatterlist sg[1];
95
int rc;
96
97
rc = init_desc(&desc);
98
if (rc != 0)
99
return rc;
100
101
sg_init_one(sg, template, template_len);
102
rc = crypto_hash_update(&desc, sg, template_len);
103
if (!rc)
104
rc = crypto_hash_final(&desc, digest);
105
crypto_free_hash(desc.tfm);
106
return rc;
107
}
108
109
static void __init ima_pcrread(int idx, u8 *pcr)
110
{
111
if (!ima_used_chip)
112
return;
113
114
if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
115
pr_err("IMA: Error Communicating to TPM chip\n");
116
}
117
118
/*
119
* Calculate the boot aggregate hash
120
*/
121
int __init ima_calc_boot_aggregate(char *digest)
122
{
123
struct hash_desc desc;
124
struct scatterlist sg;
125
u8 pcr_i[IMA_DIGEST_SIZE];
126
int rc, i;
127
128
rc = init_desc(&desc);
129
if (rc != 0)
130
return rc;
131
132
/* cumulative sha1 over tpm registers 0-7 */
133
for (i = TPM_PCR0; i < TPM_PCR8; i++) {
134
ima_pcrread(i, pcr_i);
135
/* now accumulate with current aggregate */
136
sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE);
137
rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE);
138
}
139
if (!rc)
140
crypto_hash_final(&desc, digest);
141
crypto_free_hash(desc.tfm);
142
return rc;
143
}
144
145