mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 05:32:00 +00:00
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>
This commit is contained in:
parent
0fbd39cf7f
commit
b56e5a17b6
23
include/keys/system_keyring.h
Normal file
23
include/keys/system_keyring.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* System keyring containing trusted public keys.
|
||||
*
|
||||
* Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* 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
init/Kconfig
13
init/Kconfig
@ -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
|
||||
@ -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
|
||||
|
@ -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
|
||||
@ -141,11 +142,11 @@ 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
|
||||
@ -153,6 +154,7 @@ ifeq ($(CONFIG_MODULE_SIG),y)
|
||||
# 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), \
|
||||
@ -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)
|
||||
@ -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
|
||||
|
@ -1,104 +0,0 @@
|
||||
/* Public keys for module signature verification
|
||||
*
|
||||
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/err.h>
|
||||
#include <keys/asymmetric-type.h>
|
||||
#include "module-internal.h"
|
||||
|
||||
struct key *modsign_keyring;
|
||||
|
||||
extern __initconst const u8 modsign_certificate_list[];
|
||||
extern __initconst const u8 modsign_certificate_list_end[];
|
||||
|
||||
/*
|
||||
* We need to make sure ccache doesn't cache the .o file as it doesn't notice
|
||||
* if modsign.pub changes.
|
||||
*/
|
||||
static __initconst const char annoy_ccache[] = __TIME__ "foo";
|
||||
|
||||
/*
|
||||
* Load the compiled-in keys
|
||||
*/
|
||||
static __init int module_verify_init(void)
|
||||
{
|
||||
pr_notice("Initialise module verification\n");
|
||||
|
||||
modsign_keyring = keyring_alloc(".module_sign",
|
||||
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(modsign_keyring))
|
||||
panic("Can't allocate module signing keyring\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be initialised before we try and load the keys into the keyring.
|
||||
*/
|
||||
device_initcall(module_verify_init);
|
||||
|
||||
/*
|
||||
* Load the compiled-in keys
|
||||
*/
|
||||
static __init int load_module_signing_keys(void)
|
||||
{
|
||||
key_ref_t key;
|
||||
const u8 *p, *end;
|
||||
size_t plen;
|
||||
|
||||
pr_notice("Loading module verification certificates\n");
|
||||
|
||||
end = modsign_certificate_list_end;
|
||||
p = modsign_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(modsign_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("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n",
|
||||
PTR_ERR(key));
|
||||
else
|
||||
pr_notice("MODSIGN: Loaded cert '%s'\n",
|
||||
key_ref_to_ptr(key)->description);
|
||||
p += plen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
dodgy_cert:
|
||||
pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n");
|
||||
return 0;
|
||||
}
|
||||
late_initcall(load_module_signing_keys);
|
@ -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);
|
||||
|
@ -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"
|
||||
|
||||
/*
|
||||
@ -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",
|
||||
|
@ -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
kernel/system_keyring.c
Normal file
103
kernel/system_keyring.c
Normal file
@ -0,0 +1,103 @@
|
||||
/* System trusted keyring for trusted public keys
|
||||
*
|
||||
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* 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);
|
Loading…
Reference in New Issue
Block a user