aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2015-08-14 10:20:41 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2015-08-14 11:06:13 -0400
commitcfc411e7fff3e15cd6354ff69773907e2c9d1c0c (patch)
treec67e679c1c2bbe4a657ce58d60e995c63535952b /kernel
parent0e38c35815f50e5a347977d76fb5eb4c3bf020b5 (diff)
Move certificate handling to its own directory
Move certificate handling out of the kernel/ directory and into a certs/ directory to get all the weird stuff in one place and move the generated signing keys into this directory. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile143
-rw-r--r--kernel/system_certificates.S23
-rw-r--r--kernel/system_keyring.c157
3 files changed, 0 insertions, 323 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 65ef3846fbe8..1aa153a1be21 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -45,7 +45,6 @@ ifneq ($(CONFIG_SMP),y)
45obj-y += up.o 45obj-y += up.o
46endif 46endif
47obj-$(CONFIG_UID16) += uid16.o 47obj-$(CONFIG_UID16) += uid16.o
48obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
49obj-$(CONFIG_MODULES) += module.o 48obj-$(CONFIG_MODULES) += module.o
50obj-$(CONFIG_MODULE_SIG) += module_signing.o 49obj-$(CONFIG_MODULE_SIG) += module_signing.o
51obj-$(CONFIG_KALLSYMS) += kallsyms.o 50obj-$(CONFIG_KALLSYMS) += kallsyms.o
@@ -111,145 +110,3 @@ $(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE
111targets += config_data.h 110targets += config_data.h
112$(obj)/config_data.h: $(obj)/config_data.gz FORCE 111$(obj)/config_data.h: $(obj)/config_data.gz FORCE
113 $(call filechk,ikconfiggz) 112 $(call filechk,ikconfiggz)
114
115###############################################################################
116#
117# When a Kconfig string contains a filename, it is suitable for
118# passing to shell commands. It is surrounded by double-quotes, and
119# any double-quotes or backslashes within it are escaped by
120# backslashes.
121#
122# This is no use for dependencies or $(wildcard). We need to strip the
123# surrounding quotes and the escaping from quotes and backslashes, and
124# we *do* need to escape any spaces in the string. So, for example:
125#
126# Usage: $(eval $(call config_filename,FOO))
127#
128# Defines FOO_FILENAME based on the contents of the CONFIG_FOO option,
129# transformed as described above to be suitable for use within the
130# makefile.
131#
132# Also, if the filename is a relative filename and exists in the source
133# tree but not the build tree, define FOO_SRCPREFIX as $(srctree)/ to
134# be prefixed to *both* command invocation and dependencies.
135#
136# Note: We also print the filenames in the quiet_cmd_foo text, and
137# perhaps ought to have a version specially escaped for that purpose.
138# But it's only cosmetic, and $(patsubst "%",%,$(CONFIG_FOO)) is good
139# enough. It'll strip the quotes in the common case where there's no
140# space and it's a simple filename, and it'll retain the quotes when
141# there's a space. There are some esoteric cases in which it'll print
142# the wrong thing, but we don't really care. The actual dependencies
143# and commands *do* get it right, with various combinations of single
144# and double quotes, backslashes and spaces in the filenames.
145#
146###############################################################################
147#
148quote := $(firstword " ")
149space :=
150space +=
151space_escape := %%%SPACE%%%
152#
153define config_filename
154ifneq ($$(CONFIG_$(1)),"")
155$(1)_FILENAME := $$(subst \\,\,$$(subst \$$(quote),$$(quote),$$(subst $$(space_escape),\$$(space),$$(patsubst "%",%,$$(subst $$(space),$$(space_escape),$$(CONFIG_$(1)))))))
156ifneq ($$(patsubst /%,%,$$(firstword $$($(1)_FILENAME))),$$(firstword $$($(1)_FILENAME)))
157else
158ifeq ($$(wildcard $$($(1)_FILENAME)),)
159ifneq ($$(wildcard $$(srctree)/$$($(1)_FILENAME)),)
160$(1)_SRCPREFIX := $(srctree)/
161endif
162endif
163endif
164endif
165endef
166#
167###############################################################################
168
169ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
170
171$(eval $(call config_filename,SYSTEM_TRUSTED_KEYS))
172
173# GCC doesn't include .incbin files in -MD generated dependencies (PR#66871)
174$(obj)/system_certificates.o: $(obj)/x509_certificate_list
175
176# Cope with signing_key.x509 existing in $(srctree) not $(objtree)
177AFLAGS_system_certificates.o := -I$(srctree)
178
179quiet_cmd_extract_certs = EXTRACT_CERTS $(patsubst "%",%,$(2))
180 cmd_extract_certs = scripts/extract-cert $(2) $@ || ( rm $@; exit 1)
181
182targets += x509_certificate_list
183$(obj)/x509_certificate_list: scripts/extract-cert $(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(SYSTEM_TRUSTED_KEYS_FILENAME) FORCE
184 $(call if_changed,extract_certs,$(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(CONFIG_SYSTEM_TRUSTED_KEYS))
185endif
186
187clean-files := x509_certificate_list .x509.list
188
189ifeq ($(CONFIG_MODULE_SIG),y)
190###############################################################################
191#
192# If module signing is requested, say by allyesconfig, but a key has not been
193# supplied, then one will need to be generated to make sure the build does not
194# fail and that the kernel may be used afterwards.
195#
196###############################################################################
197ifndef CONFIG_MODULE_SIG_HASH
198$(error Could not determine digest type to use from kernel config)
199endif
200
201# We do it this way rather than having a boolean option for enabling an
202# external private key, because 'make randconfig' might enable such a
203# boolean option and we unfortunately can't make it depend on !RANDCONFIG.
204ifeq ($(CONFIG_MODULE_SIG_KEY),"signing_key.pem")
205signing_key.pem: x509.genkey
206 @echo "###"
207 @echo "### Now generating an X.509 key pair to be used for signing modules."
208 @echo "###"
209 @echo "### If this takes a long time, you might wish to run rngd in the"
210 @echo "### background to keep the supply of entropy topped up. It"
211 @echo "### needs to be run as root, and uses a hardware random"
212 @echo "### number generator if one is available."
213 @echo "###"
214 openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \
215 -batch -x509 -config x509.genkey \
216 -outform PEM -out signing_key.pem \
217 -keyout signing_key.pem 2>&1
218 @echo "###"
219 @echo "### Key pair generated."
220 @echo "###"
221
222x509.genkey:
223 @echo Generating X.509 key generation config
224 @echo >x509.genkey "[ req ]"
225 @echo >>x509.genkey "default_bits = 4096"
226 @echo >>x509.genkey "distinguished_name = req_distinguished_name"
227 @echo >>x509.genkey "prompt = no"
228 @echo >>x509.genkey "string_mask = utf8only"
229 @echo >>x509.genkey "x509_extensions = myexts"
230 @echo >>x509.genkey
231 @echo >>x509.genkey "[ req_distinguished_name ]"
232 @echo >>x509.genkey "#O = Unspecified company"
233 @echo >>x509.genkey "CN = Build time autogenerated kernel key"
234 @echo >>x509.genkey "#emailAddress = unspecified.user@unspecified.company"
235 @echo >>x509.genkey
236 @echo >>x509.genkey "[ myexts ]"
237 @echo >>x509.genkey "basicConstraints=critical,CA:FALSE"
238 @echo >>x509.genkey "keyUsage=digitalSignature"
239 @echo >>x509.genkey "subjectKeyIdentifier=hash"
240 @echo >>x509.genkey "authorityKeyIdentifier=keyid"
241endif
242
243$(eval $(call config_filename,MODULE_SIG_KEY))
244
245# If CONFIG_MODULE_SIG_KEY isn't a PKCS#11 URI, depend on it
246ifeq ($(patsubst pkcs11:%,%,$(firstword $(MODULE_SIG_KEY_FILENAME))),$(firstword $(MODULE_SIG_KEY_FILENAME)))
247X509_DEP := $(MODULE_SIG_KEY_SRCPREFIX)$(MODULE_SIG_KEY_FILENAME)
248endif
249
250# GCC PR#66871 again.
251$(obj)/system_certificates.o: signing_key.x509
252
253signing_key.x509: scripts/extract-cert include/config/module/sig/key.h $(X509_DEP)
254 $(call cmd,extract_certs,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY))
255endif
diff --git a/kernel/system_certificates.S b/kernel/system_certificates.S
deleted file mode 100644
index 6ba2f75e7ba5..000000000000
--- a/kernel/system_certificates.S
+++ /dev/null
@@ -1,23 +0,0 @@
1#include <linux/export.h>
2#include <linux/init.h>
3
4 __INITRODATA
5
6 .align 8
7 .globl VMLINUX_SYMBOL(system_certificate_list)
8VMLINUX_SYMBOL(system_certificate_list):
9__cert_list_start:
10#ifdef CONFIG_MODULE_SIG
11 .incbin "signing_key.x509"
12#endif
13 .incbin "kernel/x509_certificate_list"
14__cert_list_end:
15
16 .align 8
17 .globl VMLINUX_SYMBOL(system_certificate_list_size)
18VMLINUX_SYMBOL(system_certificate_list_size):
19#ifdef CONFIG_64BIT
20 .quad __cert_list_end - __cert_list_start
21#else
22 .long __cert_list_end - __cert_list_start
23#endif
diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
deleted file mode 100644
index 2570598b784d..000000000000
--- a/kernel/system_keyring.c
+++ /dev/null
@@ -1,157 +0,0 @@
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 <crypto/pkcs7.h>
20
21struct key *system_trusted_keyring;
22EXPORT_SYMBOL_GPL(system_trusted_keyring);
23
24extern __initconst const u8 system_certificate_list[];
25extern __initconst const unsigned long system_certificate_list_size;
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 | KEY_USR_SEARCH),
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 set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags);
44 return 0;
45}
46
47/*
48 * Must be initialised before we try and load the keys into the keyring.
49 */
50device_initcall(system_trusted_keyring_init);
51
52/*
53 * Load the compiled-in list of X.509 certificates.
54 */
55static __init int load_system_certificate_list(void)
56{
57 key_ref_t key;
58 const u8 *p, *end;
59 size_t plen;
60
61 pr_notice("Loading compiled-in X.509 certificates\n");
62
63 p = system_certificate_list;
64 end = p + system_certificate_list_size;
65 while (p < end) {
66 /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
67 * than 256 bytes in size.
68 */
69 if (end - p < 4)
70 goto dodgy_cert;
71 if (p[0] != 0x30 &&
72 p[1] != 0x82)
73 goto dodgy_cert;
74 plen = (p[2] << 8) | p[3];
75 plen += 4;
76 if (plen > end - p)
77 goto dodgy_cert;
78
79 key = key_create_or_update(make_key_ref(system_trusted_keyring, 1),
80 "asymmetric",
81 NULL,
82 p,
83 plen,
84 ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
85 KEY_USR_VIEW | KEY_USR_READ),
86 KEY_ALLOC_NOT_IN_QUOTA |
87 KEY_ALLOC_TRUSTED);
88 if (IS_ERR(key)) {
89 pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
90 PTR_ERR(key));
91 } else {
92 set_bit(KEY_FLAG_BUILTIN, &key_ref_to_ptr(key)->flags);
93 pr_notice("Loaded X.509 cert '%s'\n",
94 key_ref_to_ptr(key)->description);
95 key_ref_put(key);
96 }
97 p += plen;
98 }
99
100 return 0;
101
102dodgy_cert:
103 pr_err("Problem parsing in-kernel X.509 certificate list\n");
104 return 0;
105}
106late_initcall(load_system_certificate_list);
107
108#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
109
110/**
111 * Verify a PKCS#7-based signature on system data.
112 * @data: The data to be verified.
113 * @len: Size of @data.
114 * @raw_pkcs7: The PKCS#7 message that is the signature.
115 * @pkcs7_len: The size of @raw_pkcs7.
116 * @usage: The use to which the key is being put.
117 */
118int system_verify_data(const void *data, unsigned long len,
119 const void *raw_pkcs7, size_t pkcs7_len,
120 enum key_being_used_for usage)
121{
122 struct pkcs7_message *pkcs7;
123 bool trusted;
124 int ret;
125
126 pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
127 if (IS_ERR(pkcs7))
128 return PTR_ERR(pkcs7);
129
130 /* The data should be detached - so we need to supply it. */
131 if (pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
132 pr_err("PKCS#7 signature with non-detached data\n");
133 ret = -EBADMSG;
134 goto error;
135 }
136
137 ret = pkcs7_verify(pkcs7, usage);
138 if (ret < 0)
139 goto error;
140
141 ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
142 if (ret < 0)
143 goto error;
144
145 if (!trusted) {
146 pr_err("PKCS#7 signature not signed with a trusted key\n");
147 ret = -ENOKEY;
148 }
149
150error:
151 pkcs7_free_message(pkcs7);
152 pr_devel("<==%s() = %d\n", __func__, ret);
153 return ret;
154}
155EXPORT_SYMBOL_GPL(system_verify_data);
156
157#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */