On 02.03.21 17:39, Sughosh Ganu wrote: > > > On Tue, 2 Mar 2021 at 21:27, Heinrich Schuchardt <xypron.g...@gmx.de > <mailto:xypron.g...@gmx.de>> wrote: > > On 02.03.21 15:48, Sughosh Ganu wrote: > > hi Heinrich, > > > > On Tue, 2 Mar 2021 at 16:45, Heinrich Schuchardt > <xypron.g...@gmx.de <mailto:xypron.g...@gmx.de> > > <mailto:xypron.g...@gmx.de <mailto:xypron.g...@gmx.de>>> wrote: > > > > On 30.12.20 14:57, Sughosh Ganu wrote: > > > Add documentation highlighting the steps for using the uefi > capsule > > > update feature for updating the u-boot firmware image. > > > > > > Signed-off-by: Sughosh Ganu <sughosh.g...@linaro.org > <mailto:sughosh.g...@linaro.org> > > <mailto:sughosh.g...@linaro.org <mailto:sughosh.g...@linaro.org>>> > > > --- > > > > > > Changes since V3: None > > > > > > doc/board/emulation/index.rst | 1 + > > > doc/board/emulation/qemu_capsule_update.rst | 210 > > ++++++++++++++++++++ > > > 2 files changed, 211 insertions(+) > > > create mode 100644 doc/board/emulation/qemu_capsule_update.rst > > > > > > diff --git a/doc/board/emulation/index.rst > > b/doc/board/emulation/index.rst > > > index 1adefee155..a09ead1c35 100644 > > > --- a/doc/board/emulation/index.rst > > > +++ b/doc/board/emulation/index.rst > > > @@ -10,3 +10,4 @@ Emulation > > > qemu-mips > > > qemu-riscv > > > qemu-x86 > > > + qemu_capsule_update > > > diff --git a/doc/board/emulation/qemu_capsule_update.rst > > b/doc/board/emulation/qemu_capsule_update.rst > > > new file mode 100644 > > > index 0000000000..9fec75f8f1 > > > --- /dev/null > > > +++ b/doc/board/emulation/qemu_capsule_update.rst > > > @@ -0,0 +1,210 @@ > > > +.. SPDX-License-Identifier: GPL-2.0+ > > > +.. Copyright (C) 2020, Linaro Limited > > > + > > > +Enabling UEFI Capsule Update feature > > > +------------------------------------ > > > + > > > +Support has been added for the UEFI capsule update feature > which > > > +enables updating the U-Boot image using the UEFI firmware > management > > > +protocol (fmp). The capsules are not passed to the firmware > through > > > +the UpdateCapsule runtime service. Instead, capsule-on-disk > > > +functionality is used for fetching the capsule from the EFI > System > > > +Partition (ESP) by placing the capsule file under the > > > +\EFI\UpdateCapsule directory. > > > + > > > +Currently, support has been added on the QEMU ARM64 virt > platform for > > > +updating the U-Boot binary as a raw image when the platform > is booted > > > +in non-secure mode, i.e. with CONFIG_TFABOOT disabled. For this > > > +configuration, the QEMU platform needs to be booted with > > > +'secure=off'. The U-Boot binary placed on the first bank of > the NOR > > > +flash at offset 0x0. The U-Boot environment is placed on > the second > > > +NOR flash bank at offset 0x4000000. > > > + > > > +The capsule update feature is enabled with the following > > configuration > > > +settings:: > > > + > > > + CONFIG_MTD=y > > > + CONFIG_FLASH_CFI_MTD=y > > > + CONFIG_CMD_MTDPARTS=y > > > + CONFIG_CMD_DFU=y > > > + CONFIG_DFU_MTD=y > > > + CONFIG_PCI_INIT_R=y > > > + CONFIG_EFI_CAPSULE_ON_DISK=y > > > + CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y > > > + CONFIG_EFI_CAPSULE_FIRMWARE=y > > > + CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y > > > + CONFIG_EFI_CAPSULE_FMP_HEADER=y > > > + > > > +In addition, the following config needs to be disabled(QEMU ARM > > specific):: > > > + > > > + CONFIG_TFABOOT > > > + > > > +The capsule file can be generated by using the > GenerateCapsule.py > > > +script in EDKII:: > > > + > > > + $ ./BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ > > > + <capsule_file_name> --fw-version <val> --lsv <val> --guid \ > > > + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose > > --update-image-index \ > > > + <val> --verbose <u-boot.bin> > > > + > > > +The above is a wrapper script(GenerateCapsule) which > eventually calls > > > +the actual GenerateCapsule.py script. > > > + > > > +As per the UEFI specification, the capsule file needs to be > placed on > > > +the EFI System Partition, under the \EFI\UpdateCapsule > directory. The > > > +EFI System Partition can be a virtio-blk-device. > > > + > > > +Before initiating the firmware update, the efi variables > BootNext, > > > +BootXXXX and OsIndications need to be set. The BootXXXX > variable > > needs > > > +to be pointing to the EFI System Partition which contains > the capsule > > > +file. The BootNext, BootXXXX and OsIndications variables > can be set > > > +using the following commands:: > > > + > > > + => efidebug boot add 0 Boot0000 virtio 0:1 > <capsule_file_name> > > > + => efidebug boot next 0 > > > + => setenv -e -nv -bs -rt -v OsIndications =0x04 > > > + => saveenv > > > + > > > +Finally, the capsule update can be initiated with the following > > > +command:: > > > + > > > + => efidebug capsule disk-update > > > + > > > +The updated U-Boot image will be booted on subsequent boot. > > > + > > > +Enabling Capsule Authentication > > > +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > > + > > > +The UEFI specification defines a way of authenticating the > capsule to > > > +be updated by verifying the capsule signature. The capsule > signature > > > +is computed and prepended to the capsule payload at the time of > > > +capsule generation. This signature is then verified by > using the > > > +public key stored as part of the X509 certificate. This > > certificate is > > > +in the form of an efi signature list (esl) file, which is > embedded as > > > +part of the platform's device tree blob using the mkeficapsule > > > +utility. > > > + > > > +On the QEMU virt platforms, the device-tree is generated on > the fly > > > +based on the devices configured. This device tree is then > passed > > on to > > > +the various software components booting on the platform, > including > > > +U-Boot. Therefore, on the QEMU virt platform, the signatute is > > > +embedded on an overlay. This overlay is then applied at runtime > > to the > > > +base platform device-tree. Steps needed for embedding the > esl file in > > > +the overlay are highlighted below. > > > + > > > +The capsule authentication feature can be enabled through the > > > +following config, in addition to the configs listed above > for capsule > > > +update:: > > > + > > > + CONFIG_EFI_CAPSULE_AUTHENTICATE=y > > > + > > > +The public and private keys used for the signing process are > > generated > > > +and used by the steps highlighted below:: > > > + > > > + 1. Install utility commands on your host > > > + * OPENSSL > > > + * efitools > > > + > > > + 2. Create signing keys and certificate files on your host > > > + > > > + $ openssl req -x509 -sha256 -newkey rsa:2048 -subj > /CN=CRT/ \ > > > + -keyout CRT.key -out CRT.crt -nodes -days 365 > > > + $ cert-to-efi-sig-list CRT.crt CRT.esl > > > + > > > + $ openssl x509 -in CRT.crt -out CRT.cer -outform DER > > > + $ openssl x509 -inform DER -in CRT.cer -outform PEM > -out > > CRT.pub.pem > > > + > > > + $ openssl pkcs12 -export -out CRT.pfx -inkey > CRT.key -in > > CRT.crt > > > + $ openssl pkcs12 -in CRT.pfx -nodes -out CRT.pem > > > + > > > +The capsule file can be generated by using the > GenerateCapsule.py > > > +script in EDKII:: > > > + > > > + $ ./BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ > > > + <capsule_file_name> --monotonic-count <val> > --fw-version \ > > > + <val> --lsv <val> --guid \ > > > + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose \ > > > + --update-image-index <val> --signer-private-cert \ > > > + /path/to/CRT.pem --trusted-public-cert \ > > > + /path/to/CRT.pub.pem --other-public-cert > /path/to/CRT.pub.pem \ > > > + <u-boot.bin> > > > + > > > +Place the capsule generated in the above step on the EFI System > > > +Partition under the EFI/UpdateCapsule directory > > > + > > > +For embedding the public key certificate, the following > steps need to > > > +be followed:: > > > + > > > + 1. Generate a skeleton overlay dts file, with a single > fragment > > > + node and an empty __overlay__ node > > > + > > > + A typical skeleton overlay file will look like this > > > + > > > + /dts-v1/; > > > + /plugin/; > > > + > > > + / { > > > + fragment@0 { > > > + target-path = "/"; > > > + __overlay__ { > > > + }; > > > + }; > > > + }; > > > + > > > + > > > + 2. Convert the dts to a corresponding dtb with the > following > > > > Shouldn't this be dtbo? > > > > > + command > > > + ./scripts/dtc/dtc -@ -I dts -O dtb -o > <ov_dtb_file_name> \ > > > + <dts_file> > > > + > > > + 3. Run the dtb file generated above through the > mkeficapsule tool > > > + in U-Boot > > > + ./tools/mkeficapsule -O <pub_key.esl> -D <ov_dtb> > > > + > > > +Running the above command results in the creation of a > 'signature' > > > +node in the dtb, under which the public key is stored as a > > > +'capsule-key' property. The '-O' option is to be used since the > > > +public key certificate(esl) file is being embedded in an > overlay. > > > + > > > +The dtb file embedded with the certificate is now to be > placed on an > > > +EFI System Partition. This would then be loaded and > "merged" with the > > > +base platform flattened device-tree(dtb) at runtime. > > > + > > > +Build U-Boot with the following steps(QEMU ARM64):: > > > + > > > + $ make qemu_arm64_defconfig > > > + $ make menuconfig > > > + Disable CONFIG_TFABOOT > > > + Enable CONFIG_EFI_CAPSULE_AUTHENTICATE > > > + Enable all configs needed for capsule update(listed > above) > > > + $ make all > > > + > > > +Boot the platform and perform the following steps on the U-Boot > > > +command line:: > > > + > > > + 1. Enable capsule authentication by setting the > following env > > > + variable > > > + > > > + => setenv capsule_authentication_enabled 1 > > > + => saveenv > > > + > > > + 2. Load the overlay dtb to memory and merge it with the > base fdt > > > + > > > + => fatload virtio 0:1 <$fdtovaddr> EFI/<ov_dtb_file> > > > + => fdt addr $fdtcontroladdr > > > + => fdt resize <size_of_ov_dtb_file> > > > + => fdt apply <$fdtovaddr> > > > > Having the public key on the disk means that any public key can be > > placed here and we get zero security. > > > > > > But that does not mean the authentication will succeed unless the > > private key is compromised. Deleting or tampering the public key > on the > > disk can result in a denial of service attack, as the capsule > > authentication would fail, but that is true even when the public > key is > > embedded in u-boot -- the public key or the u-boot image can be > tampered > > with, resulting in a board brick. For countering this kind of > denial of > > service attack, the public key needs to be placed on a secure storage > > device, which cannot be modified or removed from the normal world. > > Moreover, how is this different to the placement of the signature > > database used for the uefi secure boot as part of the uefi > authenticated > > variables on a storage device that can be accessed from the normal > world. > > The public key is what you use to verify that a capsule was signed by an > authorized party. Who controls the public keys used for capsule checking > can crack the device: > > I just have to create a public/private key pair to sign my malware and > place both the public key and the malware capsule on the disk. > > > But when tf-a verifies this this BL33 during boot, it would fail > authentication and would not boot that BL33 image. So it is the same as > denial of service, isn't it.
You cannot stop denial of service, but you can stop malware. That is why I don't want the public key used for capsule verification on disk. Best regards Heinrich > > -sughosh > > > > We should not allow public keys for capsules to be on disk. > > TF-A checks BL33 (U-Boot). If the public key is part of BL33 then only > capsules signed with this trusted key can be installed. > > An attacker can still change U-Boot in a way that TF-A will not load it > leading to a denial of service. But he cannot launch malware via > capsules. > > Best regards > > Heinrich > > > > > > We need to build the public key into U-Boot. > > > > Could you, please, investigate how we can adjust the build process > > accordingly. > > > > Best regards > > > > Heinrich > > > > > + > > > + 3. Set the following environment and UEFI boot variables > > > + > > > + => setenv -e -nv -bs -rt -v OsIndications =0x04 > > > + => efidebug boot add 0 Boot0000 virtio 0:1 > > <capsule_file_name> > > > + => efidebug boot next 0 > > > + => saveenv > > > + > > > + 4. Finally, the capsule update can be initiated with the > > following > > > + command > > > + > > > + => efidebug capsule disk-update > > > + > > > +On subsequent reboot, the platform should boot the updated > U-Boot > > binary. > > > > > >