xref: /openbmc/linux/kernel/module/signing.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1cfc1d277SAaron Tomlin // SPDX-License-Identifier: GPL-2.0-or-later
2cfc1d277SAaron Tomlin /* Module signature checker
3cfc1d277SAaron Tomlin  *
4cfc1d277SAaron Tomlin  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
5cfc1d277SAaron Tomlin  * Written by David Howells (dhowells@redhat.com)
6cfc1d277SAaron Tomlin  */
7cfc1d277SAaron Tomlin 
8cfc1d277SAaron Tomlin #include <linux/kernel.h>
9cfc1d277SAaron Tomlin #include <linux/errno.h>
10cfc1d277SAaron Tomlin #include <linux/module.h>
11cfc1d277SAaron Tomlin #include <linux/module_signature.h>
12cfc1d277SAaron Tomlin #include <linux/string.h>
13cfc1d277SAaron Tomlin #include <linux/verification.h>
140c1e4280SAaron Tomlin #include <linux/security.h>
15cfc1d277SAaron Tomlin #include <crypto/public_key.h>
160c1e4280SAaron Tomlin #include <uapi/linux/module.h>
17cfc1d277SAaron Tomlin #include "internal.h"
18cfc1d277SAaron Tomlin 
19*73503963SSaravana Kannan #undef MODULE_PARAM_PREFIX
20*73503963SSaravana Kannan #define MODULE_PARAM_PREFIX "module."
21*73503963SSaravana Kannan 
220c1e4280SAaron Tomlin static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE);
230c1e4280SAaron Tomlin module_param(sig_enforce, bool_enable_only, 0644);
240c1e4280SAaron Tomlin 
250c1e4280SAaron Tomlin /*
260c1e4280SAaron Tomlin  * Export sig_enforce kernel cmdline parameter to allow other subsystems rely
270c1e4280SAaron Tomlin  * on that instead of directly to CONFIG_MODULE_SIG_FORCE config.
280c1e4280SAaron Tomlin  */
is_module_sig_enforced(void)290c1e4280SAaron Tomlin bool is_module_sig_enforced(void)
300c1e4280SAaron Tomlin {
310c1e4280SAaron Tomlin 	return sig_enforce;
320c1e4280SAaron Tomlin }
330c1e4280SAaron Tomlin EXPORT_SYMBOL(is_module_sig_enforced);
340c1e4280SAaron Tomlin 
set_module_sig_enforced(void)350c1e4280SAaron Tomlin void set_module_sig_enforced(void)
360c1e4280SAaron Tomlin {
370c1e4280SAaron Tomlin 	sig_enforce = true;
380c1e4280SAaron Tomlin }
390c1e4280SAaron Tomlin 
40cfc1d277SAaron Tomlin /*
41cfc1d277SAaron Tomlin  * Verify the signature on a module.
42cfc1d277SAaron Tomlin  */
mod_verify_sig(const void * mod,struct load_info * info)43cfc1d277SAaron Tomlin int mod_verify_sig(const void *mod, struct load_info *info)
44cfc1d277SAaron Tomlin {
45cfc1d277SAaron Tomlin 	struct module_signature ms;
46cfc1d277SAaron Tomlin 	size_t sig_len, modlen = info->len;
47cfc1d277SAaron Tomlin 	int ret;
48cfc1d277SAaron Tomlin 
49cfc1d277SAaron Tomlin 	pr_devel("==>%s(,%zu)\n", __func__, modlen);
50cfc1d277SAaron Tomlin 
51cfc1d277SAaron Tomlin 	if (modlen <= sizeof(ms))
52cfc1d277SAaron Tomlin 		return -EBADMSG;
53cfc1d277SAaron Tomlin 
54cfc1d277SAaron Tomlin 	memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
55cfc1d277SAaron Tomlin 
56cfc1d277SAaron Tomlin 	ret = mod_check_sig(&ms, modlen, "module");
57cfc1d277SAaron Tomlin 	if (ret)
58cfc1d277SAaron Tomlin 		return ret;
59cfc1d277SAaron Tomlin 
60cfc1d277SAaron Tomlin 	sig_len = be32_to_cpu(ms.sig_len);
61cfc1d277SAaron Tomlin 	modlen -= sig_len + sizeof(ms);
62cfc1d277SAaron Tomlin 	info->len = modlen;
63cfc1d277SAaron Tomlin 
64cfc1d277SAaron Tomlin 	return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
65cfc1d277SAaron Tomlin 				      VERIFY_USE_SECONDARY_KEYRING,
66cfc1d277SAaron Tomlin 				      VERIFYING_MODULE_SIGNATURE,
67cfc1d277SAaron Tomlin 				      NULL, NULL);
68cfc1d277SAaron Tomlin }
690c1e4280SAaron Tomlin 
module_sig_check(struct load_info * info,int flags)700c1e4280SAaron Tomlin int module_sig_check(struct load_info *info, int flags)
710c1e4280SAaron Tomlin {
720c1e4280SAaron Tomlin 	int err = -ENODATA;
730c1e4280SAaron Tomlin 	const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
740c1e4280SAaron Tomlin 	const char *reason;
750c1e4280SAaron Tomlin 	const void *mod = info->hdr;
760c1e4280SAaron Tomlin 	bool mangled_module = flags & (MODULE_INIT_IGNORE_MODVERSIONS |
770c1e4280SAaron Tomlin 				       MODULE_INIT_IGNORE_VERMAGIC);
780c1e4280SAaron Tomlin 	/*
790c1e4280SAaron Tomlin 	 * Do not allow mangled modules as a module with version information
800c1e4280SAaron Tomlin 	 * removed is no longer the module that was signed.
810c1e4280SAaron Tomlin 	 */
820c1e4280SAaron Tomlin 	if (!mangled_module &&
830c1e4280SAaron Tomlin 	    info->len > markerlen &&
840c1e4280SAaron Tomlin 	    memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
850c1e4280SAaron Tomlin 		/* We truncate the module to discard the signature */
860c1e4280SAaron Tomlin 		info->len -= markerlen;
870c1e4280SAaron Tomlin 		err = mod_verify_sig(mod, info);
880c1e4280SAaron Tomlin 		if (!err) {
890c1e4280SAaron Tomlin 			info->sig_ok = true;
900c1e4280SAaron Tomlin 			return 0;
910c1e4280SAaron Tomlin 		}
920c1e4280SAaron Tomlin 	}
930c1e4280SAaron Tomlin 
940c1e4280SAaron Tomlin 	/*
950c1e4280SAaron Tomlin 	 * We don't permit modules to be loaded into the trusted kernels
960c1e4280SAaron Tomlin 	 * without a valid signature on them, but if we're not enforcing,
970c1e4280SAaron Tomlin 	 * certain errors are non-fatal.
980c1e4280SAaron Tomlin 	 */
990c1e4280SAaron Tomlin 	switch (err) {
1000c1e4280SAaron Tomlin 	case -ENODATA:
1010c1e4280SAaron Tomlin 		reason = "unsigned module";
1020c1e4280SAaron Tomlin 		break;
1030c1e4280SAaron Tomlin 	case -ENOPKG:
1040c1e4280SAaron Tomlin 		reason = "module with unsupported crypto";
1050c1e4280SAaron Tomlin 		break;
1060c1e4280SAaron Tomlin 	case -ENOKEY:
1070c1e4280SAaron Tomlin 		reason = "module with unavailable key";
1080c1e4280SAaron Tomlin 		break;
1090c1e4280SAaron Tomlin 
1100c1e4280SAaron Tomlin 	default:
1110c1e4280SAaron Tomlin 		/*
1120c1e4280SAaron Tomlin 		 * All other errors are fatal, including lack of memory,
1130c1e4280SAaron Tomlin 		 * unparseable signatures, and signature check failures --
1140c1e4280SAaron Tomlin 		 * even if signatures aren't required.
1150c1e4280SAaron Tomlin 		 */
1160c1e4280SAaron Tomlin 		return err;
1170c1e4280SAaron Tomlin 	}
1180c1e4280SAaron Tomlin 
1190c1e4280SAaron Tomlin 	if (is_module_sig_enforced()) {
1200c1e4280SAaron Tomlin 		pr_notice("Loading of %s is rejected\n", reason);
1210c1e4280SAaron Tomlin 		return -EKEYREJECTED;
1220c1e4280SAaron Tomlin 	}
1230c1e4280SAaron Tomlin 
1240c1e4280SAaron Tomlin 	return security_locked_down(LOCKDOWN_MODULE_SIGNATURE);
1250c1e4280SAaron Tomlin }
126