bcbbbd794e1da209d519baca7de8b0ddf1115716
[kvmfornfv.git] / kernel / crypto / asymmetric_keys / asymmetric_type.c
1 /* Asymmetric public-key cryptography key type
2  *
3  * See Documentation/security/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 #include <keys/asymmetric-subtype.h>
14 #include <keys/asymmetric-parser.h>
15 #include <linux/seq_file.h>
16 #include <linux/module.h>
17 #include <linux/slab.h>
18 #include <linux/ctype.h>
19 #include "asymmetric_keys.h"
20
21 MODULE_LICENSE("GPL");
22
23 static LIST_HEAD(asymmetric_key_parsers);
24 static DECLARE_RWSEM(asymmetric_key_parsers_sem);
25
26 /**
27  * asymmetric_key_generate_id: Construct an asymmetric key ID
28  * @val_1: First binary blob
29  * @len_1: Length of first binary blob
30  * @val_2: Second binary blob
31  * @len_2: Length of second binary blob
32  *
33  * Construct an asymmetric key ID from a pair of binary blobs.
34  */
35 struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
36                                                      size_t len_1,
37                                                      const void *val_2,
38                                                      size_t len_2)
39 {
40         struct asymmetric_key_id *kid;
41
42         kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2,
43                       GFP_KERNEL);
44         if (!kid)
45                 return ERR_PTR(-ENOMEM);
46         kid->len = len_1 + len_2;
47         memcpy(kid->data, val_1, len_1);
48         memcpy(kid->data + len_1, val_2, len_2);
49         return kid;
50 }
51 EXPORT_SYMBOL_GPL(asymmetric_key_generate_id);
52
53 /**
54  * asymmetric_key_id_same - Return true if two asymmetric keys IDs are the same.
55  * @kid_1, @kid_2: The key IDs to compare
56  */
57 bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
58                             const struct asymmetric_key_id *kid2)
59 {
60         if (!kid1 || !kid2)
61                 return false;
62         if (kid1->len != kid2->len)
63                 return false;
64         return memcmp(kid1->data, kid2->data, kid1->len) == 0;
65 }
66 EXPORT_SYMBOL_GPL(asymmetric_key_id_same);
67
68 /**
69  * asymmetric_key_id_partial - Return true if two asymmetric keys IDs
70  * partially match
71  * @kid_1, @kid_2: The key IDs to compare
72  */
73 bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1,
74                                const struct asymmetric_key_id *kid2)
75 {
76         if (!kid1 || !kid2)
77                 return false;
78         if (kid1->len < kid2->len)
79                 return false;
80         return memcmp(kid1->data + (kid1->len - kid2->len),
81                       kid2->data, kid2->len) == 0;
82 }
83 EXPORT_SYMBOL_GPL(asymmetric_key_id_partial);
84
85 /**
86  * asymmetric_match_key_ids - Search asymmetric key IDs
87  * @kids: The list of key IDs to check
88  * @match_id: The key ID we're looking for
89  * @match: The match function to use
90  */
91 static bool asymmetric_match_key_ids(
92         const struct asymmetric_key_ids *kids,
93         const struct asymmetric_key_id *match_id,
94         bool (*match)(const struct asymmetric_key_id *kid1,
95                       const struct asymmetric_key_id *kid2))
96 {
97         int i;
98
99         if (!kids || !match_id)
100                 return false;
101         for (i = 0; i < ARRAY_SIZE(kids->id); i++)
102                 if (match(kids->id[i], match_id))
103                         return true;
104         return false;
105 }
106
107 /**
108  * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
109  * @id: The ID as a hex string.
110  */
111 struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
112 {
113         struct asymmetric_key_id *match_id;
114         size_t hexlen;
115         int ret;
116
117         if (!*id)
118                 return ERR_PTR(-EINVAL);
119         hexlen = strlen(id);
120         if (hexlen & 1)
121                 return ERR_PTR(-EINVAL);
122
123         match_id = kmalloc(sizeof(struct asymmetric_key_id) + hexlen / 2,
124                            GFP_KERNEL);
125         if (!match_id)
126                 return ERR_PTR(-ENOMEM);
127         match_id->len = hexlen / 2;
128         ret = hex2bin(match_id->data, id, hexlen / 2);
129         if (ret < 0) {
130                 kfree(match_id);
131                 return ERR_PTR(-EINVAL);
132         }
133         return match_id;
134 }
135
136 /*
137  * Match asymmetric keys by an exact match on an ID.
138  */
139 static bool asymmetric_key_cmp(const struct key *key,
140                                const struct key_match_data *match_data)
141 {
142         const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
143         const struct asymmetric_key_id *match_id = match_data->preparsed;
144
145         return asymmetric_match_key_ids(kids, match_id,
146                                         asymmetric_key_id_same);
147 }
148
149 /*
150  * Match asymmetric keys by a partial match on an IDs.
151  */
152 static bool asymmetric_key_cmp_partial(const struct key *key,
153                                        const struct key_match_data *match_data)
154 {
155         const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
156         const struct asymmetric_key_id *match_id = match_data->preparsed;
157
158         return asymmetric_match_key_ids(kids, match_id,
159                                         asymmetric_key_id_partial);
160 }
161
162 /*
163  * Preparse the match criterion.  If we don't set lookup_type and cmp,
164  * the default will be an exact match on the key description.
165  *
166  * There are some specifiers for matching key IDs rather than by the key
167  * description:
168  *
169  *      "id:<id>" - find a key by partial match on any available ID
170  *      "ex:<id>" - find a key by exact match on any available ID
171  *
172  * These have to be searched by iteration rather than by direct lookup because
173  * the key is hashed according to its description.
174  */
175 static int asymmetric_key_match_preparse(struct key_match_data *match_data)
176 {
177         struct asymmetric_key_id *match_id;
178         const char *spec = match_data->raw_data;
179         const char *id;
180         bool (*cmp)(const struct key *, const struct key_match_data *) =
181                 asymmetric_key_cmp;
182
183         if (!spec || !*spec)
184                 return -EINVAL;
185         if (spec[0] == 'i' &&
186             spec[1] == 'd' &&
187             spec[2] == ':') {
188                 id = spec + 3;
189                 cmp = asymmetric_key_cmp_partial;
190         } else if (spec[0] == 'e' &&
191                    spec[1] == 'x' &&
192                    spec[2] == ':') {
193                 id = spec + 3;
194         } else {
195                 goto default_match;
196         }
197
198         match_id = asymmetric_key_hex_to_key_id(id);
199         if (IS_ERR(match_id))
200                 return PTR_ERR(match_id);
201
202         match_data->preparsed = match_id;
203         match_data->cmp = cmp;
204         match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
205         return 0;
206
207 default_match:
208         return 0;
209 }
210
211 /*
212  * Free the preparsed the match criterion.
213  */
214 static void asymmetric_key_match_free(struct key_match_data *match_data)
215 {
216         kfree(match_data->preparsed);
217 }
218
219 /*
220  * Describe the asymmetric key
221  */
222 static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
223 {
224         const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
225         const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
226         const struct asymmetric_key_id *kid;
227         const unsigned char *p;
228         int n;
229
230         seq_puts(m, key->description);
231
232         if (subtype) {
233                 seq_puts(m, ": ");
234                 subtype->describe(key, m);
235
236                 if (kids && kids->id[1]) {
237                         kid = kids->id[1];
238                         seq_putc(m, ' ');
239                         n = kid->len;
240                         p = kid->data;
241                         if (n > 4) {
242                                 p += n - 4;
243                                 n = 4;
244                         }
245                         seq_printf(m, "%*phN", n, p);
246                 }
247
248                 seq_puts(m, " [");
249                 /* put something here to indicate the key's capabilities */
250                 seq_putc(m, ']');
251         }
252 }
253
254 /*
255  * Preparse a asymmetric payload to get format the contents appropriately for the
256  * internal payload to cut down on the number of scans of the data performed.
257  *
258  * We also generate a proposed description from the contents of the key that
259  * can be used to name the key if the user doesn't want to provide one.
260  */
261 static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
262 {
263         struct asymmetric_key_parser *parser;
264         int ret;
265
266         pr_devel("==>%s()\n", __func__);
267
268         if (prep->datalen == 0)
269                 return -EINVAL;
270
271         down_read(&asymmetric_key_parsers_sem);
272
273         ret = -EBADMSG;
274         list_for_each_entry(parser, &asymmetric_key_parsers, link) {
275                 pr_debug("Trying parser '%s'\n", parser->name);
276
277                 ret = parser->parse(prep);
278                 if (ret != -EBADMSG) {
279                         pr_debug("Parser recognised the format (ret %d)\n",
280                                  ret);
281                         break;
282                 }
283         }
284
285         up_read(&asymmetric_key_parsers_sem);
286         pr_devel("<==%s() = %d\n", __func__, ret);
287         return ret;
288 }
289
290 /*
291  * Clean up the preparse data
292  */
293 static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
294 {
295         struct asymmetric_key_subtype *subtype = prep->type_data[0];
296         struct asymmetric_key_ids *kids = prep->type_data[1];
297         int i;
298
299         pr_devel("==>%s()\n", __func__);
300
301         if (subtype) {
302                 subtype->destroy(prep->payload[0]);
303                 module_put(subtype->owner);
304         }
305         if (kids) {
306                 for (i = 0; i < ARRAY_SIZE(kids->id); i++)
307                         kfree(kids->id[i]);
308                 kfree(kids);
309         }
310         kfree(prep->description);
311 }
312
313 /*
314  * dispose of the data dangling from the corpse of a asymmetric key
315  */
316 static void asymmetric_key_destroy(struct key *key)
317 {
318         struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
319         struct asymmetric_key_ids *kids = key->type_data.p[1];
320
321         if (subtype) {
322                 subtype->destroy(key->payload.data);
323                 module_put(subtype->owner);
324                 key->type_data.p[0] = NULL;
325         }
326
327         if (kids) {
328                 kfree(kids->id[0]);
329                 kfree(kids->id[1]);
330                 kfree(kids);
331                 key->type_data.p[1] = NULL;
332         }
333 }
334
335 struct key_type key_type_asymmetric = {
336         .name           = "asymmetric",
337         .preparse       = asymmetric_key_preparse,
338         .free_preparse  = asymmetric_key_free_preparse,
339         .instantiate    = generic_key_instantiate,
340         .match_preparse = asymmetric_key_match_preparse,
341         .match_free     = asymmetric_key_match_free,
342         .destroy        = asymmetric_key_destroy,
343         .describe       = asymmetric_key_describe,
344 };
345 EXPORT_SYMBOL_GPL(key_type_asymmetric);
346
347 /**
348  * register_asymmetric_key_parser - Register a asymmetric key blob parser
349  * @parser: The parser to register
350  */
351 int register_asymmetric_key_parser(struct asymmetric_key_parser *parser)
352 {
353         struct asymmetric_key_parser *cursor;
354         int ret;
355
356         down_write(&asymmetric_key_parsers_sem);
357
358         list_for_each_entry(cursor, &asymmetric_key_parsers, link) {
359                 if (strcmp(cursor->name, parser->name) == 0) {
360                         pr_err("Asymmetric key parser '%s' already registered\n",
361                                parser->name);
362                         ret = -EEXIST;
363                         goto out;
364                 }
365         }
366
367         list_add_tail(&parser->link, &asymmetric_key_parsers);
368
369         pr_notice("Asymmetric key parser '%s' registered\n", parser->name);
370         ret = 0;
371
372 out:
373         up_write(&asymmetric_key_parsers_sem);
374         return ret;
375 }
376 EXPORT_SYMBOL_GPL(register_asymmetric_key_parser);
377
378 /**
379  * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
380  * @parser: The parser to unregister
381  */
382 void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser)
383 {
384         down_write(&asymmetric_key_parsers_sem);
385         list_del(&parser->link);
386         up_write(&asymmetric_key_parsers_sem);
387
388         pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name);
389 }
390 EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser);
391
392 /*
393  * Module stuff
394  */
395 static int __init asymmetric_key_init(void)
396 {
397         return register_key_type(&key_type_asymmetric);
398 }
399
400 static void __exit asymmetric_key_cleanup(void)
401 {
402         unregister_key_type(&key_type_asymmetric);
403 }
404
405 module_init(asymmetric_key_init);
406 module_exit(asymmetric_key_cleanup);