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