public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* OVMF Secure Boot variable storage issue
@ 2017-07-06 17:31 Jason Dickens
  2017-07-06 18:30 ` Bill Paul
  2017-07-06 18:49 ` Laszlo Ersek
  0 siblings, 2 replies; 6+ messages in thread
From: Jason Dickens @ 2017-07-06 17:31 UTC (permalink / raw)
  To: edk2-devel

All,

I'm trying to understand why the secure boot variables (PK, KEK, db, 
etc) when using the OVMF build are not retained across reboot? It seems 
that this code uses roughly the same SetVariable, GetVariable2 approach 
as say the PlatformConfig uses to store screen resolution (which is 
retained). Additionally, the NvVars file is being at least touched by 
the secure boot configuration. So why are none of the keys retained on 
the next reboot?

I know this was an issue in the past, but I haven't found the resolution?

Jason




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: OVMF Secure Boot variable storage issue
  2017-07-06 17:31 OVMF Secure Boot variable storage issue Jason Dickens
@ 2017-07-06 18:30 ` Bill Paul
  2017-07-06 18:55   ` Jason Dickens
  2017-07-06 19:08   ` Laszlo Ersek
  2017-07-06 18:49 ` Laszlo Ersek
  1 sibling, 2 replies; 6+ messages in thread
From: Bill Paul @ 2017-07-06 18:30 UTC (permalink / raw)
  To: edk2-devel; +Cc: Jason Dickens

Of all the gin joints in all the towns in all the world, Jason Dickens had to 
walk into mine at 10:31:18 on Thursday 06 July 2017 and say:

> All,
> 
> I'm trying to understand why the secure boot variables (PK, KEK, db,
> etc) when using the OVMF build are not retained across reboot? It seems
> that this code uses roughly the same SetVariable, GetVariable2 approach
> as say the PlatformConfig uses to store screen resolution (which is
> retained). Additionally, the NvVars file is being at least touched by
> the secure boot configuration. So why are none of the keys retained on
> the next reboot?

If you're running OVMF in the QEMU simulator, and you're using the -bios 
option, try using the -pflash option instead.

I know that when using -bios, QEMU only pretends to allow writes to the 
firmware region, and if you stop QEMU all changes are discarded. The same 
might be true if you just trigger a hard reboot in the simulator too.

If you use -pflash instead, your changes will be saved. Note that this means 
your OVMF image will be modified, so keep a copy of the original elsewhere so 
that you can start over fresh again if you need to.

(Unfortunately I don't think OVMF has a "load factor defaults" option in its 
internal menus.)

-Bill
 
> I know this was an issue in the past, but I haven't found the resolution?
> 
> Jason
> 
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel

-- 
=============================================================================
-Bill Paul            (510) 749-2329 | Senior Member of Technical Staff,
                 wpaul@windriver.com | Master of Unix-Fu - Wind River Systems
=============================================================================
   "I put a dollar in a change machine. Nothing changed." - George Carlin
=============================================================================


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: OVMF Secure Boot variable storage issue
  2017-07-06 17:31 OVMF Secure Boot variable storage issue Jason Dickens
  2017-07-06 18:30 ` Bill Paul
@ 2017-07-06 18:49 ` Laszlo Ersek
  1 sibling, 0 replies; 6+ messages in thread
From: Laszlo Ersek @ 2017-07-06 18:49 UTC (permalink / raw)
  To: Jason Dickens, edk2-devel

Hi Jason,

On 07/06/17 19:31, Jason Dickens wrote:
> All,
> 
> I'm trying to understand why the secure boot variables (PK, KEK, db,
> etc) when using the OVMF build are not retained across reboot?

They *are* retained across reboot, you just have to use a virtualization
platform that provides a working pflash (persistent flash) device model.

With regards to the variable store, you can use OVMF in three different
QEMU configurations. In chronological order (which also matches
increasing usefulness order):

(1) -bios OVMF.fd

With this option, the unified firmware image called "OVMF.fd" (which
contains both the firmware executable and the variable store) is mapped
into the guest address space as ROM.

