From mboxrd@z Thu Jan 1 00:00:00 1970 From: Sughosh Ganu Date: Tue, 2 Mar 2021 23:08:24 +0530 Subject: [PATCH v4 14/14] qemu: arm64: Add documentation for capsule update In-Reply-To: <12038307-658c-d2c0-b91c-cb4c8268ade3@gmx.de> References: <20201230135712.5289-1-sughosh.ganu@linaro.org> <20201230135712.5289-15-sughosh.ganu@linaro.org> <297f9d9a-34df-8ba2-faf4-e3f472670503@gmx.de> <17c7b93c-fc40-80ce-0994-ac64645eac10@gmx.de> <12038307-658c-d2c0-b91c-cb4c8268ade3@gmx.de> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On Tue, 2 Mar 2021 at 22:36, Heinrich Schuchardt wrote: > On 02.03.21 17:39, Sughosh Ganu wrote: > > > > > > On Tue, 2 Mar 2021 at 21:27, Heinrich Schuchardt > > wrote: > > > > On 02.03.21 15:48, Sughosh Ganu wrote: > > > hi Heinrich, > > > > > > On Tue, 2 Mar 2021 at 16:45, Heinrich Schuchardt > > > > > >> 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.ganu at 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 \ > > > > + --fw-version --lsv > --guid \ > > > > + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose > > > --update-image-index \ > > > > + --verbose > > > > + > > > > +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 > > > > > > + => 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 \ > > > > + --monotonic-count > > --fw-version \ > > > > + --lsv --guid \ > > > > + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose \ > > > > + --update-image-index --signer-private-cert \ > > > > + /path/to/CRT.pem --trusted-public-cert \ > > > > + /path/to/CRT.pub.pem --other-public-cert > > /path/to/CRT.pub.pem \ > > > > + > > > > + > > > > +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 at 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 > > \ > > > > + > > > > + > > > > + 3. Run the dtb file generated above through the > > mkeficapsule tool > > > > + in U-Boot > > > > + ./tools/mkeficapsule -O -D > > > > + > > > > +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/ > > > > + => fdt addr $fdtcontroladdr > > > > + => fdt resize > > > > + => 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. > If we have a trusted boot flow[1], with tf-a authenticating the BL33(u-boot) image before booting, how do we allow malware to boot on the system. -sughosh [1] - https://trustedfirmware-a.readthedocs.io/en/latest/design/trusted-board-boot.html > > 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 > > > > > > > + => 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. > > > > > > > > > > >