Linux Audio

Check our new training course

Yocto / OpenEmbedded training

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