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  */
asymmetric_key_generate_id(const void * val_1,size_t len_1,const void * val_2,size_t len_2)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  */
asymmetric_key_id_same(const struct asymmetric_key_id * kid1,const struct asymmetric_key_id * kid2)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  */
asymmetric_key_id_partial(const struct asymmetric_key_id * kid1,const struct asymmetric_key_id * kid2)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  */
asymmetric_match_key_ids(const struct asymmetric_key_ids * kids,const struct asymmetric_key_id * match_id,bool (* match)(const struct asymmetric_key_id * kid1,const struct asymmetric_key_id * kid2))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 */
__asymmetric_key_hex_to_key_id(const char * id,struct asymmetric_key_id * match_id,size_t hexlen)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  */
asymmetric_key_hex_to_key_id(const char * id)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  */
asymmetric_key_cmp(const struct key * key,const struct key_match_data * match_data)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  */
asymmetric_key_cmp_partial(const struct key * key,const struct key_match_data * match_data)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  */
asymmetric_key_match_preparse(struct key_match_data * match_data)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  */
asymmetric_key_match_free(struct key_match_data * match_data)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  */
asymmetric_key_describe(const struct key * key,struct seq_file * m)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  */
asymmetric_key_preparse(struct key_preparsed_payload * prep)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 key ID list
311  */
asymmetric_key_free_kids(struct asymmetric_key_ids * kids)312 static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids)
313 {
314 	int i;
315 
316 	if (kids) {
317 		for (i = 0; i < ARRAY_SIZE(kids->id); i++)
318 			kfree(kids->id[i]);
319 		kfree(kids);
320 	}
321 }
322 
323 /*
324  * Clean up the preparse data
325  */
asymmetric_key_free_preparse(struct key_preparsed_payload * prep)326 static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
327 {
328 	struct asymmetric_key_subtype *subtype = prep->payload.data[asym_subtype];
329 	struct asymmetric_key_ids *kids = prep->payload.data[asym_key_ids];
330 
331 	pr_devel("==>%s()\n", __func__);
332 
333 	if (subtype) {
334 		subtype->destroy(prep->payload.data[asym_crypto]);
335 		module_put(subtype->owner);
336 	}
337 	asymmetric_key_free_kids(kids);
338 	kfree(prep->description);
339 }
340 
341 /*
342  * dispose of the data dangling from the corpse of a asymmetric key
343  */
asymmetric_key_destroy(struct key * key)344 static void asymmetric_key_destroy(struct key *key)
345 {
346 	struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
347 	struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids];
348 	void *data = key->payload.data[asym_crypto];
349 
350 	key->payload.data[asym_crypto] = NULL;
351 	key->payload.data[asym_subtype] = NULL;
352 	key->payload.data[asym_key_ids] = NULL;
353 
354 	if (subtype) {
355 		subtype->destroy(data);
356 		module_put(subtype->owner);
357 	}
358 
359 	asymmetric_key_free_kids(kids);
360 }
361 
362 struct key_type key_type_asymmetric = {
363 	.name		= "asymmetric",
364 	.preparse	= asymmetric_key_preparse,
365 	.free_preparse	= asymmetric_key_free_preparse,
366 	.instantiate	= generic_key_instantiate,
367 	.match_preparse	= asymmetric_key_match_preparse,
368 	.match_free	= asymmetric_key_match_free,
369 	.destroy	= asymmetric_key_destroy,
370 	.describe	= asymmetric_key_describe,
371 };
372 EXPORT_SYMBOL_GPL(key_type_asymmetric);
373 
374 /**
375  * register_asymmetric_key_parser - Register a asymmetric key blob parser
376  * @parser: The parser to register
377  */
register_asymmetric_key_parser(struct asymmetric_key_parser * parser)378 int register_asymmetric_key_parser(struct asymmetric_key_parser *parser)
379 {
380 	struct asymmetric_key_parser *cursor;
381 	int ret;
382 
383 	down_write(&asymmetric_key_parsers_sem);
384 
385 	list_for_each_entry(cursor, &asymmetric_key_parsers, link) {
386 		if (strcmp(cursor->name, parser->name) == 0) {
387 			pr_err("Asymmetric key parser '%s' already registered\n",
388 			       parser->name);
389 			ret = -EEXIST;
390 			goto out;
391 		}
392 	}
393 
394 	list_add_tail(&parser->link, &asymmetric_key_parsers);
395 
396 	pr_notice("Asymmetric key parser '%s' registered\n", parser->name);
397 	ret = 0;
398 
399 out:
400 	up_write(&asymmetric_key_parsers_sem);
401 	return ret;
402 }
403 EXPORT_SYMBOL_GPL(register_asymmetric_key_parser);
404 
405 /**
406  * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
407  * @parser: The parser to unregister
408  */
unregister_asymmetric_key_parser(struct asymmetric_key_parser * parser)409 void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser)
410 {
411 	down_write(&asymmetric_key_parsers_sem);
412 	list_del(&parser->link);
413 	up_write(&asymmetric_key_parsers_sem);
414 
415 	pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name);
416 }
417 EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser);
418 
419 /*
420  * Module stuff
421  */
asymmetric_key_init(void)422 static int __init asymmetric_key_init(void)
423 {
424 	return register_key_type(&key_type_asymmetric);
425 }
426 
asymmetric_key_cleanup(void)427 static void __exit asymmetric_key_cleanup(void)
428 {
429 	unregister_key_type(&key_type_asymmetric);
430 }
431 
432 module_init(asymmetric_key_init);
433 module_exit(asymmetric_key_cleanup);
434