From nobody Fri Oct 31 16:38:18 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=citrix.com ARC-Seal: i=1; a=rsa-sha256; t=1748871437; cv=none; d=zohomail.com; s=zohoarc; b=ZL9BVYAaV2jl+AnGOaUe6jSt+imDE2Ump/f6/2CRX2kwAMfh9d7jV7fmyB+LLpTTeZ1aSNDb41Xqa75PTglxFOMMQXCLf1YTby4fNSmQA5Jty1cqAl5ygwAjzc6ZSGec8ock4hgZ9uE9XE5XG96/PGqmogF1j0UCYRlndCTHoko= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1748871437; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=eXyFKt8SkeFv2JRAXt3PYp9ZfiPqxDGxVcFws6/GjMQ=; b=CWymvbSA9nG9ylhe5qWMMte9wKEsTaEKyS91Oe5e1l8eY1IxFXKC6XWPzNRryiWJqBR6iFWtFw8IzuSqVOPbtlZN05yFv1zKuhMrLUGrCmvQLkTyRJF3NPQjYfruIbNgwpV9YmHsvh12XrpqvNgepXs4xkTZPf4fQJYwekwkwrQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 174887143738181.42809617020214; Mon, 2 Jun 2025 06:37:17 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1003321.1382854 (Exim 4.92) (envelope-from ) id 1uM5LR-0000O3-DF; Mon, 02 Jun 2025 13:36:53 +0000 Received: by outflank-mailman (output) from mailman id 1003321.1382854; Mon, 02 Jun 2025 13:36:53 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uM5LR-0000Nw-A3; Mon, 02 Jun 2025 13:36:53 +0000 Received: by outflank-mailman (input) for mailman id 1003321; Mon, 02 Jun 2025 13:36:52 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uM5LQ-0000AN-S9 for xen-devel@lists.xenproject.org; Mon, 02 Jun 2025 13:36:52 +0000 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [2a00:1450:4864:20::62b]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id a39e7a3b-3fb6-11f0-a300-13f23c93f187; Mon, 02 Jun 2025 15:36:51 +0200 (CEST) Received: by mail-ej1-x62b.google.com with SMTP id a640c23a62f3a-ad51ef2424bso850932766b.0 for ; Mon, 02 Jun 2025 06:36:51 -0700 (PDT) Received: from rossla-pc.eng.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ada5d82becbsm801962166b.39.2025.06.02.06.36.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Jun 2025 06:36:49 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: a39e7a3b-3fb6-11f0-a300-13f23c93f187 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1748871410; x=1749476210; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=eXyFKt8SkeFv2JRAXt3PYp9ZfiPqxDGxVcFws6/GjMQ=; b=C7S7NmLvXn4Aiavsyg3n9EpbG/w5QwFcli1QncfilI8mGHC49wLHJ/t93944dvjf6A kx6bHqBuOzNfPqMHlMcl5CFuB0k+Fuw4GXtDRnt3snAeXmfY8woiswB8vY+Suyejw5at DLIfOmZEeediUplTaR4aiLj5oqOspaj62hF8U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1748871410; x=1749476210; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eXyFKt8SkeFv2JRAXt3PYp9ZfiPqxDGxVcFws6/GjMQ=; b=GgnKT5rEbA1QCulOqrVkOEshQMr43bFH1royt6Ov66frSPYsQ1MrwYbeks1FeFusug Q8kVXeG7FF85c4OQrZhixbx6MHpM0LZvAxmMey31R5VTq7xdbG0AqecFMpXDJKZB5PYK UUbsyjSw7JQp+s8is/oI4xwXP0PI6g4KHgBazBQEkpvIJz44bIhU+bxLFbM60z/M/F3N pr5i8+Edqe81u7CrChXnJKtf6q8DPCAcWpzymtakeJ9SSJsEB3OZRKqfOuAPKE3D4ZDU QlWTPd6iG7f4mfsj/DUJNTGWE7ALKND1pgNqB8aY0LPMhxloFyuz2AFSfC9hZaYsfj3V pV9w== X-Gm-Message-State: AOJu0YwY+zYtZm1GgdVYn/CGvFr2/kruQINrMI9kOzPBStf6d3yYb/O7 CYk4VOX59kqA7B7L7aWL0TjVyry0NTG5tJDjQgDqQHTM5SISYWnFz0zZkFqPksmGuruLAAard4Y bR7Q= X-Gm-Gg: ASbGncuyyOXAIzHW53MB+r1Tsa5WJckwCNv77Q3uON1nKKT7dRteN/eoV6r1dCbi9Z3 1Fo4he6oy4ywIORY3/AzoPrJLRt7mNNzB5kgBcE1PXjiPJSsCceYEGdfzWOEN8GESBMJVqHlB85 rCGTqgUP3Kn6U8uZrEQWuz74/rQjKv2pv8M//Gr+iJTr0xU3PC0GOOhf/CCTI64cvCBxA2mqjYr MWV31a7NvpfsqEy5tLjXzTL1C7n1u9NqCXWbDIXzG1+dsyWCZtz7sgMlCSKSsFH7N5tIW4S4U2D N3lQfT7zp72lwnSu6hjN5gOjQty5d2i9Cvc6UdIih90OLiiuu8GJDmltVY8UvcvyHm/RUV7xyEo = X-Google-Smtp-Source: AGHT+IFDR2jTnNkplK5MDSg0EiFkL63MSZQoNcI1lDzXXdOHZRHY4hs4m38UOsREknK3kO+gkCgGBA== X-Received: by 2002:a17:907:9488:b0:ad8:99e7:171 with SMTP id a640c23a62f3a-adb493e28f3mr800031766b.21.1748871410169; Mon, 02 Jun 2025 06:36:50 -0700 (PDT) From: Ross Lagerwall To: xen-devel@lists.xenproject.org Cc: Kevin Lampis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini , Ross Lagerwall Subject: [PATCH v3 2/5] livepatch: Embed public key in Xen Date: Mon, 2 Jun 2025 14:36:34 +0100 Message-ID: <20250602133639.2871212-3-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250602133639.2871212-1-ross.lagerwall@citrix.com> References: <20250602133639.2871212-1-ross.lagerwall@citrix.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @citrix.com) X-ZM-MESSAGEID: 1748871439598116600 Content-Type: text/plain; charset="utf-8" From: Kevin Lampis 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=3DXX/ST=3DStateName/L=3DCityName/O=3DCompanyName/OU=3DCompany= SectionName/CN=3DCommonNameOrHostname" openssl x509 -inform PEM -in pub.pem -outform PEM -pubkey -nocert -out veri= fy_key.pem Signed-off-by: Kevin Lampis Signed-off-by: Ross Lagerwall --- In v3: * Drop unnecessary condition in Makefile * Use dashes instead of underscores * Drop section placement annotation on declaration * Clarify endianness of embedded key xen/common/Kconfig | 18 +++++++++++++++++ xen/crypto/Makefile | 11 ++++++++++ xen/include/xen/livepatch.h | 5 +++++ xen/tools/extract-key.py | 40 +++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100755 xen/tools/extract-key.py diff --git a/xen/common/Kconfig b/xen/common/Kconfig index 0951d4c2f286..74673078202a 100644 --- a/xen/common/Kconfig +++ b/xen/common/Kconfig @@ -472,6 +472,24 @@ config LIVEPATCH =20 If unsure, say Y. =20 +config PAYLOAD_VERIFY + 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_VERIFY_KEY + string "File name of public key used to verify payloads" + default "verify_key.pem" + depends on PAYLOAD_VERIFY + 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/crypto/Makefile b/xen/crypto/Makefile index db29655333a3..3d17232b78bc 100644 --- a/xen/crypto/Makefile +++ b/xen/crypto/Makefile @@ -1,2 +1,13 @@ obj-y +=3D rijndael.o obj-y +=3D vmac.o + +obj-$(CONFIG_PAYLOAD_VERIFY) +=3D builtin-payload-key.o + +key-path :=3D $(objtree)/$(patsubst "%",%,$(CONFIG_PAYLOAD_VERIFY_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: BINFILE_FLAGS :=3D -i +$(obj)/builtin-payload-key.S: $(srctree)/tools/binfile $(obj)/builtin-payl= oad-key.bin FORCE + $(call if_changed,binfile,$(obj)/builtin-payload-key.bin xen_livepatch_ke= y_data) diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h index d074a5bebecc..52f90cbed45b 100644 --- a/xen/include/xen/livepatch.h +++ b/xen/include/xen/livepatch.h @@ -143,6 +143,11 @@ struct payload; int revert_payload(struct payload *data); void revert_payload_tail(struct payload *data); =20 +#ifdef CONFIG_PAYLOAD_VERIFY +/* The public key data contained with Xen used to verify payload signature= s. */ +extern const uint8_t xen_livepatch_key_data[]; +#endif + #else =20 /* diff --git a/xen/tools/extract-key.py b/xen/tools/extract-key.py new file mode 100755 index 000000000000..05c6bc261b3f --- /dev/null +++ b/xen/tools/extract-key.py @@ -0,0 +1,40 @@ +#!/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 =3D subprocess.check_output(['openssl', 'rsa', '-pubin', '-inform', 'P= EM', + '-noout', '-text'], stdin=3Dsys.stdin, + universal_newlines=3DTrue) +combined =3D '' +for line in out.split('\n'): + line =3D line.rstrip() + if line.startswith(' '): + combined +=3D line.strip().replace(':', '') + match =3D re.match(r'Exponent: .* \(0x(.*)\)', line) + if match: + e =3D match.group(1) + +n =3D combined.lstrip('0') +if len(n) % 2 =3D=3D 1: + n =3D '0' + n +n =3D binascii.unhexlify(n) +e =3D e.lstrip('0') +if len(e) % 2 =3D=3D 1: + e =3D '0' + e +e =3D binascii.unhexlify(e) + +# Use little-endian for lengths. +# Use big-endian for byte sequences (as openssl does). + +sys.stdout.buffer.write(struct.pack('