On 02/13/18 21:29, Stefan Berger wrote:
> On 02/13/2018 02:59 PM, Laszlo Ersek wrote:
>> On 02/13/18 20:37, Kevin O'Connor wrote:
>>> On Tue, Feb 13, 2018 at 05:16:49PM +0100, Laszlo Ersek wrote:
>>>> On 02/12/18 21:49, Stefan Berger wrote:
>>>>> On 02/12/2018 03:46 PM, Kevin O'Connor wrote:
>>>>>> I'm not sure I fully understand the goals of the PPI interface.
>>>>>> Here's what I understand so far:
>>>>>> The TPM specs define some actions that are considered privileged.  An
>>>>>> example of this would be disabling the TPM itself.  In order to
>>>>>> prevent an attacker from performing these actions without
>>>>>> authorization, the TPM specs define a mechanism to assert "physical
>>>>>> presence" before the privileged action can be done.  They do this by
>>>>>> having the firmware present a menu during early boot that permits
>>>>>> these privileged operations, and then the firmware locks the TPM chip
>>>>>> so the actions can no longer be done by any software that runs after
>>>>>> the firmware.  Thus "physical presence" is asserted by demonstrating
>>>>>> one has console access to the machine during early boot.
>>>>>> The PPI spec implements a work around for this - presumably some
>>>>>> found
>>>>>> the enforcement mechanism too onerous.  It allows the OS to provide a
>>>>>> request code to the firmware, and on the next boot the firmware will
>>>>>> take the requested action before it locks the chip.  Thus allowing
>>>>>> the
>>>>>> OS to indirectly perform the privileged action even after the chip
>>>>>> has
>>>>>> been locked.  Thus, the PPI system seems to be an "elaborate hack" to
>>>>>> allow users to circumvent the physical presence mechanism (if they
>>>>>> choose to).
>>>>> Correct.
>>>>>> Here's what I understand the proposed implementation involves:
>>>>>> 1 - in addition to emulating the TPM device itself, QEMU will also
>>>>>>       introduce a virtual memory device with 0x400 bytes.
>>>>> Correct.
>>>>>> 2 - on first boot the firmware (seabios and uefi) will populate the
>>>>>>       memory region created in step 1.  In particular it will fill an
>>>>>>       array with the list of request codes it supports.  (Each
>>>>>> request
>>>>>>       is an 8bit value, the array has 256 entries.)
>>>>> Correct. Each firmware would fill out the 256 byte array depending on
>>>>> what it supports. The 8 bit values are basically flags and so on.
>>>>>> 3 - QEMU will produce AML code implementing the standard PPI ACPI
>>>>>>       interface.  This AML code will take the request, find the table
>>>>>>       produced in step 1, compare it to the list of accepted requests
>>>>>>       produced in step 2, and then place the 8bit request in another
>>>>>>       qemu virtual memory device (at 0xFFFF0000 or 0xFED45000).
>>>>> Correct.
>>>>> Now EDK2 wants to store the code in a UEFI variable in NVRAM. We
>>>>> therefore would need to trigger an SMI. In SeaBIOS we wouldn't have to
>>>>> do this.
>>>>>> 4 - the OS will signal a reboot, qemu will do its normal reboot
>>>>>> logic,
>>>>>>       and the firmware will be run again.
>>>>>> 5 - the firmware will extract the code written in stage 3, and if the
>>>>>>       tpm device has been configured to accept PPI codes from the
>>>>>> OS, it
>>>>>>       will invoke the requested action.
>>>>> SeaBIOS would look into memory to find the code. EDK2 will read the
>>>>> code
>>>>> from a UEFI variable.
>>>>>> Did I understand the above correctly?
>>>>> I think so. With the fine differences between SeaBIOS and EDK2
>>>>> pointed out.
>>>> Here's what I suggest:
>>>> Please everyone continue working on this, according to Kevin's &
>>>> Stefan's description, but focus on QEMU and SeaBIOS *only*. Ignore edk2
>>>> for now.
>>> If this were targetted at SeaBIOS, I'd look for a simpler
>>> QEMU/firmware interface.  Something like:
>>> A - QEMU produces AML code implementing the standard PPI ACPI
>>>      interface that generates a request code and stores it in the
>>>      device memory of an existing device (eg, writable fw_cfg or an
>>>      extension field in the existing emulated TPM device).
> ACPI code writing into fw_cfg sounds difficult.
> I initially had PPI SeaBIOS code write into the TPM TIS device's memory
> into some custom addresses. I'd consider this a hack. Now we have that
> virtual memory device with those 0x400 bytes...
> In these 0x400 bytes we have 256 bytes that are used for configuration
> flags describing the supported opcode as you previously described. This
> array allows us to decouple the firmware implementation from the ACPI
> code and we need not hard code what is supported in the firmware inside
> the ACPI code (which would be difficult to do anyway since in QEMU we
> would not what firmware will be started and what PPI opcodes are
> support) and the ppi sysfs entries in Linux for example show exactly
> those PPI opcodes that are supported. The firmware needs to set those
> flags and the firmware knows what it supports.
> I hope we can settle that this device is the right path.
>>> B - after a reboot the firmware extracts the PPI request code
>>>      (produced in step A) and performs the requested action (if the TPM
>>>      is configured to accept OS generated codes).
>>> That is, skip steps 1 and 2 from the original proposal.
>> I think A/B can work fine, as long as
>> - the firmware can somehow dynamically recognize the device / "register
>>    block" that the request codes have to be pulled from, and
> I experimented with what Igor had suggested with the fw_cfg file
> callback and so on.
>> - QEMU is free to move the device or register block around, from release
>>    to release, without disturbing migration.
> I think we should basically limit the firmware to writing two addresses
> into this fw_cfg file:
> - SeaBIOS: write back the same address that QEMU suggested in the file
> (currently 0xfed4 5000)
> - EDK2: write back 0xffff 0000
Given that I intend to rip the SecurityPkg ASL code out of OVMF's
solution for this, I don't think that the address 0xffff_0000 has any
relevance for OVMF. If the QEMU x86 MMIO space generally has a suitable
gap at 0xfed4_5000 (and I do think it has, even considering pflash &
LAPIC), then just put the register block there.

As long as Igor agrees. :)

Another question just occurred to me. If the guest OS queues some PPI
operations, and then the VM is powered down fully (instead of a reboot),
then we're at liberty to forget the queued PPI ops, right?


> No other address would be accepted by QEMU since presumably QEMU knows
> where otherwise address collisions can occur.

Reply via email to