18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* System trusted keyring for trusted public keys
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/export.h>
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <linux/sched.h>
118c2ecf20Sopenharmony_ci#include <linux/cred.h>
128c2ecf20Sopenharmony_ci#include <linux/err.h>
138c2ecf20Sopenharmony_ci#include <linux/slab.h>
148c2ecf20Sopenharmony_ci#include <linux/verification.h>
158c2ecf20Sopenharmony_ci#include <keys/asymmetric-type.h>
168c2ecf20Sopenharmony_ci#include <keys/system_keyring.h>
178c2ecf20Sopenharmony_ci#include <crypto/pkcs7.h>
188c2ecf20Sopenharmony_ci#include "common.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic struct key *builtin_trusted_keys;
218c2ecf20Sopenharmony_ci#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
228c2ecf20Sopenharmony_cistatic struct key *secondary_trusted_keys;
238c2ecf20Sopenharmony_ci#endif
248c2ecf20Sopenharmony_ci#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
258c2ecf20Sopenharmony_cistatic struct key *platform_trusted_keys;
268c2ecf20Sopenharmony_ci#endif
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciextern __initconst const u8 system_certificate_list[];
298c2ecf20Sopenharmony_ciextern __initconst const unsigned long system_certificate_list_size;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/**
328c2ecf20Sopenharmony_ci * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
338c2ecf20Sopenharmony_ci *
348c2ecf20Sopenharmony_ci * Restrict the addition of keys into a keyring based on the key-to-be-added
358c2ecf20Sopenharmony_ci * being vouched for by a key in the built in system keyring.
368c2ecf20Sopenharmony_ci */
378c2ecf20Sopenharmony_ciint restrict_link_by_builtin_trusted(struct key *dest_keyring,
388c2ecf20Sopenharmony_ci				     const struct key_type *type,
398c2ecf20Sopenharmony_ci				     const union key_payload *payload,
408c2ecf20Sopenharmony_ci				     struct key *restriction_key)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	return restrict_link_by_signature(dest_keyring, type, payload,
438c2ecf20Sopenharmony_ci					  builtin_trusted_keys);
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
478c2ecf20Sopenharmony_ci/**
488c2ecf20Sopenharmony_ci * restrict_link_by_builtin_and_secondary_trusted - Restrict keyring
498c2ecf20Sopenharmony_ci *   addition by both builtin and secondary keyrings
508c2ecf20Sopenharmony_ci *
518c2ecf20Sopenharmony_ci * Restrict the addition of keys into a keyring based on the key-to-be-added
528c2ecf20Sopenharmony_ci * being vouched for by a key in either the built-in or the secondary system
538c2ecf20Sopenharmony_ci * keyrings.
548c2ecf20Sopenharmony_ci */
558c2ecf20Sopenharmony_ciint restrict_link_by_builtin_and_secondary_trusted(
568c2ecf20Sopenharmony_ci	struct key *dest_keyring,
578c2ecf20Sopenharmony_ci	const struct key_type *type,
588c2ecf20Sopenharmony_ci	const union key_payload *payload,
598c2ecf20Sopenharmony_ci	struct key *restrict_key)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	/* If we have a secondary trusted keyring, then that contains a link
628c2ecf20Sopenharmony_ci	 * through to the builtin keyring and the search will follow that link.
638c2ecf20Sopenharmony_ci	 */
648c2ecf20Sopenharmony_ci	if (type == &key_type_keyring &&
658c2ecf20Sopenharmony_ci	    dest_keyring == secondary_trusted_keys &&
668c2ecf20Sopenharmony_ci	    payload == &builtin_trusted_keys->payload)
678c2ecf20Sopenharmony_ci		/* Allow the builtin keyring to be added to the secondary */
688c2ecf20Sopenharmony_ci		return 0;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	return restrict_link_by_signature(dest_keyring, type, payload,
718c2ecf20Sopenharmony_ci					  secondary_trusted_keys);
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/**
758c2ecf20Sopenharmony_ci * Allocate a struct key_restriction for the "builtin and secondary trust"
768c2ecf20Sopenharmony_ci * keyring. Only for use in system_trusted_keyring_init().
778c2ecf20Sopenharmony_ci */
788c2ecf20Sopenharmony_cistatic __init struct key_restriction *get_builtin_and_secondary_restriction(void)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	struct key_restriction *restriction;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	if (!restriction)
858c2ecf20Sopenharmony_ci		panic("Can't allocate secondary trusted keyring restriction\n");
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	restriction->check = restrict_link_by_builtin_and_secondary_trusted;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	return restriction;
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci#endif
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/*
948c2ecf20Sopenharmony_ci * Create the trusted keyrings
958c2ecf20Sopenharmony_ci */
968c2ecf20Sopenharmony_cistatic __init int system_trusted_keyring_init(void)
978c2ecf20Sopenharmony_ci{
988c2ecf20Sopenharmony_ci	pr_notice("Initialise system trusted keyrings\n");
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	builtin_trusted_keys =
1018c2ecf20Sopenharmony_ci		keyring_alloc(".builtin_trusted_keys",
1028c2ecf20Sopenharmony_ci			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
1038c2ecf20Sopenharmony_ci			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
1048c2ecf20Sopenharmony_ci			      KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
1058c2ecf20Sopenharmony_ci			      KEY_ALLOC_NOT_IN_QUOTA,
1068c2ecf20Sopenharmony_ci			      NULL, NULL);
1078c2ecf20Sopenharmony_ci	if (IS_ERR(builtin_trusted_keys))
1088c2ecf20Sopenharmony_ci		panic("Can't allocate builtin trusted keyring\n");
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
1118c2ecf20Sopenharmony_ci	secondary_trusted_keys =
1128c2ecf20Sopenharmony_ci		keyring_alloc(".secondary_trusted_keys",
1138c2ecf20Sopenharmony_ci			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
1148c2ecf20Sopenharmony_ci			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
1158c2ecf20Sopenharmony_ci			       KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
1168c2ecf20Sopenharmony_ci			       KEY_USR_WRITE),
1178c2ecf20Sopenharmony_ci			      KEY_ALLOC_NOT_IN_QUOTA,
1188c2ecf20Sopenharmony_ci			      get_builtin_and_secondary_restriction(),
1198c2ecf20Sopenharmony_ci			      NULL);
1208c2ecf20Sopenharmony_ci	if (IS_ERR(secondary_trusted_keys))
1218c2ecf20Sopenharmony_ci		panic("Can't allocate secondary trusted keyring\n");
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	if (key_link(secondary_trusted_keys, builtin_trusted_keys) < 0)
1248c2ecf20Sopenharmony_ci		panic("Can't link trusted keyrings\n");
1258c2ecf20Sopenharmony_ci#endif
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	return 0;
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci/*
1318c2ecf20Sopenharmony_ci * Must be initialised before we try and load the keys into the keyring.
1328c2ecf20Sopenharmony_ci */
1338c2ecf20Sopenharmony_cidevice_initcall(system_trusted_keyring_init);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci/*
1368c2ecf20Sopenharmony_ci * Load the compiled-in list of X.509 certificates.
1378c2ecf20Sopenharmony_ci */
1388c2ecf20Sopenharmony_cistatic __init int load_system_certificate_list(void)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	pr_notice("Loading compiled-in X.509 certificates\n");
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	return load_certificate_list(system_certificate_list, system_certificate_list_size,
1438c2ecf20Sopenharmony_ci				     builtin_trusted_keys);
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_cilate_initcall(load_system_certificate_list);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci/**
1508c2ecf20Sopenharmony_ci * verify_pkcs7_message_sig - Verify a PKCS#7-based signature on system data.
1518c2ecf20Sopenharmony_ci * @data: The data to be verified (NULL if expecting internal data).
1528c2ecf20Sopenharmony_ci * @len: Size of @data.
1538c2ecf20Sopenharmony_ci * @pkcs7: The PKCS#7 message that is the signature.
1548c2ecf20Sopenharmony_ci * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
1558c2ecf20Sopenharmony_ci *					(void *)1UL for all trusted keys).
1568c2ecf20Sopenharmony_ci * @usage: The use to which the key is being put.
1578c2ecf20Sopenharmony_ci * @view_content: Callback to gain access to content.
1588c2ecf20Sopenharmony_ci * @ctx: Context for callback.
1598c2ecf20Sopenharmony_ci */
1608c2ecf20Sopenharmony_ciint verify_pkcs7_message_sig(const void *data, size_t len,
1618c2ecf20Sopenharmony_ci			     struct pkcs7_message *pkcs7,
1628c2ecf20Sopenharmony_ci			     struct key *trusted_keys,
1638c2ecf20Sopenharmony_ci			     enum key_being_used_for usage,
1648c2ecf20Sopenharmony_ci			     int (*view_content)(void *ctx,
1658c2ecf20Sopenharmony_ci						 const void *data, size_t len,
1668c2ecf20Sopenharmony_ci						 size_t asn1hdrlen),
1678c2ecf20Sopenharmony_ci			     void *ctx)
1688c2ecf20Sopenharmony_ci{
1698c2ecf20Sopenharmony_ci	int ret;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	/* The data should be detached - so we need to supply it. */
1728c2ecf20Sopenharmony_ci	if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
1738c2ecf20Sopenharmony_ci		pr_err("PKCS#7 signature with non-detached data\n");
1748c2ecf20Sopenharmony_ci		ret = -EBADMSG;
1758c2ecf20Sopenharmony_ci		goto error;
1768c2ecf20Sopenharmony_ci	}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	ret = pkcs7_verify(pkcs7, usage);
1798c2ecf20Sopenharmony_ci	if (ret < 0)
1808c2ecf20Sopenharmony_ci		goto error;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	if (!trusted_keys) {
1838c2ecf20Sopenharmony_ci		trusted_keys = builtin_trusted_keys;
1848c2ecf20Sopenharmony_ci	} else if (trusted_keys == VERIFY_USE_SECONDARY_KEYRING) {
1858c2ecf20Sopenharmony_ci#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
1868c2ecf20Sopenharmony_ci		trusted_keys = secondary_trusted_keys;
1878c2ecf20Sopenharmony_ci#else
1888c2ecf20Sopenharmony_ci		trusted_keys = builtin_trusted_keys;
1898c2ecf20Sopenharmony_ci#endif
1908c2ecf20Sopenharmony_ci	} else if (trusted_keys == VERIFY_USE_PLATFORM_KEYRING) {
1918c2ecf20Sopenharmony_ci#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
1928c2ecf20Sopenharmony_ci		trusted_keys = platform_trusted_keys;
1938c2ecf20Sopenharmony_ci#else
1948c2ecf20Sopenharmony_ci		trusted_keys = NULL;
1958c2ecf20Sopenharmony_ci#endif
1968c2ecf20Sopenharmony_ci		if (!trusted_keys) {
1978c2ecf20Sopenharmony_ci			ret = -ENOKEY;
1988c2ecf20Sopenharmony_ci			pr_devel("PKCS#7 platform keyring is not available\n");
1998c2ecf20Sopenharmony_ci			goto error;
2008c2ecf20Sopenharmony_ci		}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci		ret = is_key_on_revocation_list(pkcs7);
2038c2ecf20Sopenharmony_ci		if (ret != -ENOKEY) {
2048c2ecf20Sopenharmony_ci			pr_devel("PKCS#7 platform key is on revocation list\n");
2058c2ecf20Sopenharmony_ci			goto error;
2068c2ecf20Sopenharmony_ci		}
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci	ret = pkcs7_validate_trust(pkcs7, trusted_keys);
2098c2ecf20Sopenharmony_ci	if (ret < 0) {
2108c2ecf20Sopenharmony_ci		if (ret == -ENOKEY)
2118c2ecf20Sopenharmony_ci			pr_devel("PKCS#7 signature not signed with a trusted key\n");
2128c2ecf20Sopenharmony_ci		goto error;
2138c2ecf20Sopenharmony_ci	}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	if (view_content) {
2168c2ecf20Sopenharmony_ci		size_t asn1hdrlen;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci		ret = pkcs7_get_content_data(pkcs7, &data, &len, &asn1hdrlen);
2198c2ecf20Sopenharmony_ci		if (ret < 0) {
2208c2ecf20Sopenharmony_ci			if (ret == -ENODATA)
2218c2ecf20Sopenharmony_ci				pr_devel("PKCS#7 message does not contain data\n");
2228c2ecf20Sopenharmony_ci			goto error;
2238c2ecf20Sopenharmony_ci		}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci		ret = view_content(ctx, data, len, asn1hdrlen);
2268c2ecf20Sopenharmony_ci	}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cierror:
2298c2ecf20Sopenharmony_ci	pr_devel("<==%s() = %d\n", __func__, ret);
2308c2ecf20Sopenharmony_ci	return ret;
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci/**
2348c2ecf20Sopenharmony_ci * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
2358c2ecf20Sopenharmony_ci * @data: The data to be verified (NULL if expecting internal data).
2368c2ecf20Sopenharmony_ci * @len: Size of @data.
2378c2ecf20Sopenharmony_ci * @raw_pkcs7: The PKCS#7 message that is the signature.
2388c2ecf20Sopenharmony_ci * @pkcs7_len: The size of @raw_pkcs7.
2398c2ecf20Sopenharmony_ci * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
2408c2ecf20Sopenharmony_ci *					(void *)1UL for all trusted keys).
2418c2ecf20Sopenharmony_ci * @usage: The use to which the key is being put.
2428c2ecf20Sopenharmony_ci * @view_content: Callback to gain access to content.
2438c2ecf20Sopenharmony_ci * @ctx: Context for callback.
2448c2ecf20Sopenharmony_ci */
2458c2ecf20Sopenharmony_ciint verify_pkcs7_signature(const void *data, size_t len,
2468c2ecf20Sopenharmony_ci			   const void *raw_pkcs7, size_t pkcs7_len,
2478c2ecf20Sopenharmony_ci			   struct key *trusted_keys,
2488c2ecf20Sopenharmony_ci			   enum key_being_used_for usage,
2498c2ecf20Sopenharmony_ci			   int (*view_content)(void *ctx,
2508c2ecf20Sopenharmony_ci					       const void *data, size_t len,
2518c2ecf20Sopenharmony_ci					       size_t asn1hdrlen),
2528c2ecf20Sopenharmony_ci			   void *ctx)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	struct pkcs7_message *pkcs7;
2558c2ecf20Sopenharmony_ci	int ret;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
2588c2ecf20Sopenharmony_ci	if (IS_ERR(pkcs7))
2598c2ecf20Sopenharmony_ci		return PTR_ERR(pkcs7);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	ret = verify_pkcs7_message_sig(data, len, pkcs7, trusted_keys, usage,
2628c2ecf20Sopenharmony_ci				       view_content, ctx);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	pkcs7_free_message(pkcs7);
2658c2ecf20Sopenharmony_ci	pr_devel("<==%s() = %d\n", __func__, ret);
2668c2ecf20Sopenharmony_ci	return ret;
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(verify_pkcs7_signature);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
2738c2ecf20Sopenharmony_civoid __init set_platform_trusted_keys(struct key *keyring)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	platform_trusted_keys = keyring;
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci#endif
278