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_match(const struct key *key, const void *description)
64 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
65 const char *spec = description;
69 if (!subtype || !spec || !*spec)
72 /* See if the full key description matches as is */
73 if (key->description && strcmp(key->description, description) == 0)
76 /* All tests from here on break the criterion description into a
77 * specifier, a colon and then an identifier.
79 id = strchr(spec, ':');
86 if (speclen == 2 && memcmp(spec, "id", 2) == 0)
87 return asymmetric_keyid_match(asymmetric_key_id(key), id);
89 if (speclen == subtype->name_len &&
90 memcmp(spec, subtype->name, speclen) == 0)
97 * Describe the asymmetric key
99 static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
101 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
102 const char *kid = asymmetric_key_id(key);
105 seq_puts(m, key->description);
109 subtype->describe(key, m);
117 seq_puts(m, kid + n - 8);
121 /* put something here to indicate the key's capabilities */
127 * Preparse a asymmetric payload to get format the contents appropriately for the
128 * internal payload to cut down on the number of scans of the data performed.
130 * We also generate a proposed description from the contents of the key that
131 * can be used to name the key if the user doesn't want to provide one.
133 static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
135 struct asymmetric_key_parser *parser;
138 pr_devel("==>%s()\n", __func__);
140 if (prep->datalen == 0)
143 down_read(&asymmetric_key_parsers_sem);
146 list_for_each_entry(parser, &asymmetric_key_parsers, link) {
147 pr_debug("Trying parser '%s'\n", parser->name);
149 ret = parser->parse(prep);
150 if (ret != -EBADMSG) {
151 pr_debug("Parser recognised the format (ret %d)\n",
157 up_read(&asymmetric_key_parsers_sem);
158 pr_devel("<==%s() = %d\n", __func__, ret);
163 * Clean up the preparse data
165 static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
167 struct asymmetric_key_subtype *subtype = prep->type_data[0];
169 pr_devel("==>%s()\n", __func__);
172 subtype->destroy(prep->payload[0]);
173 module_put(subtype->owner);
175 kfree(prep->type_data[1]);
176 kfree(prep->description);
180 * dispose of the data dangling from the corpse of a asymmetric key
182 static void asymmetric_key_destroy(struct key *key)
184 struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
186 subtype->destroy(key->payload.data);
187 module_put(subtype->owner);
188 key->type_data.p[0] = NULL;
190 kfree(key->type_data.p[1]);
191 key->type_data.p[1] = NULL;
194 struct key_type key_type_asymmetric = {
195 .name = "asymmetric",
196 .preparse = asymmetric_key_preparse,
197 .free_preparse = asymmetric_key_free_preparse,
198 .instantiate = generic_key_instantiate,
199 .match = asymmetric_key_match,
200 .destroy = asymmetric_key_destroy,
201 .describe = asymmetric_key_describe,
202 .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE,
204 EXPORT_SYMBOL_GPL(key_type_asymmetric);
207 * register_asymmetric_key_parser - Register a asymmetric key blob parser
208 * @parser: The parser to register
210 int register_asymmetric_key_parser(struct asymmetric_key_parser *parser)
212 struct asymmetric_key_parser *cursor;
215 down_write(&asymmetric_key_parsers_sem);
217 list_for_each_entry(cursor, &asymmetric_key_parsers, link) {
218 if (strcmp(cursor->name, parser->name) == 0) {
219 pr_err("Asymmetric key parser '%s' already registered\n",
226 list_add_tail(&parser->link, &asymmetric_key_parsers);
228 pr_notice("Asymmetric key parser '%s' registered\n", parser->name);
232 up_write(&asymmetric_key_parsers_sem);
235 EXPORT_SYMBOL_GPL(register_asymmetric_key_parser);
238 * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
239 * @parser: The parser to unregister
241 void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser)
243 down_write(&asymmetric_key_parsers_sem);
244 list_del(&parser->link);
245 up_write(&asymmetric_key_parsers_sem);
247 pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name);
249 EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser);
254 static int __init asymmetric_key_init(void)
256 return register_key_type(&key_type_asymmetric);
259 static void __exit asymmetric_key_cleanup(void)
261 unregister_key_type(&key_type_asymmetric);
264 module_init(asymmetric_key_init);
265 module_exit(asymmetric_key_cleanup);