[PATCH 0/6] EFI variable support via OP-TEE

Ilias Apalodimas ilias.apalodimas at linaro.org
Wed May 6 21:12:40 CEST 2020

With new OP-TEE and EDK2 patches (not yet upstreamed [1][2]) we can run a
secure world application which manages UEFI variables. 
Leveraging the U-Boot's OP-TEE supplicant we can then store those values 
in an RPMB device.

The Secure World application responsible for doing that is coming from
EDK2 (StandAloneMM). The StandAloneMM application is compiled from EDK2 
and then appended in the OP-TEE binary which executes that in Secure World.

There are various advantages in using StandAloneMM directly. Apart from the
obvious ones, such as running the whole code in Secure World, we are using
the EDK2 Fault Tolerant Write protocol to protect the variables against
corruption. We also avoid adding complicated code to U-Boot for the variable 
management. The only code U-Boot needs is a set OP-TEE APIs to access the new

>From a user's perspective this changes nothing to the usual way UEFI variables
are treated. The user will still use 'setenv/printenv -e' to perform the 
variable operations.
An 'efidebug query' command is added to retrieve information about the 
container used to store UEFI variables.

Since patches for the rest of the projects are not yet upstreamed I've tried to
provide a QEMU emulation for anyone interested in testing the patchset.

1. Download precompiled TF-A, OP-TEE binaries and a DTB from
   bl33.bin is a precompiled U-Boot binary. If you use that skip (2)

2. git clone --single-branch --branch rpmb_hack \
   I've included a defconfig to make your life easier
   export CROSS_COMPILE=aarch64-linux-gnu-
   export ARCH=arm64
   make qemu_tfa_mm_defconfig && make -j4
   Safely ignore the warnings, they are a result of the RPMB emulation
   monstrosity ...
   The branch contains an extra patch which adds RPMB emulation into OP-TEE
   supplicant but breaks proper RPMB hardware. The patch is a gross hack 
   (but can be upstreamed later for Gitlab testing if needed).
   Since QEMU has no RPMB emulation providing one through the OP-TEE supplicant
   was the easiest way to test the patchset.

3. Create PK, KEK etc
   - PK:
   openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_PK/ -keyout \
    PK.key -out PK.crt -nodes -days 365
   cert-to-efi-sig-list -g 11111111-2222-3333-4444-123456789abc PK.crt \
    PK.esl; sign-efi-sig-list -c PK.crt -k PK.key PK PK.esl PK.auth

   - KEK:
   openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_KEK/ -keyout \
    KEK.key -out KEK.crt -nodes -days 365
   cert-to-efi-sig-list -g 11111111-2222-3333-4444-123456789abc KEK.crt \
    KEK.esl; sign-efi-sig-list -c PK.crt -k PK.key KEK KEK.esl KEK.auth

   - put them in a file and create an image
   mkdir tmp && cp PK.auth KEK.auth tmp/
   virt-make-fs -s 1M -t ext4 tmp certs.img

4. Launch QEMU (note tested on QEMU 3.1 and 5.0)
   qemu-system-aarch64  -m 1024 -smp 2 -show-cursor -serial stdio \
   -monitor null -nographic \
   -cpu cortex-a57 -bios bl1.bin  -machine virt,secure=on -d unimp \
   -semihosting-config enable,target=native -dtb ledge-qemuarm64.dtb \
   -drive if=none,file=certs.img,id=mydisk \
   -device nvme,drive=mydisk,serial=foo

   You can now load and test the certificates 
   nvme scan
   load nvme 0 0x70000000 PK.auth
   setenv -e -nv -bs -rt -at -i 0x70000000,$filesize PK; 
   load nvme 0 0x70000000 KEK.auth
   setenv -e -nv -bs -rt -at -i 0x70000000,$filesize KEK; 
   efidebug query
   printenv -e -all

This has been tested against U-Boot efi_sefltest but since StandAloneMM will
write a non-existent variable if APPEND_WRITE is specified, this test will fail.
It has also been tested for the runtime variable support (or rather absence of
it) with FWTS (https://wiki.ubuntu.com/FirmwareTestSuite).

This patchset adds the needed APIs between U-Boot and OP-TEE and StandAloneMM
to perform the variable storage.

[1] https://github.com/apalos/optee_os/tree/stmm_upstream_03_clean
[2] https://git.linaro.org/people/ilias.apalodimas/edk2-platforms.git/log/?h=patch_pcd

Ilias Apalodimas (4):
  efi_loader: Implement EFI variable handling via OP-TEE
  cmd: efidebug: Add support for querying UEFI variable storage
  MAINTAINERS: Add maintainer for EFI variables via OP-TEE
  doc: uefi.rst: Add OP-TEE variable storage config options

Sughosh Ganu (2):
  charset: Add support for calculating bytes occupied by a u16 string
  efi_loader: Add headers for EDK2 StandAloneMM communication

 MAINTAINERS                       |   7 +
 cmd/efidebug.c                    |  45 ++-
 doc/uefi/uefi.rst                 |  10 +
 include/charset.h                 |  11 +
 include/mm_communication.h        |  28 ++
 include/mm_variable.h             |  78 ++++
 lib/charset.c                     |   5 +
 lib/efi_loader/Kconfig            |   9 +
 lib/efi_loader/Makefile           |   4 +
 lib/efi_loader/efi_variable_tee.c | 645 ++++++++++++++++++++++++++++++
 10 files changed, 841 insertions(+), 1 deletion(-)
 create mode 100644 include/mm_communication.h
 create mode 100644 include/mm_variable.h
 create mode 100644 lib/efi_loader/efi_variable_tee.c


More information about the U-Boot mailing list