2 * Copyright (C) 2013 Politecnico di Torino, Italy
3 * TORSEC group -- http://security.polito.it
5 * Author: Roberto Sassu <roberto.sassu@polito.it>
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
12 * File: ima_template.c
13 * Helpers to manage template descriptors.
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 #include <linux/rculist.h>
20 #include "ima_template_lib.h"
22 enum header_fields { HDR_PCR, HDR_DIGEST, HDR_TEMPLATE_NAME,
23 HDR_TEMPLATE_DATA, HDR__LAST };
25 static struct ima_template_desc builtin_templates[] = {
26 {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
27 {.name = "ima-ng", .fmt = "d-ng|n-ng"},
28 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
29 {.name = "", .fmt = ""}, /* placeholder for a custom format */
32 static LIST_HEAD(defined_templates);
33 static DEFINE_SPINLOCK(template_list);
34 static int template_setup_done;
36 static struct ima_template_field supported_fields[] = {
37 {.field_id = "d", .field_init = ima_eventdigest_init,
38 .field_show = ima_show_template_digest},
39 {.field_id = "n", .field_init = ima_eventname_init,
40 .field_show = ima_show_template_string},
41 {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
42 .field_show = ima_show_template_digest_ng},
43 {.field_id = "n-ng", .field_init = ima_eventname_ng_init,
44 .field_show = ima_show_template_string},
45 {.field_id = "sig", .field_init = ima_eventsig_init,
46 .field_show = ima_show_template_sig},
48 #define MAX_TEMPLATE_NAME_LEN 15
50 static struct ima_template_desc *ima_template;
51 static struct ima_template_desc *lookup_template_desc(const char *name);
52 static int template_desc_init_fields(const char *template_fmt,
53 struct ima_template_field ***fields,
56 static int __init ima_template_setup(char *str)
58 struct ima_template_desc *template_desc;
59 int template_len = strlen(str);
61 if (template_setup_done)
65 ima_init_template_list();
68 * Verify that a template with the supplied name exists.
69 * If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
71 template_desc = lookup_template_desc(str);
73 pr_err("template %s not found, using %s\n",
74 str, CONFIG_IMA_DEFAULT_TEMPLATE);
79 * Verify whether the current hash algorithm is supported
80 * by the 'ima' template.
82 if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 &&
83 ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) {
84 pr_err("template does not support hash alg\n");
88 ima_template = template_desc;
89 template_setup_done = 1;
92 __setup("ima_template=", ima_template_setup);
94 static int __init ima_template_fmt_setup(char *str)
96 int num_templates = ARRAY_SIZE(builtin_templates);
98 if (template_setup_done)
101 if (template_desc_init_fields(str, NULL, NULL) < 0) {
102 pr_err("format string '%s' not valid, using template %s\n",
103 str, CONFIG_IMA_DEFAULT_TEMPLATE);
107 builtin_templates[num_templates - 1].fmt = str;
108 ima_template = builtin_templates + num_templates - 1;
109 template_setup_done = 1;
113 __setup("ima_template_fmt=", ima_template_fmt_setup);
115 static struct ima_template_desc *lookup_template_desc(const char *name)
117 struct ima_template_desc *template_desc;
121 list_for_each_entry_rcu(template_desc, &defined_templates, list) {
122 if ((strcmp(template_desc->name, name) == 0) ||
123 (strcmp(template_desc->fmt, name) == 0)) {
129 return found ? template_desc : NULL;
132 static struct ima_template_field *lookup_template_field(const char *field_id)
136 for (i = 0; i < ARRAY_SIZE(supported_fields); i++)
137 if (strncmp(supported_fields[i].field_id, field_id,
138 IMA_TEMPLATE_FIELD_ID_MAX_LEN) == 0)
139 return &supported_fields[i];
143 static int template_fmt_size(const char *template_fmt)
146 int template_fmt_len = strlen(template_fmt);
149 while (i < template_fmt_len) {
159 static int template_desc_init_fields(const char *template_fmt,
160 struct ima_template_field ***fields,
163 const char *template_fmt_ptr;
164 struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX];
165 int template_num_fields;
168 if (num_fields && *num_fields > 0) /* already initialized? */
171 template_num_fields = template_fmt_size(template_fmt);
173 if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) {
174 pr_err("format string '%s' contains too many fields\n",
179 for (i = 0, template_fmt_ptr = template_fmt; i < template_num_fields;
180 i++, template_fmt_ptr += len + 1) {
181 char tmp_field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN + 1];
183 len = strchrnul(template_fmt_ptr, '|') - template_fmt_ptr;
184 if (len == 0 || len > IMA_TEMPLATE_FIELD_ID_MAX_LEN) {
185 pr_err("Invalid field with length %d\n", len);
189 memcpy(tmp_field_id, template_fmt_ptr, len);
190 tmp_field_id[len] = '\0';
191 found_fields[i] = lookup_template_field(tmp_field_id);
192 if (!found_fields[i]) {
193 pr_err("field '%s' not found\n", tmp_field_id);
198 if (fields && num_fields) {
199 *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL);
203 memcpy(*fields, found_fields, i * sizeof(*fields));
210 void ima_init_template_list(void)
214 if (!list_empty(&defined_templates))
217 spin_lock(&template_list);
218 for (i = 0; i < ARRAY_SIZE(builtin_templates); i++) {
219 list_add_tail_rcu(&builtin_templates[i].list,
222 spin_unlock(&template_list);
225 struct ima_template_desc *ima_template_desc_current(void)
228 ima_init_template_list();
230 lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE);
235 int __init ima_init_template(void)
237 struct ima_template_desc *template = ima_template_desc_current();
240 result = template_desc_init_fields(template->fmt,
242 &(template->num_fields));
244 pr_err("template %s init failed, result: %d\n",
245 (strlen(template->name) ?
246 template->name : template->fmt), result);
251 static struct ima_template_desc *restore_template_fmt(char *template_name)
253 struct ima_template_desc *template_desc = NULL;
256 ret = template_desc_init_fields(template_name, NULL, NULL);
258 pr_err("attempting to initialize the template \"%s\" failed\n",
263 template_desc = kzalloc(sizeof(*template_desc), GFP_KERNEL);
267 template_desc->name = "";
268 template_desc->fmt = kstrdup(template_name, GFP_KERNEL);
269 if (!template_desc->fmt)
272 spin_lock(&template_list);
273 list_add_tail_rcu(&template_desc->list, &defined_templates);
274 spin_unlock(&template_list);
276 return template_desc;
279 static int ima_restore_template_data(struct ima_template_desc *template_desc,
281 int template_data_size,
282 struct ima_template_entry **entry)
287 *entry = kzalloc(sizeof(**entry) +
288 template_desc->num_fields * sizeof(struct ima_field_data),
293 ret = ima_parse_buf(template_data, template_data + template_data_size,
294 NULL, template_desc->num_fields,
295 (*entry)->template_data, NULL, NULL,
296 ENFORCE_FIELDS | ENFORCE_BUFEND, "template data");
302 (*entry)->template_desc = template_desc;
303 for (i = 0; i < template_desc->num_fields; i++) {
304 struct ima_field_data *field_data = &(*entry)->template_data[i];
305 u8 *data = field_data->data;
307 (*entry)->template_data[i].data =
308 kzalloc(field_data->len + 1, GFP_KERNEL);
309 if (!(*entry)->template_data[i].data) {
313 memcpy((*entry)->template_data[i].data, data, field_data->len);
314 (*entry)->template_data_len += sizeof(field_data->len);
315 (*entry)->template_data_len += field_data->len;
319 ima_free_template_entry(*entry);
326 /* Restore the serialized binary measurement list without extending PCRs. */
327 int ima_restore_measurement_list(loff_t size, void *buf)
329 char template_name[MAX_TEMPLATE_NAME_LEN];
331 struct ima_kexec_hdr *khdr = buf;
332 struct ima_field_data hdr[HDR__LAST] = {
333 [HDR_PCR] = {.len = sizeof(u32)},
334 [HDR_DIGEST] = {.len = TPM_DIGEST_SIZE},
337 void *bufp = buf + sizeof(*khdr);
339 struct ima_template_entry *entry;
340 struct ima_template_desc *template_desc;
341 DECLARE_BITMAP(hdr_mask, HDR__LAST);
342 unsigned long count = 0;
345 if (!buf || size < sizeof(*khdr))
348 if (ima_canonical_fmt) {
349 khdr->version = le16_to_cpu(khdr->version);
350 khdr->count = le64_to_cpu(khdr->count);
351 khdr->buffer_size = le64_to_cpu(khdr->buffer_size);
354 if (khdr->version != 1) {
355 pr_err("attempting to restore a incompatible measurement list");
359 if (khdr->count > ULONG_MAX - 1) {
360 pr_err("attempting to restore too many measurements");
364 bitmap_zero(hdr_mask, HDR__LAST);
365 bitmap_set(hdr_mask, HDR_PCR, 1);
366 bitmap_set(hdr_mask, HDR_DIGEST, 1);
369 * ima kexec buffer prefix: version, buffer size, count
370 * v1 format: pcr, digest, template-name-len, template-name,
371 * template-data-size, template-data
373 bufendp = buf + khdr->buffer_size;
374 while ((bufp < bufendp) && (count++ < khdr->count)) {
375 int enforce_mask = ENFORCE_FIELDS;
377 enforce_mask |= (count == khdr->count) ? ENFORCE_BUFEND : 0;
378 ret = ima_parse_buf(bufp, bufendp, &bufp, HDR__LAST, hdr, NULL,
379 hdr_mask, enforce_mask, "entry header");
383 if (hdr[HDR_TEMPLATE_NAME].len >= MAX_TEMPLATE_NAME_LEN) {
384 pr_err("attempting to restore a template name \
385 that is too long\n");
390 /* template name is not null terminated */
391 memcpy(template_name, hdr[HDR_TEMPLATE_NAME].data,
392 hdr[HDR_TEMPLATE_NAME].len);
393 template_name[hdr[HDR_TEMPLATE_NAME].len] = 0;
395 if (strcmp(template_name, "ima") == 0) {
396 pr_err("attempting to restore an unsupported \
397 template \"%s\" failed\n", template_name);
402 template_desc = lookup_template_desc(template_name);
403 if (!template_desc) {
404 template_desc = restore_template_fmt(template_name);
410 * Only the running system's template format is initialized
411 * on boot. As needed, initialize the other template formats.
413 ret = template_desc_init_fields(template_desc->fmt,
414 &(template_desc->fields),
415 &(template_desc->num_fields));
417 pr_err("attempting to restore the template fmt \"%s\" \
418 failed\n", template_desc->fmt);
423 ret = ima_restore_template_data(template_desc,
424 hdr[HDR_TEMPLATE_DATA].data,
425 hdr[HDR_TEMPLATE_DATA].len,
430 memcpy(entry->digest, hdr[HDR_DIGEST].data,
431 hdr[HDR_DIGEST].len);
432 entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) :
433 le32_to_cpu(*(hdr[HDR_PCR].data));
434 ret = ima_restore_measurement_entry(entry);