aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-09-13 10:17:32 -0400
committerRusty Russell <rusty@rustcorp.com.au>2012-10-07 23:20:13 -0400
commit46c6f1776e2f53eebb1fc361946877bab7533227 (patch)
treeef326bf43e5b20dbe88f2506481c6bdb4487e3de
parent964f3b3bf49eb84b5831121446a28b76de3fb23a (diff)
KEYS: Asymmetric key pluggable data parsers
The instantiation data passed to the asymmetric key type are expected to be formatted in some way, and there are several possible standard ways to format the data. The two obvious standards are OpenPGP keys and X.509 certificates. The latter is especially useful when dealing with UEFI, and the former might be useful when dealing with, say, eCryptfs. Further, it might be desirable to provide formatted blobs that indicate hardware is to be accessed to retrieve the keys or that the keys live unretrievably in a hardware store, but that the keys can be used by means of the hardware. From userspace, the keys can be loaded using the keyctl command, for example, an X.509 binary certificate: keyctl padd asymmetric foo @s <dhowells.pem or a PGP key: keyctl padd asymmetric bar @s <dhowells.pub or a pointer into the contents of the TPM: keyctl add asymmetric zebra "TPM:04982390582905f8" @s Inside the kernel, pluggable parsers register themselves and then get to examine the payload data to see if they can handle it. If they can, they get to: (1) Propose a name for the key, to be used it the name is "" or NULL. (2) Specify the key subtype. (3) Provide the data for the subtype. The key type asks the parser to do its stuff before a key is allocated and thus before the name is set. If successful, the parser stores the suggested data into the key_preparsed_payload struct, which will be either used (if the key is successfully created and instantiated or updated) or discarded. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c120
-rw-r--r--include/keys/asymmetric-parser.h37
2 files changed, 156 insertions, 1 deletions
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index bfb0424026aa..cf807654d221 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -11,6 +11,7 @@
11 * 2 of the Licence, or (at your option) any later version. 11 * 2 of the Licence, or (at your option) any later version.
12 */ 12 */
13#include <keys/asymmetric-subtype.h> 13#include <keys/asymmetric-subtype.h>
14#include <keys/asymmetric-parser.h>
14#include <linux/seq_file.h> 15#include <linux/seq_file.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/slab.h> 17#include <linux/slab.h>
@@ -18,6 +19,9 @@
18 19
19MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
20 21
22static LIST_HEAD(asymmetric_key_parsers);
23static DECLARE_RWSEM(asymmetric_key_parsers_sem);
24
21/* 25/*
22 * Match asymmetric keys on (part of) their name 26 * Match asymmetric keys on (part of) their name
23 * We have some shorthand methods for matching keys. We allow: 27 * We have some shorthand methods for matching keys. We allow:
@@ -107,12 +111,79 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
107} 111}
108 112
109/* 113/*
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.
116 *
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.
119 */
120static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
121{
122 struct asymmetric_key_parser *parser;
123 int ret;
124
125 pr_devel("==>%s()\n", __func__);
126
127 if (prep->datalen == 0)
128 return -EINVAL;
129
130 down_read(&asymmetric_key_parsers_sem);
131
132 ret = -EBADMSG;
133 list_for_each_entry(parser, &asymmetric_key_parsers, link) {
134 pr_debug("Trying parser '%s'\n", parser->name);
135
136 ret = parser->parse(prep);
137 if (ret != -EBADMSG) {
138 pr_debug("Parser recognised the format (ret %d)\n",
139 ret);
140 break;
141 }
142 }
143
144 up_read(&asymmetric_key_parsers_sem);
145 pr_devel("<==%s() = %d\n", __func__, ret);
146 return ret;
147}
148
149/*
150 * Clean up the preparse data
151 */
152static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
153{
154 struct asymmetric_key_subtype *subtype = prep->type_data[0];
155
156 pr_devel("==>%s()\n", __func__);
157
158 if (subtype) {
159 subtype->destroy(prep->payload);
160 module_put(subtype->owner);
161 }
162 kfree(prep->type_data[1]);
163 kfree(prep->description);
164}
165
166/*
110 * Instantiate a asymmetric_key defined key. The key was preparsed, so we just 167 * Instantiate a asymmetric_key defined key. The key was preparsed, so we just
111 * have to transfer the data here. 168 * have to transfer the data here.
112 */ 169 */
113static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) 170static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
114{ 171{
115 return -EOPNOTSUPP; 172 int ret;
173
174 pr_devel("==>%s()\n", __func__);
175
176 ret = key_payload_reserve(key, prep->quotalen);
177 if (ret == 0) {
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;
184 }
185 pr_devel("<==%s() = %d\n", __func__, ret);
186 return ret;
116} 187}
117 188
118/* 189/*
@@ -132,6 +203,8 @@ static void asymmetric_key_destroy(struct key *key)
132 203
133struct key_type key_type_asymmetric = { 204struct key_type key_type_asymmetric = {
134 .name = "asymmetric", 205 .name = "asymmetric",
206 .preparse = asymmetric_key_preparse,
207 .free_preparse = asymmetric_key_free_preparse,
135 .instantiate = asymmetric_key_instantiate, 208 .instantiate = asymmetric_key_instantiate,
136 .match = asymmetric_key_match, 209 .match = asymmetric_key_match,
137 .destroy = asymmetric_key_destroy, 210 .destroy = asymmetric_key_destroy,
@@ -139,6 +212,51 @@ struct key_type key_type_asymmetric = {
139}; 212};
140EXPORT_SYMBOL_GPL(key_type_asymmetric); 213EXPORT_SYMBOL_GPL(key_type_asymmetric);
141 214
215/**
216 * register_asymmetric_key_parser - Register a asymmetric key blob parser
217 * @parser: The parser to register
218 */
219int register_asymmetric_key_parser(struct asymmetric_key_parser *parser)
220{
221 struct asymmetric_key_parser *cursor;
222 int ret;
223
224 down_write(&asymmetric_key_parsers_sem);
225
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",
229 parser->name);
230 ret = -EEXIST;
231 goto out;
232 }
233 }
234
235 list_add_tail(&parser->link, &asymmetric_key_parsers);
236
237 pr_notice("Asymmetric key parser '%s' registered\n", parser->name);
238 ret = 0;
239
240out:
241 up_write(&asymmetric_key_parsers_sem);
242 return ret;
243}
244EXPORT_SYMBOL_GPL(register_asymmetric_key_parser);
245
246/**
247 * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
248 * @parser: The parser to unregister
249 */
250void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser)
251{
252 down_write(&asymmetric_key_parsers_sem);
253 list_del(&parser->link);
254 up_write(&asymmetric_key_parsers_sem);
255
256 pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name);
257}
258EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser);
259
142/* 260/*
143 * Module stuff 261 * Module stuff
144 */ 262 */
diff --git a/include/keys/asymmetric-parser.h b/include/keys/asymmetric-parser.h
new file mode 100644
index 000000000000..09b3b4807f5c
--- /dev/null
+++ b/include/keys/asymmetric-parser.h
@@ -0,0 +1,37 @@
1/* Asymmetric public-key cryptography data parser
2 *
3 * See Documentation/crypto/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
14#ifndef _KEYS_ASYMMETRIC_PARSER_H
15#define _KEYS_ASYMMETRIC_PARSER_H
16
17/*
18 * Key data parser. Called during key instantiation.
19 */
20struct asymmetric_key_parser {
21 struct list_head link;
22 struct module *owner;
23 const char *name;
24
25 /* Attempt to parse a key from the data blob passed to add_key() or
26 * keyctl_instantiate(). Should also generate a proposed description
27 * that the caller can optionally use for the key.
28 *
29 * Return EBADMSG if not recognised.
30 */
31 int (*parse)(struct key_preparsed_payload *prep);
32};
33
34extern int register_asymmetric_key_parser(struct asymmetric_key_parser *);
35extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *);
36
37#endif /* _KEYS_ASYMMETRIC_PARSER_H */