Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 091f6e26 authored by David Howells's avatar David Howells
Browse files

MODSIGN: Extract the blob PKCS#7 signature verifier from module signing



Extract the function that drives the PKCS#7 signature verification given a
data blob and a PKCS#7 blob out from the module signing code and lump it with
the system keyring code as it's generic.  This makes it independent of module
config options and opens it to use by the firmware loader.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Cc: Luis R. Rodriguez <mcgrof@suse.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Ming Lei <ming.lei@canonical.com>
Cc: Seth Forshee <seth.forshee@canonical.com>
Cc: Kyle McMartin <kyle@kernel.org>
parent 1c394499
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -28,4 +28,9 @@ static inline struct key *get_system_trusted_keyring(void)
}
#endif

#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
extern int system_verify_data(const void *data, unsigned long len,
			      const void *raw_pkcs7, size_t pkcs7_len);
#endif

#endif /* _KEYS_SYSTEM_KEYRING_H */
+19 −10
Original line number Diff line number Diff line
@@ -1752,6 +1752,24 @@ config SYSTEM_TRUSTED_KEYRING

	  Keys in this keyring are used by module signature checking.

config SYSTEM_DATA_VERIFICATION
	def_bool n
	select SYSTEM_TRUSTED_KEYRING
	select KEYS
	select CRYPTO
	select ASYMMETRIC_KEY_TYPE
	select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
	select PUBLIC_KEY_ALGO_RSA
	select ASN1
	select OID_REGISTRY
	select X509_CERTIFICATE_PARSER
	select PKCS7_MESSAGE_PARSER
	help
	  Provide PKCS#7 message verification using the contents of the system
	  trusted keyring to provide public keys.  This then can be used for
	  module verification, kexec image verification and firmware blob
	  verification.

config PROFILING
	bool "Profiling support"
	help
@@ -1860,16 +1878,7 @@ config MODULE_SRCVERSION_ALL
config MODULE_SIG
	bool "Module signature verification"
	depends on MODULES
	select SYSTEM_TRUSTED_KEYRING
	select KEYS
	select CRYPTO
	select ASYMMETRIC_KEY_TYPE
	select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
	select PUBLIC_KEY_ALGO_RSA
	select ASN1
	select OID_REGISTRY
	select X509_CERTIFICATE_PARSER
	select PKCS7_MESSAGE_PARSER
	select SYSTEM_DATA_VERIFICATION
	help
	  Check modules for valid signatures upon load: the signature
	  is simply appended to the module. For more information see
+1 −43
Original line number Diff line number Diff line
@@ -10,10 +10,8 @@
 */

#include <linux/kernel.h>
#include <linux/err.h>
#include <keys/system_keyring.h>
#include <crypto/public_key.h>
#include <crypto/pkcs7.h>
#include "module-internal.h"

/*
@@ -36,46 +34,6 @@ struct module_signature {
	__be32	sig_len;	/* Length of signature data */
};

/*
 * Verify a PKCS#7-based signature on a module.
 */
static int mod_verify_pkcs7(const void *mod, unsigned long modlen,
			    const void *raw_pkcs7, size_t pkcs7_len)
{
	struct pkcs7_message *pkcs7;
	bool trusted;
	int ret;

	pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
	if (IS_ERR(pkcs7))
		return PTR_ERR(pkcs7);

	/* The data should be detached - so we need to supply it. */
	if (pkcs7_supply_detached_data(pkcs7, mod, modlen) < 0) {
		pr_err("PKCS#7 signature with non-detached data\n");
		ret = -EBADMSG;
		goto error;
	}

	ret = pkcs7_verify(pkcs7);
	if (ret < 0)
		goto error;

	ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
	if (ret < 0)
		goto error;

	if (!trusted) {
		pr_err("PKCS#7 signature not signed with a trusted key\n");
		ret = -ENOKEY;
	}

error:
	pkcs7_free_message(pkcs7);
	pr_devel("<==%s() = %d\n", __func__, ret);
	return ret;
}

/*
 * Verify the signature on a module.
 */
@@ -114,5 +72,5 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen)
		return -EBADMSG;
	}

	return mod_verify_pkcs7(mod, modlen, mod + modlen, sig_len);
	return system_verify_data(mod, modlen, mod + modlen, sig_len);
}
+50 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/err.h>
#include <keys/asymmetric-type.h>
#include <keys/system_keyring.h>
#include <crypto/pkcs7.h>

struct key *system_trusted_keyring;
EXPORT_SYMBOL_GPL(system_trusted_keyring);
@@ -103,3 +104,52 @@ static __init int load_system_certificate_list(void)
	return 0;
}
late_initcall(load_system_certificate_list);

#ifdef CONFIG_SYSTEM_DATA_VERIFICATION

/**
 * Verify a PKCS#7-based signature on system data.
 * @data: The data to be verified.
 * @len: Size of @data.
 * @raw_pkcs7: The PKCS#7 message that is the signature.
 * @pkcs7_len: The size of @raw_pkcs7.
 */
int system_verify_data(const void *data, unsigned long len,
		       const void *raw_pkcs7, size_t pkcs7_len)
{
	struct pkcs7_message *pkcs7;
	bool trusted;
	int ret;

	pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
	if (IS_ERR(pkcs7))
		return PTR_ERR(pkcs7);

	/* The data should be detached - so we need to supply it. */
	if (pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
		pr_err("PKCS#7 signature with non-detached data\n");
		ret = -EBADMSG;
		goto error;
	}

	ret = pkcs7_verify(pkcs7);
	if (ret < 0)
		goto error;

	ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
	if (ret < 0)
		goto error;

	if (!trusted) {
		pr_err("PKCS#7 signature not signed with a trusted key\n");
		ret = -ENOKEY;
	}

error:
	pkcs7_free_message(pkcs7);
	pr_devel("<==%s() = %d\n", __func__, ret);
	return ret;
}
EXPORT_SYMBOL_GPL(system_verify_data);

#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */