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 key id with partial match
27 * @id: key id to match in a form "id:<id>"
29 int asymmetric_keyid_match(const char *kid, const char *id)
36 /* make it possible to use id as in the request: "id:<id>" */
37 if (strncmp(id, "id:", 3) == 0)
40 /* Anything after here requires a partial match on the ID string */
46 kid += kidlen - idlen;
47 if (strcasecmp(id, kid) != 0)
52 EXPORT_SYMBOL_GPL(asymmetric_keyid_match);
55 * Match asymmetric keys on (part of) their name
56 * We have some shorthand methods for matching keys. We allow:
58 * "<desc>" - request a key by description
59 * "id:<id>" - request a key matching the ID
60 * "<subtype>:<id>" - request a key of a subtype
62 static int asymmetric_key_cmp(const struct key *key,
63 const struct key_match_data *match_data)
65 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
66 const char *description = match_data->raw_data;
67 const char *spec = description;
71 if (!subtype || !spec || !*spec)
74 /* See if the full key description matches as is */
75 if (key->description && strcmp(key->description, description) == 0)
78 /* All tests from here on break the criterion description into a
79 * specifier, a colon and then an identifier.
81 id = strchr(spec, ':');
88 if (speclen == 2 && memcmp(spec, "id", 2) == 0)
89 return asymmetric_keyid_match(asymmetric_key_id(key), id);
91 if (speclen == subtype->name_len &&
92 memcmp(spec, subtype->name, speclen) == 0)
99 * Preparse the match criterion. If we don't set lookup_type and cmp,
100 * the default will be an exact match on the key description.
102 * There are some specifiers for matching key IDs rather than by the key
105 * "id:<id>" - request a key by any available ID
107 * These have to be searched by iteration rather than by direct lookup because
108 * the key is hashed according to its description.
110 static int asymmetric_key_match_preparse(struct key_match_data *match_data)
112 match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
113 match_data->cmp = asymmetric_key_cmp;
118 * Free the preparsed the match criterion.
120 static void asymmetric_key_match_free(struct key_match_data *match_data)
125 * Describe the asymmetric key
127 static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
129 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
130 const char *kid = asymmetric_key_id(key);
133 seq_puts(m, key->description);
137 subtype->describe(key, m);
145 seq_puts(m, kid + n - 8);
149 /* put something here to indicate the key's capabilities */
155 * Preparse a asymmetric payload to get format the contents appropriately for the
156 * internal payload to cut down on the number of scans of the data performed.
158 * We also generate a proposed description from the contents of the key that
159 * can be used to name the key if the user doesn't want to provide one.
161 static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
163 struct asymmetric_key_parser *parser;
166 pr_devel("==>%s()\n", __func__);
168 if (prep->datalen == 0)
171 down_read(&asymmetric_key_parsers_sem);
174 list_for_each_entry(parser, &asymmetric_key_parsers, link) {
175 pr_debug("Trying parser '%s'\n", parser->name);
177 ret = parser->parse(prep);
178 if (ret != -EBADMSG) {
179 pr_debug("Parser recognised the format (ret %d)\n",
185 up_read(&asymmetric_key_parsers_sem);
186 pr_devel("<==%s() = %d\n", __func__, ret);
191 * Clean up the preparse data
193 static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
195 struct asymmetric_key_subtype *subtype = prep->type_data[0];
197 pr_devel("==>%s()\n", __func__);
200 subtype->destroy(prep->payload[0]);
201 module_put(subtype->owner);
203 kfree(prep->type_data[1]);
204 kfree(prep->description);
208 * dispose of the data dangling from the corpse of a asymmetric key
210 static void asymmetric_key_destroy(struct key *key)
212 struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
214 subtype->destroy(key->payload.data);
215 module_put(subtype->owner);
216 key->type_data.p[0] = NULL;
218 kfree(key->type_data.p[1]);
219 key->type_data.p[1] = NULL;
222 struct key_type key_type_asymmetric = {
223 .name = "asymmetric",
224 .preparse = asymmetric_key_preparse,
225 .free_preparse = asymmetric_key_free_preparse,
226 .instantiate = generic_key_instantiate,
227 .match_preparse = asymmetric_key_match_preparse,
228 .match_free = asymmetric_key_match_free,
229 .destroy = asymmetric_key_destroy,
230 .describe = asymmetric_key_describe,
232 EXPORT_SYMBOL_GPL(key_type_asymmetric);
235 * register_asymmetric_key_parser - Register a asymmetric key blob parser
236 * @parser: The parser to register
238 int register_asymmetric_key_parser(struct asymmetric_key_parser *parser)
240 struct asymmetric_key_parser *cursor;
243 down_write(&asymmetric_key_parsers_sem);
245 list_for_each_entry(cursor, &asymmetric_key_parsers, link) {
246 if (strcmp(cursor->name, parser->name) == 0) {
247 pr_err("Asymmetric key parser '%s' already registered\n",
254 list_add_tail(&parser->link, &asymmetric_key_parsers);
256 pr_notice("Asymmetric key parser '%s' registered\n", parser->name);
260 up_write(&asymmetric_key_parsers_sem);
263 EXPORT_SYMBOL_GPL(register_asymmetric_key_parser);
266 * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
267 * @parser: The parser to unregister
269 void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser)
271 down_write(&asymmetric_key_parsers_sem);
272 list_del(&parser->link);
273 up_write(&asymmetric_key_parsers_sem);
275 pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name);
277 EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser);
282 static int __init asymmetric_key_init(void)
284 return register_key_type(&key_type_asymmetric);
287 static void __exit asymmetric_key_cleanup(void)
289 unregister_key_type(&key_type_asymmetric);
292 module_init(asymmetric_key_init);
293 module_exit(asymmetric_key_cleanup);