In this case, the lowest level of the variable driver stack -- the flash
block driver -- is provided by "OvmfPkg/EmuVariableFvbRuntimeDxe", which
emulates the "flash" in a normal RAM block, pre-reserved by
"OvmfPkg/PlatformPei", at an address that does not vary across reboots.

Whenever there is a write to the flash, EmuVariableFvbRuntimeDxe does
the following things:

- updates the in-memory (fake) flash,
- calls out to Library/EmuVariableFvbLib (PlatformFvbDataWritten()),
- that function signals an event identified by PcdEmuVariableEvent
  before ExitBootServices(), and does nothing after ExitBootServices().

>From the other side, "OvmfPkg/Library/PlatformBootManagerLib", which is
built into "MdeModulePkg/Universal/BdsDxe", does the following things:

- Using OvmfPkg/Library/NvVarsFileLib -- which in turn uses
  OvmfPkg/Library/SerializeVariablesLib --, PlatformBootManagerLib
  de-serializes variable content from the \NvVars binary file from
  any EFI system partition that it finds, and restores the content to
  the UEFI variables with the SetVariable() runtime service.

- PlatformBootManagerLib also configures the event mentioned above,
  setting up PcdEmuVariableEvent. Whenever EmuVariableFvbRuntimeDxe
  signals the event (upon a flash write), BdsDxe will call out to
  NvVarsFileLib, and serialize the full set of variables (using the
  GetVariable() runtime service)) to said \NvVars file.

Problems with this approach:

- Variable updates after ExitBootServices() are only stored in memory.
  This is because at that point, the ESP is owned (mounted) by the
  operating system, so the firmware must not write to it.

- If the VM is powered down with variable updates pending in memory,
  those updates are lost.

- If the VM is rebooted instead, then the next startup of the firmware
  will sync out the memory contents to disk, with the same
  SaveNvVarsToFs() function that is used by the serialization logic
  described above.

- If a DXE driver specifies an explicit dependency on the read-only
  variable protocol (or installs a protocol notify for it), it may
  validly attempt to read variables before BDS restores variables from
  \NvVars. The result is a GetVariable() runtime service that lies to
  callers. (This issue is exacerbated when considering read-only
  variable access in the PEI phase.)

- Authenticated variables cannot be restored by way of SetVariable()
  calls issued in an unspecified order, hence the deserialization
  doesn't work for them.

