Re: [PATCH v1 0/8] Measured SEV boot with kernel/initrd/cmdline


Dov Murik
 

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.

-Dov

Join devel@edk2.groups.io to automatically receive all group messages.