18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#include <linux/kernel.h>
48c2ecf20Sopenharmony_ci#include <linux/key.h>
58c2ecf20Sopenharmony_ci#include "common.h"
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciint load_certificate_list(const u8 cert_list[],
88c2ecf20Sopenharmony_ci			  const unsigned long list_size,
98c2ecf20Sopenharmony_ci			  const struct key *keyring)
108c2ecf20Sopenharmony_ci{
118c2ecf20Sopenharmony_ci	key_ref_t key;
128c2ecf20Sopenharmony_ci	const u8 *p, *end;
138c2ecf20Sopenharmony_ci	size_t plen;
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci	p = cert_list;
168c2ecf20Sopenharmony_ci	end = p + list_size;
178c2ecf20Sopenharmony_ci	while (p < end) {
188c2ecf20Sopenharmony_ci		/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
198c2ecf20Sopenharmony_ci		 * than 256 bytes in size.
208c2ecf20Sopenharmony_ci		 */
218c2ecf20Sopenharmony_ci		if (end - p < 4)
228c2ecf20Sopenharmony_ci			goto dodgy_cert;
238c2ecf20Sopenharmony_ci		if (p[0] != 0x30 &&
248c2ecf20Sopenharmony_ci		    p[1] != 0x82)
258c2ecf20Sopenharmony_ci			goto dodgy_cert;
268c2ecf20Sopenharmony_ci		plen = (p[2] << 8) | p[3];
278c2ecf20Sopenharmony_ci		plen += 4;
288c2ecf20Sopenharmony_ci		if (plen > end - p)
298c2ecf20Sopenharmony_ci			goto dodgy_cert;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci		key = key_create_or_update(make_key_ref(keyring, 1),
328c2ecf20Sopenharmony_ci					   "asymmetric",
338c2ecf20Sopenharmony_ci					   NULL,
348c2ecf20Sopenharmony_ci					   p,
358c2ecf20Sopenharmony_ci					   plen,
368c2ecf20Sopenharmony_ci					   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
378c2ecf20Sopenharmony_ci					   KEY_USR_VIEW | KEY_USR_READ),
388c2ecf20Sopenharmony_ci					   KEY_ALLOC_NOT_IN_QUOTA |
398c2ecf20Sopenharmony_ci					   KEY_ALLOC_BUILT_IN |
408c2ecf20Sopenharmony_ci					   KEY_ALLOC_BYPASS_RESTRICTION);
418c2ecf20Sopenharmony_ci		if (IS_ERR(key)) {
428c2ecf20Sopenharmony_ci			pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
438c2ecf20Sopenharmony_ci			       PTR_ERR(key));
448c2ecf20Sopenharmony_ci		} else {
458c2ecf20Sopenharmony_ci			pr_notice("Loaded X.509 cert '%s'\n",
468c2ecf20Sopenharmony_ci				  key_ref_to_ptr(key)->description);
478c2ecf20Sopenharmony_ci			key_ref_put(key);
488c2ecf20Sopenharmony_ci		}
498c2ecf20Sopenharmony_ci		p += plen;
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	return 0;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cidodgy_cert:
558c2ecf20Sopenharmony_ci	pr_err("Problem parsing in-kernel X.509 certificate list\n");
568c2ecf20Sopenharmony_ci	return 0;
578c2ecf20Sopenharmony_ci}
58