diff options
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_type.c | 120 | ||||
-rw-r--r-- | include/keys/asymmetric-parser.h | 37 |
2 files changed, 156 insertions, 1 deletions
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index bfb0424026aa..cf807654d221 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * 2 of the Licence, or (at your option) any later version. | 11 | * 2 of the Licence, or (at your option) any later version. |
12 | */ | 12 | */ |
13 | #include <keys/asymmetric-subtype.h> | 13 | #include <keys/asymmetric-subtype.h> |
14 | #include <keys/asymmetric-parser.h> | ||
14 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
@@ -18,6 +19,9 @@ | |||
18 | 19 | ||
19 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
20 | 21 | ||
22 | static LIST_HEAD(asymmetric_key_parsers); | ||
23 | static DECLARE_RWSEM(asymmetric_key_parsers_sem); | ||
24 | |||
21 | /* | 25 | /* |
22 | * Match asymmetric keys on (part of) their name | 26 | * Match asymmetric keys on (part of) their name |
23 | * We have some shorthand methods for matching keys. We allow: | 27 | * We have some shorthand methods for matching keys. We allow: |
@@ -107,12 +111,79 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m) | |||
107 | } | 111 | } |
108 | 112 | ||
109 | /* | 113 | /* |
114 | * Preparse a asymmetric payload to get format the contents appropriately for the | ||
115 | * internal payload to cut down on the number of scans of the data performed. | ||
116 | * | ||
117 | * We also generate a proposed description from the contents of the key that | ||
118 | * can be used to name the key if the user doesn't want to provide one. | ||
119 | */ | ||
120 | static int asymmetric_key_preparse(struct key_preparsed_payload *prep) | ||
121 | { | ||
122 | struct asymmetric_key_parser *parser; | ||
123 | int ret; | ||
124 | |||
125 | pr_devel("==>%s()\n", __func__); | ||
126 | |||
127 | if (prep->datalen == 0) | ||
128 | return -EINVAL; | ||
129 | |||
130 | down_read(&asymmetric_key_parsers_sem); | ||
131 | |||
132 | ret = -EBADMSG; | ||
133 | list_for_each_entry(parser, &asymmetric_key_parsers, link) { | ||
134 | pr_debug("Trying parser '%s'\n", parser->name); | ||
135 | |||
136 | ret = parser->parse(prep); | ||
137 | if (ret != -EBADMSG) { | ||
138 | pr_debug("Parser recognised the format (ret %d)\n", | ||
139 | ret); | ||
140 | break; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | up_read(&asymmetric_key_parsers_sem); | ||
145 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Clean up the preparse data | ||
151 | */ | ||
152 | static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) | ||
153 | { | ||
154 | struct asymmetric_key_subtype *subtype = prep->type_data[0]; | ||
155 | |||
156 | pr_devel("==>%s()\n", __func__); | ||
157 | |||
158 | if (subtype) { | ||
159 | subtype->destroy(prep->payload); | ||
160 | module_put(subtype->owner); | ||
161 | } | ||
162 | kfree(prep->type_data[1]); | ||
163 | kfree(prep->description); | ||
164 | } | ||
165 | |||
166 | /* | ||
110 | * Instantiate a asymmetric_key defined key. The key was preparsed, so we just | 167 | * Instantiate a asymmetric_key defined key. The key was preparsed, so we just |
111 | * have to transfer the data here. | 168 | * have to transfer the data here. |
112 | */ | 169 | */ |
113 | static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | 170 | static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) |
114 | { | 171 | { |
115 | return -EOPNOTSUPP; | 172 | int ret; |
173 | |||
174 | pr_devel("==>%s()\n", __func__); | ||
175 | |||
176 | ret = key_payload_reserve(key, prep->quotalen); | ||
177 | if (ret == 0) { | ||
178 | key->type_data.p[0] = prep->type_data[0]; | ||
179 | key->type_data.p[1] = prep->type_data[1]; | ||
180 | key->payload.data = prep->payload; | ||
181 | prep->type_data[0] = NULL; | ||
182 | prep->type_data[1] = NULL; | ||
183 | prep->payload = NULL; | ||
184 | } | ||
185 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
186 | return ret; | ||
116 | } | 187 | } |
117 | 188 | ||
118 | /* | 189 | /* |
@@ -132,6 +203,8 @@ static void asymmetric_key_destroy(struct key *key) | |||
132 | 203 | ||
133 | struct key_type key_type_asymmetric = { | 204 | struct key_type key_type_asymmetric = { |
134 | .name = "asymmetric", | 205 | .name = "asymmetric", |
206 | .preparse = asymmetric_key_preparse, | ||
207 | .free_preparse = asymmetric_key_free_preparse, | ||
135 | .instantiate = asymmetric_key_instantiate, | 208 | .instantiate = asymmetric_key_instantiate, |
136 | .match = asymmetric_key_match, | 209 | .match = asymmetric_key_match, |
137 | .destroy = asymmetric_key_destroy, | 210 | .destroy = asymmetric_key_destroy, |
@@ -139,6 +212,51 @@ struct key_type key_type_asymmetric = { | |||
139 | }; | 212 | }; |
140 | EXPORT_SYMBOL_GPL(key_type_asymmetric); | 213 | EXPORT_SYMBOL_GPL(key_type_asymmetric); |
141 | 214 | ||
215 | /** | ||
216 | * register_asymmetric_key_parser - Register a asymmetric key blob parser | ||
217 | * @parser: The parser to register | ||
218 | */ | ||
219 | int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) | ||
220 | { | ||
221 | struct asymmetric_key_parser *cursor; | ||
222 | int ret; | ||
223 | |||
224 | down_write(&asymmetric_key_parsers_sem); | ||
225 | |||
226 | list_for_each_entry(cursor, &asymmetric_key_parsers, link) { | ||
227 | if (strcmp(cursor->name, parser->name) == 0) { | ||
228 | pr_err("Asymmetric key parser '%s' already registered\n", | ||
229 | parser->name); | ||
230 | ret = -EEXIST; | ||
231 | goto out; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | list_add_tail(&parser->link, &asymmetric_key_parsers); | ||
236 | |||
237 | pr_notice("Asymmetric key parser '%s' registered\n", parser->name); | ||
238 | ret = 0; | ||
239 | |||
240 | out: | ||
241 | up_write(&asymmetric_key_parsers_sem); | ||
242 | return ret; | ||
243 | } | ||
244 | EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); | ||
245 | |||
246 | /** | ||
247 | * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser | ||
248 | * @parser: The parser to unregister | ||
249 | */ | ||
250 | void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) | ||
251 | { | ||
252 | down_write(&asymmetric_key_parsers_sem); | ||
253 | list_del(&parser->link); | ||
254 | up_write(&asymmetric_key_parsers_sem); | ||
255 | |||
256 | pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); | ||
257 | } | ||
258 | EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); | ||
259 | |||
142 | /* | 260 | /* |
143 | * Module stuff | 261 | * Module stuff |
144 | */ | 262 | */ |
diff --git a/include/keys/asymmetric-parser.h b/include/keys/asymmetric-parser.h new file mode 100644 index 000000000000..09b3b4807f5c --- /dev/null +++ b/include/keys/asymmetric-parser.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* Asymmetric public-key cryptography data parser | ||
2 | * | ||
3 | * See Documentation/crypto/asymmetric-keys.txt | ||
4 | * | ||
5 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
6 | * Written by David Howells (dhowells@redhat.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public Licence | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the Licence, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef _KEYS_ASYMMETRIC_PARSER_H | ||
15 | #define _KEYS_ASYMMETRIC_PARSER_H | ||
16 | |||
17 | /* | ||
18 | * Key data parser. Called during key instantiation. | ||
19 | */ | ||
20 | struct asymmetric_key_parser { | ||
21 | struct list_head link; | ||
22 | struct module *owner; | ||
23 | const char *name; | ||
24 | |||
25 | /* Attempt to parse a key from the data blob passed to add_key() or | ||
26 | * keyctl_instantiate(). Should also generate a proposed description | ||
27 | * that the caller can optionally use for the key. | ||
28 | * | ||
29 | * Return EBADMSG if not recognised. | ||
30 | */ | ||
31 | int (*parse)(struct key_preparsed_payload *prep); | ||
32 | }; | ||
33 | |||
34 | extern int register_asymmetric_key_parser(struct asymmetric_key_parser *); | ||
35 | extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *); | ||
36 | |||
37 | #endif /* _KEYS_ASYMMETRIC_PARSER_H */ | ||