aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
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 /kernel
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>
Diffstat (limited to 'kernel')
-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
6 files changed, 119 insertions, 115 deletions
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);