xref: /linux/security/integrity/ima/ima_template.c (revision 94c3aac567a9ddb9e868a7fae3c927c08b51b7c6)
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.c
13  *      Helpers to manage template descriptors.
14  */
15 
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17 
18 #include "ima.h"
19 #include "ima_template_lib.h"
20 
21 static struct ima_template_desc defined_templates[] = {
22 	{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
23 	{.name = "ima-ng", .fmt = "d-ng|n-ng"},
24 	{.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
25 	{.name = "", .fmt = ""},	/* placeholder for a custom format */
26 };
27 
28 static struct ima_template_field supported_fields[] = {
29 	{.field_id = "d", .field_init = ima_eventdigest_init,
30 	 .field_show = ima_show_template_digest},
31 	{.field_id = "n", .field_init = ima_eventname_init,
32 	 .field_show = ima_show_template_string},
33 	{.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
34 	 .field_show = ima_show_template_digest_ng},
35 	{.field_id = "n-ng", .field_init = ima_eventname_ng_init,
36 	 .field_show = ima_show_template_string},
37 	{.field_id = "sig", .field_init = ima_eventsig_init,
38 	 .field_show = ima_show_template_sig},
39 };
40 #define MAX_TEMPLATE_NAME_LEN 15
41 
42 static struct ima_template_desc *ima_template;
43 static struct ima_template_desc *lookup_template_desc(const char *name);
44 static int template_desc_init_fields(const char *template_fmt,
45 				     struct ima_template_field ***fields,
46 				     int *num_fields);
47 
48 static int __init ima_template_setup(char *str)
49 {
50 	struct ima_template_desc *template_desc;
51 	int template_len = strlen(str);
52 
53 	if (ima_template)
54 		return 1;
55 
56 	/*
57 	 * Verify that a template with the supplied name exists.
58 	 * If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
59 	 */
60 	template_desc = lookup_template_desc(str);
61 	if (!template_desc) {
62 		pr_err("template %s not found, using %s\n",
63 		       str, CONFIG_IMA_DEFAULT_TEMPLATE);
64 		return 1;
65 	}
66 
67 	/*
68 	 * Verify whether the current hash algorithm is supported
69 	 * by the 'ima' template.
70 	 */
71 	if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 &&
72 	    ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) {
73 		pr_err("template does not support hash alg\n");
74 		return 1;
75 	}
76 
77 	ima_template = template_desc;
78 	return 1;
79 }
80 __setup("ima_template=", ima_template_setup);
81 
82 static int __init ima_template_fmt_setup(char *str)
83 {
84 	int num_templates = ARRAY_SIZE(defined_templates);
85 
86 	if (ima_template)
87 		return 1;
88 
89 	if (template_desc_init_fields(str, NULL, NULL) < 0) {
90 		pr_err("format string '%s' not valid, using template %s\n",
91 		       str, CONFIG_IMA_DEFAULT_TEMPLATE);
92 		return 1;
93 	}
94 
95 	defined_templates[num_templates - 1].fmt = str;
96 	ima_template = defined_templates + num_templates - 1;
97 	return 1;
98 }
99 __setup("ima_template_fmt=", ima_template_fmt_setup);
100 
101 static struct ima_template_desc *lookup_template_desc(const char *name)
102 {
103 	int i;
104 
105 	for (i = 0; i < ARRAY_SIZE(defined_templates); i++) {
106 		if (strcmp(defined_templates[i].name, name) == 0)
107 			return defined_templates + i;
108 	}
109 
110 	return NULL;
111 }
112 
113 static struct ima_template_field *lookup_template_field(const char *field_id)
114 {
115 	int i;
116 
117 	for (i = 0; i < ARRAY_SIZE(supported_fields); i++)
118 		if (strncmp(supported_fields[i].field_id, field_id,
119 			    IMA_TEMPLATE_FIELD_ID_MAX_LEN) == 0)
120 			return &supported_fields[i];
121 	return NULL;
122 }
123 
124 static int template_fmt_size(const char *template_fmt)
125 {
126 	char c;
127 	int template_fmt_len = strlen(template_fmt);
128 	int i = 0, j = 0;
129 
130 	while (i < template_fmt_len) {
131 		c = template_fmt[i];
132 		if (c == '|')
133 			j++;
134 		i++;
135 	}
136 
137 	return j + 1;
138 }
139 
140 static int template_desc_init_fields(const char *template_fmt,
141 				     struct ima_template_field ***fields,
142 				     int *num_fields)
143 {
144 	const char *template_fmt_ptr;
145 	struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX];
146 	int template_num_fields = template_fmt_size(template_fmt);
147 	int i, len;
148 
149 	if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) {
150 		pr_err("format string '%s' contains too many fields\n",
151 		       template_fmt);
152 		return -EINVAL;
153 	}
154 
155 	for (i = 0, template_fmt_ptr = template_fmt; i < template_num_fields;
156 	     i++, template_fmt_ptr += len + 1) {
157 		char tmp_field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN + 1];
158 
159 		len = strchrnul(template_fmt_ptr, '|') - template_fmt_ptr;
160 		if (len == 0 || len > IMA_TEMPLATE_FIELD_ID_MAX_LEN) {
161 			pr_err("Invalid field with length %d\n", len);
162 			return -EINVAL;
163 		}
164 
165 		memcpy(tmp_field_id, template_fmt_ptr, len);
166 		tmp_field_id[len] = '\0';
167 		found_fields[i] = lookup_template_field(tmp_field_id);
168 		if (!found_fields[i]) {
169 			pr_err("field '%s' not found\n", tmp_field_id);
170 			return -ENOENT;
171 		}
172 	}
173 
174 	if (fields && num_fields) {
175 		*fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL);
176 		if (*fields == NULL)
177 			return -ENOMEM;
178 
179 		memcpy(*fields, found_fields, i * sizeof(*fields));
180 		*num_fields = i;
181 	}
182 
183 	return 0;
184 }
185 
186 struct ima_template_desc *ima_template_desc_current(void)
187 {
188 	if (!ima_template)
189 		ima_template =
190 		    lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE);
191 	return ima_template;
192 }
193 
194 int __init ima_init_template(void)
195 {
196 	struct ima_template_desc *template = ima_template_desc_current();
197 	int result;
198 
199 	result = template_desc_init_fields(template->fmt,
200 					   &(template->fields),
201 					   &(template->num_fields));
202 	if (result < 0)
203 		pr_err("template %s init failed, result: %d\n",
204 		       (strlen(template->name) ?
205 		       template->name : template->fmt), result);
206 
207 	return result;
208 }
209 
210 static int ima_restore_template_data(struct ima_template_desc *template_desc,
211 				     void *template_data,
212 				     int template_data_size,
213 				     struct ima_template_entry **entry)
214 {
215 	struct binary_field_data {
216 		u32 len;
217 		u8 data[0];
218 	} __packed;
219 
220 	struct binary_field_data *field_data;
221 	int offset = 0;
222 	int ret = 0;
223 	int i;
224 
225 	*entry = kzalloc(sizeof(**entry) +
226 		    template_desc->num_fields * sizeof(struct ima_field_data),
227 		    GFP_NOFS);
228 	if (!*entry)
229 		return -ENOMEM;
230 
231 	(*entry)->template_desc = template_desc;
232 	for (i = 0; i < template_desc->num_fields; i++) {
233 		field_data = template_data + offset;
234 
235 		/* Each field of the template data is prefixed with a length. */
236 		if (offset > (template_data_size - sizeof(*field_data))) {
237 			pr_err("Restoring the template field failed\n");
238 			ret = -EINVAL;
239 			break;
240 		}
241 		offset += sizeof(*field_data);
242 
243 		if (offset > (template_data_size - field_data->len)) {
244 			pr_err("Restoring the template field data failed\n");
245 			ret = -EINVAL;
246 			break;
247 		}
248 		offset += field_data->len;
249 
250 		(*entry)->template_data[i].len = field_data->len;
251 		(*entry)->template_data_len += sizeof(field_data->len);
252 
253 		(*entry)->template_data[i].data =
254 			kzalloc(field_data->len + 1, GFP_KERNEL);
255 		if (!(*entry)->template_data[i].data) {
256 			ret = -ENOMEM;
257 			break;
258 		}
259 		memcpy((*entry)->template_data[i].data, field_data->data,
260 			field_data->len);
261 		(*entry)->template_data_len += field_data->len;
262 	}
263 
264 	if (ret < 0) {
265 		ima_free_template_entry(*entry);
266 		*entry = NULL;
267 	}
268 
269 	return ret;
270 }
271 
272 /* Restore the serialized binary measurement list without extending PCRs. */
273 int ima_restore_measurement_list(loff_t size, void *buf)
274 {
275 	struct binary_hdr_v1 {
276 		u32 pcr;
277 		u8 digest[TPM_DIGEST_SIZE];
278 		u32 template_name_len;
279 		char template_name[0];
280 	} __packed;
281 	char template_name[MAX_TEMPLATE_NAME_LEN];
282 
283 	struct binary_data_v1 {
284 		u32 template_data_size;
285 		char template_data[0];
286 	} __packed;
287 
288 	struct ima_kexec_hdr *khdr = buf;
289 	struct binary_hdr_v1 *hdr_v1;
290 	struct binary_data_v1 *data_v1;
291 
292 	void *bufp = buf + sizeof(*khdr);
293 	void *bufendp = buf + khdr->buffer_size;
294 	struct ima_template_entry *entry;
295 	struct ima_template_desc *template_desc;
296 	unsigned long count = 0;
297 	int ret = 0;
298 
299 	if (!buf || size < sizeof(*khdr))
300 		return 0;
301 
302 	if (khdr->version != 1) {
303 		pr_err("attempting to restore a incompatible measurement list");
304 		return -EINVAL;
305 	}
306 
307 	if (khdr->count > ULONG_MAX - 1) {
308 		pr_err("attempting to restore too many measurements");
309 		return -EINVAL;
310 	}
311 
312 	/*
313 	 * ima kexec buffer prefix: version, buffer size, count
314 	 * v1 format: pcr, digest, template-name-len, template-name,
315 	 *	      template-data-size, template-data
316 	 */
317 	while ((bufp < bufendp) && (count++ < khdr->count)) {
318 		hdr_v1 = bufp;
319 		if (bufp > (bufendp - sizeof(*hdr_v1))) {
320 			pr_err("attempting to restore partial measurement\n");
321 			ret = -EINVAL;
322 			break;
323 		}
324 		bufp += sizeof(*hdr_v1);
325 
326 		if ((hdr_v1->template_name_len >= MAX_TEMPLATE_NAME_LEN) ||
327 		    (bufp > (bufendp - hdr_v1->template_name_len))) {
328 			pr_err("attempting to restore a template name \
329 				that is too long\n");
330 			ret = -EINVAL;
331 			break;
332 		}
333 		data_v1 = bufp += (u_int8_t)hdr_v1->template_name_len;
334 
335 		/* template name is not null terminated */
336 		memcpy(template_name, hdr_v1->template_name,
337 		       hdr_v1->template_name_len);
338 		template_name[hdr_v1->template_name_len] = 0;
339 
340 		if (strcmp(template_name, "ima") == 0) {
341 			pr_err("attempting to restore an unsupported \
342 				template \"%s\" failed\n", template_name);
343 			ret = -EINVAL;
344 			break;
345 		}
346 
347 		/* get template format */
348 		template_desc = lookup_template_desc(template_name);
349 		if (!template_desc) {
350 			pr_err("template \"%s\" not found\n", template_name);
351 			ret = -EINVAL;
352 			break;
353 		}
354 
355 		if (bufp > (bufendp - sizeof(data_v1->template_data_size))) {
356 			pr_err("restoring the template data size failed\n");
357 			ret = -EINVAL;
358 			break;
359 		}
360 		bufp += (u_int8_t) sizeof(data_v1->template_data_size);
361 
362 		if (bufp > (bufendp - data_v1->template_data_size)) {
363 			pr_err("restoring the template data failed\n");
364 			ret = -EINVAL;
365 			break;
366 		}
367 		bufp += data_v1->template_data_size;
368 
369 		ret = ima_restore_template_data(template_desc,
370 						data_v1->template_data,
371 						data_v1->template_data_size,
372 						&entry);
373 		if (ret < 0)
374 			break;
375 
376 		memcpy(entry->digest, hdr_v1->digest, TPM_DIGEST_SIZE);
377 		entry->pcr = hdr_v1->pcr;
378 		ret = ima_restore_measurement_entry(entry);
379 		if (ret < 0)
380 			break;
381 
382 	}
383 	return ret;
384 }
385