Skip to content

Commit

Permalink
KEYS: Separate the kernel signature checking keyring from module signing
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
dhowells committed Sep 25, 2013
1 parent 0fbd39c commit b56e5a1
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 115 deletions.
23 changes: 23 additions & 0 deletions include/keys/system_keyring.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* System keyring containing trusted public keys.
*
* Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
* Written by David Howells ([email protected])
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/

#ifndef _KEYS_SYSTEM_KEYRING_H
#define _KEYS_SYSTEM_KEYRING_H

#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING

#include <linux/key.h>

extern struct key *system_trusted_keyring;

#endif

#endif /* _KEYS_SYSTEM_KEYRING_H */
13 changes: 13 additions & 0 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1668,6 +1668,18 @@ config BASE_SMALL
default 0 if BASE_FULL
default 1 if !BASE_FULL

config SYSTEM_TRUSTED_KEYRING
bool "Provide system-wide ring of trusted keys"
depends on KEYS
help
Provide a system keyring to which trusted keys can be added. Keys in
the keyring are considered to be trusted. Keys may be added at will
by the kernel from compiled-in data and from hardware key stores, but
userspace may only add extra keys if those keys can be verified by
keys already in the keyring.

Keys in this keyring are used by module signature checking.

menuconfig MODULES
bool "Enable loadable module support"
option modules
Expand Down Expand Up @@ -1741,6 +1753,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
Expand Down
15 changes: 10 additions & 5 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ obj-$(CONFIG_SMP) += spinlock.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o
obj-$(CONFIG_MODULE_SIG) += module_signing.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
Expand Down Expand Up @@ -141,18 +142,19 @@ targets += timeconst.h
$(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
$(call if_changed,bc)

ifeq ($(CONFIG_MODULE_SIG),y)
###############################################################################
#
# Roll all the X.509 certificates that we can find together and pull them into
# the kernel.
# the kernel so that they get loaded into the system trusted keyring during
# boot.
#
# We look in the source root and the build root for all files whose name ends
# in ".x509". Unfortunately, this will generate duplicate filenames, so we
# have make canonicalise the pathnames and then sort them to discard the
# duplicates.
#
###############################################################################
ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509)
X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509
X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
Expand All @@ -169,10 +171,11 @@ $(shell rm $(obj)/.x509.list)
endif
endif

kernel/modsign_certificate.o: $(obj)/x509_certificate_list
kernel/system_certificates.o: $(obj)/x509_certificate_list

quiet_cmd_x509certs = CERTS $@
cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@
cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; echo " - Including cert $(X509)")

targets += $(obj)/x509_certificate_list
$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
$(call if_changed,x509certs)
Expand All @@ -182,7 +185,9 @@ $(obj)/.x509.list:
@echo $(X509_CERTIFICATES) >$@

clean-files := x509_certificate_list .x509.list
endif

ifeq ($(CONFIG_MODULE_SIG),y)
###############################################################################
#
# If module signing is requested, say by allyesconfig, but a key has not been
Expand Down
104 changes: 0 additions & 104 deletions kernel/modsign_pubkey.c

This file was deleted.

2 changes: 0 additions & 2 deletions kernel/module-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,4 @@
* 2 of the Licence, or (at your option) any later version.
*/

extern struct key *modsign_keyring;

extern int mod_verify_sig(const void *mod, unsigned long *_modlen);
3 changes: 2 additions & 1 deletion kernel/module_signing.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <crypto/public_key.h>
#include <crypto/hash.h>
#include <keys/asymmetric-type.h>
#include <keys/system_keyring.h>
#include "module-internal.h"

/*
Expand Down Expand Up @@ -157,7 +158,7 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,

pr_debug("Look up: \"%s\"\n", id);

key = keyring_search(make_key_ref(modsign_keyring, 1),
key = keyring_search(make_key_ref(system_trusted_keyring, 1),
&key_type_asymmetric, id);
if (IS_ERR(key))
pr_warn("Request for unknown module key '%s' err %ld\n",
Expand Down
7 changes: 4 additions & 3 deletions kernel/modsign_certificate.S → kernel/system_certificates.S
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#include <linux/export.h>
#include <linux/init.h>

#define GLOBAL(name) \
.globl VMLINUX_SYMBOL(name); \
VMLINUX_SYMBOL(name):

.section ".init.data","aw"
__INITRODATA

GLOBAL(modsign_certificate_list)
GLOBAL(system_certificate_list)
.incbin "kernel/x509_certificate_list"
GLOBAL(modsign_certificate_list_end)
GLOBAL(system_certificate_list_end)
103 changes: 103 additions & 0 deletions kernel/system_keyring.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* System trusted keyring for trusted public keys
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells ([email protected])
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/

#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/cred.h>
#include <linux/err.h>
#include <keys/asymmetric-type.h>
#include <keys/system_keyring.h>
#include "module-internal.h"

struct key *system_trusted_keyring;
EXPORT_SYMBOL_GPL(system_trusted_keyring);

extern __initconst const u8 system_certificate_list[];
extern __initconst const u8 system_certificate_list_end[];

/*
* Load the compiled-in keys
*/
static __init int system_trusted_keyring_init(void)
{
pr_notice("Initialise system trusted keyring\n");

system_trusted_keyring =
keyring_alloc(".system_keyring",
KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ),
KEY_ALLOC_NOT_IN_QUOTA, NULL);
if (IS_ERR(system_trusted_keyring))
panic("Can't allocate system trusted keyring\n");

return 0;
}

/*
* Must be initialised before we try and load the keys into the keyring.
*/
device_initcall(system_trusted_keyring_init);

/*
* Load the compiled-in list of X.509 certificates.
*/
static __init int load_system_certificate_list(void)
{
key_ref_t key;
const u8 *p, *end;
size_t plen;

pr_notice("Loading compiled-in X.509 certificates\n");

end = system_certificate_list_end;
p = system_certificate_list;
while (p < end) {
/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
* than 256 bytes in size.
*/
if (end - p < 4)
goto dodgy_cert;
if (p[0] != 0x30 &&
p[1] != 0x82)
goto dodgy_cert;
plen = (p[2] << 8) | p[3];
plen += 4;
if (plen > end - p)
goto dodgy_cert;

key = key_create_or_update(make_key_ref(system_trusted_keyring, 1),
"asymmetric",
NULL,
p,
plen,
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW,
KEY_ALLOC_NOT_IN_QUOTA);
if (IS_ERR(key)) {
pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
PTR_ERR(key));
} else {
pr_notice("Loaded X.509 cert '%s'\n",
key_ref_to_ptr(key)->description);
key_ref_put(key);
}
p += plen;
}

return 0;

dodgy_cert:
pr_err("Problem parsing in-kernel X.509 certificate list\n");
return 0;
}
late_initcall(load_system_certificate_list);

0 comments on commit b56e5a1

Please sign in to comment.