/uefistored

Variables store for UEFI guests. Note: in XCP-ng 8.3+, we switched to varstored in order to share a common implementation with XenServer.

Primary LanguageCGNU General Public License v2.0GPL-2.0

uefistored

This project aims to support UEFI Secure Boot in guest VMs on XCP-ng.

Overview

uefistored is a service that runs in dom0 userspace for servicing port IO RPC requests from the OVMF XenVariable module, therefore providing a protected UEFI Variables Service implementation.

Building

To build uefistored:

make all

Use make help to see make targets:

$ make help

uefistored - UEFI Secure Boot Support for Xen Guest VMs

all:               Build uefistored (same as uefistored target)
uefistored:        Build uefistored
uefistored-debug:  Build uefistored with debug symbols
test:              Run uefistored unit tests with address sanitizers
install:           Install uefistored and secureboot-certs
deploy:            Deploy uefistored to a host
help:              Display this help
scan-build:        Use scan-build for static analysis

Building using Docker

Building the container

Run docker build -t xcp-ng/xcp-ng-build-env:8.2-uefistored -f Dockerfile-8.2-uefistored . xcp-ng/xcp-ng-build-env:8.2 is needed to build the container, it's available in the build-env git repo.

Using the container

To run manually a make command in the container:

$ make docker-shell
container$ make <cmd>

To directly run a command in the container:

$ make docker-<cmd>

Dependencies

uefistored depends on the following libraries:

  • clang-analyzer
  • glib2-devel
  • libseccomp-devel
  • libxml2-devel
  • openssl-devel
  • xen-dom0-libs-devel

Test dependencies

  • asan
  • valgrind

Initializing keys for uefistored

Because Microsoft key's are not freely distributable, we must require users to download the keys and use them themselves instead of packaging and distributing the keys alongside uefistored.

This section shows you how to generate and install keys for uefistored, using the Microsoft/UEFI keys necessary to support both Shim and Windows in secure boot mode.

# Generate KEK
openssl req -newkey rsa:4096 -nodes -new -x509 -sha256 -days 3650 \
        -subj "/CN=KEK Owner/" \
        -keyout KEK.key \
        -out KEK.crt

# Self-sign KEK and creat KEK.auth
# NOTE: because this cert is self-signed it will not be provisionable from
# the guest, only as a file for uefistored to read from /var/lib/uefistored
/opt/xensource/libexec/create-auth -k KEK.key -c KEK.crt KEK KEK.auth KEK.crt

# Download Microsoft UEFI CA 2011
curl 'https://www.microsoft.com/pkiops/certs/MicCorUEFCA2011_2011-06-27.crt' --output MicCorUEFCA2011_2011-06-27.crt

# Download Microsoft UEFI PCA 2011
curl 'https://www.microsoft.com/pkiops/certs/MicWinProPCA2011_2011-10-19.crt' --output MicWinProPCA2011_2011-10-19.crt

# Note, if curling fails the original redirect links to the certs are here:
# * [MicWinProPCA2011_2011-10-19.crt](https://go.microsoft.com/fwlink/p/?linkid=321192)
# * [MicCorUEFCA2011_2011-06-27.crt](https://go.microsoft.com/fwlink/p/?linkid=321194)

# Sign Microsoft certs with your KEK and create a db.auth
/opt/xensource/libexec/create-auth -k KEK.key -c KEK.crt db db.auth MicWinProPCA2011_2011-10-19.crt MicCorUEFCA2011_2011-06-27.crt

cp *.auth /var/lib/uefistored/

# If you would like the most recent dbx, it may be found here:
# https://www.uefi.org/revocationlistfile

NOTE: If both curling and the redirect links fail, you may manually download the UEFI CA 2011 and Production PCA 2011 from here

Logging

uefistored supports defining log levels using the file /etc/uefistored/uefistored.conf.

In /etc/uefistored/uefistored.conf, set the "loglevel" variable, such as:

# /etc/uefistored/uefistored.conf
[default]
loglevel=DEBUG

Possible values for loglevel are:

loglevel
DEBUG
WARNING
ERROR
INFO

The default level is INFO.

Deployment during Test

If you just want to deploy to a known host:

$ make all
$ HOST=$HOSTNAME_OR_IP make deploy

Backends

uefistored supports the implementation of alternative backends for the persistent storage of variables.

Currently, the only implemented backend is for XAPI.

The XAPI backend

uefistored uses Xen's libxen to register itself as a device emulator for the HVM domU that XAPI has started. XenVariable, found in OVMF, knows how to communicate with uefistored using the device emulation protocol. See OVMF and uefistored for more details.

OVMF and uefistored

OVMF's XenVariable module implements the UEFI Variables service (see the UEFI v2 spec). When a call is made to the UEFI Variables service, XenVariable passes the call to uefistored via a mechanism of port IO and shared memory.

For example, when OVMF makes a GetVariable call, XenVariable packages a call ID indicating "GetVariable" and the arguments of the call onto a memory page that is shared with uefistored [1]. It writes the address of that shared memory to port 0x100, which Xen routes to uefistored. uefistored then grabs the memory location, maps it in, and handles the request resident in it. Once it has been handled and the response has been loaded into the shared memory, an event channel notification is used to indicate to the guest that its GetVariable request has been served and the response is ready for processing.

[1] uefistored uses the xenforeignmemory_map() API to map in the OVMF memory page that XenVariable uses. XenVariable communicates the location of this page to uefistored using port IO caught by an IOREQ server initialized by uefistored.

Contributing

Contributions are welcome and may be submitted as PRs to github.

Reporting bugs

Bugs may be reported as github issues.

Some helpful information may include:

  • The output from cat /var/log/daemon.log | grep uefistored (if on XCP-ng) or from uefistored stdout/stderr.
  • Screenshots or text from the guest.

Maintainers

Acknowledgements

The overall design of this solution and some of the code comes from the varstored. Some of the code is also derived from edk2.