On 5/31/19 4:47 PM, Ilias Apalodimas wrote:
> Hi Grant,
>> On 24/05/2019 16:28, Ilias Apalodimas wrote:
>>> Hello all,
>>>
>>> Continuing the discussions we had on securing the boot flow and OS as much 
>>> as
>>> possible, we came up with the following idea.
>>>
>>> We are currently sorting out what's needed to add UEFI Secure Boot in 
>>> U-Boot.
>>> This will cover the next payload (shim/grub2/shim depending on board needs).
>>>
>>> In order to provide better overall security for the OS we'll need to at 
>>> least
>>> verify DTB (if provided externally), initramfs and kernel modules.
>>>
>>> 1. For the kernel modules we can use kernel module signing facilities [1 > 
>>> 2. In case someone wants to provide an external DTB, we can use FIT
>> images
>>> to secure that. The FIT images will contain the DTB(s) we need. Those will
>>> only be used if the authentication process succeeds. This will allow us to
>>> verify DTBs without introducing any new functionality to U-Boot.
>>
>> The trouble with this scenario is it uses a different authentication
>> scheme from the OS boot. OS boot would verify against the Secure boot
>> DB/DBX variables, but the FIT image containing a new DTB uses an
>> entirely different authentication path, and the platform needs a way to
>> break into the boot flow early (before UEFI Boot Device Selection) to
>> perform the custom DTB load step before choosing the kernel to boot.
>> That might be too early to know which .dtb needs to be loaded.
>>
> This is exactly the reason i mentioned this on my first mail.
>
> "This also makes the development process for LEDGE pretty clear. We'll have to
>  add UEFI Secure Boot implementation on U-Boot *only* since the rest of the
>  functionality can be achieved with the existing code (minor adjustments might
>  be needed though)".
> s/minor adjustments/Your option #2/
>
> I was wondering how hard/acceptable is to do option #2

I think option 2 is quite easy to implement:

In U-Boot we already have a tool file2include which we can use to
convert the FDT into an include. Now we only have to build the EFI
binary from a C file with the include. Building an EFI binary is easy
with gnu-efi. Last step is to sign the EFI binary with sbsign. The
essential point is that the C file will be constant, only the generated
include will change.

The good thing about option 2 is its compatibility with any UEFI
implementation and not just U-Boot.

I think an operating system should not have to worry about the firmware
I am using. E.g. on the MACCHIATObin either of U-Boot or EDK II can be used.

In U-Boot updates to the device tree are not done at ExitBootServices()
but when invoking bootefi.

Updating the device tree may result in a larger device tree so it cannot
be done in place. Instead we have to install a copy. The problem about
updating in ExitBootServices() is that we do not know if the EFI
application calling it holds a pointer to the device tree across the call.

bootefi replaces any device tree with its own device tree if not called
with a device tree argument. We will have to change this when going with
option 2.

Best regards

Heinrich

>
>> I see two ways to handle this that fits with the Secure Boot
>> authentication path:
>>
>> Option 1: Leave it to the OS loader
>> We could simply say that if the OS wants to replace the DTB, then it
>> should take care of authentication itself within the OS loader (possibly
>> the in-kernel UEFI stub) and install a replacement DTB in the
>> configuration table before calling exit boot services. In this scenario,
>> U-Boot doesn't authenticate the DTB at all.
>>
>> In fact, Option 1 is pretty close to what is required for the initrd.
>>
>> I wonder if it is possible to wrap the DTB with a PE/COFF so that the os
>> loader can use load_image to authenticate and retrieve the data without
>> actually executing the image. That would allow for the DTB & initrd to
>> be authenticated in the same way as the kernel.
>>
>> Option 2: Put a PE/COFF wrapper around the dtb
>> The wrapper can be really simple. Little more than the following code:
>> {
>>      bootservices.allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
>> EFI_RUNTIME_SERVICES_DATA, 1, &dtb_addr);
>>      memcpy()
>>      bootservices.install_configuration_table(dtb_guid, dtb_addr);
>> }
>>
>> This allows the DTB to be managed separately from the kernel (which may
>> or may not be desired; depending on use-case), and it uses the same
>> authentication scheme as for the OS loader. It would would on both
>> Tianocore and U-Boot UEFI implementations. The dtb toolchain could be
>> modified to use a stock wrapper. The same technique could even be used
>> to load and apply dtb overlays. Downside is the wrapper would be
>> architecture dependent
>>
>> I think option 1 is pretty close to the approach used by stub, and I
>> suspect it fits better into the deployment scenarios that would want to
>> ship a DTB with the kernel. I would go down that path.
>>
>> In either case, I'm now leaning toward the opinion that calling
>> install_configuration_table() to change the dtb is the right thing to
>> do. The DTB still gets exposed to the kernel in the same way, and it
>> provides the option of firmware applying updates (ie. kernel command
>> line) to the new dtb at ExitBootServices() time. It also acknowledges
>> that the DTB used to boot the kernel isn't always the DTB used
>> internally by U-Boot.
>>
>
>
> Thanks
> /Ilias
> _______________________________________________
> boot-architecture mailing list
> [email protected]
> https://lists.linaro.org/mailman/listinfo/boot-architecture
>

_______________________________________________
boot-architecture mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/boot-architecture

Reply via email to