1 /* Asymmetric public-key cryptography key type
3 * See Documentation/security/asymmetric-keys.txt
5 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
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.
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 "asymmetric_keys.h"
20 MODULE_LICENSE("GPL");
22 static LIST_HEAD(asymmetric_key_parsers
);
23 static DECLARE_RWSEM(asymmetric_key_parsers_sem
);
26 * Match asymmetric keys on (part of) their name
27 * We have some shorthand methods for matching keys. We allow:
29 * "<desc>" - request a key by description
30 * "id:<id>" - request a key matching the ID
31 * "<subtype>:<id>" - request a key of a subtype
33 static int asymmetric_key_match(const struct key
*key
, const void *description
)
35 const struct asymmetric_key_subtype
*subtype
= asymmetric_key_subtype(key
);
36 const char *spec
= description
;
41 if (!subtype
|| !spec
|| !*spec
)
44 /* See if the full key description matches as is */
45 if (key
->description
&& strcmp(key
->description
, description
) == 0)
48 /* All tests from here on break the criterion description into a
49 * specifier, a colon and then an identifier.
51 id
= strchr(spec
, ':');
58 /* Anything after here requires a partial match on the ID string */
59 kid
= asymmetric_key_id(key
);
68 kid
+= kidlen
- idlen
;
69 if (strcasecmp(id
, kid
) != 0)
73 memcmp(spec
, "id", 2) == 0)
76 if (speclen
== subtype
->name_len
&&
77 memcmp(spec
, subtype
->name
, speclen
) == 0)
84 * Describe the asymmetric key
86 static void asymmetric_key_describe(const struct key
*key
, struct seq_file
*m
)
88 const struct asymmetric_key_subtype
*subtype
= asymmetric_key_subtype(key
);
89 const char *kid
= asymmetric_key_id(key
);
92 seq_puts(m
, key
->description
);
96 subtype
->describe(key
, m
);
104 seq_puts(m
, kid
+ n
- 8);
108 /* put something here to indicate the key's capabilities */
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.
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.
120 static int asymmetric_key_preparse(struct key_preparsed_payload
*prep
)
122 struct asymmetric_key_parser
*parser
;
125 pr_devel("==>%s()\n", __func__
);
127 if (prep
->datalen
== 0)
130 down_read(&asymmetric_key_parsers_sem
);
133 list_for_each_entry(parser
, &asymmetric_key_parsers
, link
) {
134 pr_debug("Trying parser '%s'\n", parser
->name
);
136 ret
= parser
->parse(prep
);
137 if (ret
!= -EBADMSG
) {
138 pr_debug("Parser recognised the format (ret %d)\n",
144 up_read(&asymmetric_key_parsers_sem
);
145 pr_devel("<==%s() = %d\n", __func__
, ret
);
150 * Clean up the preparse data
152 static void asymmetric_key_free_preparse(struct key_preparsed_payload
*prep
)
154 struct asymmetric_key_subtype
*subtype
= prep
->type_data
[0];
156 pr_devel("==>%s()\n", __func__
);
159 subtype
->destroy(prep
->payload
);
160 module_put(subtype
->owner
);
162 kfree(prep
->type_data
[1]);
163 kfree(prep
->description
);
167 * Instantiate a asymmetric_key defined key. The key was preparsed, so we just
168 * have to transfer the data here.
170 static int asymmetric_key_instantiate(struct key
*key
, struct key_preparsed_payload
*prep
)
174 pr_devel("==>%s()\n", __func__
);
176 ret
= key_payload_reserve(key
, prep
->quotalen
);
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
;
185 pr_devel("<==%s() = %d\n", __func__
, ret
);
190 * dispose of the data dangling from the corpse of a asymmetric key
192 static void asymmetric_key_destroy(struct key
*key
)
194 struct asymmetric_key_subtype
*subtype
= asymmetric_key_subtype(key
);
196 subtype
->destroy(key
->payload
.data
);
197 module_put(subtype
->owner
);
198 key
->type_data
.p
[0] = NULL
;
200 kfree(key
->type_data
.p
[1]);
201 key
->type_data
.p
[1] = NULL
;
204 struct key_type key_type_asymmetric
= {
205 .name
= "asymmetric",
206 .preparse
= asymmetric_key_preparse
,
207 .free_preparse
= asymmetric_key_free_preparse
,
208 .instantiate
= asymmetric_key_instantiate
,
209 .match
= asymmetric_key_match
,
210 .destroy
= asymmetric_key_destroy
,
211 .describe
= asymmetric_key_describe
,
213 EXPORT_SYMBOL_GPL(key_type_asymmetric
);
216 * register_asymmetric_key_parser - Register a asymmetric key blob parser
217 * @parser: The parser to register
219 int register_asymmetric_key_parser(struct asymmetric_key_parser
*parser
)
221 struct asymmetric_key_parser
*cursor
;
224 down_write(&asymmetric_key_parsers_sem
);
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",
235 list_add_tail(&parser
->link
, &asymmetric_key_parsers
);
237 pr_notice("Asymmetric key parser '%s' registered\n", parser
->name
);
241 up_write(&asymmetric_key_parsers_sem
);
244 EXPORT_SYMBOL_GPL(register_asymmetric_key_parser
);
247 * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
248 * @parser: The parser to unregister
250 void unregister_asymmetric_key_parser(struct asymmetric_key_parser
*parser
)
252 down_write(&asymmetric_key_parsers_sem
);
253 list_del(&parser
->link
);
254 up_write(&asymmetric_key_parsers_sem
);
256 pr_notice("Asymmetric key parser '%s' unregistered\n", parser
->name
);
258 EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser
);
263 static int __init
asymmetric_key_init(void)
265 return register_key_type(&key_type_asymmetric
);
268 static void __exit
asymmetric_key_cleanup(void)
270 unregister_key_type(&key_type_asymmetric
);
273 module_init(asymmetric_key_init
);
274 module_exit(asymmetric_key_cleanup
);