aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-08-30 11:07:30 -0400
committerDavid Howells <dhowells@redhat.com>2013-09-25 12:17:01 -0400
commitb56e5a17b6b9acd16997960504b9940d0d7984e7 (patch)
tree3041aadaf0eb3e79c0a5d1e7f9715489340f868a
parent0fbd39cf7ffe3b6a787b66b672d21b84e4675352 (diff)
KEYS: Separate the kernel signature checking keyring from module signing
Separate the kernel signature checking keyring from module signing so that it can be used by code other than the module-signing code. Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--include/keys/system_keyring.h23
-rw-r--r--init/Kconfig13
-rw-r--r--kernel/Makefile15
-rw-r--r--kernel/modsign_pubkey.c104
-rw-r--r--kernel/module-internal.h2
-rw-r--r--kernel/module_signing.c3
-rw-r--r--kernel/system_certificates.S (renamed from kernel/modsign_certificate.S)7
-rw-r--r--kernel/system_keyring.c103
8 files changed, 155 insertions, 115 deletions
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
new file mode 100644
index 000000000000..8dabc399bd1d
--- /dev/null
+++ b/include/keys/system_keyring.h
@@ -0,0 +1,23 @@
1/* System keyring containing trusted public keys.
2 *
3 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#ifndef _KEYS_SYSTEM_KEYRING_H
13#define _KEYS_SYSTEM_KEYRING_H
14
15#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING
16
17#include <linux/key.h>
18
19extern struct key *system_trusted_keyring;
20
21#endif
22
23#endif /* _KEYS_SYSTEM_KEYRING_H */
diff --git a/init/Kconfig b/init/Kconfig
index 3ecd8a1178f1..0ff5407a8378 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1668,6 +1668,18 @@ config BASE_SMALL
1668 default 0 if BASE_FULL 1668 default 0 if BASE_FULL
1669 default 1 if !BASE_FULL 1669 default 1 if !BASE_FULL
1670 1670
1671config SYSTEM_TRUSTED_KEYRING
1672 bool "Provide system-wide ring of trusted keys"
1673 depends on KEYS
1674 help
1675 Provide a system keyring to which trusted keys can be added. Keys in
1676 the keyring are considered to be trusted. Keys may be added at will
1677 by the kernel from compiled-in data and from hardware key stores, but
1678 userspace may only add extra keys if those keys can be verified by
1679 keys already in the keyring.
1680
1681 Keys in this keyring are used by module signature checking.
1682
1671menuconfig MODULES 1683menuconfig MODULES
1672 bool "Enable loadable module support" 1684 bool "Enable loadable module support"
1673 option modules 1685 option modules
@@ -1741,6 +1753,7 @@ config MODULE_SRCVERSION_ALL
1741config MODULE_SIG 1753config MODULE_SIG
1742 bool "Module signature verification" 1754 bool "Module signature verification"
1743 depends on MODULES 1755 depends on MODULES
1756 select SYSTEM_TRUSTED_KEYRING
1744 select KEYS 1757 select KEYS
1745 select CRYPTO 1758 select CRYPTO
1746 select ASYMMETRIC_KEY_TYPE 1759 select ASYMMETRIC_KEY_TYPE
diff --git a/kernel/Makefile b/kernel/Makefile
index 2c24195249d5..63136989c132 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -54,8 +54,9 @@ obj-$(CONFIG_SMP) += spinlock.o
54obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o 54obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
55obj-$(CONFIG_PROVE_LOCKING) += spinlock.o 55obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
56obj-$(CONFIG_UID16) += uid16.o 56obj-$(CONFIG_UID16) += uid16.o
57obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
57obj-$(CONFIG_MODULES) += module.o 58obj-$(CONFIG_MODULES) += module.o
58obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o 59obj-$(CONFIG_MODULE_SIG) += module_signing.o
59obj-$(CONFIG_KALLSYMS) += kallsyms.o 60obj-$(CONFIG_KALLSYMS) += kallsyms.o
60obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o 61obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
61obj-$(CONFIG_KEXEC) += kexec.o 62obj-$(CONFIG_KEXEC) += kexec.o
@@ -141,11 +142,11 @@ targets += timeconst.h
141$(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE 142$(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
142 $(call if_changed,bc) 143 $(call if_changed,bc)
143 144
144ifeq ($(CONFIG_MODULE_SIG),y)
145############################################################################### 145###############################################################################
146# 146#
147# Roll all the X.509 certificates that we can find together and pull them into 147# Roll all the X.509 certificates that we can find together and pull them into
148# the kernel. 148# the kernel so that they get loaded into the system trusted keyring during
149# boot.
149# 150#
150# We look in the source root and the build root for all files whose name ends 151# We look in the source root and the build root for all files whose name ends
151# in ".x509". Unfortunately, this will generate duplicate filenames, so we 152# in ".x509". Unfortunately, this will generate duplicate filenames, so we
@@ -153,6 +154,7 @@ ifeq ($(CONFIG_MODULE_SIG),y)
153# duplicates. 154# duplicates.
154# 155#
155############################################################################### 156###############################################################################
157ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
156X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) 158X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509)
157X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 159X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509
158X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \ 160X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
@@ -169,10 +171,11 @@ $(shell rm $(obj)/.x509.list)
169endif 171endif
170endif 172endif
171 173
172kernel/modsign_certificate.o: $(obj)/x509_certificate_list 174kernel/system_certificates.o: $(obj)/x509_certificate_list
173 175
174quiet_cmd_x509certs = CERTS $@ 176quiet_cmd_x509certs = CERTS $@
175 cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ 177 cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; echo " - Including cert $(X509)")
178
176targets += $(obj)/x509_certificate_list 179targets += $(obj)/x509_certificate_list
177$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list 180$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
178 $(call if_changed,x509certs) 181 $(call if_changed,x509certs)
@@ -182,7 +185,9 @@ $(obj)/.x509.list:
182 @echo $(X509_CERTIFICATES) >$@ 185 @echo $(X509_CERTIFICATES) >$@
183 186
184clean-files := x509_certificate_list .x509.list 187clean-files := x509_certificate_list .x509.list
188endif
185 189
190ifeq ($(CONFIG_MODULE_SIG),y)
186############################################################################### 191###############################################################################
187# 192#
188# If module signing is requested, say by allyesconfig, but a key has not been 193# If module signing is requested, say by allyesconfig, but a key has not been
diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c
deleted file mode 100644
index 7cbd4507a7e6..000000000000
--- a/kernel/modsign_pubkey.c
+++ /dev/null
@@ -1,104 +0,0 @@
1/* Public keys for module signature verification
2 *
3 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/sched.h>
14#include <linux/cred.h>
15#include <linux/err.h>
16#include <keys/asymmetric-type.h>
17#include "module-internal.h"
18
19struct key *modsign_keyring;
20
21extern __initconst const u8 modsign_certificate_list[];
22extern __initconst const u8 modsign_certificate_list_end[];
23
24/*
25 * We need to make sure ccache doesn't cache the .o file as it doesn't notice
26 * if modsign.pub changes.
27 */
28static __initconst const char annoy_ccache[] = __TIME__ "foo";
29
30/*
31 * Load the compiled-in keys
32 */
33static __init int module_verify_init(void)
34{
35 pr_notice("Initialise module verification\n");
36
37 modsign_keyring = keyring_alloc(".module_sign",
38 KUIDT_INIT(0), KGIDT_INIT(0),
39 current_cred(),
40 ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
41 KEY_USR_VIEW | KEY_USR_READ),
42 KEY_ALLOC_NOT_IN_QUOTA, NULL);
43 if (IS_ERR(modsign_keyring))
44 panic("Can't allocate module signing keyring\n");
45
46 return 0;
47}
48
49/*
50 * Must be initialised before we try and load the keys into the keyring.
51 */
52device_initcall(module_verify_init);
53
54/*
55 * Load the compiled-in keys
56 */
57static __init int load_module_signing_keys(void)
58{
59 key_ref_t key;
60 const u8 *p, *end;
61 size_t plen;
62
63 pr_notice("Loading module verification certificates\n");
64
65 end = modsign_certificate_list_end;
66 p = modsign_certificate_list;
67 while (p < end) {
68 /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
69 * than 256 bytes in size.
70 */
71 if (end - p < 4)
72 goto dodgy_cert;
73 if (p[0] != 0x30 &&
74 p[1] != 0x82)
75 goto dodgy_cert;
76 plen = (p[2] << 8) | p[3];
77 plen += 4;
78 if (plen > end - p)
79 goto dodgy_cert;
80
81 key = key_create_or_update(make_key_ref(modsign_keyring, 1),
82 "asymmetric",
83 NULL,
84 p,
85 plen,
86 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
87 KEY_USR_VIEW,
88 KEY_ALLOC_NOT_IN_QUOTA);
89 if (IS_ERR(key))
90 pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n",
91 PTR_ERR(key));
92 else
93 pr_notice("MODSIGN: Loaded cert '%s'\n",
94 key_ref_to_ptr(key)->description);
95 p += plen;
96 }
97
98 return 0;
99
100dodgy_cert:
101 pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n");
102 return 0;
103}
104late_initcall(load_module_signing_keys);
diff --git a/kernel/module-internal.h b/kernel/module-internal.h
index 24f9247b7d02..915e123a430f 100644
--- a/kernel/module-internal.h
+++ b/kernel/module-internal.h
@@ -9,6 +9,4 @@
9 * 2 of the Licence, or (at your option) any later version. 9 * 2 of the Licence, or (at your option) any later version.
10 */ 10 */
11 11
12extern struct key *modsign_keyring;
13
14extern int mod_verify_sig(const void *mod, unsigned long *_modlen); 12extern int mod_verify_sig(const void *mod, unsigned long *_modlen);
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index ee476404167b..0b6b870dc5e4 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -14,6 +14,7 @@
14#include <crypto/public_key.h> 14#include <crypto/public_key.h>
15#include <crypto/hash.h> 15#include <crypto/hash.h>
16#include <keys/asymmetric-type.h> 16#include <keys/asymmetric-type.h>
17#include <keys/system_keyring.h>
17#include "module-internal.h" 18#include "module-internal.h"
18 19
19/* 20/*
@@ -157,7 +158,7 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
157 158
158 pr_debug("Look up: \"%s\"\n", id); 159 pr_debug("Look up: \"%s\"\n", id);
159 160
160 key = keyring_search(make_key_ref(modsign_keyring, 1), 161 key = keyring_search(make_key_ref(system_trusted_keyring, 1),
161 &key_type_asymmetric, id); 162 &key_type_asymmetric, id);
162 if (IS_ERR(key)) 163 if (IS_ERR(key))
163 pr_warn("Request for unknown module key '%s' err %ld\n", 164 pr_warn("Request for unknown module key '%s' err %ld\n",
diff --git a/kernel/modsign_certificate.S b/kernel/system_certificates.S
index 6fe03c7ffe72..552d47b2d463 100644
--- a/kernel/modsign_certificate.S
+++ b/kernel/system_certificates.S
@@ -1,11 +1,12 @@
1#include <linux/export.h> 1#include <linux/export.h>
2#include <linux/init.h>
2 3
3#define GLOBAL(name) \ 4#define GLOBAL(name) \
4 .globl VMLINUX_SYMBOL(name); \ 5 .globl VMLINUX_SYMBOL(name); \
5 VMLINUX_SYMBOL(name): 6 VMLINUX_SYMBOL(name):
6 7
7 .section ".init.data","aw" 8 __INITRODATA
8 9
9GLOBAL(modsign_certificate_list) 10GLOBAL(system_certificate_list)
10 .incbin "kernel/x509_certificate_list" 11 .incbin "kernel/x509_certificate_list"
11GLOBAL(modsign_certificate_list_end) 12GLOBAL(system_certificate_list_end)
diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
new file mode 100644
index 000000000000..51c35141a13a
--- /dev/null
+++ b/kernel/system_keyring.c
@@ -0,0 +1,103 @@
1/* System trusted keyring for trusted public keys
2 *
3 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/export.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/cred.h>
16#include <linux/err.h>
17#include <keys/asymmetric-type.h>
18#include <keys/system_keyring.h>
19#include "module-internal.h"
20
21struct key *system_trusted_keyring;
22EXPORT_SYMBOL_GPL(system_trusted_keyring);
23
24extern __initconst const u8 system_certificate_list[];
25extern __initconst const u8 system_certificate_list_end[];
26
27/*
28 * Load the compiled-in keys
29 */
30static __init int system_trusted_keyring_init(void)
31{
32 pr_notice("Initialise system trusted keyring\n");
33
34 system_trusted_keyring =
35 keyring_alloc(".system_keyring",
36 KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
37 ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
38 KEY_USR_VIEW | KEY_USR_READ),
39 KEY_ALLOC_NOT_IN_QUOTA, NULL);
40 if (IS_ERR(system_trusted_keyring))
41 panic("Can't allocate system trusted keyring\n");
42
43 return 0;
44}
45
46/*
47 * Must be initialised before we try and load the keys into the keyring.
48 */
49device_initcall(system_trusted_keyring_init);
50
51/*
52 * Load the compiled-in list of X.509 certificates.
53 */
54static __init int load_system_certificate_list(void)
55{
56 key_ref_t key;
57 const u8 *p, *end;
58 size_t plen;
59
60 pr_notice("Loading compiled-in X.509 certificates\n");
61
62 end = system_certificate_list_end;
63 p = system_certificate_list;
64 while (p < end) {
65 /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
66 * than 256 bytes in size.
67 */
68 if (end - p < 4)
69 goto dodgy_cert;
70 if (p[0] != 0x30 &&
71 p[1] != 0x82)
72 goto dodgy_cert;
73 plen = (p[2] << 8) | p[3];
74 plen += 4;
75 if (plen > end - p)
76 goto dodgy_cert;
77
78 key = key_create_or_update(make_key_ref(system_trusted_keyring, 1),
79 "asymmetric",
80 NULL,
81 p,
82 plen,
83 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
84 KEY_USR_VIEW,
85 KEY_ALLOC_NOT_IN_QUOTA);
86 if (IS_ERR(key)) {
87 pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
88 PTR_ERR(key));
89 } else {
90 pr_notice("Loaded X.509 cert '%s'\n",
91 key_ref_to_ptr(key)->description);
92 key_ref_put(key);
93 }
94 p += plen;
95 }
96
97 return 0;
98
99dodgy_cert:
100 pr_err("Problem parsing in-kernel X.509 certificate list\n");
101 return 0;
102}
103late_initcall(load_system_certificate_list);