From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by mx.groups.io with SMTP id smtpd.web09.3022.1606768140728025397 for ; Mon, 30 Nov 2020 12:29:00 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@ibm.com header.s=pp1 header.b=tl+F5uXU; spf=pass (domain: linux.ibm.com, ip: 148.163.156.1, mailfrom: jejb@linux.ibm.com) Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 0AUKPsPV161539; Mon, 30 Nov 2020 15:28:55 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : mime-version : content-transfer-encoding; s=pp1; bh=E4lmCzrE/G2Z6OyGujuMsz/3RpP6atdFu06HxlOZ4CM=; b=tl+F5uXUbExUsfngzyBxjeZDVFjQAGiLGEqfz/mlISCYaBDWjjb6Mv2Dme9OF9SFMo1F YxIBdwC+feaWoHkMwEO9pUELg20M4phCqJSMCQdwcuuZ7gvBjYXKCOH11h3AI470MEcb SPWQV+mp5S3abI4g8TWByLdqlxEMFlKG1eRRERuXUm4HAMEXyvLu3dpMslyIGlxfhZTn l5175la5OVn2IZCP8fwibGI5LSdtGi4DWce+kwXxS8OF7BsF3PYzMiRCSP51/ZX1sYNx 2FdXEo+0ONFPWeFdGcm69y+R3U95VZ69s4yP5YPnu57Re6dWDcKjvgZXe/pl2wZ4zgTq Aw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3557s3r1bu-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 30 Nov 2020 15:28:55 -0500 Received: from m0098399.ppops.net (m0098399.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.36/8.16.0.36) with SMTP id 0AUKQcK7166487; Mon, 30 Nov 2020 15:28:55 -0500 Received: from ppma03dal.us.ibm.com (b.bd.3ea9.ip4.static.sl-reverse.com [169.62.189.11]) by mx0a-001b2d01.pphosted.com with ESMTP id 3557s3r1bp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 30 Nov 2020 15:28:54 -0500 Received: from pps.filterd (ppma03dal.us.ibm.com [127.0.0.1]) by ppma03dal.us.ibm.com (8.16.0.42/8.16.0.42) with SMTP id 0AUKMNK7013958; Mon, 30 Nov 2020 20:28:54 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma03dal.us.ibm.com with ESMTP id 353e68y1cq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 30 Nov 2020 20:28:54 +0000 Received: from b01ledav002.gho.pok.ibm.com (b01ledav002.gho.pok.ibm.com [9.57.199.107]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 0AUKSqAQ5309000 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 30 Nov 2020 20:28:52 GMT Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E6E77124054; Mon, 30 Nov 2020 20:28:51 +0000 (GMT) Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 06696124052; Mon, 30 Nov 2020 20:28:49 +0000 (GMT) Received: from jarvis.int.hansenpartnership.com (unknown [9.80.201.242]) by b01ledav002.gho.pok.ibm.com (Postfix) with ESMTP; Mon, 30 Nov 2020 20:28:49 +0000 (GMT) From: "James Bottomley" To: devel@edk2.groups.io Cc: dovmurik@linux.vnet.ibm.com, Dov.Murik1@il.ibm.com, ashish.kalra@amd.com, brijesh.singh@amd.com, tobin@ibm.com, david.kaplan@amd.com, jon.grimm@amd.com, thomas.lendacky@amd.com, jejb@linux.ibm.com, frankeh@us.ibm.com, "Dr . David Alan Gilbert" , Laszlo Ersek , Jordan Justen , Ard Biesheuvel Subject: [PATCH v3 0/6] SEV Encrypted Boot for Ovmf Date: Mon, 30 Nov 2020 12:28:13 -0800 Message-Id: <20201130202819.3910-1-jejb@linux.ibm.com> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.312,18.0.737 definitions=2020-11-30_08:2020-11-30,2020-11-30 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 malwarescore=0 mlxscore=0 phishscore=0 priorityscore=1501 spamscore=0 adultscore=0 bulkscore=0 suspectscore=0 clxscore=1011 mlxlogscore=999 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2011300126 Content-Transfer-Encoding: 8bit v3: - More grub and boot stripping (I think I got everything out, but there may be something that strayed in the boot panic resolution). - grub.sh tidy up with tabs->spaces. - Move the reset vector GUIDisation patch to the front so it can be applied independently - Update the .dsc and .fdf files for variable policy v2: - Strip more out of AmdSev image (networking, secure boot, smm) - give sev reset block a generic table guid and use it for boot secret area - separate secret patches and make grub script more robust - Add copyrights and fix formatting issues v1: Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3077 This patch series is modelled on the structure of the Bhyve patches for Ovmf, since it does somewhat similar things. This patch series creates a separate build for an AmdSev OVMF.fd that does nothing except combine with grub and boot straight through the internal grub to try to mount an encrypted volume. Concept: SEV Secure Encrypted Images ==================================== The SEV patches in Linux and OVMF allow for the booting of SEV VMs in an encrypted state, but don't really show how this could be done with an encrypted image. Since the key used to decrypt the image must be maintained within the SEV encryption envelope, encrypted QCOW is not an option because the key would then have to be known to QEMU which is outside the encryption envelope. The proposal here is that an encrypted image should be a QCOW image consisting of two partitions, the normal unencrypted EFI partition (Identifying it as an OVMF bootable image) and a luks encrypted root partition. The kernel would be inside the encrypted root in the /boot directory. The secret injected securely through QEMU is extracted by OVMF and passed to grub which uses it to mount the encrypted root and boot the kernel normally. The creator of the secret bundle must be satisfied with the SEV attestation before the secret is constructed. Unfortunately, the SEV attestation can only be on the first QEMU firmware volume and nothing else, so this patch series builds grub itself into a firmware volume and places it inside OVMF so that the entire boot system can be attested. In a normal OVMF KVM system, the variable store is on the second flash volume (which is read/write). Unfortunately, this mutable configuration provided by the variables is outside the attestation envelope and can significantly alter the boot path, possibly leading to secret leak, so encrypted image boot should only be done with the OVMF.fd that combines both the code and variables. the OVMF.fd is constructed so that it becomes impossible to interrupt the boot sequence after attestation and the system will either boot the image or fail. The boot sequence runs the grub.efi embedded in the OVMF firmware volume so the encrypted image owner knows their own version of grub is the only one that will boot before injecting the secret. Note this boot path actually ignores the unencrypted EFI partition. However, as part of this design, the encrypted image may be booted by a standard OVMF KVM boot and in that case, the user will have to type the encryption password. This standard boot will be insecure but it might be used by the constructor of the encrypted images on their own private laptop, for instance. The standard boot path will use the unencrypted EFI partition. Patches Required Outside of OVMF ================================ There is a patch set to grub which allows it to extract the SEV secret area from the configuration table and use the secret as a password to do a luks crypto mount of root (this is the sevsecret grub module): https://lists.gnu.org/archive/html/grub-devel/2020-11/msg00078.html There is also a patch to qemu which allows it to search through the OVMF.fd and find the SEV secret area which is now described inside the Reset Vector using the existing SEV_ES reset block. This area is the place QEMU will inject the encrypted SEV secret bundle. Security of the System ====================== Since Grub is now part of the attested OVMF.fd bundle, the VM owner knows absolutely that it will proceed straight to partition decryption inside the attested code and boot the kernel off the encrypted partition. Even if a different QCOW image is substituted, the boot will fail without revealing the secret because the system is designed to fail hard in that case and because the secret is always contained within the encrypted envelope it should be impossible for the cloud operator to obtain it even if they can pause the boot and examine the machine memory. Putting it All Together ======================= This is somewhat hard. You must first understand how to boot a QEMU system so as to have the VM pause after firmware loading (-S option) and use the qmp port to request an attestation. Only if the attestation corresponds to the expected sha256sum of OVMF.fd should the secret bundle be constructed and injected using qmp. The tools for constructing the secret bundle are in https://github.com/AMDESE/sev-tool/ James --- James Bottomley (6): OvmfPkg/ResetVector: convert SEV-ES Reset Block structure to be GUIDed OvmfPkg/Amdsev: Base commit to build encrypted boot specific OVMF OvmfPkg/AmdSev: add Grub Firmware Volume Package OvmfPkg: create a SEV secret area in the AmdSev memfd OvmfPkg/AmdSev: assign and protect the Sev Secret area OvmfPkg/AmdSev: Expose the Sev Secret area using a configuration table OvmfPkg/OvmfPkg.dec | 8 + OvmfPkg/AmdSev/AmdSevX64.dsc | 844 ++++++++++ OvmfPkg/AmdSev/AmdSevX64.fdf | 456 +++++ OvmfPkg/AmdSev/Grub/Grub.inf | 39 + OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf | 37 + OvmfPkg/AmdSev/SecretPei/SecretPei.inf | 35 + .../PlatformBootManagerLibGrub.inf | 71 + OvmfPkg/ResetVector/ResetVector.inf | 4 + OvmfPkg/Include/Guid/SevLaunchSecret.h | 28 + .../PlatformBootManagerLibGrub/BdsPlatform.h | 175 ++ OvmfPkg/AmdSev/SecretDxe/SecretDxe.c | 26 + OvmfPkg/AmdSev/SecretPei/SecretPei.c | 25 + .../PlatformBootManagerLibGrub/BdsPlatform.c | 1482 +++++++++++++++++ .../PlatformBootManagerLibGrub/PlatformData.c | 214 +++ OvmfPkg/AmdSev/Grub/.gitignore | 1 + OvmfPkg/AmdSev/Grub/grub.cfg | 46 + OvmfPkg/AmdSev/Grub/grub.sh | 93 ++ OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 70 +- OvmfPkg/ResetVector/ResetVector.nasmb | 2 + 19 files changed, 3645 insertions(+), 11 deletions(-) create mode 100644 OvmfPkg/AmdSev/AmdSevX64.dsc create mode 100644 OvmfPkg/AmdSev/AmdSevX64.fdf create mode 100644 OvmfPkg/AmdSev/Grub/Grub.inf create mode 100644 OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf create mode 100644 OvmfPkg/AmdSev/SecretPei/SecretPei.inf create mode 100644 OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformBootManagerLibGrub.inf create mode 100644 OvmfPkg/Include/Guid/SevLaunchSecret.h create mode 100644 OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.h create mode 100644 OvmfPkg/AmdSev/SecretDxe/SecretDxe.c create mode 100644 OvmfPkg/AmdSev/SecretPei/SecretPei.c create mode 100644 OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.c create mode 100644 OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformData.c create mode 100644 OvmfPkg/AmdSev/Grub/.gitignore create mode 100644 OvmfPkg/AmdSev/Grub/grub.cfg create mode 100644 OvmfPkg/AmdSev/Grub/grub.sh -- 2.26.2