[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 3/4] livepatch: Embed public key in Xen
From: Kevin Lampis <klampis@xxxxxxxxx> Make it possible to embed a public key in Xen to be used when verifying live patch payloads. Inclusion of the public key is optional. To avoid needing to include a DER / X.509 parser in the hypervisor, the public key is unpacked at build time and included in a form that is convenient for the hypervisor to consume. This is different approach from that used by Linux which embeds the entire X.509 certificate and builds in a parser for it. A suitable key can be created using openssl: openssl req -x509 -newkey rsa:2048 -keyout priv.pem -out pub.pem \ -sha256 -days 3650 -nodes \ -subj "/C=XX/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=CommonNameOrHostname" openssl x509 -inform PEM -in pub.pem -outform PEM -pubkey -nocert -out crypto/signing_key.pem Signed-off-by: Kevin Lampis <klampis@xxxxxxxxx> Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx> --- xen/common/Kconfig | 18 ++++++++++++++++++ xen/common/Makefile | 2 +- xen/common/livepatch.c | 41 ++++++++++++++++++++++++++++++++++++++++ xen/crypto/Makefile | 14 +++++++++++++- xen/tools/extract-key.py | 37 ++++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 2 deletions(-) create mode 100755 xen/tools/extract-key.py diff --git a/xen/common/Kconfig b/xen/common/Kconfig index 4bec78c6f267..e3e4fe2f3477 100644 --- a/xen/common/Kconfig +++ b/xen/common/Kconfig @@ -481,6 +481,24 @@ config LIVEPATCH If unsure, say Y. +config PAYLOAD_SIGNING + bool "Verify signed LivePatch payloads" + depends on LIVEPATCH + select CRYPTO + help + Verify signed LivePatch payloads using an RSA public key built + into the Xen hypervisor. Selecting this option requires a + public key in PEM format to be available for embedding during + the build. + +config PAYLOAD_SIG_KEY + string "File name of payload signing public key" + default "signing_key.pem" + depends on PAYLOAD_SIGNING + help + The file name of an RSA public key in PEM format to be used for + verifying signed LivePatch payloads. + config FAST_SYMBOL_LOOKUP bool "Fast symbol lookup (bigger binary)" default y diff --git a/xen/common/Makefile b/xen/common/Makefile index ece6548bb072..c75cbfa868a0 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -28,7 +28,7 @@ obj-$(CONFIG_LIVEPATCH) += livepatch.o livepatch_elf.o obj-$(CONFIG_LLC_COLORING) += llc-coloring.o obj-$(CONFIG_VM_EVENT) += mem_access.o obj-y += memory.o -obj-y += mpi.o +obj-$(CONFIG_PAYLOAD_SIGNING) += mpi.o obj-y += multicall.o obj-y += notifier.o obj-$(CONFIG_NUMA) += numa.o diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c index be9b7e367553..947d05671b4f 100644 --- a/xen/common/livepatch.c +++ b/xen/common/livepatch.c @@ -11,6 +11,8 @@ #include <xen/lib.h> #include <xen/list.h> #include <xen/mm.h> +#include <xen/mpi.h> +#include <xen/rsa.h> #include <xen/sched.h> #include <xen/smp.h> #include <xen/softirq.h> @@ -73,6 +75,12 @@ static struct livepatch_work livepatch_work; static DEFINE_PER_CPU(bool, work_to_do); static DEFINE_PER_CPU(struct tasklet, livepatch_tasklet); +#ifdef CONFIG_PAYLOAD_SIGNING +/* The public key contained with Xen used to verify payload signatures. */ +extern const uint8_t xen_livepatch_key_data[]; +static struct rsa_public_key builtin_payload_key; +#endif + static int get_name(const struct xen_livepatch_name *name, char *n) { if ( !name->size || name->size > XEN_LIVEPATCH_NAME_SIZE ) @@ -2287,6 +2295,34 @@ static void cf_check livepatch_printall(unsigned char key) spin_unlock(&payload_lock); } +#ifdef CONFIG_PAYLOAD_SIGNING +static int __init load_builtin_payload_key(void) +{ + const uint8_t *ptr; + uint32_t len; + + rsa_public_key_init(&builtin_payload_key); + + ptr = xen_livepatch_key_data; + + memcpy(&len, ptr, sizeof(len)); + ptr += sizeof(len); + builtin_payload_key.n = mpi_read_raw_data(ptr, len); + ptr += len; + + memcpy(&len, ptr, sizeof(len)); + ptr += sizeof(len); + builtin_payload_key.e = mpi_read_raw_data(ptr, len); + + return rsa_public_key_prepare(&builtin_payload_key); +} +#else +static int __init load_builtin_payload_key(void) +{ + return 0; +} +#endif + static int cf_check cpu_callback( struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -2305,6 +2341,11 @@ static struct notifier_block cpu_nfb = { static int __init cf_check livepatch_init(void) { unsigned int cpu; + int err; + + err = load_builtin_payload_key(); + if (err) + return err; for_each_online_cpu ( cpu ) { diff --git a/xen/crypto/Makefile b/xen/crypto/Makefile index d88374ddf221..e81302d7cd54 100644 --- a/xen/crypto/Makefile +++ b/xen/crypto/Makefile @@ -1,3 +1,15 @@ obj-y += rijndael.o -obj-y += rsa.o +obj-$(CONFIG_PAYLOAD_SIGNING) += rsa.o obj-y += vmac.o + +obj-$(CONFIG_PAYLOAD_SIGNING) += builtin_payload_key.o + +ifeq ($(CONFIG_PAYLOAD_SIGNING),y) +key_path := $(srctree)/crypto/$(patsubst "%",%,$(CONFIG_PAYLOAD_SIG_KEY)) +$(obj)/builtin_payload_key.bin: $(key_path) $(srctree)/tools/extract-key.py + $(srctree)/tools/extract-key.py < $< > $@.new + $(call move-if-changed,$@.new,$@) + +$(obj)/builtin_payload_key.S: $(srctree)/tools/binfile $(obj)/builtin_payload_key.bin FORCE + $(call if_changed,binfile,$(obj)/builtin_payload_key.bin xen_livepatch_key_data) +endif diff --git a/xen/tools/extract-key.py b/xen/tools/extract-key.py new file mode 100755 index 000000000000..2980264b757d --- /dev/null +++ b/xen/tools/extract-key.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +# SPDX-License-Identifier: GPL-2.0 + +import binascii +import struct +import sys +import subprocess +import re + +# Decode a certificate into a format suitable for embedding in Xen. + +out = subprocess.check_output(['openssl', 'rsa', '-pubin', '-inform', 'PEM', + '-noout', '-text'], stdin=sys.stdin, + universal_newlines=True) +combined = '' +for line in out.split('\n'): + line = line.rstrip() + if line.startswith(' '): + combined += line.strip().replace(':', '') + match = re.match(r'Exponent: .* \(0x(.*)\)', line) + if match: + e = match.group(1) + +n = combined.lstrip('0') +if len(n) % 2 == 1: + n = '0' + n +n = binascii.unhexlify(n) +e = e.lstrip('0') +if len(e) % 2 == 1: + e = '0' + e +e = binascii.unhexlify(e) + +sys.stdout.buffer.write(struct.pack('I', len(n))) +sys.stdout.buffer.write(n) +sys.stdout.buffer.write(struct.pack('I', len(e))) +sys.stdout.buffer.write(e) -- 2.49.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |