Skip to content

Commit

Permalink
MODSIGN: Extract the blob PKCS#7 signature verifier from module signing
Browse files Browse the repository at this point in the history
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: David 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>
  • Loading branch information
dhowells committed Aug 7, 2015
1 parent 1c39449 commit 091f6e2
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 53 deletions.
5 changes: 5 additions & 0 deletions include/keys/system_keyring.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
29 changes: 19 additions & 10 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
44 changes: 1 addition & 43 deletions kernel/module_signing.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

/*
Expand All @@ -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.
*/
Expand Down Expand Up @@ -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 changes: 50 additions & 0 deletions kernel/system_keyring.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 */

0 comments on commit 091f6e2

Please sign in to comment.