1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Asymmetric public-key cryptography key type
3 *
4 * See Documentation/crypto/asymmetric-keys.txt
5 *
6 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
7 * Written by David Howells (dhowells@redhat.com)
8 */
9 #ifndef __UBOOT__
10 #include <log.h>
11 #include <dm/devres.h>
12 #include <keys/asymmetric-subtype.h>
13 #include <keys/asymmetric-parser.h>
14 #endif
15 #ifdef __UBOOT__
16 #include <linux/bug.h>
17 #include <linux/compat.h>
18 #include <linux/ctype.h>
19 #include <linux/err.h>
20 #include <linux/printk.h>
21 #include <linux/string.h>
22 #else
23 #include <linux/seq_file.h>
24 #include <linux/module.h>
25 #include <linux/slab.h>
26 #include <linux/ctype.h>
27 #endif
28 #include <crypto/public_key.h>
29 #ifdef __UBOOT__
30 #include <keys/asymmetric-type.h>
31 #else
32 #include <keys/system_keyring.h>
33 #include <keys/user-type.h>
34 #include "asymmetric_keys.h"
35 #endif
36
37 MODULE_LICENSE("GPL");
38
39 #ifndef __UBOOT__
40 const char *const key_being_used_for[NR__KEY_BEING_USED_FOR] = {
41 [VERIFYING_MODULE_SIGNATURE] = "mod sig",
42 [VERIFYING_FIRMWARE_SIGNATURE] = "firmware sig",
43 [VERIFYING_KEXEC_PE_SIGNATURE] = "kexec PE sig",
44 [VERIFYING_KEY_SIGNATURE] = "key sig",
45 [VERIFYING_KEY_SELF_SIGNATURE] = "key self sig",
46 [VERIFYING_UNSPECIFIED_SIGNATURE] = "unspec sig",
47 };
48 EXPORT_SYMBOL_GPL(key_being_used_for);
49
50 static LIST_HEAD(asymmetric_key_parsers);
51 static DECLARE_RWSEM(asymmetric_key_parsers_sem);
52
53 /**
54 * find_asymmetric_key - Find a key by ID.
55 * @keyring: The keys to search.
56 * @id_0: The first ID to look for or NULL.
57 * @id_1: The second ID to look for or NULL.
58 * @partial: Use partial match if true, exact if false.
59 *
60 * Find a key in the given keyring by identifier. The preferred identifier is
61 * the id_0 and the fallback identifier is the id_1. If both are given, the
62 * lookup is by the former, but the latter must also match.
63 */
find_asymmetric_key(struct key * keyring,const struct asymmetric_key_id * id_0,const struct asymmetric_key_id * id_1,bool partial)64 struct key *find_asymmetric_key(struct key *keyring,
65 const struct asymmetric_key_id *id_0,
66 const struct asymmetric_key_id *id_1,
67 bool partial)
68 {
69 struct key *key;
70 key_ref_t ref;
71 const char *lookup;
72 char *req, *p;
73 int len;
74
75 BUG_ON(!id_0 && !id_1);
76
77 if (id_0) {
78 lookup = id_0->data;
79 len = id_0->len;
80 } else {
81 lookup = id_1->data;
82 len = id_1->len;
83 }
84
85 /* Construct an identifier "id:<keyid>". */
86 p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL);
87 if (!req)
88 return ERR_PTR(-ENOMEM);
89
90 if (partial) {
91 *p++ = 'i';
92 *p++ = 'd';
93 } else {
94 *p++ = 'e';
95 *p++ = 'x';
96 }
97 *p++ = ':';
98 p = bin2hex(p, lookup, len);
99 *p = 0;
100
101 pr_debug("Look up: \"%s\"\n", req);
102
103 ref = keyring_search(make_key_ref(keyring, 1),
104 &key_type_asymmetric, req, true);
105 if (IS_ERR(ref))
106 pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
107 kfree(req);
108
109 if (IS_ERR(ref)) {
110 switch (PTR_ERR(ref)) {
111 /* Hide some search errors */
112 case -EACCES:
113 case -ENOTDIR:
114 case -EAGAIN:
115 return ERR_PTR(-ENOKEY);
116 default:
117 return ERR_CAST(ref);
118 }
119 }
120
121 key = key_ref_to_ptr(ref);
122 if (id_0 && id_1) {
123 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
124
125 if (!kids->id[1]) {
126 pr_debug("First ID matches, but second is missing\n");
127 goto reject;
128 }
129 if (!asymmetric_key_id_same(id_1, kids->id[1])) {
130 pr_debug("First ID matches, but second does not\n");
131 goto reject;
132 }
133 }
134
135 pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key));
136 return key;
137
138 reject:
139 key_put(key);
140 return ERR_PTR(-EKEYREJECTED);
141 }
142 EXPORT_SYMBOL_GPL(find_asymmetric_key);
143 #endif /* !__UBOOT__ */
144
145 /**
146 * asymmetric_key_generate_id: Construct an asymmetric key ID
147 * @val_1: First binary blob
148 * @len_1: Length of first binary blob
149 * @val_2: Second binary blob
150 * @len_2: Length of second binary blob
151 *
152 * Construct an asymmetric key ID from a pair of binary blobs.
153 */
asymmetric_key_generate_id(const void * val_1,size_t len_1,const void * val_2,size_t len_2)154 struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
155 size_t len_1,
156 const void *val_2,
157 size_t len_2)
158 {
159 struct asymmetric_key_id *kid;
160
161 kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2,
162 GFP_KERNEL);
163 if (!kid)
164 return ERR_PTR(-ENOMEM);
165 kid->len = len_1 + len_2;
166 memcpy(kid->data, val_1, len_1);
167 memcpy(kid->data + len_1, val_2, len_2);
168 return kid;
169 }
170 EXPORT_SYMBOL_GPL(asymmetric_key_generate_id);
171
172 /**
173 * asymmetric_key_id_same - Return true if two asymmetric keys IDs are the same.
174 * @kid_1, @kid_2: The key IDs to compare
175 */
asymmetric_key_id_same(const struct asymmetric_key_id * kid1,const struct asymmetric_key_id * kid2)176 bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
177 const struct asymmetric_key_id *kid2)
178 {
179 if (!kid1 || !kid2)
180 return false;
181 if (kid1->len != kid2->len)
182 return false;
183 return memcmp(kid1->data, kid2->data, kid1->len) == 0;
184 }
185 EXPORT_SYMBOL_GPL(asymmetric_key_id_same);
186
187 /**
188 * asymmetric_key_id_partial - Return true if two asymmetric keys IDs
189 * partially match
190 * @kid_1, @kid_2: The key IDs to compare
191 */
asymmetric_key_id_partial(const struct asymmetric_key_id * kid1,const struct asymmetric_key_id * kid2)192 bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1,
193 const struct asymmetric_key_id *kid2)
194 {
195 if (!kid1 || !kid2)
196 return false;
197 if (kid1->len < kid2->len)
198 return false;
199 return memcmp(kid1->data + (kid1->len - kid2->len),
200 kid2->data, kid2->len) == 0;
201 }
202 EXPORT_SYMBOL_GPL(asymmetric_key_id_partial);
203
204 #ifndef __UBOOT__
205 /**
206 * asymmetric_match_key_ids - Search asymmetric key IDs
207 * @kids: The list of key IDs to check
208 * @match_id: The key ID we're looking for
209 * @match: The match function to use
210 */
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))211 static bool asymmetric_match_key_ids(
212 const struct asymmetric_key_ids *kids,
213 const struct asymmetric_key_id *match_id,
214 bool (*match)(const struct asymmetric_key_id *kid1,
215 const struct asymmetric_key_id *kid2))
216 {
217 int i;
218
219 if (!kids || !match_id)
220 return false;
221 for (i = 0; i < ARRAY_SIZE(kids->id); i++)
222 if (match(kids->id[i], match_id))
223 return true;
224 return false;
225 }
226
227 /* 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)228 inline int __asymmetric_key_hex_to_key_id(const char *id,
229 struct asymmetric_key_id *match_id,
230 size_t hexlen)
231 {
232 match_id->len = hexlen;
233 return hex2bin(match_id->data, id, hexlen);
234 }
235
236 /**
237 * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
238 * @id: The ID as a hex string.
239 */
asymmetric_key_hex_to_key_id(const char * id)240 struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
241 {
242 struct asymmetric_key_id *match_id;
243 size_t asciihexlen;
244 int ret;
245
246 if (!*id)
247 return ERR_PTR(-EINVAL);
248 asciihexlen = strlen(id);
249 if (asciihexlen & 1)
250 return ERR_PTR(-EINVAL);
251
252 match_id = kmalloc(sizeof(struct asymmetric_key_id) + asciihexlen / 2,
253 GFP_KERNEL);
254 if (!match_id)
255 return ERR_PTR(-ENOMEM);
256 ret = __asymmetric_key_hex_to_key_id(id, match_id, asciihexlen / 2);
257 if (ret < 0) {
258 kfree(match_id);
259 return ERR_PTR(-EINVAL);
260 }
261 return match_id;
262 }
263
264 /*
265 * Match asymmetric keys by an exact match on an ID.
266 */
asymmetric_key_cmp(const struct key * key,const struct key_match_data * match_data)267 static bool asymmetric_key_cmp(const struct key *key,
268 const struct key_match_data *match_data)
269 {
270 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
271 const struct asymmetric_key_id *match_id = match_data->preparsed;
272
273 return asymmetric_match_key_ids(kids, match_id,
274 asymmetric_key_id_same);
275 }
276
277 /*
278 * Match asymmetric keys by a partial match on an IDs.
279 */
asymmetric_key_cmp_partial(const struct key * key,const struct key_match_data * match_data)280 static bool asymmetric_key_cmp_partial(const struct key *key,
281 const struct key_match_data *match_data)
282 {
283 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
284 const struct asymmetric_key_id *match_id = match_data->preparsed;
285
286 return asymmetric_match_key_ids(kids, match_id,
287 asymmetric_key_id_partial);
288 }
289
290 /*
291 * Preparse the match criterion. If we don't set lookup_type and cmp,
292 * the default will be an exact match on the key description.
293 *
294 * There are some specifiers for matching key IDs rather than by the key
295 * description:
296 *
297 * "id:<id>" - find a key by partial match on any available ID
298 * "ex:<id>" - find a key by exact match on any available ID
299 *
300 * These have to be searched by iteration rather than by direct lookup because
301 * the key is hashed according to its description.
302 */
asymmetric_key_match_preparse(struct key_match_data * match_data)303 static int asymmetric_key_match_preparse(struct key_match_data *match_data)
304 {
305 struct asymmetric_key_id *match_id;
306 const char *spec = match_data->raw_data;
307 const char *id;
308 bool (*cmp)(const struct key *, const struct key_match_data *) =
309 asymmetric_key_cmp;
310
311 if (!spec || !*spec)
312 return -EINVAL;
313 if (spec[0] == 'i' &&
314 spec[1] == 'd' &&
315 spec[2] == ':') {
316 id = spec + 3;
317 cmp = asymmetric_key_cmp_partial;
318 } else if (spec[0] == 'e' &&
319 spec[1] == 'x' &&
320 spec[2] == ':') {
321 id = spec + 3;
322 } else {
323 goto default_match;
324 }
325
326 match_id = asymmetric_key_hex_to_key_id(id);
327 if (IS_ERR(match_id))
328 return PTR_ERR(match_id);
329
330 match_data->preparsed = match_id;
331 match_data->cmp = cmp;
332 match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
333 return 0;
334
335 default_match:
336 return 0;
337 }
338
339 /*
340 * Free the preparsed the match criterion.
341 */
asymmetric_key_match_free(struct key_match_data * match_data)342 static void asymmetric_key_match_free(struct key_match_data *match_data)
343 {
344 kfree(match_data->preparsed);
345 }
346
347 /*
348 * Describe the asymmetric key
349 */
asymmetric_key_describe(const struct key * key,struct seq_file * m)350 static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
351 {
352 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
353 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
354 const struct asymmetric_key_id *kid;
355 const unsigned char *p;
356 int n;
357
358 seq_puts(m, key->description);
359
360 if (subtype) {
361 seq_puts(m, ": ");
362 subtype->describe(key, m);
363
364 if (kids && kids->id[1]) {
365 kid = kids->id[1];
366 seq_putc(m, ' ');
367 n = kid->len;
368 p = kid->data;
369 if (n > 4) {
370 p += n - 4;
371 n = 4;
372 }
373 seq_printf(m, "%*phN", n, p);
374 }
375
376 seq_puts(m, " [");
377 /* put something here to indicate the key's capabilities */
378 seq_putc(m, ']');
379 }
380 }
381
382 /*
383 * Preparse a asymmetric payload to get format the contents appropriately for the
384 * internal payload to cut down on the number of scans of the data performed.
385 *
386 * We also generate a proposed description from the contents of the key that
387 * can be used to name the key if the user doesn't want to provide one.
388 */
asymmetric_key_preparse(struct key_preparsed_payload * prep)389 static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
390 {
391 struct asymmetric_key_parser *parser;
392 int ret;
393
394 pr_devel("==>%s()\n", __func__);
395
396 if (prep->datalen == 0)
397 return -EINVAL;
398
399 down_read(&asymmetric_key_parsers_sem);
400
401 ret = -EBADMSG;
402 list_for_each_entry(parser, &asymmetric_key_parsers, link) {
403 pr_debug("Trying parser '%s'\n", parser->name);
404
405 ret = parser->parse(prep);
406 if (ret != -EBADMSG) {
407 pr_debug("Parser recognised the format (ret %d)\n",
408 ret);
409 break;
410 }
411 }
412
413 up_read(&asymmetric_key_parsers_sem);
414 pr_devel("<==%s() = %d\n", __func__, ret);
415 return ret;
416 }
417
418 /*
419 * Clean up the key ID list
420 */
asymmetric_key_free_kids(struct asymmetric_key_ids * kids)421 static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids)
422 {
423 int i;
424
425 if (kids) {
426 for (i = 0; i < ARRAY_SIZE(kids->id); i++)
427 kfree(kids->id[i]);
428 kfree(kids);
429 }
430 }
431
432 /*
433 * Clean up the preparse data
434 */
asymmetric_key_free_preparse(struct key_preparsed_payload * prep)435 static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
436 {
437 struct asymmetric_key_subtype *subtype = prep->payload.data[asym_subtype];
438 struct asymmetric_key_ids *kids = prep->payload.data[asym_key_ids];
439
440 pr_devel("==>%s()\n", __func__);
441
442 if (subtype) {
443 subtype->destroy(prep->payload.data[asym_crypto],
444 prep->payload.data[asym_auth]);
445 module_put(subtype->owner);
446 }
447 asymmetric_key_free_kids(kids);
448 kfree(prep->description);
449 }
450
451 /*
452 * dispose of the data dangling from the corpse of a asymmetric key
453 */
asymmetric_key_destroy(struct key * key)454 static void asymmetric_key_destroy(struct key *key)
455 {
456 struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
457 struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids];
458 void *data = key->payload.data[asym_crypto];
459 void *auth = key->payload.data[asym_auth];
460
461 key->payload.data[asym_crypto] = NULL;
462 key->payload.data[asym_subtype] = NULL;
463 key->payload.data[asym_key_ids] = NULL;
464 key->payload.data[asym_auth] = NULL;
465
466 if (subtype) {
467 subtype->destroy(data, auth);
468 module_put(subtype->owner);
469 }
470
471 asymmetric_key_free_kids(kids);
472 }
473
asymmetric_restriction_alloc(key_restrict_link_func_t check,struct key * key)474 static struct key_restriction *asymmetric_restriction_alloc(
475 key_restrict_link_func_t check,
476 struct key *key)
477 {
478 struct key_restriction *keyres =
479 kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
480
481 if (!keyres)
482 return ERR_PTR(-ENOMEM);
483
484 keyres->check = check;
485 keyres->key = key;
486 keyres->keytype = &key_type_asymmetric;
487
488 return keyres;
489 }
490
491 /*
492 * look up keyring restrict functions for asymmetric keys
493 */
asymmetric_lookup_restriction(const char * restriction)494 static struct key_restriction *asymmetric_lookup_restriction(
495 const char *restriction)
496 {
497 char *restrict_method;
498 char *parse_buf;
499 char *next;
500 struct key_restriction *ret = ERR_PTR(-EINVAL);
501
502 if (strcmp("builtin_trusted", restriction) == 0)
503 return asymmetric_restriction_alloc(
504 restrict_link_by_builtin_trusted, NULL);
505
506 if (strcmp("builtin_and_secondary_trusted", restriction) == 0)
507 return asymmetric_restriction_alloc(
508 restrict_link_by_builtin_and_secondary_trusted, NULL);
509
510 parse_buf = kstrndup(restriction, PAGE_SIZE, GFP_KERNEL);
511 if (!parse_buf)
512 return ERR_PTR(-ENOMEM);
513
514 next = parse_buf;
515 restrict_method = strsep(&next, ":");
516
517 if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) {
518 char *key_text;
519 key_serial_t serial;
520 struct key *key;
521 key_restrict_link_func_t link_fn =
522 restrict_link_by_key_or_keyring;
523 bool allow_null_key = false;
524
525 key_text = strsep(&next, ":");
526
527 if (next) {
528 if (strcmp(next, "chain") != 0)
529 goto out;
530
531 link_fn = restrict_link_by_key_or_keyring_chain;
532 allow_null_key = true;
533 }
534
535 if (kstrtos32(key_text, 0, &serial) < 0)
536 goto out;
537
538 if ((serial == 0) && allow_null_key) {
539 key = NULL;
540 } else {
541 key = key_lookup(serial);
542 if (IS_ERR(key)) {
543 ret = ERR_CAST(key);
544 goto out;
545 }
546 }
547
548 ret = asymmetric_restriction_alloc(link_fn, key);
549 if (IS_ERR(ret))
550 key_put(key);
551 }
552
553 out:
554 kfree(parse_buf);
555 return ret;
556 }
557
asymmetric_key_eds_op(struct kernel_pkey_params * params,const void * in,void * out)558 int asymmetric_key_eds_op(struct kernel_pkey_params *params,
559 const void *in, void *out)
560 {
561 const struct asymmetric_key_subtype *subtype;
562 struct key *key = params->key;
563 int ret;
564
565 pr_devel("==>%s()\n", __func__);
566
567 if (key->type != &key_type_asymmetric)
568 return -EINVAL;
569 subtype = asymmetric_key_subtype(key);
570 if (!subtype ||
571 !key->payload.data[0])
572 return -EINVAL;
573 if (!subtype->eds_op)
574 return -ENOTSUPP;
575
576 ret = subtype->eds_op(params, in, out);
577
578 pr_devel("<==%s() = %d\n", __func__, ret);
579 return ret;
580 }
581
asymmetric_key_verify_signature(struct kernel_pkey_params * params,const void * in,const void * in2)582 static int asymmetric_key_verify_signature(struct kernel_pkey_params *params,
583 const void *in, const void *in2)
584 {
585 struct public_key_signature sig = {
586 .s_size = params->in2_len,
587 .digest_size = params->in_len,
588 .encoding = params->encoding,
589 .hash_algo = params->hash_algo,
590 .digest = (void *)in,
591 .s = (void *)in2,
592 };
593
594 return verify_signature(params->key, &sig);
595 }
596
597 struct key_type key_type_asymmetric = {
598 .name = "asymmetric",
599 .preparse = asymmetric_key_preparse,
600 .free_preparse = asymmetric_key_free_preparse,
601 .instantiate = generic_key_instantiate,
602 .match_preparse = asymmetric_key_match_preparse,
603 .match_free = asymmetric_key_match_free,
604 .destroy = asymmetric_key_destroy,
605 .describe = asymmetric_key_describe,
606 .lookup_restriction = asymmetric_lookup_restriction,
607 .asym_query = query_asymmetric_key,
608 .asym_eds_op = asymmetric_key_eds_op,
609 .asym_verify_signature = asymmetric_key_verify_signature,
610 };
611 EXPORT_SYMBOL_GPL(key_type_asymmetric);
612
613 /**
614 * register_asymmetric_key_parser - Register a asymmetric key blob parser
615 * @parser: The parser to register
616 */
register_asymmetric_key_parser(struct asymmetric_key_parser * parser)617 int register_asymmetric_key_parser(struct asymmetric_key_parser *parser)
618 {
619 struct asymmetric_key_parser *cursor;
620 int ret;
621
622 down_write(&asymmetric_key_parsers_sem);
623
624 list_for_each_entry(cursor, &asymmetric_key_parsers, link) {
625 if (strcmp(cursor->name, parser->name) == 0) {
626 pr_err("Asymmetric key parser '%s' already registered\n",
627 parser->name);
628 ret = -EEXIST;
629 goto out;
630 }
631 }
632
633 list_add_tail(&parser->link, &asymmetric_key_parsers);
634
635 pr_notice("Asymmetric key parser '%s' registered\n", parser->name);
636 ret = 0;
637
638 out:
639 up_write(&asymmetric_key_parsers_sem);
640 return ret;
641 }
642 EXPORT_SYMBOL_GPL(register_asymmetric_key_parser);
643
644 /**
645 * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
646 * @parser: The parser to unregister
647 */
unregister_asymmetric_key_parser(struct asymmetric_key_parser * parser)648 void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser)
649 {
650 down_write(&asymmetric_key_parsers_sem);
651 list_del(&parser->link);
652 up_write(&asymmetric_key_parsers_sem);
653
654 pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name);
655 }
656 EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser);
657
658 /*
659 * Module stuff
660 */
asymmetric_key_init(void)661 static int __init asymmetric_key_init(void)
662 {
663 return register_key_type(&key_type_asymmetric);
664 }
665
asymmetric_key_cleanup(void)666 static void __exit asymmetric_key_cleanup(void)
667 {
668 unregister_key_type(&key_type_asymmetric);
669 }
670
671 module_init(asymmetric_key_init);
672 module_exit(asymmetric_key_cleanup);
673 #endif /* !__UBOOT__ */
674