summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Jung Bauermann <bauerman@linux.ibm.com>2019-07-04 14:57:34 -0400
committerMimi Zohar <zohar@linux.ibm.com>2019-08-05 18:39:56 -0400
commitc8424e776b093280d3fdd104d850706b3b229ac8 (patch)
tree3f14381fe576439fa1fa94736b67d1015c40752d
parentb36f281f4a314de4be0a51d6511b794691f8a244 (diff)
MODSIGN: Export module signature definitions
IMA will use the module_signature format for append signatures, so export the relevant definitions and factor out the code which verifies that the appended signature trailer is valid. Also, create a CONFIG_MODULE_SIG_FORMAT option so that IMA can select it and be able to use mod_check_sig() without having to depend on either CONFIG_MODULE_SIG or CONFIG_MODULES. s390 duplicated the definition of struct module_signature so now they can use the new <linux/module_signature.h> header instead. Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com> Acked-by: Jessica Yu <jeyu@kernel.org> Reviewed-by: Philipp Rudo <prudo@linux.ibm.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/s390/kernel/machine_kexec_file.c24
-rw-r--r--include/linux/module.h3
-rw-r--r--include/linux/module_signature.h44
-rw-r--r--init/Kconfig6
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/module.c1
-rw-r--r--kernel/module_signature.c46
-rw-r--r--kernel/module_signing.c56
-rw-r--r--scripts/Makefile2
10 files changed, 108 insertions, 77 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index a4ad2733eedf..e0ae0d51f985 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -538,7 +538,7 @@ config ARCH_HAS_KEXEC_PURGATORY
538 538
539config KEXEC_VERIFY_SIG 539config KEXEC_VERIFY_SIG
540 bool "Verify kernel signature during kexec_file_load() syscall" 540 bool "Verify kernel signature during kexec_file_load() syscall"
541 depends on KEXEC_FILE && SYSTEM_DATA_VERIFICATION 541 depends on KEXEC_FILE && MODULE_SIG_FORMAT
542 help 542 help
543 This option makes kernel signature verification mandatory for 543 This option makes kernel signature verification mandatory for
544 the kexec_file_load() syscall. 544 the kexec_file_load() syscall.
diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
index fbdd3ea73667..1ac9fbc6e01e 100644
--- a/arch/s390/kernel/machine_kexec_file.c
+++ b/arch/s390/kernel/machine_kexec_file.c
@@ -10,7 +10,7 @@
10#include <linux/elf.h> 10#include <linux/elf.h>
11#include <linux/errno.h> 11#include <linux/errno.h>
12#include <linux/kexec.h> 12#include <linux/kexec.h>
13#include <linux/module.h> 13#include <linux/module_signature.h>
14#include <linux/verification.h> 14#include <linux/verification.h>
15#include <asm/boot_data.h> 15#include <asm/boot_data.h>
16#include <asm/ipl.h> 16#include <asm/ipl.h>
@@ -23,28 +23,6 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
23}; 23};
24 24
25#ifdef CONFIG_KEXEC_VERIFY_SIG 25#ifdef CONFIG_KEXEC_VERIFY_SIG
26/*
27 * Module signature information block.
28 *
29 * The constituents of the signature section are, in order:
30 *
31 * - Signer's name
32 * - Key identifier
33 * - Signature data
34 * - Information block
35 */
36struct module_signature {
37 u8 algo; /* Public-key crypto algorithm [0] */
38 u8 hash; /* Digest algorithm [0] */
39 u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
40 u8 signer_len; /* Length of signer's name [0] */
41 u8 key_id_len; /* Length of key identifier [0] */
42 u8 __pad[3];
43 __be32 sig_len; /* Length of signature data */
44};
45
46#define PKEY_ID_PKCS7 2
47
48int s390_verify_sig(const char *kernel, unsigned long kernel_len) 26int s390_verify_sig(const char *kernel, unsigned long kernel_len)
49{ 27{
50 const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1; 28 const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;
diff --git a/include/linux/module.h b/include/linux/module.h
index 1455812dd325..f6fc1dae74f4 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -26,9 +26,6 @@
26#include <linux/percpu.h> 26#include <linux/percpu.h>
27#include <asm/module.h> 27#include <asm/module.h>
28 28
29/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
30#define MODULE_SIG_STRING "~Module signature appended~\n"
31
32/* Not Yet Implemented */ 29/* Not Yet Implemented */
33#define MODULE_SUPPORTED_DEVICE(name) 30#define MODULE_SUPPORTED_DEVICE(name)
34 31
diff --git a/include/linux/module_signature.h b/include/linux/module_signature.h
new file mode 100644
index 000000000000..523617fc5b6a
--- /dev/null
+++ b/include/linux/module_signature.h
@@ -0,0 +1,44 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Module signature handling.
4 *
5 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
7 */
8
9#ifndef _LINUX_MODULE_SIGNATURE_H
10#define _LINUX_MODULE_SIGNATURE_H
11
12/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
13#define MODULE_SIG_STRING "~Module signature appended~\n"
14
15enum pkey_id_type {
16 PKEY_ID_PGP, /* OpenPGP generated key ID */
17 PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
18 PKEY_ID_PKCS7, /* Signature in PKCS#7 message */
19};
20
21/*
22 * Module signature information block.
23 *
24 * The constituents of the signature section are, in order:
25 *
26 * - Signer's name
27 * - Key identifier
28 * - Signature data
29 * - Information block
30 */
31struct module_signature {
32 u8 algo; /* Public-key crypto algorithm [0] */
33 u8 hash; /* Digest algorithm [0] */
34 u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
35 u8 signer_len; /* Length of signer's name [0] */
36 u8 key_id_len; /* Length of key identifier [0] */
37 u8 __pad[3];
38 __be32 sig_len; /* Length of signature data */
39};
40
41int mod_check_sig(const struct module_signature *ms, size_t file_len,
42 const char *name);
43
44#endif /* _LINUX_MODULE_SIGNATURE_H */
diff --git a/init/Kconfig b/init/Kconfig
index bd7d650d4a99..2dca877c9ed7 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1930,6 +1930,10 @@ config BASE_SMALL
1930 default 0 if BASE_FULL 1930 default 0 if BASE_FULL
1931 default 1 if !BASE_FULL 1931 default 1 if !BASE_FULL
1932 1932
1933config MODULE_SIG_FORMAT
1934 def_bool n
1935 select SYSTEM_DATA_VERIFICATION
1936
1933menuconfig MODULES 1937menuconfig MODULES
1934 bool "Enable loadable module support" 1938 bool "Enable loadable module support"
1935 option modules 1939 option modules
@@ -2007,7 +2011,7 @@ config MODULE_SRCVERSION_ALL
2007config MODULE_SIG 2011config MODULE_SIG
2008 bool "Module signature verification" 2012 bool "Module signature verification"
2009 depends on MODULES 2013 depends on MODULES
2010 select SYSTEM_DATA_VERIFICATION 2014 select MODULE_SIG_FORMAT
2011 help 2015 help
2012 Check modules for valid signatures upon load: the signature 2016 Check modules for valid signatures upon load: the signature
2013 is simply appended to the module. For more information see 2017 is simply appended to the module. For more information see
diff --git a/kernel/Makefile b/kernel/Makefile
index a8d923b5481b..179b44ab8b46 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -58,6 +58,7 @@ endif
58obj-$(CONFIG_UID16) += uid16.o 58obj-$(CONFIG_UID16) += uid16.o
59obj-$(CONFIG_MODULES) += module.o 59obj-$(CONFIG_MODULES) += module.o
60obj-$(CONFIG_MODULE_SIG) += module_signing.o 60obj-$(CONFIG_MODULE_SIG) += module_signing.o
61obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signature.o
61obj-$(CONFIG_KALLSYMS) += kallsyms.o 62obj-$(CONFIG_KALLSYMS) += kallsyms.o
62obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o 63obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
63obj-$(CONFIG_CRASH_CORE) += crash_core.o 64obj-$(CONFIG_CRASH_CORE) += crash_core.o
diff --git a/kernel/module.c b/kernel/module.c
index 5933395af9a0..5ac22efc3685 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -7,6 +7,7 @@
7#include <linux/export.h> 7#include <linux/export.h>
8#include <linux/extable.h> 8#include <linux/extable.h>
9#include <linux/moduleloader.h> 9#include <linux/moduleloader.h>
10#include <linux/module_signature.h>
10#include <linux/trace_events.h> 11#include <linux/trace_events.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/kallsyms.h> 13#include <linux/kallsyms.h>
diff --git a/kernel/module_signature.c b/kernel/module_signature.c
new file mode 100644
index 000000000000..4224a1086b7d
--- /dev/null
+++ b/kernel/module_signature.c
@@ -0,0 +1,46 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Module signature checker
4 *
5 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
7 */
8
9#include <linux/errno.h>
10#include <linux/printk.h>
11#include <linux/module_signature.h>
12#include <asm/byteorder.h>
13
14/**
15 * mod_check_sig - check that the given signature is sane
16 *
17 * @ms: Signature to check.
18 * @file_len: Size of the file to which @ms is appended.
19 * @name: What is being checked. Used for error messages.
20 */
21int mod_check_sig(const struct module_signature *ms, size_t file_len,
22 const char *name)
23{
24 if (be32_to_cpu(ms->sig_len) >= file_len - sizeof(*ms))
25 return -EBADMSG;
26
27 if (ms->id_type != PKEY_ID_PKCS7) {
28 pr_err("%s: Module is not signed with expected PKCS#7 message\n",
29 name);
30 return -ENOPKG;
31 }
32
33 if (ms->algo != 0 ||
34 ms->hash != 0 ||
35 ms->signer_len != 0 ||
36 ms->key_id_len != 0 ||
37 ms->__pad[0] != 0 ||
38 ms->__pad[1] != 0 ||
39 ms->__pad[2] != 0) {
40 pr_err("%s: PKCS#7 signature info has unexpected non-zero params\n",
41 name);
42 return -EBADMSG;
43 }
44
45 return 0;
46}
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index b10fb1986ca9..9d9fc678c91d 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -7,37 +7,13 @@
7 7
8#include <linux/kernel.h> 8#include <linux/kernel.h>
9#include <linux/errno.h> 9#include <linux/errno.h>
10#include <linux/module.h>
11#include <linux/module_signature.h>
10#include <linux/string.h> 12#include <linux/string.h>
11#include <linux/verification.h> 13#include <linux/verification.h>
12#include <crypto/public_key.h> 14#include <crypto/public_key.h>
13#include "module-internal.h" 15#include "module-internal.h"
14 16
15enum pkey_id_type {
16 PKEY_ID_PGP, /* OpenPGP generated key ID */
17 PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
18 PKEY_ID_PKCS7, /* Signature in PKCS#7 message */
19};
20
21/*
22 * Module signature information block.
23 *
24 * The constituents of the signature section are, in order:
25 *
26 * - Signer's name
27 * - Key identifier
28 * - Signature data
29 * - Information block
30 */
31struct module_signature {
32 u8 algo; /* Public-key crypto algorithm [0] */
33 u8 hash; /* Digest algorithm [0] */
34 u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
35 u8 signer_len; /* Length of signer's name [0] */
36 u8 key_id_len; /* Length of key identifier [0] */
37 u8 __pad[3];
38 __be32 sig_len; /* Length of signature data */
39};
40
41/* 17/*
42 * Verify the signature on a module. 18 * Verify the signature on a module.
43 */ 19 */
@@ -45,6 +21,7 @@ int mod_verify_sig(const void *mod, struct load_info *info)
45{ 21{
46 struct module_signature ms; 22 struct module_signature ms;
47 size_t sig_len, modlen = info->len; 23 size_t sig_len, modlen = info->len;
24 int ret;
48 25
49 pr_devel("==>%s(,%zu)\n", __func__, modlen); 26 pr_devel("==>%s(,%zu)\n", __func__, modlen);
50 27
@@ -52,32 +29,15 @@ int mod_verify_sig(const void *mod, struct load_info *info)
52 return -EBADMSG; 29 return -EBADMSG;
53 30
54 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); 31 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
55 modlen -= sizeof(ms); 32
33 ret = mod_check_sig(&ms, modlen, info->name);
34 if (ret)
35 return ret;
56 36
57 sig_len = be32_to_cpu(ms.sig_len); 37 sig_len = be32_to_cpu(ms.sig_len);
58 if (sig_len >= modlen) 38 modlen -= sig_len + sizeof(ms);
59 return -EBADMSG;
60 modlen -= sig_len;
61 info->len = modlen; 39 info->len = modlen;
62 40
63 if (ms.id_type != PKEY_ID_PKCS7) {
64 pr_err("%s: Module is not signed with expected PKCS#7 message\n",
65 info->name);
66 return -ENOPKG;
67 }
68
69 if (ms.algo != 0 ||
70 ms.hash != 0 ||
71 ms.signer_len != 0 ||
72 ms.key_id_len != 0 ||
73 ms.__pad[0] != 0 ||
74 ms.__pad[1] != 0 ||
75 ms.__pad[2] != 0) {
76 pr_err("%s: PKCS#7 signature info has unexpected non-zero params\n",
77 info->name);
78 return -EBADMSG;
79 }
80
81 return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len, 41 return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
82 VERIFY_USE_SECONDARY_KEYRING, 42 VERIFY_USE_SECONDARY_KEYRING,
83 VERIFYING_MODULE_SIGNATURE, 43 VERIFYING_MODULE_SIGNATURE,
diff --git a/scripts/Makefile b/scripts/Makefile
index 16bcb8087899..532f7e0915c3 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -17,7 +17,7 @@ hostprogs-$(CONFIG_VT) += conmakehash
17hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount 17hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
18hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable 18hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
19hostprogs-$(CONFIG_ASN1) += asn1_compiler 19hostprogs-$(CONFIG_ASN1) += asn1_compiler
20hostprogs-$(CONFIG_MODULE_SIG) += sign-file 20hostprogs-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
21hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert 21hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
22hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert 22hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
23 23