Commit e23a8020 authored by Philipp Rudo's avatar Philipp Rudo Committed by Martin Schwidefsky

s390/kexec_file: Signature verification prototype

Add kernel signature verification to kexec_file. The verification is based
on module signature verification and works with kernel images signed via
scripts/sign-file.
Signed-off-by: default avatarPhilipp Rudo <prudo@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 653beba2
...@@ -553,6 +553,17 @@ config ARCH_HAS_KEXEC_PURGATORY ...@@ -553,6 +553,17 @@ config ARCH_HAS_KEXEC_PURGATORY
def_bool y def_bool y
depends on KEXEC_FILE depends on KEXEC_FILE
config KEXEC_VERIFY_SIG
bool "Verify kernel signature during kexec_file_load() syscall"
depends on KEXEC_FILE && SYSTEM_DATA_VERIFICATION
help
This option makes kernel signature verification mandatory for
the kexec_file_load() syscall.
In addition to that option, you need to enable signature
verification for the corresponding kernel image type being
loaded in order for this to work.
config ARCH_RANDOM config ARCH_RANDOM
def_bool y def_bool y
prompt "s390 architectural random number generation API" prompt "s390 architectural random number generation API"
......
...@@ -64,6 +64,7 @@ CONFIG_NUMA=y ...@@ -64,6 +64,7 @@ CONFIG_NUMA=y
CONFIG_PREEMPT=y CONFIG_PREEMPT=y
CONFIG_HZ_100=y CONFIG_HZ_100=y
CONFIG_KEXEC_FILE=y CONFIG_KEXEC_FILE=y
CONFIG_KEXEC_VERIFY_SIG=y
CONFIG_EXPOLINE=y CONFIG_EXPOLINE=y
CONFIG_EXPOLINE_AUTO=y CONFIG_EXPOLINE_AUTO=y
CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTPLUG=y
......
...@@ -65,6 +65,7 @@ CONFIG_NR_CPUS=512 ...@@ -65,6 +65,7 @@ CONFIG_NR_CPUS=512
CONFIG_NUMA=y CONFIG_NUMA=y
CONFIG_HZ_100=y CONFIG_HZ_100=y
CONFIG_KEXEC_FILE=y CONFIG_KEXEC_FILE=y
CONFIG_KEXEC_VERIFY_SIG=y
CONFIG_EXPOLINE=y CONFIG_EXPOLINE=y
CONFIG_EXPOLINE_AUTO=y CONFIG_EXPOLINE_AUTO=y
CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTPLUG=y
......
...@@ -39,6 +39,7 @@ CONFIG_NR_CPUS=256 ...@@ -39,6 +39,7 @@ CONFIG_NR_CPUS=256
CONFIG_NUMA=y CONFIG_NUMA=y
CONFIG_HZ_100=y CONFIG_HZ_100=y
CONFIG_KEXEC_FILE=y CONFIG_KEXEC_FILE=y
CONFIG_KEXEC_VERIFY_SIG=y
CONFIG_CRASH_DUMP=y CONFIG_CRASH_DUMP=y
CONFIG_HIBERNATION=y CONFIG_HIBERNATION=y
CONFIG_PM_DEBUG=y CONFIG_PM_DEBUG=y
......
...@@ -65,6 +65,7 @@ struct s390_load_data { ...@@ -65,6 +65,7 @@ struct s390_load_data {
size_t memsz; size_t memsz;
}; };
int s390_verify_sig(const char *kernel, unsigned long kernel_len);
void *kexec_file_add_components(struct kimage *image, void *kexec_file_add_components(struct kimage *image,
int (*add_kernel)(struct kimage *image, int (*add_kernel)(struct kimage *image,
struct s390_load_data *data)); struct s390_load_data *data));
......
...@@ -125,4 +125,7 @@ static int s390_elf_probe(const char *buf, unsigned long len) ...@@ -125,4 +125,7 @@ static int s390_elf_probe(const char *buf, unsigned long len)
const struct kexec_file_ops s390_kexec_elf_ops = { const struct kexec_file_ops s390_kexec_elf_ops = {
.probe = s390_elf_probe, .probe = s390_elf_probe,
.load = s390_elf_load, .load = s390_elf_load,
#ifdef CONFIG_KEXEC_VERIFY_SIG
.verify_sig = s390_verify_sig,
#endif /* CONFIG_KEXEC_VERIFY_SIG */
}; };
...@@ -54,4 +54,7 @@ static int s390_image_probe(const char *buf, unsigned long len) ...@@ -54,4 +54,7 @@ static int s390_image_probe(const char *buf, unsigned long len)
const struct kexec_file_ops s390_kexec_image_ops = { const struct kexec_file_ops s390_kexec_image_ops = {
.probe = s390_image_probe, .probe = s390_image_probe,
.load = s390_image_load, .load = s390_image_load,
#ifdef CONFIG_KEXEC_VERIFY_SIG
.verify_sig = s390_verify_sig,
#endif /* CONFIG_KEXEC_VERIFY_SIG */
}; };
...@@ -8,7 +8,11 @@ ...@@ -8,7 +8,11 @@
*/ */
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/errno.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/module.h>
#include <linux/verification.h>
#include <asm/ipl.h>
#include <asm/setup.h> #include <asm/setup.h>
const struct kexec_file_ops * const kexec_file_loaders[] = { const struct kexec_file_ops * const kexec_file_loaders[] = {
...@@ -17,6 +21,76 @@ const struct kexec_file_ops * const kexec_file_loaders[] = { ...@@ -17,6 +21,76 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
NULL, NULL,
}; };
#ifdef CONFIG_KEXEC_VERIFY_SIG
/*
* Module signature information block.
*
* The constituents of the signature section are, in order:
*
* - Signer's name
* - Key identifier
* - Signature data
* - Information block
*/
struct module_signature {
u8 algo; /* Public-key crypto algorithm [0] */
u8 hash; /* Digest algorithm [0] */
u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
u8 signer_len; /* Length of signer's name [0] */
u8 key_id_len; /* Length of key identifier [0] */
u8 __pad[3];
__be32 sig_len; /* Length of signature data */
};
#define PKEY_ID_PKCS7 2
int s390_verify_sig(const char *kernel, unsigned long kernel_len)
{
const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;
struct module_signature *ms;
unsigned long sig_len;
/* Skip signature verification when not secure IPLed. */
if (!ipl_secure_flag)
return 0;
if (marker_len > kernel_len)
return -EKEYREJECTED;
if (memcmp(kernel + kernel_len - marker_len, MODULE_SIG_STRING,
marker_len))
return -EKEYREJECTED;
kernel_len -= marker_len;
ms = (void *)kernel + kernel_len - sizeof(*ms);
kernel_len -= sizeof(*ms);
sig_len = be32_to_cpu(ms->sig_len);
if (sig_len >= kernel_len)
return -EKEYREJECTED;
kernel_len -= sig_len;
if (ms->id_type != PKEY_ID_PKCS7)
return -EKEYREJECTED;
if (ms->algo != 0 ||
ms->hash != 0 ||
ms->signer_len != 0 ||
ms->key_id_len != 0 ||
ms->__pad[0] != 0 ||
ms->__pad[1] != 0 ||
ms->__pad[2] != 0) {
return -EBADMSG;
}
return verify_pkcs7_signature(kernel, kernel_len,
kernel + kernel_len, sig_len,
VERIFY_USE_PLATFORM_KEYRING,
VERIFYING_MODULE_SIGNATURE,
NULL, NULL);
}
#endif /* CONFIG_KEXEC_VERIFY_SIG */
static int kexec_file_update_purgatory(struct kimage *image, static int kexec_file_update_purgatory(struct kimage *image,
struct s390_load_data *data) struct s390_load_data *data)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment