xref: /linux/security/integrity/ima/ima_template_lib.c (revision c4ee0af3fa0dc65f690fc908f02b8355f9576ea0)
1 /*
2  * Copyright (C) 2013 Politecnico di Torino, Italy
3  *                    TORSEC group -- http://security.polito.it
4  *
5  * Author: Roberto Sassu <roberto.sassu@polito.it>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation, version 2 of the
10  * License.
11  *
12  * File: ima_template_lib.c
13  *      Library of supported template fields.
14  */
15 #include <crypto/hash_info.h>
16 
17 #include "ima_template_lib.h"
18 
19 static bool ima_template_hash_algo_allowed(u8 algo)
20 {
21 	if (algo == HASH_ALGO_SHA1 || algo == HASH_ALGO_MD5)
22 		return true;
23 
24 	return false;
25 }
26 
27 enum data_formats {
28 	DATA_FMT_DIGEST = 0,
29 	DATA_FMT_DIGEST_WITH_ALGO,
30 	DATA_FMT_EVENT_NAME,
31 	DATA_FMT_STRING,
32 	DATA_FMT_HEX
33 };
34 
35 static int ima_write_template_field_data(const void *data, const u32 datalen,
36 					 enum data_formats datafmt,
37 					 struct ima_field_data *field_data)
38 {
39 	u8 *buf, *buf_ptr;
40 	u32 buflen;
41 
42 	switch (datafmt) {
43 	case DATA_FMT_EVENT_NAME:
44 		buflen = IMA_EVENT_NAME_LEN_MAX + 1;
45 		break;
46 	case DATA_FMT_STRING:
47 		buflen = datalen + 1;
48 		break;
49 	default:
50 		buflen = datalen;
51 	}
52 
53 	buf = kzalloc(buflen, GFP_KERNEL);
54 	if (!buf)
55 		return -ENOMEM;
56 
57 	memcpy(buf, data, datalen);
58 
59 	/*
60 	 * Replace all space characters with underscore for event names and
61 	 * strings. This avoid that, during the parsing of a measurements list,
62 	 * filenames with spaces or that end with the suffix ' (deleted)' are
63 	 * split into multiple template fields (the space is the delimitator
64 	 * character for measurements lists in ASCII format).
65 	 */
66 	if (datafmt == DATA_FMT_EVENT_NAME || datafmt == DATA_FMT_STRING) {
67 		for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++)
68 			if (*buf_ptr == ' ')
69 				*buf_ptr = '_';
70 	}
71 
72 	field_data->data = buf;
73 	field_data->len = buflen;
74 	return 0;
75 }
76 
77 static void ima_show_template_data_ascii(struct seq_file *m,
78 					 enum ima_show_type show,
79 					 enum data_formats datafmt,
80 					 struct ima_field_data *field_data)
81 {
82 	u8 *buf_ptr = field_data->data, buflen = field_data->len;
83 
84 	switch (datafmt) {
85 	case DATA_FMT_DIGEST_WITH_ALGO:
86 		buf_ptr = strnchr(field_data->data, buflen, ':');
87 		if (buf_ptr != field_data->data)
88 			seq_printf(m, "%s", field_data->data);
89 
90 		/* skip ':' and '\0' */
91 		buf_ptr += 2;
92 		buflen -= buf_ptr - field_data->data;
93 	case DATA_FMT_DIGEST:
94 	case DATA_FMT_HEX:
95 		if (!buflen)
96 			break;
97 		ima_print_digest(m, buf_ptr, buflen);
98 		break;
99 	case DATA_FMT_STRING:
100 		seq_printf(m, "%s", buf_ptr);
101 		break;
102 	default:
103 		break;
104 	}
105 }
106 
107 static void ima_show_template_data_binary(struct seq_file *m,
108 					  enum ima_show_type show,
109 					  enum data_formats datafmt,
110 					  struct ima_field_data *field_data)
111 {
112 	if (show != IMA_SHOW_BINARY_NO_FIELD_LEN)
113 		ima_putc(m, &field_data->len, sizeof(u32));
114 
115 	if (!field_data->len)
116 		return;
117 
118 	ima_putc(m, field_data->data, field_data->len);
119 }
120 
121 static void ima_show_template_field_data(struct seq_file *m,
122 					 enum ima_show_type show,
123 					 enum data_formats datafmt,
124 					 struct ima_field_data *field_data)
125 {
126 	switch (show) {
127 	case IMA_SHOW_ASCII:
128 		ima_show_template_data_ascii(m, show, datafmt, field_data);
129 		break;
130 	case IMA_SHOW_BINARY:
131 	case IMA_SHOW_BINARY_NO_FIELD_LEN:
132 		ima_show_template_data_binary(m, show, datafmt, field_data);
133 		break;
134 	default:
135 		break;
136 	}
137 }
138 
139 void ima_show_template_digest(struct seq_file *m, enum ima_show_type show,
140 			      struct ima_field_data *field_data)
141 {
142 	ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data);
143 }
144 
145 void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
146 				 struct ima_field_data *field_data)
147 {
148 	ima_show_template_field_data(m, show, DATA_FMT_DIGEST_WITH_ALGO,
149 				     field_data);
150 }
151 
152 void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
153 			      struct ima_field_data *field_data)
154 {
155 	ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data);
156 }
157 
158 void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
159 			   struct ima_field_data *field_data)
160 {
161 	ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data);
162 }
163 
164 static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo,
165 				       struct ima_field_data *field_data,
166 				       bool size_limit)
167 {
168 	/*
169 	 * digest formats:
170 	 *  - DATA_FMT_DIGEST: digest
171 	 *  - DATA_FMT_DIGEST_WITH_ALGO: [<hash algo>] + ':' + '\0' + digest,
172 	 *    where <hash algo> is provided if the hash algoritm is not
173 	 *    SHA1 or MD5
174 	 */
175 	u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 };
176 	enum data_formats fmt = DATA_FMT_DIGEST;
177 	u32 offset = 0;
178 
179 	if (!size_limit) {
180 		fmt = DATA_FMT_DIGEST_WITH_ALGO;
181 		if (hash_algo < HASH_ALGO__LAST)
182 			offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1,
183 					   "%s", hash_algo_name[hash_algo]);
184 		buffer[offset] = ':';
185 		offset += 2;
186 	}
187 
188 	if (digest)
189 		memcpy(buffer + offset, digest, digestsize);
190 	else
191 		/*
192 		 * If digest is NULL, the event being recorded is a violation.
193 		 * Make room for the digest by increasing the offset of
194 		 * IMA_DIGEST_SIZE.
195 		 */
196 		offset += IMA_DIGEST_SIZE;
197 
198 	return ima_write_template_field_data(buffer, offset + digestsize,
199 					     fmt, field_data);
200 }
201 
202 /*
203  * This function writes the digest of an event (with size limit).
204  */
205 int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
206 			 const unsigned char *filename,
207 			 struct evm_ima_xattr_data *xattr_value, int xattr_len,
208 			 struct ima_field_data *field_data)
209 {
210 	struct {
211 		struct ima_digest_data hdr;
212 		char digest[IMA_MAX_DIGEST_SIZE];
213 	} hash;
214 	u8 *cur_digest = NULL;
215 	u32 cur_digestsize = 0;
216 	struct inode *inode;
217 	int result;
218 
219 	memset(&hash, 0, sizeof(hash));
220 
221 	if (!iint)		/* recording a violation. */
222 		goto out;
223 
224 	if (ima_template_hash_algo_allowed(iint->ima_hash->algo)) {
225 		cur_digest = iint->ima_hash->digest;
226 		cur_digestsize = iint->ima_hash->length;
227 		goto out;
228 	}
229 
230 	if (!file)		/* missing info to re-calculate the digest */
231 		return -EINVAL;
232 
233 	inode = file_inode(file);
234 	hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
235 	    ima_hash_algo : HASH_ALGO_SHA1;
236 	result = ima_calc_file_hash(file, &hash.hdr);
237 	if (result) {
238 		integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
239 				    filename, "collect_data",
240 				    "failed", result, 0);
241 		return result;
242 	}
243 	cur_digest = hash.hdr.digest;
244 	cur_digestsize = hash.hdr.length;
245 out:
246 	return ima_eventdigest_init_common(cur_digest, cur_digestsize, -1,
247 					   field_data, true);
248 }
249 
250 /*
251  * This function writes the digest of an event (without size limit).
252  */
253 int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
254 			    struct file *file, const unsigned char *filename,
255 			    struct evm_ima_xattr_data *xattr_value,
256 			    int xattr_len, struct ima_field_data *field_data)
257 {
258 	u8 *cur_digest = NULL, hash_algo = HASH_ALGO__LAST;
259 	u32 cur_digestsize = 0;
260 
261 	/* If iint is NULL, we are recording a violation. */
262 	if (!iint)
263 		goto out;
264 
265 	cur_digest = iint->ima_hash->digest;
266 	cur_digestsize = iint->ima_hash->length;
267 
268 	hash_algo = iint->ima_hash->algo;
269 out:
270 	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
271 					   hash_algo, field_data, false);
272 }
273 
274 static int ima_eventname_init_common(struct integrity_iint_cache *iint,
275 				     struct file *file,
276 				     const unsigned char *filename,
277 				     struct ima_field_data *field_data,
278 				     bool size_limit)
279 {
280 	const char *cur_filename = NULL;
281 	u32 cur_filename_len = 0;
282 	enum data_formats fmt = size_limit ?
283 	    DATA_FMT_EVENT_NAME : DATA_FMT_STRING;
284 
285 	BUG_ON(filename == NULL && file == NULL);
286 
287 	if (filename) {
288 		cur_filename = filename;
289 		cur_filename_len = strlen(filename);
290 
291 		if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX)
292 			goto out;
293 	}
294 
295 	if (file) {
296 		cur_filename = file->f_dentry->d_name.name;
297 		cur_filename_len = strlen(cur_filename);
298 	} else
299 		/*
300 		 * Truncate filename if the latter is too long and
301 		 * the file descriptor is not available.
302 		 */
303 		cur_filename_len = IMA_EVENT_NAME_LEN_MAX;
304 out:
305 	return ima_write_template_field_data(cur_filename, cur_filename_len,
306 					     fmt, field_data);
307 }
308 
309 /*
310  * This function writes the name of an event (with size limit).
311  */
312 int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
313 		       const unsigned char *filename,
314 		       struct evm_ima_xattr_data *xattr_value, int xattr_len,
315 		       struct ima_field_data *field_data)
316 {
317 	return ima_eventname_init_common(iint, file, filename,
318 					 field_data, true);
319 }
320 
321 /*
322  * This function writes the name of an event (without size limit).
323  */
324 int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
325 			  const unsigned char *filename,
326 			  struct evm_ima_xattr_data *xattr_value, int xattr_len,
327 			  struct ima_field_data *field_data)
328 {
329 	return ima_eventname_init_common(iint, file, filename,
330 					 field_data, false);
331 }
332 
333 /*
334  *  ima_eventsig_init - include the file signature as part of the template data
335  */
336 int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
337 		      const unsigned char *filename,
338 		      struct evm_ima_xattr_data *xattr_value, int xattr_len,
339 		      struct ima_field_data *field_data)
340 {
341 	enum data_formats fmt = DATA_FMT_HEX;
342 	int rc = 0;
343 
344 	if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
345 		goto out;
346 
347 	rc = ima_write_template_field_data(xattr_value, xattr_len, fmt,
348 					   field_data);
349 out:
350 	return rc;
351 }
352