We're still trying to come to a conclusion about the most maintainable
approach to getting DRTM implementations like Intel TXT working on UEFI
platforms under Linux. I'm going to try to summarise the situation here
- I'm not an expert, so details may be inaccurate, but I think this is
the rough shape of things.
Under normal circumstances on UEFI platforms, the bootloader (or system
firmware directly) load the kernel and execute code in the boot stub.
This boot stub code interacts with the firmware in various ways,
including working around some platform-specific issues and doing things
like copying the TPM event log into memory that can be used by the
kernel proper. While it remains technically possible to boot the kernel
on x86 UEFI platforms by jumping directly to the kernel entry point and
skipping the boot stub, this risks disabling certain functionality and
leaving the kernel in a slightly unexpected state. The contract that
exists between the UEFI stub and the kernel is not meaningfully
documented - portions are carried out by updating the contents of the
bootparams struct on x86 or devicetree on ARM, but other information is
conveyed via UEFI configuration tables, the boot stub may modify the
contents of certain UEFI variables, and some of this is implicit in
the form of hardware state.
The Trenchboot project is attempting to implement DRTM under Linux.
Traditional measured boot takes the form of a static root of trust -
each component in the boot chain is measured by the previous component
before being executed, and each measures what it considers to be
security relevant configuration and behavioural state. Modifying any
component will change the measurements, even if the end result is
equivalent. Dynamic Root of Trust Measurement aims to provide more
useful measurements by performing a measurement at a specific point in
time - as a result, DRTM cares only about what the state *is*, not what
happened before then.
There's a bunch of complexity involved in this that's vendor specific,
but the short version is that a launch environment is set up and a
specific CPU instruction executed that triggers a secure launch event.
The Trenchboot code consists of patches to bootloaders to support
setting up this environment, and patches to the kernel to provide
support for the "Secure Launch" kernel that handles DRTM before handing
control off to the kernel proper, skipping the UEFI boot stub.
Since this skips the UEFI boot stub, it's then the responsibility of the
bootloader to implement the functionality of the boot stub. This is made
difficult due to the absence of an express contract between the boot
stub and the rest of the kernel - our assumption has been that the code
is the contract, and this is free to change arbitrarily since both the
producer and the consumer of the information can be updated
simultaneously and can't get out of sync. That seems to leave us with
two options:
1) Formalise the contract between the boot stub and the kernel, making
it easier for other boot loaders to implement the contract. This has the
downside that even within the scope of the contract we may end up with
divergent behaviour, and also new functionality in the kernel may not be
available without the bootloader also being updated.
2) Modify the boot stub such that it can be provided with a callback,
and instead of jumping to the kernel it can jump to the callback. The
boot flow would then involve the boot loader setting up the launch
environment, calling the boot stub code, and then performing the DRTM
event. This avoids requiring an explicit contract (the boot stub would
remain part of the kernel image and would be updated in lockstep).
One complexity for both approaches is that the secure launch environment
needs to be aware of all security-critical state in the system. The
firmware nominally exposes that information for everything it's aware
of that's security-critical, but the boot stub may have performed
security-critical actions or exposed security-critical state that the
firmware is unaware of. The secure launch code from Trenchboot has to be
aware of this in order to ensure it's measured.
If there's a contract, then in theory this would be embodied in the
contract and when the contract is updated the secure launch code could
also be updated. If there's no contract, every change to the boot stub
would need to be examined and the secure launch code updated if
necessary.
While the secure launch code is currently out of tree, the goal is for
it to be integrated into the kernel tree. My feeling is that it's
going to be easier to manage this if everything is in tree - ie, all the
EFI setup code that does anything security-critical is either in the
firmware (and so the firmware takes responsibility for exposing it) or
is in the Linux tree (and so we take responsibility for updating the
secure launch code whenever something relevant changes in the boot
stub). But this requires support from the EFI maintainers in terms of
not merging things until we've established whether updates are required
to the secure launch code. The alternative is effectively the same,
except it would require updating the contract instead.
But, as mentioned, that's just my feeling - I know that Daniel feels
that the contract approach is preferable. So:
1) From an EFI maintainer perspective, is making the contract between
the boot stub and the kernel explicit viable?
2) If so, is it desirable?
3) If either (1) or (2) is "no", is it reasonable to ensure that all
potentially security-critical state or configuration changes to the
boot stub are reviewed by DRTM people to verify whether the secure
launch code needs to be updated to match?
Hi Matt,
On Tue, 29 Mar 2022 at 19:41, Matthew Garrett <[email protected]> wrote:
>
> We're still trying to come to a conclusion about the most maintainable
> approach to getting DRTM implementations like Intel TXT working on UEFI
> platforms under Linux. I'm going to try to summarise the situation here
> - I'm not an expert, so details may be inaccurate, but I think this is
> the rough shape of things.
>
> Under normal circumstances on UEFI platforms, the bootloader (or system
> firmware directly) load the kernel and execute code in the boot stub.
> This boot stub code interacts with the firmware in various ways,
> including working around some platform-specific issues and doing things
> like copying the TPM event log into memory that can be used by the
> kernel proper. While it remains technically possible to boot the kernel
> on x86 UEFI platforms by jumping directly to the kernel entry point and
> skipping the boot stub, this risks disabling certain functionality and
> leaving the kernel in a slightly unexpected state. The contract that
> exists between the UEFI stub and the kernel is not meaningfully
> documented - portions are carried out by updating the contents of the
> bootparams struct on x86 or devicetree on ARM, but other information is
> conveyed via UEFI configuration tables, the boot stub may modify the
> contents of certain UEFI variables, and some of this is implicit in
> the form of hardware state.
>
> The Trenchboot project is attempting to implement DRTM under Linux.
> Traditional measured boot takes the form of a static root of trust -
> each component in the boot chain is measured by the previous component
> before being executed, and each measures what it considers to be
> security relevant configuration and behavioural state. Modifying any
> component will change the measurements, even if the end result is
> equivalent. Dynamic Root of Trust Measurement aims to provide more
> useful measurements by performing a measurement at a specific point in
> time - as a result, DRTM cares only about what the state *is*, not what
> happened before then.
>
> There's a bunch of complexity involved in this that's vendor specific,
> but the short version is that a launch environment is set up and a
> specific CPU instruction executed that triggers a secure launch event.
> The Trenchboot code consists of patches to bootloaders to support
> setting up this environment, and patches to the kernel to provide
> support for the "Secure Launch" kernel that handles DRTM before handing
> control off to the kernel proper, skipping the UEFI boot stub.
>
> Since this skips the UEFI boot stub, it's then the responsibility of the
> bootloader to implement the functionality of the boot stub. This is made
> difficult due to the absence of an express contract between the boot
> stub and the rest of the kernel - our assumption has been that the code
> is the contract, and this is free to change arbitrarily since both the
> producer and the consumer of the information can be updated
> simultaneously and can't get out of sync. That seems to leave us with
> two options:
>
> 1) Formalise the contract between the boot stub and the kernel, making
> it easier for other boot loaders to implement the contract. This has the
> downside that even within the scope of the contract we may end up with
> divergent behaviour, and also new functionality in the kernel may not be
> available without the bootloader also being updated.
>
> 2) Modify the boot stub such that it can be provided with a callback,
> and instead of jumping to the kernel it can jump to the callback. The
> boot flow would then involve the boot loader setting up the launch
> environment, calling the boot stub code, and then performing the DRTM
> event. This avoids requiring an explicit contract (the boot stub would
> remain part of the kernel image and would be updated in lockstep).
>
> One complexity for both approaches is that the secure launch environment
> needs to be aware of all security-critical state in the system. The
> firmware nominally exposes that information for everything it's aware
> of that's security-critical, but the boot stub may have performed
> security-critical actions or exposed security-critical state that the
> firmware is unaware of. The secure launch code from Trenchboot has to be
> aware of this in order to ensure it's measured.
>
> If there's a contract, then in theory this would be embodied in the
> contract and when the contract is updated the secure launch code could
> also be updated. If there's no contract, every change to the boot stub
> would need to be examined and the secure launch code updated if
> necessary.
>
> While the secure launch code is currently out of tree, the goal is for
> it to be integrated into the kernel tree. My feeling is that it's
> going to be easier to manage this if everything is in tree - ie, all the
> EFI setup code that does anything security-critical is either in the
> firmware (and so the firmware takes responsibility for exposing it) or
> is in the Linux tree (and so we take responsibility for updating the
> secure launch code whenever something relevant changes in the boot
> stub). But this requires support from the EFI maintainers in terms of
> not merging things until we've established whether updates are required
> to the secure launch code. The alternative is effectively the same,
> except it would require updating the contract instead.
>
> But, as mentioned, that's just my feeling - I know that Daniel feels
> that the contract approach is preferable. So:
>
> 1) From an EFI maintainer perspective, is making the contract between
> the boot stub and the kernel explicit viable?
>
No. The direction of travel has been to define EFI boot only in terms
of the handover from the loader to the stub. What happens next is up
to the architecture, and is deliberately not specified, because it is
considered to be internal Linux ABI. We've deviated from this once for
Xen on ARM, but this means we have already painted ourselves into a
corner when it comes the way we use DT internally at the handover
point between stub and kernel proper, and I am not eager to repeat
that. Locking down the stub-to-kernel protocol for all architectures
is not the way to go.
> 2) If so, is it desirable?
>
> 3) If either (1) or (2) is "no", is it reasonable to ensure that all
> potentially security-critical state or configuration changes to the
> boot stub are reviewed by DRTM people to verify whether the secure
> launch code needs to be updated to match?
Wouldn't it be better for the secure launch kernel to boot the EFI
entrypoint directly? As it happens, I just completed a PoC last week
for a minimal implementation of EFI (in Rust) that only carries the
pieces that the EFI stub needs to boot Linux. It is currently just a
proof of concept that only works on QEMU/arm64, but it should not be
too hard to adapt it for x86 and for booting a kernel that has already
been loaded to memory.
[0] https://github.com/ardbiesheuvel/efilite
On Wed, 30 Mar 2022 at 09:27, Matthew Garrett <[email protected]> wrote:
>
> On Wed, Mar 30, 2022 at 09:23:17AM +0200, Ard Biesheuvel wrote:
> > On Wed, 30 Mar 2022 at 09:19, Matthew Garrett <[email protected]> wrote:
> > > From a conceptual perspective we've thought of the EFI stub as being
> > > logically part of the bootloader rather than the early kernel, and the
> > > bootloader is a point where the line is drawn. My guy feeling is that
> > > jumping into the secure kernel environment before EBS has been called is
> > > likely to end badly.
> >
> > If you jump back into the system firmware, sure.
> >
> > But the point I was trying to make is that you can replace that with
> > your own minimal implementation of EFI that just exposes a memory map
> > and some protocols and nothing else, and then the secure launch kernel
> > would be entirely in charge of the execution environment.
>
> We can't just replace system firmware with an imitation of the same -
> for instance, configuring the cold boot prevention memory overwrite
> requires us to pass a variable through to the real firmware, and that's
> something that we do in the stub.
>
But these are exactly the kinds of things the secure launch kernel
wants to be made aware of, no? The secure launch kernel could just
MITM the calls that it chooses to allow, and serve other calls itself.
But more fundamentally, I am failing to see the distinction here
between stub code and other kernel code. Is it related to the exact
moment the secure launch event is triggered?
The way I see it, being able to marshall everything that goes on
between the stub and the secure launch kernel allows the latter to
make an informed decision about how the stub has manipulated the
global system state before triggering the secure launch event at
exitbootservices time.
But perhaps my mental model is simply too inaccurate - it would be
helpful to understand what exactly needs to be locked down, and what
aspects of the system state are of interest for the DRTM measurements.
Greetings Matthew,
First thank you to you and James for taking time out of your busy
schedules to sit down with us and work through all of this.
Hey Ard,
On 3/30/22 03:02, Ard Biesheuvel wrote:>> 1) From an EFI maintainer
perspective, is making the contract between
>> the boot stub and the kernel explicit viable?
>>
>
> No. The direction of travel has been to define EFI boot only in terms
> of the handover from the loader to the stub. What happens next is up
> to the architecture, and is deliberately not specified, because it is
> considered to be internal Linux ABI. We've deviated from this once for
> Xen on ARM, but this means we have already painted ourselves into a
> corner when it comes the way we use DT internally at the handover
> point between stub and kernel proper, and I am not eager to repeat
> that. Locking down the stub-to-kernel protocol for all architectures
> is not the way to go.
To help provide some visual context, for EFI today there is,
bzImage
[EFI boot manager] -> [[efi-stub] -> [setup kernel] -> [main kernel]]
Where the efi-stub is responsible for interacting with firmware to
configure the system, store that configuration for the setup kernel and
the main kernel, and then call EBS before entering the setup kernel.
For Secure Launch the flow (on Intel) is,
CPU instruction bzImage
[preamble] -> [ACM] -> [[sl-stub] -> [setup kernel] -> [main kernel]]
In order to make the CPU instruction call to enter the ACM the system
must be in a very specific quiescent state. This includes but not
exhaustively,
* EBS must have been called
* TPM should have all localities closed
* IOMMU PMRs must be programmed appropriately
* TXT heap space allocated
* TXT heap space populated with config structures
* All APs must be in a specific idle state
* Execution is on the BSP
Carrying all this out is what is considered the DRTM preamble.
This is the wrinkle because the setup kernel and main kernel are both
predicated on the efi-stub and the efi-stub is predicated on running
before EBS. So how can this wrinkle be addressed? The TrenchBoot project
proposed that the information collected by the efi-stub be formally
documented for two reasons, 1. to allow the sl-stub to be aware of what
and where all external data is being injected into the kernel so any
data that may be security critical could be measured, and 2. it would
allow third parties, e.g. GRUB, could correctly configure the system,
pass all EFI related information correctly to the setup kernel and the
main kernel before executing the preamble. Where the former is more of a
concern than enabling the latter.
Relating to what information is security critical, this can be a bit
subjective. For example Dave Weston has a twitter thread[1][2][3] over
what state Azure Attestation can validate for a DRTM Windows system.
This reflects what Microsoft believes it's customers will want to
validate about a Windows system before accessing services and data
stored in Azure. For Linux Secure Launch measuring everything would
obviously provide the finest grain of assertions regarding how the
kernel was configured to run but that comes at the expense that is
incurred for taking the measurements. To date the selection of
measurements have been an attempt of balancing the most meaningful
measurements with how many measurements should be taken. For instance it
would be possible to hash the SRTM (firmware) TPM event log to provide
an assertion of what its contents were at dynamic launch. Is that a
meaningful measurement? Not necessarily since there are other means to
validate the log but there is likely someone who is super cautious and
would like to see the extra layer of validation.
>> 2) If so, is it desirable?
>>
>> 3) If either (1) or (2) is "no", is it reasonable to ensure that all
>> potentially security-critical state or configuration changes to the
>> boot stub are reviewed by DRTM people to verify whether the secure
>> launch code needs to be updated to match?
>
> Wouldn't it be better for the secure launch kernel to boot the EFI
> entrypoint directly? As it happens, I just completed a PoC last week
> for a minimal implementation of EFI (in Rust) that only carries the
> pieces that the EFI stub needs to boot Linux. It is currently just a
> proof of concept that only works on QEMU/arm64, but it should not be
> too hard to adapt it for x86 and for booting a kernel that has already
> been loaded to memory.
IIUC, as you can see above, entering the efi-stub from the dynamic
launch will fail because EBS will have been called.
v/r,
dps
[1] https://twitter.com/dwizzzlemsft/status/1508517758635446273
[2] https://twitter.com/dwizzzlemsft/status/1508602527482146816
[3] https://twitter.com/dwizzzlemsft/status/1508852935261794312
On Wed, 30 Mar 2022 at 09:11, Matthew Garrett <[email protected]> wrote:
>
> On Wed, Mar 30, 2022 at 09:02:18AM +0200, Ard Biesheuvel wrote:
>
> > Wouldn't it be better for the secure launch kernel to boot the EFI
> > entrypoint directly? As it happens, I just completed a PoC last week
> > for a minimal implementation of EFI (in Rust) that only carries the
> > pieces that the EFI stub needs to boot Linux. It is currently just a
> > proof of concept that only works on QEMU/arm64, but it should not be
> > too hard to adapt it for x86 and for booting a kernel that has already
> > been loaded to memory.
>
> The EFI stub carries out a bunch of actions that have meaningful
> security impact, and that's material that should be measured. Having the
> secure launch kernel execute the stub without awareness of what it does
> means it would need to measure the code without measuring the state,
> while the goal of DRTM solutions is to measure state rather than the
> code.
But how is that any different from the early kernel code?
On Wed, 2022-03-30 at 09:39 +0200, Ard Biesheuvel wrote:
> On Wed, 30 Mar 2022 at 09:27, Matthew Garrett <[email protected]>
> wrote:
> > On Wed, Mar 30, 2022 at 09:23:17AM +0200, Ard Biesheuvel wrote:
> > > On Wed, 30 Mar 2022 at 09:19, Matthew Garrett <
> > > [email protected]> wrote:
> > > > From a conceptual perspective we've thought of the EFI stub as
> > > > being logically part of the bootloader rather than the early
> > > > kernel, and the bootloader is a point where the line is drawn.
> > > > My guy feeling is that jumping into the secure kernel
> > > > environment before EBS has been called is likely to end badly.
> > >
> > > If you jump back into the system firmware, sure.
> > >
> > > But the point I was trying to make is that you can replace that
> > > with your own minimal implementation of EFI that just exposes a
> > > memory map and some protocols and nothing else, and then the
> > > secure launch kernel would be entirely in charge of the execution
> > > environment.
> >
> > We can't just replace system firmware with an imitation of the same
> > - for instance, configuring the cold boot prevention memory
> > overwrite requires us to pass a variable through to the real
> > firmware, and that's something that we do in the stub.
> >
>
> But these are exactly the kinds of things the secure launch kernel
> wants to be made aware of, no? The secure launch kernel could just
> MITM the calls that it chooses to allow, and serve other calls
> itself.
The problem would become that the MITM firmware has to be evolved in
lockstep with the boot stub. The problem isn't really a point in time,
figure out what config the boot stub extracts from EFI now and measure
it, it's an ongoing one: given an evolving kernel and UEFI subsystem
means that over time what configuration the kernel extracts from EFI
changes, how do we make sure it's all correctly measured before secure
launch?
If the MITM doesn't support a capability a newer kernel acquires, that
MITM must fail secure launch ... which becomes a nightmare for the
user.
One possibility might be that the MITM actually does nothing at all
except record Boot Service requests and responses up to exit boot
services (EBS). We could call that record the boot configuration and
measure it, plus we could then intercept EBS, and do the DRTM secure
launch to the return point. It's conceptually similar Matthew's idea
of a callback except it won't require modification of the boot
parameters.
James
On Wed, Mar 30, 2022 at 09:02:18AM +0200, Ard Biesheuvel wrote:
> Wouldn't it be better for the secure launch kernel to boot the EFI
> entrypoint directly? As it happens, I just completed a PoC last week
> for a minimal implementation of EFI (in Rust) that only carries the
> pieces that the EFI stub needs to boot Linux. It is currently just a
> proof of concept that only works on QEMU/arm64, but it should not be
> too hard to adapt it for x86 and for booting a kernel that has already
> been loaded to memory.
The EFI stub carries out a bunch of actions that have meaningful
security impact, and that's material that should be measured. Having the
secure launch kernel execute the stub without awareness of what it does
means it would need to measure the code without measuring the state,
while the goal of DRTM solutions is to measure state rather than the
code.
On 3/31/22 09:13, Ard Biesheuvel wrote:
> On Thu, 31 Mar 2022 at 02:36, Daniel P. Smith
> <[email protected]> wrote:
>>
>> Greetings Matthew,
>>
>> First thank you to you and James for taking time out of your busy
>> schedules to sit down with us and work through all of this.
>>
>> Hey Ard,
>>
>> On 3/30/22 03:02, Ard Biesheuvel wrote:>> 1) From an EFI maintainer
>> perspective, is making the contract between
>>>> the boot stub and the kernel explicit viable?
>>>>
>>>
>>> No. The direction of travel has been to define EFI boot only in terms
>>> of the handover from the loader to the stub. What happens next is up
>>> to the architecture, and is deliberately not specified, because it is
>>> considered to be internal Linux ABI. We've deviated from this once for
>>> Xen on ARM, but this means we have already painted ourselves into a
>>> corner when it comes the way we use DT internally at the handover
>>> point between stub and kernel proper, and I am not eager to repeat
>>> that. Locking down the stub-to-kernel protocol for all architectures
>>> is not the way to go.
>>
>> To help provide some visual context, for EFI today there is,
>>
>> bzImage
>> [EFI boot manager] -> [[efi-stub] -> [setup kernel] -> [main kernel]]
>>
>> Where the efi-stub is responsible for interacting with firmware to
>> configure the system, store that configuration for the setup kernel and
>> the main kernel, and then call EBS before entering the setup kernel.
>>
>> For Secure Launch the flow (on Intel) is,
>>
>> CPU instruction bzImage
>> [preamble] -> [ACM] -> [[sl-stub] -> [setup kernel] -> [main kernel]]
>>
>> In order to make the CPU instruction call to enter the ACM the system
>> must be in a very specific quiescent state. This includes but not
>> exhaustively,
>> * EBS must have been called
>> * TPM should have all localities closed
>> * IOMMU PMRs must be programmed appropriately
>> * TXT heap space allocated
>> * TXT heap space populated with config structures
>> * All APs must be in a specific idle state
>> * Execution is on the BSP
>> Carrying all this out is what is considered the DRTM preamble.
>>
>
> Thanks for the explanation, this is really helpful.
>
>> This is the wrinkle because the setup kernel and main kernel are both
>> predicated on the efi-stub and the efi-stub is predicated on running
>> before EBS.
>
> Matthew suggested this already, but can you explain why handling this
> in a callback is not an option? I'd by sympathetic to specifying a
The idea of the UEFI specification is that it is OS agnostic. So
anything that is Linux-, Windows-, BSD-, etc. specific should not live
in the UEFI firmware.
If you want to implement any Linux specific extra protocol, you should
implement it in Shim, GRUB, the kernel stub or any other UEFI binary
loaded by the UEFI firmware but, please, don't rely on the UEFI firmware
itself to implement it.
If you are able to abstract the requirements for furthering secure boot
in a way that is OS agnostic, then implementation in the UEFI firmware
starts to make sense. But remember that there is a large installed base
that is still lagging behind the current UEFI standard.
Best regards
Heinrich
> Linux specific protocol that can be grabbed before EBS() but can be
> invoked after (but not, say after SetVirtualAddressMap(), to keep
> things simple). That should allow us to call back into firmware to
> perform the secure launch right before handing over.
>
> My other suggestion, to use a minimal EFI environment just to boot the
> kernel, still seems viable to me as well, but it would boil down to
> mostly the same, thing, i.e., to inject an intermediate boot stage
> between the call to the firmware's EBS() and calling the entrypoint of
> the kernel proper. What I do like about this approach is that the EFI
> stub could execute unprivileged, which means the secure launch kernel
> could track *exactly* what the EFI stub is doing in terms of memory
> accesses and protocol invocations, which seems a bit more robust than
> the approximation of 'this might be interesting enough to measure'
> that the industry seems to have settled on.
>
>> So how can this wrinkle be addressed? The TrenchBoot project
>> proposed that the information collected by the efi-stub be formally
>> documented for two reasons, 1. to allow the sl-stub to be aware of what
>> and where all external data is being injected into the kernel so any
>> data that may be security critical could be measured, and 2. it would
>> allow third parties, e.g. GRUB, could correctly configure the system,
>> pass all EFI related information correctly to the setup kernel and the
>> main kernel before executing the preamble. Where the former is more of a
>> concern than enabling the latter.
>>
>
> The reason I am not willing to lock down the stub<->kernel boot
> protocol is because it doesn't scale: currently, the discussion is
> about x86, which is a bit different because we already so many ways to
> boot it, but for other architectures, this is going to create a huge
> maintenance burden: arm64, RISC-V and now LoongArch are all adding EFI
> boot support and are looking to support ACPI, SMBIOS and other
> features as well, and these are all gated on EFI boot, which requires
> booting via the stub.
>
> I'm not eager to kick this can down the road and go with something
> that inevitably implies either specifying and maintaining a whole
> array of internal protocols as external ABI, or revisiting this
> discussion and coming up with two different ways to do DRTM depending
> on whether you are running x86 or not.
>
>> Relating to what information is security critical, this can be a bit
>> subjective. For example Dave Weston has a twitter thread[1][2][3] over
>> what state Azure Attestation can validate for a DRTM Windows system.
>> This reflects what Microsoft believes it's customers will want to
>> validate about a Windows system before accessing services and data
>> stored in Azure. For Linux Secure Launch measuring everything would
>> obviously provide the finest grain of assertions regarding how the
>> kernel was configured to run but that comes at the expense that is
>> incurred for taking the measurements. To date the selection of
>> measurements have been an attempt of balancing the most meaningful
>> measurements with how many measurements should be taken. For instance it
>> would be possible to hash the SRTM (firmware) TPM event log to provide
>> an assertion of what its contents were at dynamic launch. Is that a
>> meaningful measurement? Not necessarily since there are other means to
>> validate the log but there is likely someone who is super cautious and
>> would like to see the extra layer of validation.
>>
>
> So how will the above translate into meaningful and fair feedback in
> response to proposed changes to this documented stub<->kernel handover
> protocol, once the need arrives to make changes? Is this super
> cautious person going to be the one NAKing everything just because he
> is super cautious?
>
> Pardon the skepticism, but I am really reluctant to let this cat out
> of the bag if the requirements are so vague and there doesn't seem to
> consensus on the scope of DRTM.
>
> Another thing I missed is how these systems are supposed to carry out
> the tasks that the stub currently handles: Matt mentioned setting
> MemoryOverwriteRequest, but there is also TPM event log handling, and
> other bits and pieces. Are you saying this is all going to be part of
> this boot protocol as well?
>
>>>> 2) If so, is it desirable?
>>>>
>>>> 3) If either (1) or (2) is "no", is it reasonable to ensure that all
>>>> potentially security-critical state or configuration changes to the
>>>> boot stub are reviewed by DRTM people to verify whether the secure
>>>> launch code needs to be updated to match?
>>>
>>> Wouldn't it be better for the secure launch kernel to boot the EFI
>>> entrypoint directly? As it happens, I just completed a PoC last week
>>> for a minimal implementation of EFI (in Rust) that only carries the
>>> pieces that the EFI stub needs to boot Linux. It is currently just a
>>> proof of concept that only works on QEMU/arm64, but it should not be
>>> too hard to adapt it for x86 and for booting a kernel that has already
>>> been loaded to memory.
>>
>> IIUC, as you can see above, entering the efi-stub from the dynamic
>> launch will fail because EBS will have been called.
>>
>
> I think you are missing my point here, tbh. What I am suggesting here
> is to run a separate, minimal EFI implementation, which has its own
> EBS() which is unrelated to the firmware one. Matthew pointed out some
> issues with this approach, but the fundamental idea is that it is just
> an impedance matcher that looks like EFI to the EFI stub, but is
> really just a loader with a memory map and some config tables.
>
> The requirement for this came up in the confidential computing space,
> but for bare metal, it seems having a tiny EFI-like shim that can only
> boot a Linux kernel (or other EFI-like payloads with no dependencies
> on the driver model or other UEFI/PI bloat) might be useful here as
> well, especially because it would be completely generic from the EFI
> side of things, as opposed to creating yet another project with
> intimate knowledge of struct bootparams, device trees, where in memory
> the kernel may be loaded on architecture X, where in memory the initrd
> may be loaded on architecture X, etc etc.
>
> So the bottom line is that we will have to make this work with EFI
> boot one way or the other, but skipping the EFI stub altogether is
> really not an option, unless you want to carry the burden of keeping
> your code in sync with the kernel. Locking this down as external ABI
> is not acceptable to me.
>
> Thanks,
> Ard.
>
> _______________________________________________
> Grub-devel mailing list
> [email protected]
> https://lists.gnu.org/mailman/listinfo/grub-devel
On Thu, 31 Mar 2022 at 02:36, Daniel P. Smith
<[email protected]> wrote:
>
> Greetings Matthew,
>
> First thank you to you and James for taking time out of your busy
> schedules to sit down with us and work through all of this.
>
> Hey Ard,
>
> On 3/30/22 03:02, Ard Biesheuvel wrote:>> 1) From an EFI maintainer
> perspective, is making the contract between
> >> the boot stub and the kernel explicit viable?
> >>
> >
> > No. The direction of travel has been to define EFI boot only in terms
> > of the handover from the loader to the stub. What happens next is up
> > to the architecture, and is deliberately not specified, because it is
> > considered to be internal Linux ABI. We've deviated from this once for
> > Xen on ARM, but this means we have already painted ourselves into a
> > corner when it comes the way we use DT internally at the handover
> > point between stub and kernel proper, and I am not eager to repeat
> > that. Locking down the stub-to-kernel protocol for all architectures
> > is not the way to go.
>
> To help provide some visual context, for EFI today there is,
>
> bzImage
> [EFI boot manager] -> [[efi-stub] -> [setup kernel] -> [main kernel]]
>
> Where the efi-stub is responsible for interacting with firmware to
> configure the system, store that configuration for the setup kernel and
> the main kernel, and then call EBS before entering the setup kernel.
>
> For Secure Launch the flow (on Intel) is,
>
> CPU instruction bzImage
> [preamble] -> [ACM] -> [[sl-stub] -> [setup kernel] -> [main kernel]]
>
> In order to make the CPU instruction call to enter the ACM the system
> must be in a very specific quiescent state. This includes but not
> exhaustively,
> * EBS must have been called
> * TPM should have all localities closed
> * IOMMU PMRs must be programmed appropriately
> * TXT heap space allocated
> * TXT heap space populated with config structures
> * All APs must be in a specific idle state
> * Execution is on the BSP
> Carrying all this out is what is considered the DRTM preamble.
>
Thanks for the explanation, this is really helpful.
> This is the wrinkle because the setup kernel and main kernel are both
> predicated on the efi-stub and the efi-stub is predicated on running
> before EBS.
Matthew suggested this already, but can you explain why handling this
in a callback is not an option? I'd by sympathetic to specifying a
Linux specific protocol that can be grabbed before EBS() but can be
invoked after (but not, say after SetVirtualAddressMap(), to keep
things simple). That should allow us to call back into firmware to
perform the secure launch right before handing over.
My other suggestion, to use a minimal EFI environment just to boot the
kernel, still seems viable to me as well, but it would boil down to
mostly the same, thing, i.e., to inject an intermediate boot stage
between the call to the firmware's EBS() and calling the entrypoint of
the kernel proper. What I do like about this approach is that the EFI
stub could execute unprivileged, which means the secure launch kernel
could track *exactly* what the EFI stub is doing in terms of memory
accesses and protocol invocations, which seems a bit more robust than
the approximation of 'this might be interesting enough to measure'
that the industry seems to have settled on.
> So how can this wrinkle be addressed? The TrenchBoot project
> proposed that the information collected by the efi-stub be formally
> documented for two reasons, 1. to allow the sl-stub to be aware of what
> and where all external data is being injected into the kernel so any
> data that may be security critical could be measured, and 2. it would
> allow third parties, e.g. GRUB, could correctly configure the system,
> pass all EFI related information correctly to the setup kernel and the
> main kernel before executing the preamble. Where the former is more of a
> concern than enabling the latter.
>
The reason I am not willing to lock down the stub<->kernel boot
protocol is because it doesn't scale: currently, the discussion is
about x86, which is a bit different because we already so many ways to
boot it, but for other architectures, this is going to create a huge
maintenance burden: arm64, RISC-V and now LoongArch are all adding EFI
boot support and are looking to support ACPI, SMBIOS and other
features as well, and these are all gated on EFI boot, which requires
booting via the stub.
I'm not eager to kick this can down the road and go with something
that inevitably implies either specifying and maintaining a whole
array of internal protocols as external ABI, or revisiting this
discussion and coming up with two different ways to do DRTM depending
on whether you are running x86 or not.
> Relating to what information is security critical, this can be a bit
> subjective. For example Dave Weston has a twitter thread[1][2][3] over
> what state Azure Attestation can validate for a DRTM Windows system.
> This reflects what Microsoft believes it's customers will want to
> validate about a Windows system before accessing services and data
> stored in Azure. For Linux Secure Launch measuring everything would
> obviously provide the finest grain of assertions regarding how the
> kernel was configured to run but that comes at the expense that is
> incurred for taking the measurements. To date the selection of
> measurements have been an attempt of balancing the most meaningful
> measurements with how many measurements should be taken. For instance it
> would be possible to hash the SRTM (firmware) TPM event log to provide
> an assertion of what its contents were at dynamic launch. Is that a
> meaningful measurement? Not necessarily since there are other means to
> validate the log but there is likely someone who is super cautious and
> would like to see the extra layer of validation.
>
So how will the above translate into meaningful and fair feedback in
response to proposed changes to this documented stub<->kernel handover
protocol, once the need arrives to make changes? Is this super
cautious person going to be the one NAKing everything just because he
is super cautious?
Pardon the skepticism, but I am really reluctant to let this cat out
of the bag if the requirements are so vague and there doesn't seem to
consensus on the scope of DRTM.
Another thing I missed is how these systems are supposed to carry out
the tasks that the stub currently handles: Matt mentioned setting
MemoryOverwriteRequest, but there is also TPM event log handling, and
other bits and pieces. Are you saying this is all going to be part of
this boot protocol as well?
> >> 2) If so, is it desirable?
> >>
> >> 3) If either (1) or (2) is "no", is it reasonable to ensure that all
> >> potentially security-critical state or configuration changes to the
> >> boot stub are reviewed by DRTM people to verify whether the secure
> >> launch code needs to be updated to match?
> >
> > Wouldn't it be better for the secure launch kernel to boot the EFI
> > entrypoint directly? As it happens, I just completed a PoC last week
> > for a minimal implementation of EFI (in Rust) that only carries the
> > pieces that the EFI stub needs to boot Linux. It is currently just a
> > proof of concept that only works on QEMU/arm64, but it should not be
> > too hard to adapt it for x86 and for booting a kernel that has already
> > been loaded to memory.
>
> IIUC, as you can see above, entering the efi-stub from the dynamic
> launch will fail because EBS will have been called.
>
I think you are missing my point here, tbh. What I am suggesting here
is to run a separate, minimal EFI implementation, which has its own
EBS() which is unrelated to the firmware one. Matthew pointed out some
issues with this approach, but the fundamental idea is that it is just
an impedance matcher that looks like EFI to the EFI stub, but is
really just a loader with a memory map and some config tables.
The requirement for this came up in the confidential computing space,
but for bare metal, it seems having a tiny EFI-like shim that can only
boot a Linux kernel (or other EFI-like payloads with no dependencies
on the driver model or other UEFI/PI bloat) might be useful here as
well, especially because it would be completely generic from the EFI
side of things, as opposed to creating yet another project with
intimate knowledge of struct bootparams, device trees, where in memory
the kernel may be loaded on architecture X, where in memory the initrd
may be loaded on architecture X, etc etc.
So the bottom line is that we will have to make this work with EFI
boot one way or the other, but skipping the EFI stub altogether is
really not an option, unless you want to carry the burden of keeping
your code in sync with the kernel. Locking this down as external ABI
is not acceptable to me.
Thanks,
Ard.
Hey Ard,
Apologies for the lag in response, I wanted to have this to you sooner,
but between a variety of events and working on building consensus on how
to address your comments made it drag out a little. Before reading this
message, I would recommend reading the proposal posted to the top of
this thread, as it details an approach that builds on Matthew's callback
proposal along with addressing your concerns with measurements. In this
message, I want to provide you direct answers to the points you raised
independent of the reply at the top of this thread to help map where
your concerns influenced the proposal.
On 3/31/22 03:13, Ard Biesheuvel wrote:
> On Thu, 31 Mar 2022 at 02:36, Daniel P. Smith
> <[email protected]> wrote:
>>
>> Greetings Matthew,
>>
>> First thank you to you and James for taking time out of your busy
>> schedules to sit down with us and work through all of this.
>>
>> Hey Ard,
>>
>> On 3/30/22 03:02, Ard Biesheuvel wrote:>> 1) From an EFI maintainer
>> perspective, is making the contract between
>>>> the boot stub and the kernel explicit viable?
>>>>
>>>
>>> No. The direction of travel has been to define EFI boot only in terms
>>> of the handover from the loader to the stub. What happens next is up
>>> to the architecture, and is deliberately not specified, because it is
>>> considered to be internal Linux ABI. We've deviated from this once for
>>> Xen on ARM, but this means we have already painted ourselves into a
>>> corner when it comes the way we use DT internally at the handover
>>> point between stub and kernel proper, and I am not eager to repeat
>>> that. Locking down the stub-to-kernel protocol for all architectures
>>> is not the way to go.
>>
>> To help provide some visual context, for EFI today there is,
>>
>> bzImage
>> [EFI boot manager] -> [[efi-stub] -> [setup kernel] -> [main kernel]]
>>
>> Where the efi-stub is responsible for interacting with firmware to
>> configure the system, store that configuration for the setup kernel and
>> the main kernel, and then call EBS before entering the setup kernel.
>>
>> For Secure Launch the flow (on Intel) is,
>>
>> CPU instruction bzImage
>> [preamble] -> [ACM] -> [[sl-stub] -> [setup kernel] -> [main kernel]]
>>
>> In order to make the CPU instruction call to enter the ACM the system
>> must be in a very specific quiescent state. This includes but not
>> exhaustively,
>> * EBS must have been called
>> * TPM should have all localities closed
>> * IOMMU PMRs must be programmed appropriately
>> * TXT heap space allocated
>> * TXT heap space populated with config structures
>> * All APs must be in a specific idle state
>> * Execution is on the BSP
>> Carrying all this out is what is considered the DRTM preamble.
>>
>
> Thanks for the explanation, this is really helpful.
Your welcome.
>> This is the wrinkle because the setup kernel and main kernel are both
>> predicated on the efi-stub and the efi-stub is predicated on running
>> before EBS.
>
> Matthew suggested this already, but can you explain why handling this
> in a callback is not an option? I'd by sympathetic to specifying a
> Linux specific protocol that can be grabbed before EBS() but can be
> invoked after (but not, say after SetVirtualAddressMap(), to keep
> things simple). That should allow us to call back into firmware to
> perform the secure launch right before handing over.
Apologies, I was not meaning to suggest this was not an option. As you
can see in the proposal posted, this approach is in fact being embraced.
It is not explicit stated in the proposal, but the approach for the
Secure Launch spec is to not explicitly dictate the location of the DL
Handler. If a firmware manufacturer wants to implement a Secure Launch
compliant DL Handler in firmware, this certainly would be welcomed, but
should not be a requirement to enable Secure Launch. For instance, in
the prototype the DL Handler is actually implemented as a stub in the
setup kernel as that is the direction we are moving towards but may not
be how the final implementation works.
> My other suggestion, to use a minimal EFI environment just to boot the
> kernel, still seems viable to me as well, but it would boil down to
> mostly the same, thing, i.e., to inject an intermediate boot stage
> between the call to the firmware's EBS() and calling the entrypoint of
> the kernel proper. What I do like about this approach is that the EFI
> stub could execute unprivileged, which means the secure launch kernel
> could track *exactly* what the EFI stub is doing in terms of memory
> accesses and protocol invocations, which seems a bit more robust than
> the approximation of 'this might be interesting enough to measure'
> that the industry seems to have settled on.
IMHO that is the beauty of the Secure Launch spec. Just as you suggest,
your EFI environment shim could track what the EFI stub does and record
it in the SLRT. In addition, your shim could also implement the DL
Handler to invoke the Dynamic Launch.
>> So how can this wrinkle be addressed? The TrenchBoot project
>> proposed that the information collected by the efi-stub be formally
>> documented for two reasons, 1. to allow the sl-stub to be aware of what
>> and where all external data is being injected into the kernel so any
>> data that may be security critical could be measured, and 2. it would
>> allow third parties, e.g. GRUB, could correctly configure the system,
>> pass all EFI related information correctly to the setup kernel and the
>> main kernel before executing the preamble. Where the former is more of a
>> concern than enabling the latter.
>>
>
> The reason I am not willing to lock down the stub<->kernel boot
> protocol is because it doesn't scale: currently, the discussion is
> about x86, which is a bit different because we already so many ways to
> boot it, but for other architectures, this is going to create a huge
> maintenance burden: arm64, RISC-V and now LoongArch are all adding EFI
> boot support and are looking to support ACPI, SMBIOS and other
> features as well, and these are all gated on EFI boot, which requires
> booting via the stub.
As I mentioned in the Secure Launch spec proposal, it was not correct
for us to seek that the efi-stub<->kernel interface to be standardized.
The reality is that Secure Launch is an entrypoint itself and like the
efi-stub should provide an interface specifying how and what needs to be
provided to it for it to function correctly.
> I'm not eager to kick this can down the road and go with something
> that inevitably implies either specifying and maintaining a whole
> array of internal protocols as external ABI, or revisiting this
> discussion and coming up with two different ways to do DRTM depending
> on whether you are running x86 or not.
Agreed, which is why we went back and worked on what is the proper way
to address this problem. As has been mentioned many times, while x86 may
have the most mature Dynamic Launch capability, it is not the only
platform with Dynamic Launch. The goal for TrenchBoot is to provide a
common experience, to the extent possible, for using Dynamic Launch
across the different platforms that provide the capability. And to be
clear, that is especially true for different environments on the same
architecture. Specifically, we want setup and configuration to be the
same on x86 coreboot and x86 UEFI.
>> Relating to what information is security critical, this can be a bit
>> subjective. For example Dave Weston has a twitter thread[1][2][3] over
>> what state Azure Attestation can validate for a DRTM Windows system.
>> This reflects what Microsoft believes it's customers will want to
>> validate about a Windows system before accessing services and data
>> stored in Azure. For Linux Secure Launch measuring everything would
>> obviously provide the finest grain of assertions regarding how the
>> kernel was configured to run but that comes at the expense that is
>> incurred for taking the measurements. To date the selection of
>> measurements have been an attempt of balancing the most meaningful
>> measurements with how many measurements should be taken. For instance it
>> would be possible to hash the SRTM (firmware) TPM event log to provide
>> an assertion of what its contents were at dynamic launch. Is that a
>> meaningful measurement? Not necessarily since there are other means to
>> validate the log but there is likely someone who is super cautious and
>> would like to see the extra layer of validation.
>>
>
> So how will the above translate into meaningful and fair feedback in
> response to proposed changes to this documented stub<->kernel handover
> protocol, once the need arrives to make changes? Is this super
> cautious person going to be the one NAKing everything just because he
> is super cautious?
There is only a mentioning of it in the proposal, but for the Secure
Launch specification there will be a policy entry that will remove the
need for having what will be measured codified in the kernel. It will
allow measurement mechanisms to be implemented in the sl-stub and the
policy will allow the selection and configuration of the mechanisms.
> Pardon the skepticism, but I am really reluctant to let this cat out
> of the bag if the requirements are so vague and there doesn't seem to
> consensus on the scope of DRTM.
I would say the scope is no less vague than it is for efi-stub. UEFI and
kernel features will increase that will change the behavior of the
kernel and affect its ability to protect information within the system.
As this changes, DRTM will need to be able to measure this expansion so
that it may be able to assert the system state/abilities to a user, a
cloud or an enterprise.
> Another thing I missed is how these systems are supposed to carry out
> the tasks that the stub currently handles: Matt mentioned setting
> MemoryOverwriteRequest, but there is also TPM event log handling, and
> other bits and pieces. Are you saying this is all going to be part of
> this boot protocol as well?
This is no longer an issue with the new proposal.
>>>> 2) If so, is it desirable?
>>>>
>>>> 3) If either (1) or (2) is "no", is it reasonable to ensure that all
>>>> potentially security-critical state or configuration changes to the
>>>> boot stub are reviewed by DRTM people to verify whether the secure
>>>> launch code needs to be updated to match?
>>>
>>> Wouldn't it be better for the secure launch kernel to boot the EFI
>>> entrypoint directly? As it happens, I just completed a PoC last week
>>> for a minimal implementation of EFI (in Rust) that only carries the
>>> pieces that the EFI stub needs to boot Linux. It is currently just a
>>> proof of concept that only works on QEMU/arm64, but it should not be
>>> too hard to adapt it for x86 and for booting a kernel that has already
>>> been loaded to memory.
>>
>> IIUC, as you can see above, entering the efi-stub from the dynamic
>> launch will fail because EBS will have been called.
>>
>
> I think you are missing my point here, tbh. What I am suggesting here
> is to run a separate, minimal EFI implementation, which has its own
> EBS() which is unrelated to the firmware one. Matthew pointed out some
> issues with this approach, but the fundamental idea is that it is just
> an impedance matcher that looks like EFI to the EFI stub, but is
> really just a loader with a memory map and some config tables.
I apologize, but I read "Wouldn't it be better for the secure launch
kernel to boot the EFI entrypoint directly?" to mean that you would be
looking for EFI entrypoint to be called by the Dyanmic Launch. If that
is the case, then again I am not sure how you would make this work as is
suggested.
Let me clarify a little further on how Dynamic Launch hardware works.
When the Dynamic Launch CPU instruction is called by the preamble, the
system enters a new type of execution state, on Intel it is literally a
separate CPU mode referred to as SMX. A very simplistic way to think of
this is that the system has gone through a soft warm boot, but
everything is now different. Instead of coming in through the reset
vector, the system will jump to the DLME entrypoint that was registered
during the preamble. There will be DMA protections in place protecting
the regions specified during the preamble, and the CPU will function in
a slightly different manner. For instance the AP rendezvous procedure
has to be done differently, if a standard INIT-SIPI-SIPI rendezvous is
attempted the system will fault. In the end, this is done to ensure to
the best ability that the system is in a proper state and the only
software executing is that which was measured by the CPU. It is a bit
impressive what the CPU does, and for Intel CPUs there is a fair amount
of detail documented under the SDM documentation for GETSEC[SENTER] [1].
This is one of the reasons there is a fair bit of assembly in the secure
launch patch series, as there is a very specific way in which the system
needs to be brought up from the minimal state it is left in by the
GETSEC[SENTER] instruction to a state that the setup kernel is able to
take control.
This might be made to work by making this EFI shim capable of being
entered by the Dynamic Launch and then call into the efi-stub. But tbh
this is a non-starter from our perspective as this would then force all
x86 environments to run this EFI shim, specifically coreboot
environments. Just as Linux-EFI is not being pushed to work like a
non-efi environment for Dynamic Launch, it would not be fair to force
non-EFI environments to function like an EFI environment.
As suggested above, under the Secure Launch spec proposal, the EFI shim
would work very well as a preamble environment that implements the
Secure Launch spec.
[1] https://github.com/HJLebbink/asm-dude/wiki/GETSEC%5BSENTER%5D
> The requirement for this came up in the confidential computing space,
> but for bare metal, it seems having a tiny EFI-like shim that can only
> boot a Linux kernel (or other EFI-like payloads with no dependencies
> on the driver model or other UEFI/PI bloat) might be useful here as
> well, especially because it would be completely generic from the EFI
> side of things, as opposed to creating yet another project with
> intimate knowledge of struct bootparams, device trees, where in memory
> the kernel may be loaded on architecture X, where in memory the initrd
> may be loaded on architecture X, etc etc.
>
> So the bottom line is that we will have to make this work with EFI
> boot one way or the other, but skipping the EFI stub altogether is
> really not an option, unless you want to carry the burden of keeping
> your code in sync with the kernel. Locking this down as external ABI
> is not acceptable to me.
Agreed, which is why just as efi-stub has its entry interface that every
bootmanager/bootloader must implement, the sl-stub is an entrypoint that
will implement the Secure Launch specification for how it should be
entered, whether that is by efi-stub or an EFI shim underneath efi-stub.
V/r,
Daniel P. Smith
Greetings,
Based on the discussions that occurred in this thread, there seems to be
two issues at hand that should be decoupled, as their solutions can and
should be implemented independently. These are:
- the handling of the Dynamic Launch preamble
- providing the complete kernel configuration for measurement
For the former, it is believed there is a consensus that Matthew's
proposed callback approach would be the preferred method. Through some
contemplating and prototyping, the determination is that this will in
fact be an approach that will ultimately benefit the TrenchBoot project
itself.
In general, the preamble consists of two activities: 1. preparing the
contents in memory and 2. preparing the hardware in order to call the
Dynamic Launch instruction. In past implementations, these two
activities were conducted sequentially, but in reality the time delta
between the two may be arbitrary. Introducing this separation does not
introduce any security concerns due to how the Dynamic Launch works. Any
tampering of the contents in memory will either cause the Dynamic Launch
to fail or result in a detectable difference in the Dynamic Launch
measurement chain.
In order to separate the hardware interactions into what will be called
the DLE Handler, this will require a collection of information regarding
how the environment is set up. When working through what would be
required, this led to the realization that this really should be
generalized into a formal specification for TrenchBoot's Secure Launch.
This will enable a reusable solution for the TrenchBoot project, versus
implementing a one-off solution for Linux. A prototype of is near
completion, for which below is a visual depiction along with a
step-by-step walk through of how it would work for efi-stub.
Secure Launch Flow:
+-----------------+
| |
+-------------->| Secure Launch +---------------+
| | Resource Table | |
| | | +------|---------------+
| +--------+--------+ | | DLME |
| | | v |
| | | +---------------+ |
+-----+---------+ v | | | |
+--+-------------+ | +-------------+ | | Secure Launch | |
| | +------>| +------->| Entry | |
| Bootloader(s) | | | DLE Handler | | | | |
| +-+ | | | +---------------+ |
+----------------+ +-------------+ +----------------------+
A quick note on the flow diagram, for simplicity all entities prior to
the DLE Handler are represented by the "Bootloader(s)" block due to the
fact that what entities are involved can and will vary. This is where
both GRUB and efi-stub are being represented even though for Linux EFI,
GRUB is considered the bootmanager while efi-stub is the bootloader.
An efi-stub walk-thru:
1. - GRUB
1.1 - GRUB will initialize the Secure Launch Resource Table (SLRT)
1.2 - GRUB will set up DLE Handler and register it in SLRT
1.5 - GRUB will load Linux kernel
1.3 - GRUB will set up DL environment appropriately for HW platform
1.4 - GRUB will record DL setup in SLRT
1.5 - GRUB will record SLRT location in platform's DL config structure
1.5 - GRUB will register SLRT in EFI configuration table under SL GUID
1.6 - GRUB will invoke efi-stub
2. - efi-stub
2.1 - efi-stub will check if SL GUID is in EFI configuration table
2.2 - for each efi-stub config action, an SLRT EFI config event will be
recorded
2.3 - efi-stub calls EBS() then jumps to DLE Handler registered in SLRT
while passing the SLRT address
3. - DL Handler
3.1 - DL Handler will retrieve SL Entry from SLRT
3.2 - DL Handler will prepare HW for calling DL CPU instruction
3.3 - DL Handler will execute DL CPU instruction
4. SL Entry
4.1 SL Entry will retrieve SLRT address from platform's DL config struct
4.2 SL Entry will use policy in SLRT to determine what to measure
4.3 SL Entry will set up HW to what Linux expects
4.4 SL Entry will jump into Linux setup kernel
4.5 SL Entry will record measurements into TPM prior to init process
starting
While Matthew's original proposal was around having a location in the
efi-stub for the callback to be registered, it is felt that it would be
better suited as part of the Secure Launch specification. What is
proposed is for the address of the DL Handler to be stored in the SLRT,
details for the SLRT are below. Then the bootloader that is responsible
for loading the DL Handler will register the SLRT in the EFI
configuration table. Checking for the SLRT GUID in the EFI configuration
table will enable the EFI bootoader responsible for calling EBS, in this
case efi-stub, to know that a Dynamic Launch has been requested. It also
seems this would be more in line with how EFI tends to work, versus a
Linux-specific callback boot param or something similar.
Hopefully this resolves the first of the two issues mentioned at the
beginning of this email in a manner that addresses most of the concerns
raised in the earlier discussions. This leaves the second issue over how
to get an accurate measurement of how the kernel was configured by
efi-stub. When reviewing the comments in the discussion, it was realized
the originally requested approach was in fact in reverse. Instead of
asking for efi-stub's internal API/ABI to be documented, Secure Launch
should specify an ABI for how any bootloader should be invoking a Secure
Launch entrypoint, particularly capturing how an EFI bootloader
configured the environment. This is the second motivation for devising
the SLRT. Specifying this ABI also provided the opportunity to
incorporate a measurement policy and thus allowing for it to be
separated away from sl-stub, as it is in the current implementation. For
this discussion the focus will be on the portions of the SLRT relating
to EFI Environments and in particular the EFI config event record
mentioned in step 2.2 of the efi-stub walk-thru.
First, a short review of what the Secure Launch Resource Table is and
its purpose. The SLRT is to provide a platform and kernel agnostic
configuration table of the meta-data pertinent to the Secure Launch
entry points for the variety of kernels the TrenchBoot project will be
seeking to support. The specification for the table is in progress, but
the consensus is that it will consist of a header structure followed by
a packed series of TLV records. The specification will describe the
various types of records, but the ones of interests in this discussion
are those that efi-stub would use to record how it configured the
environment.
The initially proposed TLV record, see below, for EFI configuration
information was devised around allowing an EFI bootloader to save
multiple config events under a single TLV record. In discussions on the
specification thus far, there are questions if it would be better to
have a TLV record for each config event or the proposed multiple events
per TLV record. It is worth noting that an assumption is being made in
the proposed record. The assumption is that a config event will either
be setting a configuration value between 1 and 8 bytes, or it will be a
data blob for which the address and size will be recorded. The question
is whether that covers all actions the efi-stub does or expects that it
will have to do in the near future.
struct slrt_entry_efi_config_event {
struct slrt_entry_hdr hdr;
uint32_t identifier; /* EFI bootloader ID */
uint16_t reserved;
uint16_t nr_entries; /* Num cfg records */
struct efi_cfg_value values[0]; /* Array of cfg values */
};
struct efi_cfg_value {
uint64_t data; /* cfg data (address or value) */
uint32_t size; /* data size if data is an addr */
uint32_t flags; /* 1L<0 IS_ADDR: data is an addr */
char evt_info[8]; /* event info str for TPM event log */
};
Hopefully the general approach here is agreeable, as IMHO it does
provide a fairly elegant approach to resolving the issues at hand.
Details can always be negotiated to address various implementation
concerns. Provided this is acceptable, then everyone here is welcome to
provide input on the Secure Launch specification, link forthcoming.
V/r,
Daniel P. Smith
Apertus Solutions, LLC
On Thu, 19 May 2022 at 22:59, Daniel P. Smith
<[email protected]> wrote:
>
>
> Greetings,
>
> Based on the discussions that occurred in this thread, there seems to be
> two issues at hand that should be decoupled, as their solutions can and
> should be implemented independently. These are:
> - the handling of the Dynamic Launch preamble
> - providing the complete kernel configuration for measurement
>
> For the former, it is believed there is a consensus that Matthew's
> proposed callback approach would be the preferred method. Through some
> contemplating and prototyping, the determination is that this will in
> fact be an approach that will ultimately benefit the TrenchBoot project
> itself.
>
> In general, the preamble consists of two activities: 1. preparing the
> contents in memory and 2. preparing the hardware in order to call the
> Dynamic Launch instruction. In past implementations, these two
> activities were conducted sequentially, but in reality the time delta
> between the two may be arbitrary. Introducing this separation does not
> introduce any security concerns due to how the Dynamic Launch works. Any
> tampering of the contents in memory will either cause the Dynamic Launch
> to fail or result in a detectable difference in the Dynamic Launch
> measurement chain.
>
> In order to separate the hardware interactions into what will be called
> the DLE Handler, this will require a collection of information regarding
> how the environment is set up. When working through what would be
> required, this led to the realization that this really should be
> generalized into a formal specification for TrenchBoot's Secure Launch.
> This will enable a reusable solution for the TrenchBoot project, versus
> implementing a one-off solution for Linux. A prototype of is near
> completion, for which below is a visual depiction along with a
> step-by-step walk through of how it would work for efi-stub.
>
> Secure Launch Flow:
>
> +-----------------+
> | |
> +-------------->| Secure Launch +---------------+
> | | Resource Table | |
> | | | +------|---------------+
> | +--------+--------+ | | DLME |
> | | | v |
> | | | +---------------+ |
> +-----+---------+ v | | | |
> +--+-------------+ | +-------------+ | | Secure Launch | |
> | | +------>| +------->| Entry | |
> | Bootloader(s) | | | DLE Handler | | | | |
> | +-+ | | | +---------------+ |
> +----------------+ +-------------+ +----------------------+
>
> A quick note on the flow diagram, for simplicity all entities prior to
> the DLE Handler are represented by the "Bootloader(s)" block due to the
> fact that what entities are involved can and will vary. This is where
> both GRUB and efi-stub are being represented even though for Linux EFI,
> GRUB is considered the bootmanager while efi-stub is the bootloader.
>
> An efi-stub walk-thru:
>
> 1. - GRUB
> 1.1 - GRUB will initialize the Secure Launch Resource Table (SLRT)
> 1.2 - GRUB will set up DLE Handler and register it in SLRT
> 1.5 - GRUB will load Linux kernel
> 1.3 - GRUB will set up DL environment appropriately for HW platform
> 1.4 - GRUB will record DL setup in SLRT
> 1.5 - GRUB will record SLRT location in platform's DL config structure
> 1.5 - GRUB will register SLRT in EFI configuration table under SL GUID
> 1.6 - GRUB will invoke efi-stub
>
> 2. - efi-stub
> 2.1 - efi-stub will check if SL GUID is in EFI configuration table
> 2.2 - for each efi-stub config action, an SLRT EFI config event will be
> recorded
> 2.3 - efi-stub calls EBS() then jumps to DLE Handler registered in SLRT
> while passing the SLRT address
>
> 3. - DL Handler
> 3.1 - DL Handler will retrieve SL Entry from SLRT
> 3.2 - DL Handler will prepare HW for calling DL CPU instruction
> 3.3 - DL Handler will execute DL CPU instruction
>
> 4. SL Entry
> 4.1 SL Entry will retrieve SLRT address from platform's DL config struct
> 4.2 SL Entry will use policy in SLRT to determine what to measure
> 4.3 SL Entry will set up HW to what Linux expects
> 4.4 SL Entry will jump into Linux setup kernel
> 4.5 SL Entry will record measurements into TPM prior to init process
> starting
>
> While Matthew's original proposal was around having a location in the
> efi-stub for the callback to be registered, it is felt that it would be
> better suited as part of the Secure Launch specification. What is
> proposed is for the address of the DL Handler to be stored in the SLRT,
> details for the SLRT are below. Then the bootloader that is responsible
> for loading the DL Handler will register the SLRT in the EFI
> configuration table. Checking for the SLRT GUID in the EFI configuration
> table will enable the EFI bootoader responsible for calling EBS, in this
> case efi-stub, to know that a Dynamic Launch has been requested. It also
> seems this would be more in line with how EFI tends to work, versus a
> Linux-specific callback boot param or something similar.
>
This all looks reasonable but it is not clear to me what a 'Linux
setup kernel' is, and what the boot protocol is for that handover.
The EFI stub to core kernel handover ABI is private to Linux,
architecture specific, and subject to change. This is basically the
point I made before: if you want to boot Linux in EFI mode, you have
to go via the EFI stub, and the EFI stub is in charge of booting the
kernel proper. This is why I (we?) suggested some kind of callback
mechanism, where the EFI stub makes a D-RTM specific call after EBS(),
but does regain control over the boot flow.
If we add another entry point into the kernel proper for the Secure
Launch Entry component to use, we are again exposing an internal ABI
in a way that limits our future ability to make changes to the EFI <->
kernel handover.
> Hopefully this resolves the first of the two issues mentioned at the
> beginning of this email in a manner that addresses most of the concerns
> raised in the earlier discussions. This leaves the second issue over how
> to get an accurate measurement of how the kernel was configured by
> efi-stub. When reviewing the comments in the discussion, it was realized
> the originally requested approach was in fact in reverse. Instead of
> asking for efi-stub's internal API/ABI to be documented, Secure Launch
> should specify an ABI for how any bootloader should be invoking a Secure
> Launch entrypoint, particularly capturing how an EFI bootloader
> configured the environment. This is the second motivation for devising
> the SLRT. Specifying this ABI also provided the opportunity to
> incorporate a measurement policy and thus allowing for it to be
> separated away from sl-stub, as it is in the current implementation. For
> this discussion the focus will be on the portions of the SLRT relating
> to EFI Environments and in particular the EFI config event record
> mentioned in step 2.2 of the efi-stub walk-thru.
>
> First, a short review of what the Secure Launch Resource Table is and
> its purpose. The SLRT is to provide a platform and kernel agnostic
> configuration table of the meta-data pertinent to the Secure Launch
> entry points for the variety of kernels the TrenchBoot project will be
> seeking to support. The specification for the table is in progress, but
> the consensus is that it will consist of a header structure followed by
> a packed series of TLV records. The specification will describe the
> various types of records, but the ones of interests in this discussion
> are those that efi-stub would use to record how it configured the
> environment.
>
> The initially proposed TLV record, see below, for EFI configuration
> information was devised around allowing an EFI bootloader to save
> multiple config events under a single TLV record. In discussions on the
> specification thus far, there are questions if it would be better to
> have a TLV record for each config event or the proposed multiple events
> per TLV record. It is worth noting that an assumption is being made in
> the proposed record. The assumption is that a config event will either
> be setting a configuration value between 1 and 8 bytes, or it will be a
> data blob for which the address and size will be recorded. The question
> is whether that covers all actions the efi-stub does or expects that it
> will have to do in the near future.
>
> struct slrt_entry_efi_config_event {
> struct slrt_entry_hdr hdr;
> uint32_t identifier; /* EFI bootloader ID */
> uint16_t reserved;
> uint16_t nr_entries; /* Num cfg records */
> struct efi_cfg_value values[0]; /* Array of cfg values */
> };
>
> struct efi_cfg_value {
> uint64_t data; /* cfg data (address or value) */
> uint32_t size; /* data size if data is an addr */
> uint32_t flags; /* 1L<0 IS_ADDR: data is an addr */
> char evt_info[8]; /* event info str for TPM event log */
> };
>
> Hopefully the general approach here is agreeable, as IMHO it does
> provide a fairly elegant approach to resolving the issues at hand.
> Details can always be negotiated to address various implementation
> concerns. Provided this is acceptable, then everyone here is welcome to
> provide input on the Secure Launch specification, link forthcoming.
>
Given that this is EFI, I would expect all these implementation
details to be exposed via a protocol that the stub can invoke, in a
way that will likely be similar (or the same?) as the TCG protocol
used for recording PCR measurements.
So could you elaborate on the types of actions? Is this simply things
like the command line, initrd contents, initrd load address, kernel
load address etc etc? There isn't generally that much going on in the
stub beyond that.
On 6/10/22 12:40, Ard Biesheuvel wrote:> On Thu, 19 May 2022 at 22:59,
Daniel P. Smith
> <[email protected]> wrote:
>>
>>
>> Greetings,
>>
<snip/>
>> While Matthew's original proposal was around having a location in the
>> efi-stub for the callback to be registered, it is felt that it would be
>> better suited as part of the Secure Launch specification. What is
>> proposed is for the address of the DL Handler to be stored in the SLRT,
>> details for the SLRT are below. Then the bootloader that is responsible
>> for loading the DL Handler will register the SLRT in the EFI
>> configuration table. Checking for the SLRT GUID in the EFI configuration
>> table will enable the EFI bootoader responsible for calling EBS, in this
>> case efi-stub, to know that a Dynamic Launch has been requested. It also
>> seems this would be more in line with how EFI tends to work, versus a
>> Linux-specific callback boot param or something similar.
>>
>
> This all looks reasonable but it is not clear to me what a 'Linux
> setup kernel' is, and what the boot protocol is for that handover.
I used the term 'Linux setup kernel' just to encapsulate the
entrypoints, compressed kernel, and pre-"kernel proper" code. As for
boot protocol, I believe the SLRT is what you are looking for, and we
are in the process of drafting and verifying with a prototype.
> The EFI stub to core kernel handover ABI is private to Linux,
> architecture specific, and subject to change. This is basically the
> point I made before: if you want to boot Linux in EFI mode, you have
> to go via the EFI stub, and the EFI stub is in charge of booting the
> kernel proper. This is why I (we?) suggested some kind of callback
> mechanism, where the EFI stub makes a D-RTM specific call after EBS(),
> but does regain control over the boot flow.
Literally, this is not how the hardware works nor in line with the
architecture developed by TrenchBoot. By doing the Dynamic Launch Event
(DLE) the system, meaning the CPU, has effectively been reset. The
CPU/Dynamic Configuration Environment (DCE) is expecting to be provided
a kernel to measures, an entrypoint within that kernel to jump to, and
that kernel understands the reset state of the system. As agreed, the
callback approach is the most satisfactory approach to allow the
efi-stub to do its private protocol. Once the flow has switched to a
dynamic launch, the system is now starting the kernel via a dynamic
launch sequence. The dynamic launch entrypoint, sl-stub, is and will be
used as the entrypoint regardless of the firmware,
UEFI/coreboot/oreboot/slimboot/etc., or CPU vendor, Intel/AMD, in use.
Once efi-stub finishes and invokes the callback, its job is complete and
the new dl-handler along with sl-stub from the current patch set will
handle the system and security setup needed before entering into the
kernel proper.
To help provide clarity, consider the following flows for comparison,
Normal/existing efi-stub:
EFI -> efi-stub -> head_64.S
Proposed secure launch:
EFI -> efi-stub -> dl-handler -> [cpu] -> sl_stub ->head_64.S
Effectively, all this is doing is after efi-stub is done, instead of
jumping into head_64.S, it will call the dynamic launch handler to do
the dynamic launch, let sl_stub bring the system back into an expected
state, and then enter head_64.S just as efi-stub would have done.
> If we add another entry point into the kernel proper for the Secure
> Launch Entry component to use, we are again exposing an internal ABI
> in a way that limits our future ability to make changes to the EFI <->
> kernel handover.
I am not sure how you make that jump, but as I stated above, when
incorporating dynamic launch it is no longer a straight pass from EFI to
kernel proper. The sl-stub is there to provide a common entry point from
the CPU as the result of a dynamic launch, regardless of firmware or
vendor. Once sl-stub is done with its start-of-day setup, it will jump
to the same location efi-stub would have jumped. This means, efi-stub
does everything it always has and is free to change what it does. The
only addition is that it will now enable a call-out to allow secure
launch to do what it needs to do, and then execution returns back to
head_64.S. To be concise, it specifically returns where efi-stub would
have jumped to without removing or circumventing anything from the
existing flow.
It should also be noted that sl-stub will not be looking to reconfigure
the kernel. It will use the kernel as it was set up by efi-stub. The
only job of sl-stub is to make the world right, measure what efi-stub
provided for measurement, and then enter the kernel proper. The design
of the SLRT structure below is specifically not to bind to anything from
the efi-stub ABI/API. The only information needed to take the
measurements is the location of any config items, their size, and an
identifier for each item. The efi-stub is free to add to and/or remove
from the list of items, along with changing where it is stored, or even
change the format of existing items. The one recommendation, not
requirement, is that the identifiers should not freely be changed. While
it has no impact on sl-stub, it will likely be unpopular with anyone
attempting to keep a manifest of valid efi-stub config items for
attestation verification. It will result in having to maintain a
volatile two-parameter map of (kernel version, identifier) to config
item, at a minimum.
<snip/>
>> First, a short review of what the Secure Launch Resource Table is and
>> its purpose. The SLRT is to provide a platform and kernel agnostic
>> configuration table of the meta-data pertinent to the Secure Launch
>> entry points for the variety of kernels the TrenchBoot project will be
>> seeking to support. The specification for the table is in progress, but
>> the consensus is that it will consist of a header structure followed by
>> a packed series of TLV records. The specification will describe the
>> various types of records, but the ones of interests in this discussion
>> are those that efi-stub would use to record how it configured the
>> environment.
>>
>> The initially proposed TLV record, see below, for EFI configuration
>> information was devised around allowing an EFI bootloader to save
>> multiple config events under a single TLV record. In discussions on the
>> specification thus far, there are questions if it would be better to
>> have a TLV record for each config event or the proposed multiple events
>> per TLV record. It is worth noting that an assumption is being made in
>> the proposed record. The assumption is that a config event will either
>> be setting a configuration value between 1 and 8 bytes, or it will be a
>> data blob for which the address and size will be recorded. The question
>> is whether that covers all actions the efi-stub does or expects that it
>> will have to do in the near future.
>>
>> struct slrt_entry_efi_config_event {
>> struct slrt_entry_hdr hdr;
>> uint32_t identifier; /* EFI bootloader ID */
>> uint16_t reserved;
>> uint16_t nr_entries; /* Num cfg records */
>> struct efi_cfg_value values[0]; /* Array of cfg values */
>> };
>>
>> struct efi_cfg_value {
>> uint64_t data; /* cfg data (address or value) */
>> uint32_t size; /* data size if data is an addr */
>> uint32_t flags; /* 1L<0 IS_ADDR: data is an addr */
>> char evt_info[8]; /* event info str for TPM event log */
>> };
>>
>> Hopefully the general approach here is agreeable, as IMHO it does
>> provide a fairly elegant approach to resolving the issues at hand.
>> Details can always be negotiated to address various implementation
>> concerns. Provided this is acceptable, then everyone here is welcome to
>> provide input on the Secure Launch specification, link forthcoming.
>>
>
> Given that this is EFI, I would expect all these implementation
> details to be exposed via a protocol that the stub can invoke, in a
> way that will likely be similar (or the same?) as the TCG protocol
> used for recording PCR measurements.
The intent here was not to devise a new EFI protocol. This table is an
agnostic structure that all TrenchBoot Secure Launch implementations
will be using for all firmware environments, and will provide platform
relevant sections like the EFI section outlined above. The table will
inform the dl-handler so that it may take appropriate setup actions for
the dynamic launch. The larger user of the table will be the sl-stub,
which it will use to have an understanding of the world it inherited
from whomever invoked the dynamic launch.
> So could you elaborate on the types of actions? Is this simply things
> like the command line, initrd contents, initrd load address, kernel
> load address etc etc? There isn't generally that much going on in the
> stub beyond that.
Actually, those items are already in well-defined locations for which we
are already taking measurements. The items of concern are the items
being passed or configured that are stored outside the boot params. For
instance, ROM files passed to the kernel or EFI environment variables
that efi-stub may have set and/or will be used by the kernel.
V/r,
Daniel P. Smith
Hi,
On Wed, Jul 6, 2022 at 4:52 AM Daniel P. Smith
<[email protected]> wrote:
> On 6/10/22 12:40, Ard Biesheuvel wrote:> On Thu, 19 May 2022 at 22:59,
> To help provide clarity, consider the following flows for comparison,
>
> Normal/existing efi-stub:
> EFI -> efi-stub -> head_64.S
>
> Proposed secure launch:
> EFI -> efi-stub -> dl-handler -> [cpu] -> sl_stub ->head_64.S
For more clarity; the entire point is to ensure that the kernel only
has to trust itself and the CPU/TPM hardware (and does not have to
trust a potentially malicious boot loader)..Any attempt to avoid a
one-off solution for Linux is an attempt to weaken security.
The only correct approach is "efi-stub -> head_64.S -> kernel's own
secure init"; where (on UEFI systems) neither GRUB nor Trenchboot has
a valid reason to exist and should never be installed.
Cheers,
Brendan
On Wed, Jul 06, 2022 at 09:33:23AM +0930, Brendan Trotter wrote:
> The only correct approach is "efi-stub -> head_64.S -> kernel's own
> secure init"; where (on UEFI systems) neither GRUB nor Trenchboot has
> a valid reason to exist and should never be installed.
Surely the entire point of DRTM is that we *don't* have to trust the
bootloader?
On 7/5/22 20:03, Brendan Trotter wrote:
> Hi,
Greetings!
Not sure why I got dropped from distro, but no worries.
> On Wed, Jul 6, 2022 at 4:52 AM Daniel P. Smith
> <[email protected]> wrote:
>> On 6/10/22 12:40, Ard Biesheuvel wrote:> On Thu, 19 May 2022 at 22:59,
>> To help provide clarity, consider the following flows for comparison,
>>
>> Normal/existing efi-stub:
>> EFI -> efi-stub -> head_64.S
>>
>> Proposed secure launch:
>> EFI -> efi-stub -> dl-handler -> [cpu] -> sl_stub ->head_64.S
>
> For more clarity; the entire point is to ensure that the kernel only
> has to trust itself and the CPU/TPM hardware (and does not have to
> trust a potentially malicious boot loader)..Any attempt to avoid a
> one-off solution for Linux is an attempt to weaken security.
Please elaborate so I might understand how this entrypoint allows for
the kernel to only trust itself and the CPU/TPM.
> The only correct approach is "efi-stub -> head_64.S -> kernel's own
> secure init"; where (on UEFI systems) neither GRUB nor Trenchboot has
> a valid reason to exist and should never be installed.
>
>
> Cheers,
>
> Brendan
v/r,
dps
Hi,
On Thu, Jul 7, 2022 at 7:18 PM Daniel P. Smith
<[email protected]> wrote:
> On 7/5/22 20:03, Brendan Trotter wrote:
> Greetings!
>
> Not sure why I got dropped from distro, but no worries.
>
> > On Wed, Jul 6, 2022 at 4:52 AM Daniel P. Smith
> > <[email protected]> wrote:
> >> On 6/10/22 12:40, Ard Biesheuvel wrote:> On Thu, 19 May 2022 at 22:59,
> >> To help provide clarity, consider the following flows for comparison,
> >>
> >> Normal/existing efi-stub:
> >> EFI -> efi-stub -> head_64.S
> >>
> >> Proposed secure launch:
> >> EFI -> efi-stub -> dl-handler -> [cpu] -> sl_stub ->head_64.S
> >
> > For more clarity; the entire point is to ensure that the kernel only
> > has to trust itself and the CPU/TPM hardware (and does not have to
> > trust a potentially malicious boot loader)..Any attempt to avoid a
> > one-off solution for Linux is an attempt to weaken security.
>
> Please elaborate so I might understand how this entrypoint allows for
> the kernel to only trust itself and the CPU/TPM.
Is this a serious request?
Kernel is started (via. firmware using the kernel's efi-stub, or via.
"kexec()", or..); and regardless of how the kernel was started the
kernel establishes its own dynamic root of trust.(e.g. AMD"s SKINIT or
Intel's TXT, followed by measuring the remainder of itself and
anything passed from firmware like APCI tables) without relying on a
call-back provided by "untrusted by kernel" third-parties that don't
exist in most cases. The dynamic root of trust that kernel creates
depends on the kernel, CPU, TPM, etc (and excludes untrusted and
unnecessary third parties)..
The only potential benefit that the callback solution provides is that
it, in theory, it could reduce duplication of work for other operating
systems (FreeBSD, Solaris, Haiku, Fuchsia, .. could use the same
callback instead of doing it themselves); but previous discussions
(talk of formalising the contract between the boot stub and the Linux
kernel) suggest that you aren't interested in any other OS.
This leaves me wondering what your true motivation is. Are you trying
to benefit GRUB/Trenchboot (at the expense of security, end-user
convenience, distro installer hassle, etc); or trying to manufacture
scope for future man-in-the middle attacks (by promoting a solution
that requires something between firmware and kernel)?
- Brendan
On Fri, Jul 08, 2022 at 01:06:19PM +0930, Brendan Trotter wrote:
> This leaves me wondering what your true motivation is. Are you trying
> to benefit GRUB/Trenchboot (at the expense of security, end-user
> convenience, distro installer hassle, etc); or trying to manufacture
> scope for future man-in-the middle attacks (by promoting a solution
> that requires something between firmware and kernel)?
The described mechanism doesn't require trusting the code that's in the
middle - if the state is perturbed by this code, the measurements will
be different, and the system will be untrusted. I agree that this
implementation is more complicated than just leaving it all up to the
kernel, but I'm having a *lot* of trouble seeing how this has any impact
on its security. Jumping immediately to impugning the motivation of the
people involved is entirely inappropriate.
On 7/7/22 23:36, Brendan Trotter wrote:
> Hi,
>
> On Thu, Jul 7, 2022 at 7:18 PM Daniel P. Smith
> <[email protected]> wrote:
>> On 7/5/22 20:03, Brendan Trotter wrote:
>> Greetings!
>>
>> Not sure why I got dropped from distro, but no worries.
>>
>>> On Wed, Jul 6, 2022 at 4:52 AM Daniel P. Smith
>>> <[email protected]> wrote:
>>>> On 6/10/22 12:40, Ard Biesheuvel wrote:> On Thu, 19 May 2022 at 22:59,
>>>> To help provide clarity, consider the following flows for comparison,
>>>>
>>>> Normal/existing efi-stub:
>>>> EFI -> efi-stub -> head_64.S
>>>>
>>>> Proposed secure launch:
>>>> EFI -> efi-stub -> dl-handler -> [cpu] -> sl_stub ->head_64.S
>>>
>>> For more clarity; the entire point is to ensure that the kernel only
>>> has to trust itself and the CPU/TPM hardware (and does not have to
>>> trust a potentially malicious boot loader)..Any attempt to avoid a
>>> one-off solution for Linux is an attempt to weaken security.
>>
>> Please elaborate so I might understand how this entrypoint allows for
>> the kernel to only trust itself and the CPU/TPM.
>
> Is this a serious request?
Yes, it was serious because I found the statements to be terse and open
to interpretation. Specifically, when I read it, it almost seemed that
the position is that dynamic launch is not needed, and that the kernel
could just establish its own RoT.
> Kernel is started (via. firmware using the kernel's efi-stub, or via.
> "kexec()", or..); and regardless of how the kernel was started the
> kernel establishes its own dynamic root of trust.(e.g. AMD"s SKINIT or
> Intel's TXT, followed by measuring the remainder of itself and
> anything passed from firmware like APCI tables) without relying on a
> call-back provided by "untrusted by kernel" third-parties that don't
> exist in most cases. The dynamic root of trust that kernel creates
> depends on the kernel, CPU, TPM, etc (and excludes untrusted and
> unnecessary third parties)..
This clarifies the previous statements and I would say, yes, this is one
approach. Considering the challenges we have/are facing in getting a
minimal post-launch handling (sl-stub) into the setup kernel, I would be
hard-pressed to believe adding all the pre-launch handling would be
found to be acceptable. If the intent is to have it completely
self-contained, this would require,
1) the introduction of a TPM driver into the setup kernel, a hole I
would rather not go down again
2) potentially the ability to load files from disk if it is not
acceptable for the bootloader to load the DCE (ACM/SLB)
3) miscellaneous system evaluations, memory table, machine check, etc.
The only thing that is gained from such an approach is to make dynamic
launch for Linux be self-contained in the kernel. It does not reduce the
TCB because the whole design of the dynamic launch is to provide a
controlled process that establishes a new trust chain/TCB that is
started from an untrusted state. Specifically, dynamic launch starts
with the CPU being provided all the material for the process by
untrusted code that is currently in control at the time the launch is
initiated.
> The only potential benefit that the callback solution provides is that
> it, in theory, it could reduce duplication of work for other operating
> systems (FreeBSD, Solaris, Haiku, Fuchsia, .. could use the same
> callback instead of doing it themselves); but previous discussions
> (talk of formalising the contract between the boot stub and the Linux
> kernel) suggest that you aren't interested in any other OS.
With all due respect, but this is where I would have to disagree. There
is substantial benefit,
1) a single code base that needs to be reviewed vs multiple OS
specific versions
2) establishes an API that decouples pre- and post-launch
3) reduces the complexity required to enable adoption by an OS
4) zero reduction in the security properties of the architecture
> This leaves me wondering what your true motivation is. Are you trying
> to benefit GRUB/Trenchboot (at the expense of security, end-user
> convenience, distro installer hassle, etc); or trying to manufacture
> scope for future man-in-the middle attacks (by promoting a solution
> that requires something between firmware and kernel)?
As a loyal member of the tinfoil hat brigade, I will always advocate for
accept nothing and question everything. All I can ask is to evaluate the
technical merit of the presentations [1][2][3] and the patch series [4].
If there is anything concerning with the theory or the implementation,
then it should be raised so that it may be addressed. A means to do so
is the "what if" game, as it is great to formulate a hypothesis. In this
case, the "what if" postulated is the assumption that the approach is to
allow a future MitM attack. Then the challenge is to examine the
process, their underlying mechanism, and the security properties of
those mechanisms to see if a MitM can be discerned. I will gladly engage
with anyone that presents an analysis demonstrating an assumption I
made/missed that opens the possibility for subversion of the launch
integrity attempting to be built.
[1] https://www.platformsecuritysummit.com/2018/speaker/smith/
[2]
https://events19.linuxfoundation.org/events/linux-security-summit-north-america-2019/program/schedule/
[3] https://lpc.events/event/7/contributions/739/
[4] https://lkml.org/lkml/2022/2/18/699
Hi,
On Sat, Jul 23, 2022 at 2:53 AM Daniel P. Smith
<[email protected]> wrote:
> On 7/7/22 23:36, Brendan Trotter wrote:
> > On Thu, Jul 7, 2022 at 7:18 PM Daniel P. Smith
> > <[email protected]> wrote:
> >> On 7/5/22 20:03, Brendan Trotter wrote:
> >>> On Wed, Jul 6, 2022 at 4:52 AM Daniel P. Smith
> >>> <[email protected]> wrote:
> >>>> On 6/10/22 12:40, Ard Biesheuvel wrote:> On Thu, 19 May 2022 at 22:59,
> >>>> To help provide clarity, consider the following flows for comparison,
> >>>>
> >>>> Normal/existing efi-stub:
> >>>> EFI -> efi-stub -> head_64.S
> >>>>
> >>>> Proposed secure launch:
> >>>> EFI -> efi-stub -> dl-handler -> [cpu] -> sl_stub ->head_64.S
> >>>
> >>> For more clarity; the entire point is to ensure that the kernel only
> >>> has to trust itself and the CPU/TPM hardware (and does not have to
> >>> trust a potentially malicious boot loader)..Any attempt to avoid a
> >>> one-off solution for Linux is an attempt to weaken security.
> >>
> >> Please elaborate so I might understand how this entrypoint allows for
> >> the kernel to only trust itself and the CPU/TPM.
> >
> > Is this a serious request?
>
> Yes, it was serious because I found the statements to be terse and open
> to interpretation. Specifically, when I read it, it almost seemed that
> the position is that dynamic launch is not needed, and that the kernel
> could just establish its own RoT.
>
> > Kernel is started (via. firmware using the kernel's efi-stub, or via.
> > "kexec()", or..); and regardless of how the kernel was started the
> > kernel establishes its own dynamic root of trust.(e.g. AMD"s SKINIT or
> > Intel's TXT, followed by measuring the remainder of itself and
> > anything passed from firmware like APCI tables) without relying on a
> > call-back provided by "untrusted by kernel" third-parties that don't
> > exist in most cases. The dynamic root of trust that kernel creates
> > depends on the kernel, CPU, TPM, etc (and excludes untrusted and
> > unnecessary third parties)..
>
> This clarifies the previous statements and I would say, yes, this is one
> approach. Considering the challenges we have/are facing in getting a
> minimal post-launch handling (sl-stub) into the setup kernel, I would be
> hard-pressed to believe adding all the pre-launch handling would be
> found to be acceptable. If the intent is to have it completely
> self-contained, this would require,
> 1) the introduction of a TPM driver into the setup kernel, a hole I
> would rather not go down again
..which is no more work than the introduction of a TPM driver into one
boot loader (probably less so, as Linux already has TPM drivers that
are used later), and significantly less work than introducing a TPM
driver into many boot loaders.
Note that to do this well (with some protection against malicious
devices) you'd disable all PCI devices, then set up IOMMU as "allow
the least possible", then establish a dynamic root of trust, then
enable and allow individual devices only if/when their driver is
started by kernel and not sooner. Without doing it like this there's
less guarantee that the code/data being measured is the same as the
code/data being executed/used (as a malicious device can modify
anything before it's measured, restore the original extremely briefly
while measurement is done, then modify anything after it's measured
and before it's used). Also note that I mean "some protection" and not
100% protection (it's unsolvable unless firmware uses an "allow the
least necessary by default" strategy) but "some protection" is better
than none.
In other words; it isn't necessarily just TPM driver alone that would
need to be started "earlier" (ideally it's also IOMMU and PCI
enumeration too). However, "earlier" is "earlier than the
establishment of dynamic root of trust"; which can be achieved by
moving the establishment of dynamic root of trust to a later stage
(rather than bringing things like TPM driver to an earlier stage)..
> 2) potentially the ability to load files from disk if it is not
> acceptable for the bootloader to load the DCE (ACM/SLB)
..which is both unnecessary and ill-advised.
> 3) miscellaneous system evaluations, memory table, machine check, etc.
..which is the same regardless of where it's done.
> The only thing that is gained from such an approach is to make dynamic
> launch for Linux be self-contained in the kernel.
Making it self-contained in the kernel means:
a) it actually works, for the most important use case (where UEFI
firmware boots Linux's efi-stub directly)
b) it actually works, for other use cases (booted via. "kexec()",
booted from LILO, booted from ELILO, ...).
c) It continues to work; even when you change/update/install/remove a
boot manager (which would otherwise change the measurement and break
anything that depended on the measurement).
d) it's more portable (e.g. easier to port to ARM/Uboot, etc)
e) It's more likely to actually be used by end-users (can just install
a kernel like normal without extra pages of instructions on how to
install and configure unnecessary bootware)
f) It'll be peer reviewed by more people
> It does not reduce the
> TCB because the whole design of the dynamic launch is to provide a
> controlled process that establishes a new trust chain/TCB that is
> started from an untrusted state. Specifically, dynamic launch starts
> with the CPU being provided all the material for the process by
> untrusted code that is currently in control at the time the launch is
> initiated.
The whole design of dynamic launch is to establish a new trust chain
that doesn't depend on an untrusted boot loader (or anything that came
before it - firmware, etc). If the "dynamic root of trust" is
established by boot loader then it partially suffers the same problems
as a static root of trust.
> > The only potential benefit that the callback solution provides is that
> > it, in theory, it could reduce duplication of work for other operating
> > systems (FreeBSD, Solaris, Haiku, Fuchsia, .. could use the same
> > callback instead of doing it themselves); but previous discussions
> > (talk of formalising the contract between the boot stub and the Linux
> > kernel) suggest that you aren't interested in any other OS.
>
> With all due respect, but this is where I would have to disagree. There
> is substantial benefit,
> 1) a single code base that needs to be reviewed vs multiple OS
> specific versions
If you wanted to minimize code duplication you'd implement it as an
open source library (with a non-restrictive licence like MIT) so that
the code can be used by all the different boot loaders instead of
duplicated by each different boot loader, in addition to being used by
all the different operating systems/kernels.
> 2) establishes an API that decouples pre- and post-launch
..by providing a call-back that kernel uses post-launch to call an API
from pre-launch, that couples pre- and post-launch more than has ever
been done before?
> 3) reduces the complexity required to enable adoption by an OS
There's only one OS that uses the Linux Boot Protocol. Any other OS
(FreeBSD, Fuschia, Haiku, ...) has to radically change everything
about how it boots before it can think about adopting your Linux
specific solution. Is there even a proposal to add support to GRUB
developers' own multi-boot specification (to "enable easy adoption" by
Solaris and its forks)?
Building it directly into the Linux kernel would make adoption by
other operating systems easier, as they wouldn't need to change their
boot code and most of them are used to porting code from Linux anway.
> 4) zero reduction in the security properties of the architecture
It's a huge reduction in the security properties. It allows a "just
lie and measure nothing" boot loader to be (pre)installed,, tricking
the kernel into thinking there's security when there is none.
> > This leaves me wondering what your true motivation is. Are you trying
> > to benefit GRUB/Trenchboot (at the expense of security, end-user
> > convenience, distro installer hassle, etc); or trying to manufacture
> > scope for future man-in-the middle attacks (by promoting a solution
> > that requires something between firmware and kernel)?
>
> As a loyal member of the tinfoil hat brigade, I will always advocate for
> accept nothing and question everything. All I can ask is to evaluate the
> technical merit of the presentations [1][2][3] and the patch series [4].
> If there is anything concerning with the theory or the implementation,
> then it should be raised so that it may be addressed. A means to do so
> is the "what if" game, as it is great to formulate a hypothesis. In this
> case, the "what if" postulated is the assumption that the approach is to
> allow a future MitM attack.
How quickly could a disgruntled system administrator (or someone
selling computers with a Linux distro pre-installed, or anyone trying
to circumvent a company's digital rights management scheme that
happens to rely on DRTM for remote attestation, or...) break your
security in a way that survives kernel updates?
My estimate is that it'd take about 5 minutes to download the boot
loader's open source code then 10 minutes to modify it.
The only real safeguard against this is UEFI's Secure Boot, which
doesn't work on old computers or most "non-8086" computers, doesn't
work if an attacker can install their own secure boot keys, and
doesn't work in most virtual machines.
> Then the challenge is to examine the
> process, their underlying mechanism, and the security properties of
> those mechanisms to see if a MitM can be discerned. I will gladly engage
> with anyone that presents an analysis demonstrating an assumption I
> made/missed that opens the possibility for subversion of the launch
> integrity attempting to be built.
Surely it'd be easier for kernel to ignore the bootloader's
"untrustworthy dynamic root of trust" (and establish its own
"trustworthy dynamic root of trust") than it would be for kernel to
detect a MiTM boot loader.
- Brendan
On Tue, 5 Jul 2022 at 21:22, Daniel P. Smith
<[email protected]> wrote:
>
> On 6/10/22 12:40, Ard Biesheuvel wrote:
...
> > The EFI stub to core kernel handover ABI is private to Linux,
> > architecture specific, and subject to change. This is basically the
> > point I made before: if you want to boot Linux in EFI mode, you have
> > to go via the EFI stub, and the EFI stub is in charge of booting the
> > kernel proper. This is why I (we?) suggested some kind of callback
> > mechanism, where the EFI stub makes a D-RTM specific call after EBS(),
> > but does regain control over the boot flow.
>
> Literally, this is not how the hardware works nor in line with the
> architecture developed by TrenchBoot. By doing the Dynamic Launch Event
> (DLE) the system, meaning the CPU, has effectively been reset. The
> CPU/Dynamic Configuration Environment (DCE) is expecting to be provided
> a kernel to measures, an entrypoint within that kernel to jump to, and
> that kernel understands the reset state of the system. As agreed, the
> callback approach is the most satisfactory approach to allow the
> efi-stub to do its private protocol. Once the flow has switched to a
> dynamic launch, the system is now starting the kernel via a dynamic
> launch sequence. The dynamic launch entrypoint, sl-stub, is and will be
> used as the entrypoint regardless of the firmware,
> UEFI/coreboot/oreboot/slimboot/etc., or CPU vendor, Intel/AMD, in use.
> Once efi-stub finishes and invokes the callback, its job is complete and
> the new dl-handler along with sl-stub from the current patch set will
> handle the system and security setup needed before entering into the
> kernel proper.
>
> To help provide clarity, consider the following flows for comparison,
>
> Normal/existing efi-stub:
> EFI -> efi-stub -> head_64.S
>
> Proposed secure launch:
> EFI -> efi-stub -> dl-handler -> [cpu] -> sl_stub ->head_64.S
>
> Effectively, all this is doing is after efi-stub is done, instead of
> jumping into head_64.S, it will call the dynamic launch handler to do
> the dynamic launch, let sl_stub bring the system back into an expected
> state, and then enter head_64.S just as efi-stub would have done.
>
OK, understood.
> > If we add another entry point into the kernel proper for the Secure
> > Launch Entry component to use, we are again exposing an internal ABI
> > in a way that limits our future ability to make changes to the EFI <->
> > kernel handover.
>
> I am not sure how you make that jump, but as I stated above, when
> incorporating dynamic launch it is no longer a straight pass from EFI to
> kernel proper. The sl-stub is there to provide a common entry point from
> the CPU as the result of a dynamic launch, regardless of firmware or
> vendor. Once sl-stub is done with its start-of-day setup, it will jump
> to the same location efi-stub would have jumped. This means, efi-stub
> does everything it always has and is free to change what it does. The
> only addition is that it will now enable a call-out to allow secure
> launch to do what it needs to do, and then execution returns back to
> head_64.S. To be concise, it specifically returns where efi-stub would
> have jumped to without removing or circumventing anything from the
> existing flow.
>
Excellent, that answers another question I had regarding the above.
> It should also be noted that sl-stub will not be looking to reconfigure
> the kernel. It will use the kernel as it was set up by efi-stub. The
> only job of sl-stub is to make the world right, measure what efi-stub
> provided for measurement, and then enter the kernel proper. The design
> of the SLRT structure below is specifically not to bind to anything from
> the efi-stub ABI/API. The only information needed to take the
> measurements is the location of any config items, their size, and an
> identifier for each item. The efi-stub is free to add to and/or remove
> from the list of items, along with changing where it is stored, or even
> change the format of existing items. The one recommendation, not
> requirement, is that the identifiers should not freely be changed. While
> it has no impact on sl-stub, it will likely be unpopular with anyone
> attempting to keep a manifest of valid efi-stub config items for
> attestation verification. It will result in having to maintain a
> volatile two-parameter map of (kernel version, identifier) to config
> item, at a minimum.
>
OK, noted. Can we add these recommendations to the header files
please? And let's make it a requirement - it's easier to relax it
later than the other way around.
> <snip/>
>
> >> First, a short review of what the Secure Launch Resource Table is and
> >> its purpose. The SLRT is to provide a platform and kernel agnostic
> >> configuration table of the meta-data pertinent to the Secure Launch
> >> entry points for the variety of kernels the TrenchBoot project will be
> >> seeking to support. The specification for the table is in progress, but
> >> the consensus is that it will consist of a header structure followed by
> >> a packed series of TLV records. The specification will describe the
> >> various types of records, but the ones of interests in this discussion
> >> are those that efi-stub would use to record how it configured the
> >> environment.
> >>
> >> The initially proposed TLV record, see below, for EFI configuration
> >> information was devised around allowing an EFI bootloader to save
> >> multiple config events under a single TLV record. In discussions on the
> >> specification thus far, there are questions if it would be better to
> >> have a TLV record for each config event or the proposed multiple events
> >> per TLV record. It is worth noting that an assumption is being made in
> >> the proposed record. The assumption is that a config event will either
> >> be setting a configuration value between 1 and 8 bytes, or it will be a
> >> data blob for which the address and size will be recorded. The question
> >> is whether that covers all actions the efi-stub does or expects that it
> >> will have to do in the near future.
> >>
> >> struct slrt_entry_efi_config_event {
> >> struct slrt_entry_hdr hdr;
> >> uint32_t identifier; /* EFI bootloader ID */
> >> uint16_t reserved;
> >> uint16_t nr_entries; /* Num cfg records */
> >> struct efi_cfg_value values[0]; /* Array of cfg values */
Nit: use [] for flex arrays please - we will become more pedantic
about this when using newer compilers.
> >> };
> >>
> >> struct efi_cfg_value {
> >> uint64_t data; /* cfg data (address or value) */
> >> uint32_t size; /* data size if data is an addr */
> >> uint32_t flags; /* 1L<0 IS_ADDR: data is an addr */
> >> char evt_info[8]; /* event info str for TPM event log */
> >> };
> >>
> >> Hopefully the general approach here is agreeable, as IMHO it does
> >> provide a fairly elegant approach to resolving the issues at hand.
> >> Details can always be negotiated to address various implementation
> >> concerns. Provided this is acceptable, then everyone here is welcome to
> >> provide input on the Secure Launch specification, link forthcoming.
> >>
> >
> > Given that this is EFI, I would expect all these implementation
> > details to be exposed via a protocol that the stub can invoke, in a
> > way that will likely be similar (or the same?) as the TCG protocol
> > used for recording PCR measurements.
>
> The intent here was not to devise a new EFI protocol. This table is an
> agnostic structure that all TrenchBoot Secure Launch implementations
> will be using for all firmware environments, and will provide platform
> relevant sections like the EFI section outlined above. The table will
> inform the dl-handler so that it may take appropriate setup actions for
> the dynamic launch. The larger user of the table will be the sl-stub,
> which it will use to have an understanding of the world it inherited
> from whomever invoked the dynamic launch.
>
OK. We'll need some useful abstraction for this internally in the stub
code, but that is not too relevant for this discussion. (We recently
added some code that measures the initrd into the TPM, and having
calls to two different kinds of measurement APIs all over the stub is
something I'd like to avoid)
> > So could you elaborate on the types of actions? Is this simply things
> > like the command line, initrd contents, initrd load address, kernel
> > load address etc etc? There isn't generally that much going on in the
> > stub beyond that.
>
> Actually, those items are already in well-defined locations for which we
> are already taking measurements. The items of concern are the items
> being passed or configured that are stored outside the boot params.
You mean the x86 specific struct bootparams, right? Not relevant, but
just out of interest: I take it you are also measuring the setup_data
linked list? This is currently being augmented to carry a RNG seed,
which may cause problems for you in the future.
> For
> instance, ROM files passed to the kernel or EFI environment variables
> that efi-stub may have set and/or will be used by the kernel.
>
Hmm, ok. I'd really like to get a peek at the impact on the code - if
we will have hooks all over the place, it is a strong indication that
you are intercepting this at the wrong level. Perhaps you'll need to
do something along the lines of interposing the boot and runtime
services, and measuring the invocations that are relevant to you.
On 7/23/22 01:15, Brendan Trotter wrote:
> Hi,
Greetings,
> On Sat, Jul 23, 2022 at 2:53 AM Daniel P. Smith
> <[email protected]> wrote:
>> On 7/7/22 23:36, Brendan Trotter wrote:
>>> On Thu, Jul 7, 2022 at 7:18 PM Daniel P. Smith
>>> <[email protected]> wrote:
>>>> On 7/5/22 20:03, Brendan Trotter wrote:
>>>>> On Wed, Jul 6, 2022 at 4:52 AM Daniel P. Smith
>>>>> <[email protected]> wrote:
>>>>>> On 6/10/22 12:40, Ard Biesheuvel wrote:> On Thu, 19 May 2022 at 22:59,
>>>>>> To help provide clarity, consider the following flows for comparison,
>>>>>>
>>>>>> Normal/existing efi-stub:
>>>>>> EFI -> efi-stub -> head_64.S
>>>>>>
>>>>>> Proposed secure launch:
>>>>>> EFI -> efi-stub -> dl-handler -> [cpu] -> sl_stub ->head_64.S
>>>>>
>>>>> For more clarity; the entire point is to ensure that the kernel only
>>>>> has to trust itself and the CPU/TPM hardware (and does not have to
>>>>> trust a potentially malicious boot loader)..Any attempt to avoid a
>>>>> one-off solution for Linux is an attempt to weaken security.
>>>>
>>>> Please elaborate so I might understand how this entrypoint allows for
>>>> the kernel to only trust itself and the CPU/TPM.
>>>
>>> Is this a serious request?
>>
>> Yes, it was serious because I found the statements to be terse and open
>> to interpretation. Specifically, when I read it, it almost seemed that
>> the position is that dynamic launch is not needed, and that the kernel
>> could just establish its own RoT.
>>
>>> Kernel is started (via. firmware using the kernel's efi-stub, or via.
>>> "kexec()", or..); and regardless of how the kernel was started the
>>> kernel establishes its own dynamic root of trust.(e.g. AMD"s SKINIT or
>>> Intel's TXT, followed by measuring the remainder of itself and
>>> anything passed from firmware like APCI tables) without relying on a
>>> call-back provided by "untrusted by kernel" third-parties that don't
>>> exist in most cases. The dynamic root of trust that kernel creates
>>> depends on the kernel, CPU, TPM, etc (and excludes untrusted and
>>> unnecessary third parties)..
>>
>> This clarifies the previous statements and I would say, yes, this is one
>> approach. Considering the challenges we have/are facing in getting a
>> minimal post-launch handling (sl-stub) into the setup kernel, I would be
>> hard-pressed to believe adding all the pre-launch handling would be
>> found to be acceptable. If the intent is to have it completely
>> self-contained, this would require,
>> 1) the introduction of a TPM driver into the setup kernel, a hole I
>> would rather not go down again
>
> ..which is no more work than the introduction of a TPM driver into one
> boot loader (probably less so, as Linux already has TPM drivers that
> are used later), and significantly less work than introducing a TPM
> driver into many boot loaders.
Already been there and no it is not as straight forward as one may
think. A minimal driver was attempted but rejected by the TPM
maintainers with the requirement to reuse the existing driver code. So
we would gladly welcome someone to come rewrite the TPM drive.
Specifically to de-tangle the core TPM interface code away from all of
its kernel proper dependencies so that it can be used by both the setup
kernel and the kernel proper.
> Note that to do this well (with some protection against malicious
> devices) you'd disable all PCI devices, then set up IOMMU as "allow
> the least possible", then establish a dynamic root of trust, then
> enable and allow individual devices only if/when their driver is
> started by kernel and not sooner. Without doing it like this there's
> less guarantee that the code/data being measured is the same as the
> code/data being executed/used (as a malicious device can modify
> anything before it's measured, restore the original extremely briefly
> while measurement is done, then modify anything after it's measured
> and before it's used). Also note that I mean "some protection" and not
> 100% protection (it's unsolvable unless firmware uses an "allow the
> least necessary by default" strategy) but "some protection" is better
> than none.
>
> In other words; it isn't necessarily just TPM driver alone that would
> need to be started "earlier" (ideally it's also IOMMU and PCI
> enumeration too). However, "earlier" is "earlier than the
> establishment of dynamic root of trust"; which can be achieved by
> moving the establishment of dynamic root of trust to a later stage
> (rather than bringing things like TPM driver to an earlier stage)..
With all due respect, the statement above demonstrates a clear lack of
understanding how the hardware dynamic launch works. I have written a
summary[1], with links to details, of how the process works. It is
highly recommended this is read, as well as the referenced sections in
Intel's SDM and AMD's APM.
>> 2) potentially the ability to load files from disk if it is not
>> acceptable for the bootloader to load the DCE (ACM/SLB)
>
> ..which is both unnecessary and ill-advised.
See [1]
>> 3) miscellaneous system evaluations, memory table, machine check, etc.
>
> ..which is the same regardless of where it's done.
>
>> The only thing that is gained from such an approach is to make dynamic
>> launch for Linux be self-contained in the kernel.
>
> Making it self-contained in the kernel means:
>
> a) it actually works, for the most important use case (where UEFI
> firmware boots Linux's efi-stub directly)
>
> b) it actually works, for other use cases (booted via. "kexec()",
> booted from LILO, booted from ELILO, ...).
>
> c) It continues to work; even when you change/update/install/remove a
> boot manager (which would otherwise change the measurement and break
> anything that depended on the measurement).
>
> d) it's more portable (e.g. easier to port to ARM/Uboot, etc)
>
> e) It's more likely to actually be used by end-users (can just install
> a kernel like normal without extra pages of instructions on how to
> install and configure unnecessary bootware)
>
> f) It'll be peer reviewed by more people
The hook approach does all of this.
>> It does not reduce the
>> TCB because the whole design of the dynamic launch is to provide a
>> controlled process that establishes a new trust chain/TCB that is
>> started from an untrusted state. Specifically, dynamic launch starts
>> with the CPU being provided all the material for the process by
>> untrusted code that is currently in control at the time the launch is
>> initiated.
>
> The whole design of dynamic launch is to establish a new trust chain
> that doesn't depend on an untrusted boot loader (or anything that came
> before it - firmware, etc). If the "dynamic root of trust" is
> established by boot loader then it partially suffers the same problems
> as a static root of trust.
See [1]
>>> The only potential benefit that the callback solution provides is that
>>> it, in theory, it could reduce duplication of work for other operating
>>> systems (FreeBSD, Solaris, Haiku, Fuchsia, .. could use the same
>>> callback instead of doing it themselves); but previous discussions
>>> (talk of formalising the contract between the boot stub and the Linux
>>> kernel) suggest that you aren't interested in any other OS.
>>
>> With all due respect, but this is where I would have to disagree. There
>> is substantial benefit,
>> 1) a single code base that needs to be reviewed vs multiple OS
>> specific versions
>
> If you wanted to minimize code duplication you'd implement it as an
> open source library (with a non-restrictive licence like MIT) so that
> the code can be used by all the different boot loaders instead of
> duplicated by each different boot loader, in addition to being used by
> all the different operating systems/kernels.
I completely agree and my intent is to get there eventually.
>> 2) establishes an API that decouples pre- and post-launch
>
> ..by providing a call-back that kernel uses post-launch to call an API
> from pre-launch, that couples pre- and post-launch more than has ever
> been done before?
That is not what is being proposed.
>> 3) reduces the complexity required to enable adoption by an OS
>
> There's only one OS that uses the Linux Boot Protocol. Any other OS
> (FreeBSD, Fuschia, Haiku, ...) has to radically change everything
> about how it boots before it can think about adopting your Linux
> specific solution. Is there even a proposal to add support to GRUB
> developers' own multi-boot specification (to "enable easy adoption" by
> Solaris and its forks)?
>
> Building it directly into the Linux kernel would make adoption by
> other operating systems easier, as they wouldn't need to change their
> boot code and most of them are used to porting code from Linux anway.
Nothing in this proposal binds it to the Linux Boot Protocol.
>> 4) zero reduction in the security properties of the architecture
>
> It's a huge reduction in the security properties. It allows a "just
> lie and measure nothing" boot loader to be (pre)installed,, tricking
> the kernel into thinking there's security when there is none.
See [1].
>>> This leaves me wondering what your true motivation is. Are you trying
>>> to benefit GRUB/Trenchboot (at the expense of security, end-user
>>> convenience, distro installer hassle, etc); or trying to manufacture
>>> scope for future man-in-the middle attacks (by promoting a solution
>>> that requires something between firmware and kernel)?
>>
>> As a loyal member of the tinfoil hat brigade, I will always advocate for
>> accept nothing and question everything. All I can ask is to evaluate the
>> technical merit of the presentations [1][2][3] and the patch series [4].
>> If there is anything concerning with the theory or the implementation,
>> then it should be raised so that it may be addressed. A means to do so
>> is the "what if" game, as it is great to formulate a hypothesis. In this
>> case, the "what if" postulated is the assumption that the approach is to
>> allow a future MitM attack.
>
> How quickly could a disgruntled system administrator (or someone
> selling computers with a Linux distro pre-installed, or anyone trying
> to circumvent a company's digital rights management scheme that
> happens to rely on DRTM for remote attestation, or...) break your
> security in a way that survives kernel updates?
>
> My estimate is that it'd take about 5 minutes to download the boot
> loader's open source code then 10 minutes to modify it.
>
> The only real safeguard against this is UEFI's Secure Boot, which
> doesn't work on old computers or most "non-8086" computers, doesn't
> work if an attacker can install their own secure boot keys, and
> doesn't work in most virtual machines.
See [1].
>> Then the challenge is to examine the
>> process, their underlying mechanism, and the security properties of
>> those mechanisms to see if a MitM can be discerned. I will gladly engage
>> with anyone that presents an analysis demonstrating an assumption I
>> made/missed that opens the possibility for subversion of the launch
>> integrity attempting to be built.
>
> Surely it'd be easier for kernel to ignore the bootloader's
> "untrustworthy dynamic root of trust" (and establish its own
> "trustworthy dynamic root of trust") than it would be for kernel to
> detect a MiTM boot loader.
See [1].
> - Brendan
[1] https://trenchboot.org/documentation/Late_Launch_Overview/
Hi,
On Tue, Aug 9, 2022 at 8:25 PM Daniel P. Smith
<[email protected]> wrote:
> On 7/23/22 01:15, Brendan Trotter wrote:
> > On Sat, Jul 23, 2022 at 2:53 AM Daniel P. Smith
> > <[email protected]> wrote:
> >> On 7/7/22 23:36, Brendan Trotter wrote:
> >>> On Thu, Jul 7, 2022 at 7:18 PM Daniel P. Smith
> >>> <[email protected]> wrote:
> >>>> On 7/5/22 20:03, Brendan Trotter wrote:
> >>>>> On Wed, Jul 6, 2022 at 4:52 AM Daniel P. Smith
> >>>>> <[email protected]> wrote:
> >>>>>> On 6/10/22 12:40, Ard Biesheuvel wrote:> On Thu, 19 May 2022 at 22:59,
> >>>>>> To help provide clarity, consider the following flows for comparison,
> >>>>>>
> >>>>>> Normal/existing efi-stub:
> >>>>>> EFI -> efi-stub -> head_64.S
> >>>>>>
> >>>>>> Proposed secure launch:
> >>>>>> EFI -> efi-stub -> dl-handler -> [cpu] -> sl_stub ->head_64.S
> >>>>>
> >>>>> For more clarity; the entire point is to ensure that the kernel only
> >>>>> has to trust itself and the CPU/TPM hardware (and does not have to
> >>>>> trust a potentially malicious boot loader)..Any attempt to avoid a
> >>>>> one-off solution for Linux is an attempt to weaken security.
> >>>>
> >>>> Please elaborate so I might understand how this entrypoint allows for
> >>>> the kernel to only trust itself and the CPU/TPM.
> >>>
> >>> Is this a serious request?
> >>
> >> Yes, it was serious because I found the statements to be terse and open
> >> to interpretation. Specifically, when I read it, it almost seemed that
> >> the position is that dynamic launch is not needed, and that the kernel
> >> could just establish its own RoT.
> >>
> >>> Kernel is started (via. firmware using the kernel's efi-stub, or via.
> >>> "kexec()", or..); and regardless of how the kernel was started the
> >>> kernel establishes its own dynamic root of trust.(e.g. AMD"s SKINIT or
> >>> Intel's TXT, followed by measuring the remainder of itself and
> >>> anything passed from firmware like APCI tables) without relying on a
> >>> call-back provided by "untrusted by kernel" third-parties that don't
> >>> exist in most cases. The dynamic root of trust that kernel creates
> >>> depends on the kernel, CPU, TPM, etc (and excludes untrusted and
> >>> unnecessary third parties)..
> >>
> >> This clarifies the previous statements and I would say, yes, this is one
> >> approach. Considering the challenges we have/are facing in getting a
> >> minimal post-launch handling (sl-stub) into the setup kernel, I would be
> >> hard-pressed to believe adding all the pre-launch handling would be
> >> found to be acceptable. If the intent is to have it completely
> >> self-contained, this would require,
> >> 1) the introduction of a TPM driver into the setup kernel, a hole I
> >> would rather not go down again
> >
> > ..which is no more work than the introduction of a TPM driver into one
> > boot loader (probably less so, as Linux already has TPM drivers that
> > are used later), and significantly less work than introducing a TPM
> > driver into many boot loaders.
>
> Already been there and no it is not as straight forward as one may
> think. A minimal driver was attempted but rejected by the TPM
> maintainers with the requirement to reuse the existing driver code. So
> we would gladly welcome someone to come rewrite the TPM drive.
> Specifically to de-tangle the core TPM interface code away from all of
> its kernel proper dependencies so that it can be used by both the setup
> kernel and the kernel proper.
>
> > Note that to do this well (with some protection against malicious
> > devices) you'd disable all PCI devices, then set up IOMMU as "allow
> > the least possible", then establish a dynamic root of trust, then
> > enable and allow individual devices only if/when their driver is
> > started by kernel and not sooner. Without doing it like this there's
> > less guarantee that the code/data being measured is the same as the
> > code/data being executed/used (as a malicious device can modify
> > anything before it's measured, restore the original extremely briefly
> > while measurement is done, then modify anything after it's measured
> > and before it's used). Also note that I mean "some protection" and not
> > 100% protection (it's unsolvable unless firmware uses an "allow the
> > least necessary by default" strategy) but "some protection" is better
> > than none.
> >
> > In other words; it isn't necessarily just TPM driver alone that would
> > need to be started "earlier" (ideally it's also IOMMU and PCI
> > enumeration too). However, "earlier" is "earlier than the
> > establishment of dynamic root of trust"; which can be achieved by
> > moving the establishment of dynamic root of trust to a later stage
> > (rather than bringing things like TPM driver to an earlier stage)..
>
> With all due respect, the statement above demonstrates a clear lack of
> understanding how the hardware dynamic launch works. I have written a
> summary[1], with links to details, of how the process works. It is
> highly recommended this is read, as well as the referenced sections in
> Intel's SDM and AMD's APM.
>
> >> 2) potentially the ability to load files from disk if it is not
> >> acceptable for the bootloader to load the DCE (ACM/SLB)
> >
> > ..which is both unnecessary and ill-advised.
>
> See [1]
Yes? If you're referring to the "authenticated code module" (as part
of senter's internal procedure) it's part of hardware/firmware and
beyond the scope of software/boot loader/kernel.
> >> 3) miscellaneous system evaluations, memory table, machine check, etc.
> >
> > ..which is the same regardless of where it's done.
> >
> >> The only thing that is gained from such an approach is to make dynamic
> >> launch for Linux be self-contained in the kernel.
> >
> > Making it self-contained in the kernel means:
> >
> > a) it actually works, for the most important use case (where UEFI
> > firmware boots Linux's efi-stub directly)
> >
> > b) it actually works, for other use cases (booted via. "kexec()",
> > booted from LILO, booted from ELILO, ...).
> >
> > c) It continues to work; even when you change/update/install/remove a
> > boot manager (which would otherwise change the measurement and break
> > anything that depended on the measurement).
> >
> > d) it's more portable (e.g. easier to port to ARM/Uboot, etc)
> >
> > e) It's more likely to actually be used by end-users (can just install
> > a kernel like normal without extra pages of instructions on how to
> > install and configure unnecessary bootware)
> >
> > f) It'll be peer reviewed by more people
>
> The hook approach does all of this.
>
> >> It does not reduce the
> >> TCB because the whole design of the dynamic launch is to provide a
> >> controlled process that establishes a new trust chain/TCB that is
> >> started from an untrusted state. Specifically, dynamic launch starts
> >> with the CPU being provided all the material for the process by
> >> untrusted code that is currently in control at the time the launch is
> >> initiated.
> >
> > The whole design of dynamic launch is to establish a new trust chain
> > that doesn't depend on an untrusted boot loader (or anything that came
> > before it - firmware, etc). If the "dynamic root of trust" is
> > established by boot loader then it partially suffers the same problems
> > as a static root of trust.
>
> See [1]
>
> >>> The only potential benefit that the callback solution provides is that
> >>> it, in theory, it could reduce duplication of work for other operating
> >>> systems (FreeBSD, Solaris, Haiku, Fuchsia, .. could use the same
> >>> callback instead of doing it themselves); but previous discussions
> >>> (talk of formalising the contract between the boot stub and the Linux
> >>> kernel) suggest that you aren't interested in any other OS.
> >>
> >> With all due respect, but this is where I would have to disagree. There
> >> is substantial benefit,
> >> 1) a single code base that needs to be reviewed vs multiple OS
> >> specific versions
> >
> > If you wanted to minimize code duplication you'd implement it as an
> > open source library (with a non-restrictive licence like MIT) so that
> > the code can be used by all the different boot loaders instead of
> > duplicated by each different boot loader, in addition to being used by
> > all the different operating systems/kernels.
>
> I completely agree and my intent is to get there eventually.
>
> >> 2) establishes an API that decouples pre- and post-launch
> >
> > ..by providing a call-back that kernel uses post-launch to call an API
> > from pre-launch, that couples pre- and post-launch more than has ever
> > been done before?
>
> That is not what is being proposed.
Maybe I'm confused. I thought the proposal was that unnecessary and
untrusted code (Trenchboot) is inserted into "pre kernel launch"
(between UEFI firmware and Linux's efi-stub), and then (during "post
kernel launch") kernel calls a callback provided by "pre kernel
launch" (Trenchboot); thereby coupling pre-launch (Trenchboot) and
post-launch (Linux kernel) more than has ever be done before.
I also assumed that if the 1st kernel runs for 6 months and then
starts a 2nd kernel via. "kexec()" ; then the 2nd kernel would call
the callback provided by "pre 1st kernel launch from 6 months ago".
> >> 3) reduces the complexity required to enable adoption by an OS
> >
> > There's only one OS that uses the Linux Boot Protocol. Any other OS
> > (FreeBSD, Fuschia, Haiku, ...) has to radically change everything
> > about how it boots before it can think about adopting your Linux
> > specific solution. Is there even a proposal to add support to GRUB
> > developers' own multi-boot specification (to "enable easy adoption" by
> > Solaris and its forks)?
> >
> > Building it directly into the Linux kernel would make adoption by
> > other operating systems easier, as they wouldn't need to change their
> > boot code and most of them are used to porting code from Linux anway.
>
> Nothing in this proposal binds it to the Linux Boot Protocol.
>
> >> 4) zero reduction in the security properties of the architecture
> >
> > It's a huge reduction in the security properties. It allows a "just
> > lie and measure nothing" boot loader to be (pre)installed,, tricking
> > the kernel into thinking there's security when there is none.
>
> See [1].
[1] doesn't provide any useful information. How does a kernel know
that the callback provided by boot loader actually measures what it's
supposed to measure, or even does anything at all?
> >>> This leaves me wondering what your true motivation is. Are you trying
> >>> to benefit GRUB/Trenchboot (at the expense of security, end-user
> >>> convenience, distro installer hassle, etc); or trying to manufacture
> >>> scope for future man-in-the middle attacks (by promoting a solution
> >>> that requires something between firmware and kernel)?
> >>
> >> As a loyal member of the tinfoil hat brigade, I will always advocate for
> >> accept nothing and question everything. All I can ask is to evaluate the
> >> technical merit of the presentations [1][2][3] and the patch series [4].
> >> If there is anything concerning with the theory or the implementation,
> >> then it should be raised so that it may be addressed. A means to do so
> >> is the "what if" game, as it is great to formulate a hypothesis. In this
> >> case, the "what if" postulated is the assumption that the approach is to
> >> allow a future MitM attack.
> >
> > How quickly could a disgruntled system administrator (or someone
> > selling computers with a Linux distro pre-installed, or anyone trying
> > to circumvent a company's digital rights management scheme that
> > happens to rely on DRTM for remote attestation, or...) break your
> > security in a way that survives kernel updates?
> >
> > My estimate is that it'd take about 5 minutes to download the boot
> > loader's open source code then 10 minutes to modify it.
> >
> > The only real safeguard against this is UEFI's Secure Boot, which
> > doesn't work on old computers or most "non-8086" computers, doesn't
> > work if an attacker can install their own secure boot keys, and
> > doesn't work in most virtual machines.
>
> See [1].
[1] doesn't provide any useful information. Dynamic root of trust is
only useful for detecting if a measurement changed; so if the
measurement was always nonsense from the beginning and never changes
it becomes worse than nothing.
> >> Then the challenge is to examine the
> >> process, their underlying mechanism, and the security properties of
> >> those mechanisms to see if a MitM can be discerned. I will gladly engage
> >> with anyone that presents an analysis demonstrating an assumption I
> >> made/missed that opens the possibility for subversion of the launch
> >> integrity attempting to be built.
> >
> > Surely it'd be easier for kernel to ignore the bootloader's
> > "untrustworthy dynamic root of trust" (and establish its own
> > "trustworthy dynamic root of trust") than it would be for kernel to
> > detect a MiTM boot loader.
>
> See [1].
[1] doesn't provide any useful information. Senter and skinit don't
provide a method for kernel to detect that (e.g.) a MiTM boot loader
has always measured a forgery and has changed unmeasured code in a
different way every time you boot.
- Brendan
On Wed, Aug 10, 2022 at 06:37:18PM +0930, Brendan Trotter wrote:
> [1] doesn't provide any useful information. How does a kernel know
> that the callback provided by boot loader actually measures what it's
> supposed to measure, or even does anything at all?
The kernel has no way to know this - *any* code you've run before
performing a measurement could tamper with the kernel such that it
believes it's fine. This is just as true in DRTM as it is in SRTM. But
you know what the expected measurements should be, so you're able to
either seal secrets to those PCR values or rely on remote attestation.
> [1] doesn't provide any useful information. Senter and skinit don't
> provide a method for kernel to detect that (e.g.) a MiTM boot loader
> has always measured a forgery and has changed unmeasured code in a
> different way every time you boot.
Measurements are not opaque objects. If you're not able to reconstruct
the expected measurement then you're doing it wrong.
Hi,
On Thu, Aug 11, 2022 at 3:16 AM Matthew Garrett <[email protected]> wrote:
> On Wed, Aug 10, 2022 at 06:37:18PM +0930, Brendan Trotter wrote:
>
> > [1] doesn't provide any useful information. How does a kernel know
> > that the callback provided by boot loader actually measures what it's
> > supposed to measure, or even does anything at all?
>
> The kernel has no way to know this - *any* code you've run before
> performing a measurement could tamper with the kernel such that it
> believes it's fine. This is just as true in DRTM as it is in SRTM. But
> you know what the expected measurements should be, so you're able to
> either seal secrets to those PCR values or rely on remote attestation.
In this scenario the kernel has no idea what the measurement should
be, it only knows the measurement that a potentially malicious boot
loader felt like giving the kernel previously (e.g. when the kernel
was installed).
> > [1] doesn't provide any useful information. Senter and skinit don't
> > provide a method for kernel to detect that (e.g.) a MiTM boot loader
> > has always measured a forgery and has changed unmeasured code in a
> > different way every time you boot.
>
> Measurements are not opaque objects. If you're not able to reconstruct
> the expected measurement then you're doing it wrong.
OK; so to detect if boot loader has always given kernel a bad/forged
measurement; the kernel repeats all of the steps involved in creating
the measurement itself exactly the same as the boot loader should have
(but might not have) so that kernel can compare a "known
good/trustworthy" measurement with the useless measurement that the
boot loader created for no sane reason whatsoever?
- Brendan
On Thu, Aug 11, 2022 at 07:25:58PM +0930, Brendan Trotter wrote:
> Hi,
>
> On Thu, Aug 11, 2022 at 3:16 AM Matthew Garrett <[email protected]> wrote:
> > On Wed, Aug 10, 2022 at 06:37:18PM +0930, Brendan Trotter wrote:
> >
> > > [1] doesn't provide any useful information. How does a kernel know
> > > that the callback provided by boot loader actually measures what it's
> > > supposed to measure, or even does anything at all?
> >
> > The kernel has no way to know this - *any* code you've run before
> > performing a measurement could tamper with the kernel such that it
> > believes it's fine. This is just as true in DRTM as it is in SRTM. But
> > you know what the expected measurements should be, so you're able to
> > either seal secrets to those PCR values or rely on remote attestation.
>
> In this scenario the kernel has no idea what the measurement should
> be, it only knows the measurement that a potentially malicious boot
> loader felt like giving the kernel previously (e.g. when the kernel
> was installed).
>
> > > [1] doesn't provide any useful information. Senter and skinit don't
> > > provide a method for kernel to detect that (e.g.) a MiTM boot loader
> > > has always measured a forgery and has changed unmeasured code in a
> > > different way every time you boot.
> >
> > Measurements are not opaque objects. If you're not able to reconstruct
> > the expected measurement then you're doing it wrong.
>
> OK; so to detect if boot loader has always given kernel a bad/forged
> measurement; the kernel repeats all of the steps involved in creating
> the measurement itself exactly the same as the boot loader should have
> (but might not have) so that kernel can compare a "known
> good/trustworthy" measurement with the useless measurement that the
> boot loader created for no sane reason whatsoever?
Could you tell us where exactly boot loader creates measurements for the DRTM?
Daniel
On Thu, Aug 11, 2022 at 07:25:58PM +0930, Brendan Trotter wrote:
> Hi,
>
> On Thu, Aug 11, 2022 at 3:16 AM Matthew Garrett <[email protected]> wrote:
> > The kernel has no way to know this - *any* code you've run before
> > performing a measurement could tamper with the kernel such that it
> > believes it's fine. This is just as true in DRTM as it is in SRTM. But
> > you know what the expected measurements should be, so you're able to
> > either seal secrets to those PCR values or rely on remote attestation.
>
> In this scenario the kernel has no idea what the measurement should
> be, it only knows the measurement that a potentially malicious boot
> loader felt like giving the kernel previously (e.g. when the kernel
> was installed).
Even if the kernel has an idea of what the measurement should be, it has
no way to verify that what it believes to be true is true - any
malicious code could simply have modified the kernel to believe that
anything it asks the TPM returns the "correct" answer.
> > Measurements are not opaque objects. If you're not able to reconstruct
> > the expected measurement then you're doing it wrong.
>
> OK; so to detect if boot loader has always given kernel a bad/forged
> measurement; the kernel repeats all of the steps involved in creating
> the measurement itself exactly the same as the boot loader should have
> (but might not have) so that kernel can compare a "known
> good/trustworthy" measurement with the useless measurement that the
> boot loader created for no sane reason whatsoever?
No, some external agent does. Code running on the local machine can
never determine whether the machine is trustworthy.
Hi,
On Fri, Aug 12, 2022 at 3:55 AM Matthew Garrett <[email protected]> wrote:
> On Thu, Aug 11, 2022 at 07:25:58PM +0930, Brendan Trotter wrote:
> > On Thu, Aug 11, 2022 at 3:16 AM Matthew Garrett <[email protected]> wrote:
> > > The kernel has no way to know this - *any* code you've run before
> > > performing a measurement could tamper with the kernel such that it
> > > believes it's fine. This is just as true in DRTM as it is in SRTM. But
> > > you know what the expected measurements should be, so you're able to
> > > either seal secrets to those PCR values or rely on remote attestation.
> >
> > In this scenario the kernel has no idea what the measurement should
> > be, it only knows the measurement that a potentially malicious boot
> > loader felt like giving the kernel previously (e.g. when the kernel
> > was installed).
>
> Even if the kernel has an idea of what the measurement should be, it has
> no way to verify that what it believes to be true is true - any
> malicious code could simply have modified the kernel to believe that
> anything it asks the TPM returns the "correct" answer.
Right. To achieve the best possible security; you'd need Secure Boot
to ensure that the kernel itself wasn't modified, and then the kernel
establishes a dynamic root of trust itself.
Anything involving a boot loader (e.g. Secure Boot ensure's boot
loader wasn't modified, then boot loader ensure's kernel wasn't
modified, then ....) increases the attack surface for no benefit.
> > > Measurements are not opaque objects. If you're not able to reconstruct
> > > the expected measurement then you're doing it wrong.
> >
> > OK; so to detect if boot loader has always given kernel a bad/forged
> > measurement; the kernel repeats all of the steps involved in creating
> > the measurement itself exactly the same as the boot loader should have
> > (but might not have) so that kernel can compare a "known
> > good/trustworthy" measurement with the useless measurement that the
> > boot loader created for no sane reason whatsoever?
>
> No, some external agent does. Code running on the local machine can
> never determine whether the machine is trustworthy.
This part of the conversation evolved from "there's no way for kernel
to detect a MiTM boot loader (that provides a bad/forged
measurement)".
I'm not convinced an external agent can detect "bad/forged
measurement" either. E.g. if a MiTM boot loader always provided a
bad/forged measurement the external agent won't detect it (as the
measurement always matches the expected measurement), and then if the
MiTM boot loader is replaced by a good/honest boot loader the external
agent will decide that the good/honest boot loader is malicious
because its measurement doesn't match the expected bad/forged
measurement.
- Brendan
On Fri, Aug 12, 2022 at 12:52:58PM +0930, Brendan Trotter wrote:
> Hi,
>
> On Fri, Aug 12, 2022 at 3:55 AM Matthew Garrett <[email protected]> wrote:
> > On Thu, Aug 11, 2022 at 07:25:58PM +0930, Brendan Trotter wrote:
> > > On Thu, Aug 11, 2022 at 3:16 AM Matthew Garrett <[email protected]> wrote:
> > > > The kernel has no way to know this - *any* code you've run before
> > > > performing a measurement could tamper with the kernel such that it
> > > > believes it's fine. This is just as true in DRTM as it is in SRTM. But
> > > > you know what the expected measurements should be, so you're able to
> > > > either seal secrets to those PCR values or rely on remote attestation.
> > >
> > > In this scenario the kernel has no idea what the measurement should
> > > be, it only knows the measurement that a potentially malicious boot
> > > loader felt like giving the kernel previously (e.g. when the kernel
> > > was installed).
> >
> > Even if the kernel has an idea of what the measurement should be, it has
> > no way to verify that what it believes to be true is true - any
> > malicious code could simply have modified the kernel to believe that
> > anything it asks the TPM returns the "correct" answer.
>
> Right. To achieve the best possible security; you'd need Secure Boot
> to ensure that the kernel itself wasn't modified, and then the kernel
> establishes a dynamic root of trust itself.
You can't rely on Secure Boot because compromised firmware might fail to
implement it, so you're back to relying on dynamic trust.
> Anything involving a boot loader (e.g. Secure Boot ensure's boot
> loader wasn't modified, then boot loader ensure's kernel wasn't
> modified, then ....) increases the attack surface for no benefit.
I honestly feel like we're talking about different things. Can you
describe the attack vector you're concerned about here?
> I'm not convinced an external agent can detect "bad/forged
> measurement" either. E.g. if a MiTM boot loader always provided a
> bad/forged measurement the external agent won't detect it (as the
> measurement always matches the expected measurement), and then if the
> MiTM boot loader is replaced by a good/honest boot loader the external
> agent will decide that the good/honest boot loader is malicious
> because its measurement doesn't match the expected bad/forged
> measurement.
The point of DRTM is that the platform (in the form of an authenticated
code module running on the CPU, outside of the control of the OS)
performs a measreument of a specific point in time. The policy it's
provided with allows an external agent to identify which component of
the runtime system is being measured. If an external malicious agent has
been executed then the measurement will be different as a result.