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.web11.3776.1622010087028030444 for ; Tue, 25 May 2021 23:21:27 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@ibm.com header.s=pp1 header.b=hM1K+jJX; spf=pass (domain: linux.ibm.com, ip: 148.163.156.1, mailfrom: dovmurik@linux.ibm.com) Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 14Q63vGG120343; Wed, 26 May 2021 02:21:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=subject : to : cc : references : from : message-id : date : mime-version : in-reply-to : content-type : content-transfer-encoding; s=pp1; bh=6RfDLYSuGB72qb1WfWX7OQYbENx8AbThXmjeIfa6qeM=; b=hM1K+jJX1wPuPDuHWrYciKu1MDdfFSNKrw8Fc5ftakEhTkdemTdHNtMnXq5JjjLLZzoO Gwt5Dtyn0V5B67JW4WppWFgWVpSo/9zRIHOR90tGH2WAGkZvMGPB3aqPn+j6HHGqnAg0 kSLsemccWGefhlSymzjdHhBNeglYsvKG25+FNVJPteFiifyglvl/U/v3XBXHPMpiIfUm AyYWIAt2t8N+9ASsS/Xx9shJa0GZNz1dd8pIKKyOfEC05BW3Xvp6fB130TVF+BxE9BH+ QlhB9BBJEwWCxNvZLbUbZpnZKAXn0OwvJYsVH6P4u2Ffm+o2oXjF0dFv7Hhcz9rOPzdF iw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 38sgr2gcm0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 26 May 2021 02:21:24 -0400 Received: from m0098393.ppops.net (m0098393.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 14Q65sLv132605; Wed, 26 May 2021 02:21:23 -0400 Received: from ppma03ams.nl.ibm.com (62.31.33a9.ip4.static.sl-reverse.com [169.51.49.98]) by mx0a-001b2d01.pphosted.com with ESMTP id 38sgr2gcke-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 26 May 2021 02:21:23 -0400 Received: from pps.filterd (ppma03ams.nl.ibm.com [127.0.0.1]) by ppma03ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 14Q6Crqn017845; Wed, 26 May 2021 06:21:21 GMT Received: from b06avi18878370.portsmouth.uk.ibm.com (b06avi18878370.portsmouth.uk.ibm.com [9.149.26.194]) by ppma03ams.nl.ibm.com with ESMTP id 38sba2r3h4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 26 May 2021 06:21:21 +0000 Received: from d06av24.portsmouth.uk.ibm.com (d06av24.portsmouth.uk.ibm.com [9.149.105.60]) by b06avi18878370.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 14Q6KmRt31916314 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 26 May 2021 06:20:48 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CB3C642042; Wed, 26 May 2021 06:21:17 +0000 (GMT) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 99DE14204F; Wed, 26 May 2021 06:21:13 +0000 (GMT) Received: from [9.65.213.35] (unknown [9.65.213.35]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTP; Wed, 26 May 2021 06:21:13 +0000 (GMT) Subject: Re: [edk2-devel] [PATCH v1 0/8] Measured SEV boot with kernel/initrd/cmdline To: Brijesh Singh , jejb@linux.ibm.com, Tom Lendacky , devel@edk2.groups.io Cc: Tobin Feldman-Fitzthum , Tobin Feldman-Fitzthum , Jim Cadden , Hubertus Franke , Laszlo Ersek , Ard Biesheuvel , Jordan Justen , Ashish Kalra , Erdem Aktas , Jiewen Yao , Min Xu References: <20210525053116.1533673-1-dovmurik@linux.ibm.com> <8b966d52-f207-b747-96a7-2ed6f29aa432@amd.com> <21593112-ea9c-8cd1-7cad-6fc6d9645242@linux.ibm.com> From: "Dov Murik" Message-ID: Date: Wed, 26 May 2021 09:21:11 +0300 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.10.2 MIME-Version: 1.0 In-Reply-To: X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: rD2BOc0tpEfgIbwZBJJBnhnN_nyq9G8T X-Proofpoint-GUID: 3X-UZHtdzRiWQDnTHKKZqZpNZEKn5o4Z X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391,18.0.761 definitions=2021-05-26_02:2021-05-25,2021-05-26 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 phishscore=0 mlxlogscore=999 lowpriorityscore=0 impostorscore=0 bulkscore=0 spamscore=0 clxscore=1015 priorityscore=1501 adultscore=0 malwarescore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2105260035 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit On 26/05/2021 2:37, Brijesh Singh wrote: > > On 5/25/21 6:15 PM, James Bottomley wrote: >> On Tue, 2021-05-25 at 15:33 -0500, Tom Lendacky wrote: >>> On 5/25/21 3:08 PM, Dov Murik wrote: >>>> Hi Brijesh, >>>> >>>> On 25/05/2021 18:48, Brijesh Singh wrote: >>>>> On 5/25/21 12:31 AM, Dov Murik wrote: >>>>>> Booting with SEV prevented the loading of kernel, initrd, and >>>>>> kernel command-line via QEMU fw_cfg interface because they >>>>>> arrive from the VMM which is untrusted in SEV. >>>>>> >>>>>> However, in some cases the kernel, initrd, and cmdline are not >>>>>> secret but should not be modified by the host. In such a case, >>>>>> we want to verify inside the trusted VM that the kernel, >>>>>> initrd, and cmdline are indeed the ones expected by the Guest >>>>>> Owner, and only if that is the case go on and boot them up >>>>>> (removing the need for grub inside OVMF in that mode). >>>>>> >>>>>> This patch series declares a new page in MEMFD which will >>>>>> contain the hashes of these three blobs (kernel, initrd, >>>>>> cmdline), each under its own GUID entry. This tables of hashes >>>>>> is populated by QEMU before launch, and encrypted as part of >>>>>> the initial VM memory; this makes sure theses hashes are part >>>>>> of the SEV measurement (which has to be approved by the Guest >>>>>> Owner for secret injection, for example). Note that this >>>>>> requires a new QEMU patch which will be submitted soon. >>>>> I have not looked at the patches, but trying to brainstorm if we >>>>> can avoid reserving a new page in the MEMFD and use the existing >>>>> EDK2 infrastructure to verify the blobs (kernel, initrd) loaded >>>>> through the FW_CFG interface in the guest memory. >>>>> >>>>> If I understand correctly, then in your proposed approach, guest >>>>> owner wants to ensure that the hypevisor passing its preferred >>>>> kernel, initrd and cmdline. The guest owner basically knows the >>>>> hashes of these components in advance. >>>> Yes, that's correct. >>>> >>>>> So, can we do something like this: >>>>> >>>>> - The secret blob provided by the guest owner should contains the >>>>> hashes (sha384) of these components. >>>>> >>>>> - Use openssl API available in the edk2 to calculate the hash >>>>> while loading the kernel, initrd and cmdline. >>>> Indeed we do something similar already - we use Sha256HashAll (see >>>> patch 5 in this series). >>>> >>>> >>>>> - Before booting the kernel, compare the calculated hash with the >>>>> one listed in the secret page. If they don't match then fail >>>>> otherwise continue. >>>> That is indeed what we do in patch 6 (the calls to our >>>> ValidateHashEntry). >>>> >>>> >>>>> Did I miss something ? >>>> Thanks for proposing this. >>>> >>>> Your approach has the advantage that there's no need for extra >>>> pre-allocated MEMFD page for the hashes, and also it makes the QEMU >>>> flow simpler (QEMU doesn't need to compute the hashes and put them >>>> in that special MEMFD page). I think that the only change we'll >>>> need from QEMU in the x86_load_linux flow (which is when the user >>>> supplies -kernel/-initrd) is that it won't modify any memory in a >>>> way that the modifies the hashes that Guest Owner expects (for >>>> example, avoid writing over the kernel's setup area). >>>> >>>> However, the disadvantage is that it unifies boot measurement with >>>> the secret injection. The Guest Owner _must_ inject the hashes, >>>> otherwise the system doesn't boot; whereas in our current >>>> suggestion the Guest Owner can check the measurement, verify that >>>> everything is OK, and just let the guest continue. >>>> >>>> But as I write this, I think that maybe without secret injection >>>> the guest is not really secure? Because the host could just >>>> continue execution of the guest without waiting for measurement >>>> check... If the Guest Owner _must_ inject a secret for SEV to be >>>> secure in any case, we might as well choose your path and let the >>>> Guest Owner inject the table of hashes themselves. >>>> >>>> I'd like to hear your (and others') thoughts. >>> Brijesh and I had a long discussion over this. I think that if you're >>> dealing with a malicious hypervisor, then it could, in fact, measure >>> all the components that it wants to be used and, using >>> LAUNCH_UPDATE_DATA, add a page, that matches the format of the guest >>> secret page, to the guest and indicate that page as the guest secret. >>> Even though the measurement would fail validation by the guest owner, >>> the hypervisor could ignore it and continue to run the guest. >>> >>> So you need something that proves ownership of the guest secret - >>> like a disk key that would fail to unlock the disk if the hypervisor >>> is faking the guest secret. >>> >>> Does all that make sense? >> I think it does for the unencrypted boot case. For the encrypted boot >> case, the HV can't inject the decryption key, because it doesn't know >> it, so the interior guest will know there's a problem as soon as it >> can't decrypt the image. I think we all agree that encrypted disk is one good solution to prove that the guest owner actually provided the secret. >> >> But I get the point that we can't rely on the secrets page for hashes >> if we have nothing cryptographic in it. However, the actual threat >> from this is somewhat unclear. As you note: the guest owner knows >> there's a problem, but the actual guest is still executing because of >> intervention by a malicious hypervisor owner. In the cloud that's more >> or less equivalent to me taking over the guest IP and trying to man in >> the middle the services ... once the guest owner knows this happened, >> they're going to be looking for a new CSP. So I think the threat would >> be potent if you could convince the guest owner that nothing were >> amiss, so they think the modified guest is legitimate, but less so >> otherwise. > > I guess if we can have the guest BIOS communicate with the guest owner > using a secure channel to obtain the hash'es or key to decrypt the > hashes then all of it be okay. To establish the secret channel the guest > BIOS will use the secret injected through the LAUNCH_SECRET. If OVMF > fails to establish the secret channel with the guest owner, then its an > indicate that malicious hypervisor booted the guest without injecting a > valid secret or skipped the attestation flow. > We can separate to two cases: (1-lax) Guest owner wants proof of integrity/trust for the VMs it asked to launch (checking the measurement). Cloud provider may be able to launch additional instances and nobody will know about it. (2-strict) Guest owner wants control of all VM launches; doesn't allow cloud provider to launch VMs without approval. For (1-lax) -- the current proposal works OK. When Guest Owner asks to launch a new VM, it'll receive the measurement and check it. If it is wrong, the guest owner will stop paying the cloud provider. In such a case nothing prevents the cloud provider to start the VM on its own terms -- with SEV disabled, with its own OVMF that performs no hash checks, etc. For (2-strict) -- Any check that relies on a simple 'if' statement (like 'if hash(kernel)==expected_hash' or 'if verify_sig(some_blob, guest_owner_pub_key)') can be circumvented by modifying the code of the if statement itself (or simply using an OVMF that doesn't perform these checks). This includes our original proposal in this patch series, and Brijesh's idea of communicating with guest owner to get the hashes and then check them. Like Tom said, measurement doesn't match, but malicious cloud provider doesn't care because it doesn't need the secret injection from the guest owner. It seems like the guest workload *must* heavily rely on an injected secret which can be one (or more) of: (a) a decryption key; it can be an encrypted root partition, or some other crucial (and unguessable[*]) part of the guest workload. (b) an API key/credentials that are checked *outside* the cloud provider's reach; the response from that API is a crucial part of the guest workload. (c) asymmetric key (like SSH private key) to access a crucial service which is part of the guest workload. The crux here is the "crucial part of the guest workload"; the cloud provider can start the VM without the secret, but such VM can't perform its actual (confidential) mission. [*] Initially I thought about adding encrypted-kernel (similar to encrypted boot partition; the kernel is decrypted in OVMF using the injected secret). But I think a malicious hypervisor can simply guess what kernel is needed, and provide its own cleartext kernel (with plain OVMF) and successfully boot the guest without the secret. -Dov