- I vaguely recall that the auth variables are also lost during an in-VM
  reboot (when de-serialization from \NvVars shouldn't be necessary). I
  think by now I've forgotten the details about this. It's possible that
  writing out & reloading always happens to and from \NvVars, and that
  loses the auth variables somehow.

  The following commits are related:

  - e678f9db899a ("OvmfPkg/SerializeVariablesLib: ignore secure variable
    restore errors", 2013-05-28)
  - db827286e283 ("OvmfPkg/SerializeVariablesLib: Relax check for the
    read-only variable", 2016-05-26)

On Xen, only "-bios" is usable.

"-bios" is incompatible with -D SMM_REQUIRE (the firmware will refuse
continuing after a specific point). The primary goal of SMM is to
protect the variable store from direct hardware access by the guest OS,
and that's impossible to do if the varstore lives in a normal RAM area
and in a file on the ESP.

(2) -pflash OVMF.fd

In this case, the same unified image is mapped into guest-phys address
space as a flash device. All of the emulation described above is
inactive. A real pflash driver is provided by
OvmfPkg/QemuFlashFvbServicesRuntimeDxe (which can be built both as a
runtime DXE driver and as an SMM driver, see the INF files in that
directory).

Variables behave as required by the UEFI spec and seen on physical
hardware. Updates are written back to the unified OVMF.fd file [*],
on-line, and variable material (auth and non-auth alike) simply survives
in the low-level flash representation.

[*] This also explains one drawback of "-pflash OVMF.fd": each virtual
machine has its own copy of the firmware executable, along with its
(justifiedly private) variable store. Updating the firmware executable
without losing variables is infeasible in practice.

This method is compatible with -D SMM_REQUIRE. For full protection, some
additional command line switches are necessary, but I'll mention those
under the next point.

(3) -drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on \
    -drive if=pflash,format=raw,unit=1,file=copy_of_OVMF_VARS.fd \

To the guest, this looks mostly the same (the only guest-visible
difference is that under (2), if the guest tried to reprogram the flash
area that holds the firmware binary, it would succeed, whereas in this
case the same attempt would fail -- see "readonly=on").

The firmware image is split in two parts. OVMF_CODE.fd is mapped as
read-only flash, and can be shared by multiple VMs. OVMF_VARS.fd is only
used as a *template* for creating private variable store files that
belong to individual VMs (see the filename "copy_of_OVMF_VARS.fd").

This method has all the benefits of (2), but we can also update
OVMF_CODE.fd centrally on a virtualization host.

When using a -D SMM_REQUIRE build, the following additions are needed:

* -machine q35

  SMM emulation is only available on pc-q35-2.5 and later

* -machine smm=on

  it's best to turn on SMM emulation explicitly

* -global driver=cfi.pflash01,property=secure,value=on

  this is the important setting that causes QEMU to actually restrict
  pflash writes to guest code that runs in System Management Mode.
  (I.e., firmware. The guest OS can itself raise an SMI if it wants to,
  but then control is transferred to the firmware just the same.)

> It seems
> that this code uses roughly the same SetVariable, GetVariable2 approach
> as say the PlatformConfig uses to store screen resolution (which is
> retained). Additionally, the NvVars file is being at least touched by
> the secure boot configuration. So why are none of the keys retained on
> the next reboot?
> 
> I know this was an issue in the past, but I haven't found the resolution?

Secure Boot with "-bios OVMF.fd" has never been resolved, due to the
reasons described above:
- inherent insecurity of the emulation,
- basic UEFI-non-compliance if the VM is powered off with runtime
  variable updates pending in the memory buffer, or if a DXE driver
  tries to consume variables before BDS de-serializes them,
- de-serialization from disk, with SetVariable(), would have to conform
  to the auth variable particulars (attributes, order)

Implementing pflash in QEMU and KVM, and adding the matching driver
(QemuFlashFvbServicesRuntimeDxe) were the future-proof solution. Jordan
did those things in the QEMU-1.6 timeframe (second half of 2013, it seems).

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: OVMF Secure Boot variable storage issue
  2017-07-06 18:30 ` Bill Paul
@ 2017-07-06 18:55   ` Jason Dickens
  2017-07-12 14:00     ` Konrad Rzeszutek Wilk
  2017-07-06 19:08   ` Laszlo Ersek
  1 sibling, 1 reply; 6+ messages in thread
From: Jason Dickens @ 2017-07-06 18:55 UTC (permalink / raw)
  To: Bill Paul, edk2-devel

Thanks for the response Bill. If I should recognize your name, I'm 
sorry, I'm bad with names, but I have been doing a lot of work with Wind 
River recently (and in the past) so its possible I should.

Actually, I should have mentioned I'm using Xen with full 
virtualization. This means that OVMF firmware can't change without 
rebuilding Xen. For reasons I don't know, it seems the Xen build uses 
the firmware image by first converting it to a C array and then 
compiling it in.

However, I'm not sure that's the real issue. As far as I'm aware, OVMF 
implements NvVars on the VM image to provide non-volatile storage 
instead of actually modifying the image. As I mentioned, "some" 
configuration changes do persist such as changing the screen resolution 
in the OVMF settings. Also I can see that NvVars is updating its 
modification time after setting secure boot variables. What I'm trying 
to determine is if there a particular reason or implementation problem 
that causes secure boot settings not persist.



On 7/6/2017 2:30 PM, Bill Paul wrote:
> Of all the gin joints in all the towns in all the world, Jason Dickens had to
> walk into mine at 10:31:18 on Thursday 06 July 2017 and say:
>
>> All,
>>
>> I'm trying to understand why the secure boot variables (PK, KEK, db,
>> etc) when using the OVMF build are not retained across reboot? It seems
>> that this code uses roughly the same SetVariable, GetVariable2 approach
>> as say the PlatformConfig uses to store screen resolution (which is
>> retained). Additionally, the NvVars file is being at least touched by
>> the secure boot configuration. So why are none of the keys retained on
>> the next reboot?
> If you're running OVMF in the QEMU simulator, and you're using the -bios
> option, try using the -pflash option instead.
>
> I know that when using -bios, QEMU only pretends to allow writes to the
> firmware region, and if you stop QEMU all changes are discarded. The same
> might be true if you just trigger a hard reboot in the simulator too.
>
> If you use -pflash instead, your changes will be saved. Note that this means
> your OVMF image will be modified, so keep a copy of the original elsewhere so
> that you can start over fresh again if you need to.
>
> (Unfortunately I don't think OVMF has a "load factor defaults" option in its
> internal menus.)
>
> -Bill
>   
>> I know this was an issue in the past, but I haven't found the resolution?
>>
>> Jason
>>
>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: OVMF Secure Boot variable storage issue
  2017-07-06 18:30 ` Bill Paul
  2017-07-06 18:55   ` Jason Dickens
@ 2017-07-06 19:08   ` Laszlo Ersek
  1 sibling, 0 replies; 6+ messages in thread
From: Laszlo Ersek @ 2017-07-06 19:08 UTC (permalink / raw)
  To: Bill Paul, edk2-devel; +Cc: Jason Dickens

On 07/06/17 20:30, Bill Paul wrote:
> Of all the gin joints in all the towns in all the world, Jason Dickens
> had to walk into mine at 10:31:18 on Thursday 06 July 2017 and say:
>
>> All,
>>
>> I'm trying to understand why the secure boot variables (PK, KEK, db,
>> etc) when using the OVMF build are not retained across reboot? It
>> seems that this code uses roughly the same SetVariable, GetVariable2
>> approach as say the PlatformConfig uses to store screen resolution
>> (which is retained). Additionally, the NvVars file is being at least
>> touched by the secure boot configuration. So why are none of the keys
>> retained on the next reboot?
>
> If you're running OVMF in the QEMU simulator, and you're using the
> -bios option, try using the -pflash option instead.
>
> I know that when using -bios, QEMU only pretends to allow writes to
> the firmware region, and if you stop QEMU all changes are discarded.
> The same might be true if you just trigger a hard reboot in the
> simulator too.
>
> If you use -pflash instead, your changes will be saved. Note that this
> means your OVMF image will be modified, so keep a copy of the original
> elsewhere so that you can start over fresh again if you need to.
>
> (Unfortunately I don't think OVMF has a "load factor defaults" option
> in its internal menus.)

Libvirt has a good pile of functionality built on top of the split image
that I described earlier. For example:

In /etc/libvirt/qemu.conf, you can provide an "nvram map", listing
several different firmware binaries, with a matching variable store
template for each.

(Different fw binaries may require different varstore formats: for
example, you can run aarch64 guests in emulation (TCG) mode, using the
ArmVirtQemu edk2 platform as your virtual firmware, and x86_64 guests in
hw virtualization (KVM) mode, using OVMF as your virtual firmware, on
the same x86_64 host. These firmwares expect a different flash layout,
so they need different varstore templates.

Another example is that you can build OVMF with 1M, 2M or 4M (unified)
image sizes, and the 4M layout uses a different (much larger) varstore
-- so the template is different for that fw binary.)

When defining a new VM, a subset of the libvirt client tools allows you
to pick a specific firmware binary. And when starting a VM that has no
varstore file under /var/lib/libvirt/qemu/nvram, libvirt will map its fw
binary to the matching varstore template, and instantiate the VM's own
varstore from the template.

As a side benefit, if you are fed up with the current contents of your
varstore, simply shut down the VM, and delete its varstore file from
under /var/lib/libvirt/qemu/nvram. When you next start the VM, libvirtd
will re-create the varstore from the pristine template.

Libvirt is an insanely powerful and great project -- I can praise it
without holding back, as I personally almost never contribute to it --,
and I do all my virt development (incl. edk2 development) exclusively
with guests that are managed by libvirt.

While the QEMU project is similarly powerful and great :) , the QEMU
command line is *not* a human interface.

(This is not to say that libvirt only composes command lines for the
VMMs that it supports -- it does a whole lot of other host management
too, such as SELinux labeling of images, setting up migration across the
network, configuring virtual networks, handling assigned physical PCI
devices, and much more.)

Thanks,
Laszlo


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: OVMF Secure Boot variable storage issue
  2017-07-06 18:55   ` Jason Dickens
@ 2017-07-12 14:00     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 6+ messages in thread
From: Konrad Rzeszutek Wilk @ 2017-07-12 14:00 UTC (permalink / raw)
  To: Jason Dickens, xen-devel; +Cc: Bill Paul, edk2-devel

On Thu, Jul 06, 2017 at 02:55:27PM -0400, Jason Dickens wrote:
> Thanks for the response Bill. If I should recognize your name, I'm sorry,
> I'm bad with names, but I have been doing a lot of work with Wind River
> recently (and in the past) so its possible I should.
> 
> Actually, I should have mentioned I'm using Xen with full virtualization.
> This means that OVMF firmware can't change without rebuilding Xen. For
> reasons I don't know, it seems the Xen build uses the firmware image by
> first converting it to a C array and then compiling it in.
> 

That can be changed - it already has the mechanism to "slurp" binary
blobs from the host. The only reason it does that right now is mostly
historic - all BIOS images where compiled in 'hvmloader'.

> However, I'm not sure that's the real issue. As far as I'm aware, OVMF
> implements NvVars on the VM image to provide non-volatile storage instead of
> actually modifying the image. As I mentioned, "some" configuration changes
> do persist such as changing the screen resolution in the OVMF settings. Also
> I can see that NvVars is updating its modification time after setting secure
> boot variables. What I'm trying to determine is if there a particular reason
> or implementation problem that causes secure boot settings not persist.
> 
> 
> 
> On 7/6/2017 2:30 PM, Bill Paul wrote:
> > Of all the gin joints in all the towns in all the world, Jason Dickens had to
> > walk into mine at 10:31:18 on Thursday 06 July 2017 and say:
> > 
> > > All,
> > > 
> > > I'm trying to understand why the secure boot variables (PK, KEK, db,
> > > etc) when using the OVMF build are not retained across reboot? It seems
> > > that this code uses roughly the same SetVariable, GetVariable2 approach
> > > as say the PlatformConfig uses to store screen resolution (which is
> > > retained). Additionally, the NvVars file is being at least touched by
> > > the secure boot configuration. So why are none of the keys retained on
> > > the next reboot?
> > If you're running OVMF in the QEMU simulator, and you're using the -bios
> > option, try using the -pflash option instead.
> > 
> > I know that when using -bios, QEMU only pretends to allow writes to the
> > firmware region, and if you stop QEMU all changes are discarded. The same
> > might be true if you just trigger a hard reboot in the simulator too.
> > 
> > If you use -pflash instead, your changes will be saved. Note that this means
> > your OVMF image will be modified, so keep a copy of the original elsewhere so
> > that you can start over fresh again if you need to.
> > 
> > (Unfortunately I don't think OVMF has a "load factor defaults" option in its
> > internal menus.)
> > 
> > -Bill
> > > I know this was an issue in the past, but I haven't found the resolution?
> > > 
> > > Jason
> > > 
> > > 
> > > _______________________________________________
> > > edk2-devel mailing list
> > > edk2-devel@lists.01.org
> > > https://lists.01.org/mailman/listinfo/edk2-devel
> 
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-07-12 13:59 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-06 17:31 OVMF Secure Boot variable storage issue Jason Dickens
2017-07-06 18:30 ` Bill Paul
2017-07-06 18:55   ` Jason Dickens
2017-07-12 14:00     ` Konrad Rzeszutek Wilk
2017-07-06 19:08   ` Laszlo Ersek
2017-07-06 18:49 ` Laszlo Ersek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox