blob: b7b359ca39ee12017a0721f011558314c84c9153 [file] [log] [blame]
Roberto Sassuadf53a72013-06-07 12:16:29 +02001/*
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 */
Joe Perches20ee4512014-02-24 13:59:56 -080015
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
Roberto Sassu9b9d4ce2013-06-07 12:16:35 +020018#include <crypto/hash_info.h>
19
Roberto Sassuadf53a72013-06-07 12:16:29 +020020#include "ima.h"
Roberto Sassu3ce1217d2013-06-07 12:16:30 +020021#include "ima_template_lib.h"
Roberto Sassuadf53a72013-06-07 12:16:29 +020022
23static struct ima_template_desc defined_templates[] = {
Roberto Sassu4d7aeee72013-06-07 12:16:32 +020024 {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +020025 {.name = "ima-ng", .fmt = "d-ng|n-ng"},
26 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
Roberto Sassuadf53a72013-06-07 12:16:29 +020027};
28
29static struct ima_template_field supported_fields[] = {
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +020030 {.field_id = "d", .field_init = ima_eventdigest_init,
Roberto Sassu3ce1217d2013-06-07 12:16:30 +020031 .field_show = ima_show_template_digest},
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +020032 {.field_id = "n", .field_init = ima_eventname_init,
Roberto Sassu3ce1217d2013-06-07 12:16:30 +020033 .field_show = ima_show_template_string},
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +020034 {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
Roberto Sassu4d7aeee72013-06-07 12:16:32 +020035 .field_show = ima_show_template_digest_ng},
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +020036 {.field_id = "n-ng", .field_init = ima_eventname_ng_init,
Roberto Sassu4d7aeee72013-06-07 12:16:32 +020037 .field_show = ima_show_template_string},
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +020038 {.field_id = "sig", .field_init = ima_eventsig_init,
Mimi Zoharbcbc9b0c2013-07-23 11:15:00 -040039 .field_show = ima_show_template_sig},
Roberto Sassuadf53a72013-06-07 12:16:29 +020040};
41
Roberto Sassua71dc652013-06-07 12:16:33 +020042static struct ima_template_desc *ima_template;
Roberto Sassu9b9d4ce2013-06-07 12:16:35 +020043static struct ima_template_desc *lookup_template_desc(const char *name);
44
45static int __init ima_template_setup(char *str)
46{
47 struct ima_template_desc *template_desc;
48 int template_len = strlen(str);
49
50 /*
51 * Verify that a template with the supplied name exists.
52 * If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
53 */
54 template_desc = lookup_template_desc(str);
Roberto Sassu71fed2e2014-10-13 14:08:38 +020055 if (!template_desc) {
56 pr_err("template %s not found, using %s\n",
57 str, CONFIG_IMA_DEFAULT_TEMPLATE);
Roberto Sassu9b9d4ce2013-06-07 12:16:35 +020058 return 1;
Roberto Sassu71fed2e2014-10-13 14:08:38 +020059 }
Roberto Sassu9b9d4ce2013-06-07 12:16:35 +020060
61 /*
62 * Verify whether the current hash algorithm is supported
63 * by the 'ima' template.
64 */
65 if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 &&
66 ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) {
Joe Perches20ee4512014-02-24 13:59:56 -080067 pr_err("template does not support hash alg\n");
Roberto Sassu9b9d4ce2013-06-07 12:16:35 +020068 return 1;
69 }
70
71 ima_template = template_desc;
72 return 1;
73}
74__setup("ima_template=", ima_template_setup);
Roberto Sassua71dc652013-06-07 12:16:33 +020075
76static struct ima_template_desc *lookup_template_desc(const char *name)
77{
78 int i;
79
80 for (i = 0; i < ARRAY_SIZE(defined_templates); i++) {
81 if (strcmp(defined_templates[i].name, name) == 0)
82 return defined_templates + i;
83 }
84
85 return NULL;
86}
87
Roberto Sassu3ce1217d2013-06-07 12:16:30 +020088static struct ima_template_field *lookup_template_field(const char *field_id)
Roberto Sassuadf53a72013-06-07 12:16:29 +020089{
90 int i;
91
92 for (i = 0; i < ARRAY_SIZE(supported_fields); i++)
93 if (strncmp(supported_fields[i].field_id, field_id,
94 IMA_TEMPLATE_FIELD_ID_MAX_LEN) == 0)
95 return &supported_fields[i];
96 return NULL;
97}
98
Roberto Sassudbc335d2013-11-25 20:18:52 +010099static int template_fmt_size(const char *template_fmt)
Roberto Sassuadf53a72013-06-07 12:16:29 +0200100{
101 char c;
102 int template_fmt_len = strlen(template_fmt);
103 int i = 0, j = 0;
104
105 while (i < template_fmt_len) {
106 c = template_fmt[i];
107 if (c == '|')
108 j++;
109 i++;
110 }
111
112 return j + 1;
113}
114
Roberto Sassudbc335d2013-11-25 20:18:52 +0100115static int template_desc_init_fields(const char *template_fmt,
Roberto Sassuadf53a72013-06-07 12:16:29 +0200116 struct ima_template_field ***fields,
117 int *num_fields)
118{
Roberto Sassuaf917062013-11-27 14:40:41 +0100119 char *c, *template_fmt_copy, *template_fmt_ptr;
Roberto Sassu3ce1217d2013-06-07 12:16:30 +0200120 int template_num_fields = template_fmt_size(template_fmt);
Roberto Sassuadf53a72013-06-07 12:16:29 +0200121 int i, result = 0;
122
Roberto Sassu71fed2e2014-10-13 14:08:38 +0200123 if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) {
124 pr_err("format string '%s' contains too many fields\n",
125 template_fmt);
Roberto Sassuadf53a72013-06-07 12:16:29 +0200126 return -EINVAL;
Roberto Sassu71fed2e2014-10-13 14:08:38 +0200127 }
Roberto Sassuadf53a72013-06-07 12:16:29 +0200128
Roberto Sassudbc335d2013-11-25 20:18:52 +0100129 /* copying is needed as strsep() modifies the original buffer */
130 template_fmt_copy = kstrdup(template_fmt, GFP_KERNEL);
131 if (template_fmt_copy == NULL)
132 return -ENOMEM;
133
Roberto Sassuadf53a72013-06-07 12:16:29 +0200134 *fields = kzalloc(template_num_fields * sizeof(*fields), GFP_KERNEL);
135 if (*fields == NULL) {
136 result = -ENOMEM;
137 goto out;
138 }
Roberto Sassuaf917062013-11-27 14:40:41 +0100139
140 template_fmt_ptr = template_fmt_copy;
141 for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL &&
Roberto Sassuadf53a72013-06-07 12:16:29 +0200142 i < template_num_fields; i++) {
Roberto Sassu3ce1217d2013-06-07 12:16:30 +0200143 struct ima_template_field *f = lookup_template_field(c);
Roberto Sassuadf53a72013-06-07 12:16:29 +0200144
145 if (!f) {
Roberto Sassu71fed2e2014-10-13 14:08:38 +0200146 pr_err("field '%s' not found\n", c);
Roberto Sassuadf53a72013-06-07 12:16:29 +0200147 result = -ENOENT;
148 goto out;
149 }
150 (*fields)[i] = f;
151 }
152 *num_fields = i;
Roberto Sassuadf53a72013-06-07 12:16:29 +0200153out:
Roberto Sassudbc335d2013-11-25 20:18:52 +0100154 if (result < 0) {
155 kfree(*fields);
156 *fields = NULL;
157 }
158 kfree(template_fmt_copy);
Roberto Sassuadf53a72013-06-07 12:16:29 +0200159 return result;
160}
161
Roberto Sassua71dc652013-06-07 12:16:33 +0200162struct ima_template_desc *ima_template_desc_current(void)
163{
164 if (!ima_template)
Mimi Zohar42865872013-06-07 12:16:34 +0200165 ima_template =
166 lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE);
Roberto Sassua71dc652013-06-07 12:16:33 +0200167 return ima_template;
168}
169
Dmitry Kasatkine4a9c512014-09-03 10:19:58 +0300170int __init ima_init_template(void)
Roberto Sassuadf53a72013-06-07 12:16:29 +0200171{
Dmitry Kasatkinb4148db2014-05-08 11:23:53 +0300172 struct ima_template_desc *template = ima_template_desc_current();
Roberto Sassu71fed2e2014-10-13 14:08:38 +0200173 int result;
Roberto Sassuadf53a72013-06-07 12:16:29 +0200174
Roberto Sassu71fed2e2014-10-13 14:08:38 +0200175 result = template_desc_init_fields(template->fmt,
176 &(template->fields),
177 &(template->num_fields));
178 if (result < 0)
Roberto Sassu7dbdb422014-10-13 14:08:39 +0200179 pr_err("template %s init failed, result: %d\n",
180 (strlen(template->name) ?
181 template->name : template->fmt), result);
Roberto Sassu71fed2e2014-10-13 14:08:38 +0200182
183 return result;
Roberto Sassuadf53a72013-06-07 12:16:29 +0200184}