All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] investigating TPM for OVMF-on-QEMU
@ 2017-07-14 18:04 Laszlo Ersek
  2017-07-14 20:30 ` Peter Jones
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Laszlo Ersek @ 2017-07-14 18:04 UTC (permalink / raw)
  To: Jiewen Yao, Stefan Berger, Javier Martinez Canillas, Peter Jones,
	Marc-André Lureau, Amarnath Valluri
  Cc: edk2-devel-01, qemu devel list

Hi,

I spent most of today reading TPM related material (specs, guides and
source code), and below I'd like to describe what I think should be our
initial attack on enabling TPM on QEMU/OVMF.

(1) Versions of UEFI abstractions regarding TPM (very roughly speaking):

    There have been three sets of specs for this, and accordingly,
    edk2's SecurityPkg/Tcg/ directory supports each set. We can call
    these TPM1, TrEE, and TPM2.

    - TPM1 was the initial TPM thing, supporting only SHA-1, and is now
      obsolete.

    - TrEE was Microsoft's own update to the TPM1 software interfaces,
      supporting TPM2 hardware with more hash algorithms, and is now
      obsolete. Because,

    - TPM2 is basically the standardized version of TrEE, the most
      recent set of specs, and what we should focus on.

(2) Drivers (and features) in edk2/SecurityPkg/Tcg.

    There are 19 modules under SecurityPkg/Tcg/. Let me categorize them.
    In each category, I'll try to list modules in loosely increasing
    dependency (or PI/UEFI phase) order.

(2a) Modules that are obsolete because they are tied to TPM1:

       TcgPei/TcgPei.inf
       PhysicalPresencePei/PhysicalPresencePei.inf
       TcgDxe/TcgDxe.inf
       TcgConfigDxe/TcgConfigDxe.inf
       TcgSmm/TcgSmm.inf

     The TPM enablement instructions at

       https://github.com/tianocore/tianocore.github.io/wiki/How-to-Enable-Security#Enabling_Trusted_Compute_Module_TPM

     are written up in terms of these modules, but that doesn't obsolete
     the article too much.

(2b) Modules that are obsolete due to being tied to TrEE:

       TrEEConfig/TrEEConfigPei.inf
       TrEEPei/TrEEPei.inf
       TrEEDxe/TrEEDxe.inf
       TrEEConfig/TrEEConfigDxe.inf
       TrEESmm/TrEESmm.inf

     There is a great Intel whitepaper called

       A Tour Beyond BIOS with the UEFI TPM2 Support in EDKII

     which is written in terms of TrEE and these modules, explaining how
     they supersede TPM1 and the modules under (2a).

     This whitepaper seems to apply to the most recent TPM2 stack as
     well (mostly just replace TrEE references with TPM2 references), so
     it is very useful.

(2c) Modules that call themselves obsolete or deprecated (without being
     obviously tied to TPM1 or TrEE):

       MemoryOverwriteRequestControlLock/TcgMorLockSmm.inf

(2d) Modules that we won't need due to no hardware support in QEMU:

       Opal/OpalPasswordDxe/OpalPasswordDxe.inf
       Opal/OpalPasswordSmm/OpalPasswordSmm.inf

     TCG's "Opal" seems to be about self-encrypting drives, see

       https://en.wikipedia.org/wiki/Opal_Storage_Specification

     so these modules are not relevant for us.

(2e) Modules that we should use. Again, in increasing order of
     dependence. And here I'll comment as well on what these do:

       Tcg2Config/Tcg2ConfigPei.inf -- Informs the firmware globally
                                       about the TPM device type. This
                                       module can perform device
                                       detection or read a cached value
                                       from a non-volatile UEFI
                                       variable.

       Tcg2Pei/Tcg2Pei.inf          -- Initializes the TPM device and
                                       measures the firmware volumes in
                                       the PEI phase into the TPM's
                                       platform config registers.

       Tcg2Dxe/Tcg2Dxe.inf          -- Measures DXE phase (and later)
                                       modules into the TPM's PCRs, and
                                       also lets the OS boot loader
                                       measure things, by exposing the
                                       EFI_TCG2_PROTOCOL.

       Tcg2Config/Tcg2ConfigDxe.inf -- Provides a Setup TUI interface to
                                       configure the TPM. IIUC, it can
                                       also save the configured TPM type
                                       for subsequent boots (see
                                       Tcg2ConfigPei.inf above).

     This driver stack supports the TIS (MMIO) hardware interface, which
     is advertized to the OS in the TPM2 ACPI Table's "start method"
     field with value 6. (The according macro is TPM2_START_METHOD_MMIO
     in the QEMU source code, and EFI_TPM2_ACPI_TABLE_START_METHOD_TIS
     in the edk2 source code.)

     Including these drivers should result in a functional
     EFI_TCG2_PROTOCOL, which is what OS boot loaders primarily care
     about, as I understand.

     Importantly, the driver stack above requires PEI-phase variable
     access, therefore
     <https://bugzilla.tianocore.org/show_bug.cgi?id=386> must be solved
     first.

     (I have had patches for said BZ ready for a while. I've failed to
     upstream them thus far because a pflash-based varstore is a hard
     requirement for them. I think that's a natural requirement, but
     thus far my arguments haven't proved compelling enough.)

     Here I should mention some ACPI and hardware aspects. Under TPM1
     (whose ACPI table was called "TCPA"), the TPM events (measurements
     I think) were logged in a reserved memory area described by the
     TCPA table. Under TPM2, the "TPM2" ACPI table does no such thing,
     it only helps identify the communication characteristics of the
     device, and the event log itself is accessible to the OS boot
     loader via the EFI_TCG2_PROTOCOL.

     (If you are curious how a legacy BIOS boot loader is supposed to
     read the event log from a TPM2-only device (no "TCPA" table): I
     don't have the slightest clue.)

     I'm not sure about the exact characteristics of the virtual TPM
     that Stefan's swtpm project:

       https://github.com/stefanberger/swtpm

     combined with Amarnath's pending QEMU patches:

       http://mid.mail-archive.com/1496666711-14630-1-git-send-email-amarnath.valluri@intel.com

     will expose to the guest. What I do know is that the current QEMU
     solution, which mostly forwards a physical (host) TPM to the guest,
     produces a "TPM2" ACPI table if said host TPM device is TPM2. The
     "TPM2" table is exposed to the guest OS with OVMF's help, and has
     the following fields:

     - address of control area: zero
     - start method: 6 (TIS plus Cancel)
     - platform specific params: none.

     This implies that neither ACPI activation (method 2) nor Command
     Response Buffer activation (method 7) nor a combination of these
     two (method 8) is available in QEMU.

     And that should be just fine, because both Linux and the above
     Tcg2* modules appear to support this (from reading, not from
     testing).

(2f) Modules that we *could* use, but *should not*, at this point:

       MemoryOverwriteControl/TcgMor.inf

     MOR is "Memory Overwrite Request". It is a feature specified
     separately, in another TCG specification ("Platform Reset Attack
     Mitigation"), and it is optional for a firmware platform to
     support. (For example, as far as I can see, Linux doesn't even try
     to detect or use it.) If you care about the threat model and how
     MOR mitigates that threat, please read the spec on the TCG website.

     For initial TPM enablement in OVMF, we should avoid MOR support.
     The module above initializes the "MemoryOverwriteRequestControl"
     variable, which is one third of the MOR implementation.

       Tcg2Smm/Tcg2Smm.inf

     This is a complex driver that we *should not* use at this point:

     (2f1) It installs two ACPI tables. One of those is a "TPM2" ACPI
           table, according to the detected / configured TPM device (see
           under (2e). This "TPM2" table would conflict with -- or more
           precisely, duplicate -- the "TPM2" table already generated by
           QEMU, and installed by OVMF.

     (2f2) The other ACPI table is an SSDT which provides a _DSM (Device
           Specific Method) to the guest OS. Whenever the _DSM is
           called, the firmware is entered (via SMI/SMM), and the OS
           request is handled. Three sets of functions are provided:

           (2f2a) TCG Hardware Information. Not needed by the guest
                  OS(es), the TIS+Cancel start method is sufficient.

           (2f2b) TCG Memory Clear Interface. This is the second third
                  of the MOR feature I mentioned above. It saves the OS
                  request in the "MemoryOverwriteRequestControl"
                  variable (only writeable in SMM).

                  Upon next boot, OVMF's PlatformPei would have to clear
                  all memory -- this would be the last third of the MOR
                  feature; see under:

                    https://github.com/tianocore/tianocore.github.io/wiki/How-to-Enable-Security#Enabling_Trusted_Compute_Module_TPM

                  However, clearing all memory in OVMF's PlatformPei
                  would be a *real* pain, as we are limited to the
                  32-bit address space there (yes, even if OVMF's PEI
                  phase is built in 64-bit mode). In physical firmware,
                  where DRAM takes actual hardware initialization, the
                  clearing can likely occur without entering long mode
                  and setting up large page tables (e.g., the memory
                  controller itself could be programmed with IO
                  accesses), so in this case physical firmware has it
                  easier.

                  Again, Linux doesn't care about MOR.

           (2f2c) TCG Physical Presence Interface. The OS can queue TPM
                  operations (?) that require Physical Presence, and at
                  next boot, OVMF's PlatformBootManagerLib (in the BDS
                  phase) would have to dispatch those pending
                  operations. (The queueing again happens in protected
                  non-volatile UEFI variables -- writeable only in SMM.)

                  This is of dubious usefulness, and presents extra
                  complication for OVMF. Said dispatching is supposed to
                  occur *before* signaling the end-of-DXE event group
                  (according to the Intel whitepaper mentioned above),
                  but *after* the console is ready (according to the
                  wiki article linked above). However, OVMF *already*
                  signals the end-of-DXE event group in
                  PlatformBootManagerBeforeConsole(), that is, *before*
                  the console is ready. Many things are orchestrated
                  around end-of-DXE, so moving around its signaling
                  looks difficult.

                  Also, while Linux appears to be capable of using
                  Physical Presence, it is again optional, and I suggest
                  to ignore it at first.

     In brief, by not including these two modules, we avoid a "TPM2"
     ACPI table duplication. We also turn off the Memory Overwrite
     Request and Physical Presence Interface features -- which are both
     optional, as far as I can see, and very messy for OVMF's platform
     code.

(3) Drivers (and features) that are *not in edk2/SecurityPkg/Tcg:

    The Intel whitepaper discusses (and Peter also mentioned earlier)
    "dTPM" versus "fTPM".

    "dTPM" is basically TPM provided in publicly specified hardware,
    where the firmware can offer support, such as EFI_TCG2_PROTOCOL, but
    the OS can also directly drive the hardware. This is what QEMU
    offers with the TIS+Cancel start method (value 6). (The "Command
    Response Buffer" start method (value 7) would also qualify as
    "dTPM"). When the platform provides "dTPM", the _DSM method
    described above *may* be offered, but it is not required.

    "fTPM" is where the hardware is completely hidden from the OS, and
    is implemented fully in firmware. The corresponding start method
    values are 2 ("ACPI") and 8 ("ACPI with CRB"). In this case, the
    _DSM method is *required*.

    To my understanding, edk2 contains no "fTPM" implementation. The
    in-tree drivers recognize hardware that describes itself as
    TIS+Cancel (6) or CRB (7). Pure ACPI variants are neither recognized
    nor offered.

    I think TIS+Cancel / dTPM is the best match: the emulated TPM has to
    be implemented in virtual hardware (not just faked within the guest,
    in RAM), so that QEMU can secure the sensitive stuff from guest
    kernel level access.

I'm going to link this post from
<https://bugzilla.tianocore.org/show_bug.cgi?id=594>; please consider
registering in the TianoCore BZ and subscribing to that bug. Discussion
should occur on the list(s), but it's nice to capture separate threads
and distilled ideas in the BZ.

Thanks
Laszlo

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] investigating TPM for OVMF-on-QEMU
  2017-07-14 18:04 [Qemu-devel] investigating TPM for OVMF-on-QEMU Laszlo Ersek
@ 2017-07-14 20:30 ` Peter Jones
  2017-07-14 21:31   ` [Qemu-devel] [edk2] " Laszlo Ersek
  2017-07-17  2:03 ` [Qemu-devel] " Yao, Jiewen
  2017-07-17  9:04 ` Javier Martinez Canillas
  2 siblings, 1 reply; 5+ messages in thread
From: Peter Jones @ 2017-07-14 20:30 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Jiewen Yao, Stefan Berger, Javier Martinez Canillas,
	Marc-André Lureau, Amarnath Valluri, edk2-devel-01,
	qemu devel list

On Fri, Jul 14, 2017 at 08:04:14PM +0200, Laszlo Ersek wrote:

>     - TPM2 is basically the standardized version of TrEE, the most
>       recent set of specs, and what we should focus on.

100% agreed.

> (2) Drivers (and features) in edk2/SecurityPkg/Tcg.
> 
>     There are 19 modules under SecurityPkg/Tcg/. Let me categorize them.
>     In each category, I'll try to list modules in loosely increasing
>     dependency (or PI/UEFI phase) order.
> 
> (2a) Modules that are obsolete because they are tied to TPM1:
> 
>        TcgPei/TcgPei.inf
>        PhysicalPresencePei/PhysicalPresencePei.inf
>        TcgDxe/TcgDxe.inf
>        TcgConfigDxe/TcgConfigDxe.inf
>        TcgSmm/TcgSmm.inf
> 
>      The TPM enablement instructions at
> 
>        https://github.com/tianocore/tianocore.github.io/wiki/How-to-Enable-Security#Enabling_Trusted_Compute_Module_TPM
> 
>      are written up in terms of these modules, but that doesn't obsolete
>      the article too much.
> 
> (2b) Modules that are obsolete due to being tied to TrEE:
> 
>        TrEEConfig/TrEEConfigPei.inf
>        TrEEPei/TrEEPei.inf
>        TrEEDxe/TrEEDxe.inf
>        TrEEConfig/TrEEConfigDxe.inf
>        TrEESmm/TrEESmm.inf
> 
>      There is a great Intel whitepaper called
> 
>        A Tour Beyond BIOS with the UEFI TPM2 Support in EDKII
> 
>      which is written in terms of TrEE and these modules, explaining how
>      they supersede TPM1 and the modules under (2a).
> 
>      This whitepaper seems to apply to the most recent TPM2 stack as
>      well (mostly just replace TrEE references with TPM2 references), so
>      it is very useful.
> 
> (2c) Modules that call themselves obsolete or deprecated (without being
>      obviously tied to TPM1 or TrEE):
> 
>        MemoryOverwriteRequestControlLock/TcgMorLockSmm.inf

Definitely do not care.

> (2d) Modules that we won't need due to no hardware support in QEMU:
> 
>        Opal/OpalPasswordDxe/OpalPasswordDxe.inf
>        Opal/OpalPasswordSmm/OpalPasswordSmm.inf
> 
>      TCG's "Opal" seems to be about self-encrypting drives, see
> 
>        https://en.wikipedia.org/wiki/Opal_Storage_Specification
> 
>      so these modules are not relevant for us.

Well, at some point somebody's going to want us to implement this,
but... they can do that when they do that.  Personally I'm never going
to trust on-drive encryption not to have an escrow key I don't know
about and can't remove, so it's a bit of a non-starter, but that's
neither here nor there.

> (2e) Modules that we should use. Again, in increasing order of
>      dependence. And here I'll comment as well on what these do:
> 
>        Tcg2Config/Tcg2ConfigPei.inf -- Informs the firmware globally
>                                        about the TPM device type. This
>                                        module can perform device
>                                        detection or read a cached value
>                                        from a non-volatile UEFI
>                                        variable.
> 
>        Tcg2Pei/Tcg2Pei.inf          -- Initializes the TPM device and
>                                        measures the firmware volumes in
>                                        the PEI phase into the TPM's
>                                        platform config registers.
> 
>        Tcg2Dxe/Tcg2Dxe.inf          -- Measures DXE phase (and later)
>                                        modules into the TPM's PCRs, and
>                                        also lets the OS boot loader
>                                        measure things, by exposing the
>                                        EFI_TCG2_PROTOCOL.
> 
>        Tcg2Config/Tcg2ConfigDxe.inf -- Provides a Setup TUI interface to
>                                        configure the TPM. IIUC, it can
>                                        also save the configured TPM type
>                                        for subsequent boots (see
>                                        Tcg2ConfigPei.inf above).
> 
>      This driver stack supports the TIS (MMIO) hardware interface, which
>      is advertized to the OS in the TPM2 ACPI Table's "start method"
>      field with value 6. (The according macro is TPM2_START_METHOD_MMIO
>      in the QEMU source code, and EFI_TPM2_ACPI_TABLE_START_METHOD_TIS
>      in the edk2 source code.)
> 
>      Including these drivers should result in a functional
>      EFI_TCG2_PROTOCOL, which is what OS boot loaders primarily care
>      about, as I understand.
> 
>      Importantly, the driver stack above requires PEI-phase variable
>      access, therefore
>      <https://bugzilla.tianocore.org/show_bug.cgi?id=386> must be solved
>      first.
> 
>      (I have had patches for said BZ ready for a while. I've failed to
>      upstream them thus far because a pflash-based varstore is a hard
>      requirement for them. I think that's a natural requirement, but
>      thus far my arguments haven't proved compelling enough.)

It does seem pretty natural... what's the counter argument?

>      Here I should mention some ACPI and hardware aspects. Under TPM1
>      (whose ACPI table was called "TCPA"), the TPM events (measurements
>      I think) were logged in a reserved memory area described by the
>      TCPA table. Under TPM2, the "TPM2" ACPI table does no such thing,
>      it only helps identify the communication characteristics of the
>      device, and the event log itself is accessible to the OS boot
>      loader via the EFI_TCG2_PROTOCOL.

Sadly EFI_TCG2_PROTOCOL and/or the TPM2 Configuration Table, with a not
completely clear merge method, but yeah.  I've got a linux kernel
implementation for this in progress here:
https://github.com/vathpela/linux/commits/efi-tpm2
and mjg59 told me on Tuesday that he was going to do some more with this
on Wednesday, but I haven't heard back from him yet.

>      (If you are curious how a legacy BIOS boot loader is supposed to
>      read the event log from a TPM2-only device (no "TCPA" table): I
>      don't have the slightest clue.)

Don't worry, we're not - based on the history of turning on TPM1
features in grub2 in Fedora betas, I've got exactly no interest in
making this work on BIOS.

>      I'm not sure about the exact characteristics of the virtual TPM
>      that Stefan's swtpm project:
> 
>        https://github.com/stefanberger/swtpm
> 
>      combined with Amarnath's pending QEMU patches:
> 
>        http://mid.mail-archive.com/1496666711-14630-1-git-send-email-amarnath.valluri@intel.com
> 
>      will expose to the guest.

It looks to me (reading both source trees quickly with grep) like
there's enough done in hw/tpm/tpm_tis.c:tpm_tis_realizefn() there that
it should be pretty straightforward to set PcdTpmBaseAddress and have
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c support it.

>      What I do know is that the current QEMU
>      solution, which mostly forwards a physical (host) TPM to the guest,
>      produces a "TPM2" ACPI table if said host TPM device is TPM2. The
>      "TPM2" table is exposed to the guest OS with OVMF's help, and has
>      the following fields:
> 
>      - address of control area: zero
>      - start method: 6 (TIS plus Cancel)
>      - platform specific params: none.
> 
>      This implies that neither ACPI activation (method 2) nor Command
>      Response Buffer activation (method 7) nor a combination of these
>      two (method 8) is available in QEMU.
> 
>      And that should be just fine, because both Linux and the above
>      Tcg2* modules appear to support this (from reading, not from
>      testing).

Yeah, that matches my reading so far, except the part where the kernel
just fails to give any of the useful info to us if we're not on
OpenFirmware on Power (and thus my github link above).

> (2f) Modules that we *could* use, but *should not*, at this point:
> 
>        MemoryOverwriteControl/TcgMor.inf
> 
>      MOR is "Memory Overwrite Request". It is a feature specified
>      separately, in another TCG specification ("Platform Reset Attack
>      Mitigation"), and it is optional for a firmware platform to
>      support. (For example, as far as I can see, Linux doesn't even try
>      to detect or use it.) If you care about the threat model and how
>      MOR mitigates that threat, please read the spec on the TCG website.

Yeah, that looks like we've already lost the whole ball game if we need
that.

<snip on lots of the detailed analysis here>

>      In brief, by not including these two modules, we avoid a "TPM2"
>      ACPI table duplication. We also turn off the Memory Overwrite
>      Request and Physical Presence Interface features -- which are both
>      optional, as far as I can see, and very messy for OVMF's platform
>      code.

Yeah, we don't need or want this.

> (3) Drivers (and features) that are *not in edk2/SecurityPkg/Tcg:
> 
>     The Intel whitepaper discusses (and Peter also mentioned earlier)
>     "dTPM" versus "fTPM".
> 
>     "dTPM" is basically TPM provided in publicly specified hardware,
>     where the firmware can offer support, such as EFI_TCG2_PROTOCOL, but
>     the OS can also directly drive the hardware. This is what QEMU
>     offers with the TIS+Cancel start method (value 6). (The "Command
>     Response Buffer" start method (value 7) would also qualify as
>     "dTPM"). When the platform provides "dTPM", the _DSM method
>     described above *may* be offered, but it is not required.

Right - this is the same thing I noted above.

> 
>     "fTPM" is where the hardware is completely hidden from the OS, and
>     is implemented fully in firmware. The corresponding start method
>     values are 2 ("ACPI") and 8 ("ACPI with CRB"). In this case, the
>     _DSM method is *required*.
> 
>     To my understanding, edk2 contains no "fTPM" implementation. The
>     in-tree drivers recognize hardware that describes itself as
>     TIS+Cancel (6) or CRB (7). Pure ACPI variants are neither recognized
>     nor offered.

MSFT keeps claiming they're going to release an edk2-licensed fTPM
implementation; I keep on not seeing it.

>     I think TIS+Cancel / dTPM is the best match: the emulated TPM has to
>     be implemented in virtual hardware (not just faked within the guest,
>     in RAM), so that QEMU can secure the sensitive stuff from guest
>     kernel level access.

This sounds right to me.

> I'm going to link this post from
> <https://bugzilla.tianocore.org/show_bug.cgi?id=594>; please consider
> registering in the TianoCore BZ and subscribing to that bug. Discussion
> should occur on the list(s), but it's nice to capture separate threads
> and distilled ideas in the BZ.

Okay.

-- 
  Peter

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [edk2] investigating TPM for OVMF-on-QEMU
  2017-07-14 20:30 ` Peter Jones
@ 2017-07-14 21:31   ` Laszlo Ersek
  0 siblings, 0 replies; 5+ messages in thread
From: Laszlo Ersek @ 2017-07-14 21:31 UTC (permalink / raw)
  To: Peter Jones
  Cc: Amarnath Valluri, Stefan Berger, edk2-devel-01,
	Javier Martinez Canillas, qemu devel list, Jiewen Yao,
	Marc-André Lureau

On 07/14/17 22:30, Peter Jones wrote:
> On Fri, Jul 14, 2017 at 08:04:14PM +0200, Laszlo Ersek wrote:

>> (2e) Modules that we should use. Again, in increasing order of
>>      dependence. And here I'll comment as well on what these do:
>>
>>        Tcg2Config/Tcg2ConfigPei.inf -- Informs the firmware globally
>>                                        about the TPM device type. This
>>                                        module can perform device
>>                                        detection or read a cached value
>>                                        from a non-volatile UEFI
>>                                        variable.
>>
>>        Tcg2Pei/Tcg2Pei.inf          -- Initializes the TPM device and
>>                                        measures the firmware volumes in
>>                                        the PEI phase into the TPM's
>>                                        platform config registers.
>>
>>        Tcg2Dxe/Tcg2Dxe.inf          -- Measures DXE phase (and later)
>>                                        modules into the TPM's PCRs, and
>>                                        also lets the OS boot loader
>>                                        measure things, by exposing the
>>                                        EFI_TCG2_PROTOCOL.
>>
>>        Tcg2Config/Tcg2ConfigDxe.inf -- Provides a Setup TUI interface to
>>                                        configure the TPM. IIUC, it can
>>                                        also save the configured TPM type
>>                                        for subsequent boots (see
>>                                        Tcg2ConfigPei.inf above).
>>
>>      This driver stack supports the TIS (MMIO) hardware interface, which
>>      is advertized to the OS in the TPM2 ACPI Table's "start method"
>>      field with value 6. (The according macro is TPM2_START_METHOD_MMIO
>>      in the QEMU source code, and EFI_TPM2_ACPI_TABLE_START_METHOD_TIS
>>      in the edk2 source code.)
>>
>>      Including these drivers should result in a functional
>>      EFI_TCG2_PROTOCOL, which is what OS boot loaders primarily care
>>      about, as I understand.
>>
>>      Importantly, the driver stack above requires PEI-phase variable
>>      access, therefore
>>      <https://bugzilla.tianocore.org/show_bug.cgi?id=386> must be solved
>>      first.
>>
>>      (I have had patches for said BZ ready for a while. I've failed to
>>      upstream them thus far because a pflash-based varstore is a hard
>>      requirement for them. I think that's a natural requirement, but
>>      thus far my arguments haven't proved compelling enough.)
>
> It does seem pretty natural... what's the counter argument?

Jordan holds the opinion that "we should continue to support the memory
vars, even if they have some obvious drawbacks":

http://mid.mail-archive.com/149065122031.28789.9113394760317457361@jljusten-skl

I'm of a different opinion: while I agree that we should not break the
existing memory emulation, I'm also convinced that we should not develop
new features for it, especially when a new feature (such as PEI-phase
R/O variable access) simply cannot be *sensibly* extended to said
emulation.

Please see the first discussion under my original patch set:

http://mid.mail-archive.com/148969026858.27582.5519307275216644796@jljusten-skl.jf.intel.com
http://mid.mail-archive.com/319ff8f1-4e99-f977-5c2e-75509a222706@redhat.com
http://mid.mail-archive.com/c20c6604-2153-aa57-cee5-24089a79b1e9@redhat.com
http://mid.mail-archive.com/149034108785.2439.14733776608486243050@jljusten-skl
http://mid.mail-archive.com/4b06b195-d8fb-a33e-3492-74fe396ebf6e@redhat.com

And the second discussion under Jordan's counter-proposal:

http://mid.mail-archive.com/a12bbf61-3f55-2fda-b855-58aeb99a4f42@redhat.com
http://mid.mail-archive.com/149065122031.28789.9113394760317457361@jljusten-skl
http://mid.mail-archive.com/121bb81b-08d1-d854-cf6f-ebc8268eb360@redhat.com
http://mid.mail-archive.com/149076505135.12962.12298731900768295093@jljusten-skl

Thanks
Laszlo

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] investigating TPM for OVMF-on-QEMU
  2017-07-14 18:04 [Qemu-devel] investigating TPM for OVMF-on-QEMU Laszlo Ersek
  2017-07-14 20:30 ` Peter Jones
@ 2017-07-17  2:03 ` Yao, Jiewen
  2017-07-17  9:04 ` Javier Martinez Canillas
  2 siblings, 0 replies; 5+ messages in thread
From: Yao, Jiewen @ 2017-07-17  2:03 UTC (permalink / raw)
  To: Laszlo Ersek, Stefan Berger, Javier Martinez Canillas,
	Peter Jones, Marc-André Lureau, Valluri, Amarnath
  Cc: edk2-devel-01, qemu devel list

Hi Laszlo
This is a good summary.

One minor comment is:
1) Tcg2Pei/Dxe are arechitecture driver. We do not expect a platform modify them.
2) Tcg2ConfigPei/Dxe are platform sample driver. A platform may have its own version based upon platform requirement. For example, if a platform supports fTPM, it may use another Tcg2Config driver.


Back to enabling, I think the first important question is how to access TPM device.

If the TPM can expose FIFO interface or CRB interface defined in "Platform TPM Profile Specification definition for TPM2.0", most current TPM2 drivers can be reused.


The second question is about PEI variable.

I do not think PEI Variable is *required* component. Tcg2Pei has gEfiPeiReadOnlyVariable2PpiGuid dependency, and I think we can remove it.

Tcg2ConfigPei has gEfiPeiReadOnlyVariable2PpiGuid dependency, but that is to support TPM selection. The Tcg2Config driver is an optional driver, and it can be customized by platform by design.


Thank you
Yao Jiewen


> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Saturday, July 15, 2017 2:04 AM
> To: Yao, Jiewen <jiewen.yao@intel.com>; Stefan Berger
> <stefanb@linux.vnet.ibm.com>; Javier Martinez Canillas <javierm@redhat.com>;
> Peter Jones <pjones@redhat.com>; Marc-André Lureau
> <marcandre.lureau@redhat.com>; Valluri, Amarnath
> <amarnath.valluri@intel.com>
> Cc: edk2-devel-01 <edk2-devel@lists.01.org>; qemu devel list
> <qemu-devel@nongnu.org>
> Subject: investigating TPM for OVMF-on-QEMU
> 
> Hi,
> 
> I spent most of today reading TPM related material (specs, guides and
> source code), and below I'd like to describe what I think should be our
> initial attack on enabling TPM on QEMU/OVMF.
> 
> (1) Versions of UEFI abstractions regarding TPM (very roughly speaking):
> 
>     There have been three sets of specs for this, and accordingly,
>     edk2's SecurityPkg/Tcg/ directory supports each set. We can call
>     these TPM1, TrEE, and TPM2.
> 
>     - TPM1 was the initial TPM thing, supporting only SHA-1, and is now
>       obsolete.
> 
>     - TrEE was Microsoft's own update to the TPM1 software interfaces,
>       supporting TPM2 hardware with more hash algorithms, and is now
>       obsolete. Because,
> 
>     - TPM2 is basically the standardized version of TrEE, the most
>       recent set of specs, and what we should focus on.
> 
> (2) Drivers (and features) in edk2/SecurityPkg/Tcg.
> 
>     There are 19 modules under SecurityPkg/Tcg/. Let me categorize them.
>     In each category, I'll try to list modules in loosely increasing
>     dependency (or PI/UEFI phase) order.
> 
> (2a) Modules that are obsolete because they are tied to TPM1:
> 
>        TcgPei/TcgPei.inf
>        PhysicalPresencePei/PhysicalPresencePei.inf
>        TcgDxe/TcgDxe.inf
>        TcgConfigDxe/TcgConfigDxe.inf
>        TcgSmm/TcgSmm.inf
> 
>      The TPM enablement instructions at
> 
> 
> https://github.com/tianocore/tianocore.github.io/wiki/How-to-Enable-Security#
> Enabling_Trusted_Compute_Module_TPM
> 
>      are written up in terms of these modules, but that doesn't obsolete
>      the article too much.
> 
> (2b) Modules that are obsolete due to being tied to TrEE:
> 
>        TrEEConfig/TrEEConfigPei.inf
>        TrEEPei/TrEEPei.inf
>        TrEEDxe/TrEEDxe.inf
>        TrEEConfig/TrEEConfigDxe.inf
>        TrEESmm/TrEESmm.inf
> 
>      There is a great Intel whitepaper called
> 
>        A Tour Beyond BIOS with the UEFI TPM2 Support in EDKII
> 
>      which is written in terms of TrEE and these modules, explaining how
>      they supersede TPM1 and the modules under (2a).
> 
>      This whitepaper seems to apply to the most recent TPM2 stack as
>      well (mostly just replace TrEE references with TPM2 references), so
>      it is very useful.
> 
> (2c) Modules that call themselves obsolete or deprecated (without being
>      obviously tied to TPM1 or TrEE):
> 
>        MemoryOverwriteRequestControlLock/TcgMorLockSmm.inf
> 
> (2d) Modules that we won't need due to no hardware support in QEMU:
> 
>        Opal/OpalPasswordDxe/OpalPasswordDxe.inf
>        Opal/OpalPasswordSmm/OpalPasswordSmm.inf
> 
>      TCG's "Opal" seems to be about self-encrypting drives, see
> 
>        https://en.wikipedia.org/wiki/Opal_Storage_Specification
> 
>      so these modules are not relevant for us.
> 
> (2e) Modules that we should use. Again, in increasing order of
>      dependence. And here I'll comment as well on what these do:
> 
>        Tcg2Config/Tcg2ConfigPei.inf -- Informs the firmware globally
>                                        about the TPM device type. This
>                                        module can perform device
>                                        detection or read a cached value
>                                        from a non-volatile UEFI
>                                        variable.
> 
>        Tcg2Pei/Tcg2Pei.inf          -- Initializes the TPM device and
>                                        measures the firmware volumes in
>                                        the PEI phase into the TPM's
>                                        platform config registers.
> 
>        Tcg2Dxe/Tcg2Dxe.inf          -- Measures DXE phase (and later)
>                                        modules into the TPM's PCRs, and
>                                        also lets the OS boot loader
>                                        measure things, by exposing the
>                                        EFI_TCG2_PROTOCOL.
> 
>        Tcg2Config/Tcg2ConfigDxe.inf -- Provides a Setup TUI interface to
>                                        configure the TPM. IIUC, it can
>                                        also save the configured TPM type
>                                        for subsequent boots (see
>                                        Tcg2ConfigPei.inf above).
> 
>      This driver stack supports the TIS (MMIO) hardware interface, which
>      is advertized to the OS in the TPM2 ACPI Table's "start method"
>      field with value 6. (The according macro is TPM2_START_METHOD_MMIO
>      in the QEMU source code, and
> EFI_TPM2_ACPI_TABLE_START_METHOD_TIS
>      in the edk2 source code.)
> 
>      Including these drivers should result in a functional
>      EFI_TCG2_PROTOCOL, which is what OS boot loaders primarily care
>      about, as I understand.
> 
>      Importantly, the driver stack above requires PEI-phase variable
>      access, therefore
>      <https://bugzilla.tianocore.org/show_bug.cgi?id=386> must be solved
>      first.
> 
>      (I have had patches for said BZ ready for a while. I've failed to
>      upstream them thus far because a pflash-based varstore is a hard
>      requirement for them. I think that's a natural requirement, but
>      thus far my arguments haven't proved compelling enough.)
> 
>      Here I should mention some ACPI and hardware aspects. Under TPM1
>      (whose ACPI table was called "TCPA"), the TPM events (measurements
>      I think) were logged in a reserved memory area described by the
>      TCPA table. Under TPM2, the "TPM2" ACPI table does no such thing,
>      it only helps identify the communication characteristics of the
>      device, and the event log itself is accessible to the OS boot
>      loader via the EFI_TCG2_PROTOCOL.
> 
>      (If you are curious how a legacy BIOS boot loader is supposed to
>      read the event log from a TPM2-only device (no "TCPA" table): I
>      don't have the slightest clue.)
> 
>      I'm not sure about the exact characteristics of the virtual TPM
>      that Stefan's swtpm project:
> 
>        https://github.com/stefanberger/swtpm
> 
>      combined with Amarnath's pending QEMU patches:
> 
> 
> http://mid.mail-archive.com/1496666711-14630-1-git-send-email-amarnath.vallur
> i@intel.com
> 
>      will expose to the guest. What I do know is that the current QEMU
>      solution, which mostly forwards a physical (host) TPM to the guest,
>      produces a "TPM2" ACPI table if said host TPM device is TPM2. The
>      "TPM2" table is exposed to the guest OS with OVMF's help, and has
>      the following fields:
> 
>      - address of control area: zero
>      - start method: 6 (TIS plus Cancel)
>      - platform specific params: none.
> 
>      This implies that neither ACPI activation (method 2) nor Command
>      Response Buffer activation (method 7) nor a combination of these
>      two (method 8) is available in QEMU.
> 
>      And that should be just fine, because both Linux and the above
>      Tcg2* modules appear to support this (from reading, not from
>      testing).
> 
> (2f) Modules that we *could* use, but *should not*, at this point:
> 
>        MemoryOverwriteControl/TcgMor.inf
> 
>      MOR is "Memory Overwrite Request". It is a feature specified
>      separately, in another TCG specification ("Platform Reset Attack
>      Mitigation"), and it is optional for a firmware platform to
>      support. (For example, as far as I can see, Linux doesn't even try
>      to detect or use it.) If you care about the threat model and how
>      MOR mitigates that threat, please read the spec on the TCG website.
> 
>      For initial TPM enablement in OVMF, we should avoid MOR support.
>      The module above initializes the "MemoryOverwriteRequestControl"
>      variable, which is one third of the MOR implementation.
> 
>        Tcg2Smm/Tcg2Smm.inf
> 
>      This is a complex driver that we *should not* use at this point:
> 
>      (2f1) It installs two ACPI tables. One of those is a "TPM2" ACPI
>            table, according to the detected / configured TPM device (see
>            under (2e). This "TPM2" table would conflict with -- or more
>            precisely, duplicate -- the "TPM2" table already generated by
>            QEMU, and installed by OVMF.
> 
>      (2f2) The other ACPI table is an SSDT which provides a _DSM (Device
>            Specific Method) to the guest OS. Whenever the _DSM is
>            called, the firmware is entered (via SMI/SMM), and the OS
>            request is handled. Three sets of functions are provided:
> 
>            (2f2a) TCG Hardware Information. Not needed by the guest
>                   OS(es), the TIS+Cancel start method is sufficient.
> 
>            (2f2b) TCG Memory Clear Interface. This is the second third
>                   of the MOR feature I mentioned above. It saves the OS
>                   request in the "MemoryOverwriteRequestControl"
>                   variable (only writeable in SMM).
> 
>                   Upon next boot, OVMF's PlatformPei would have to clear
>                   all memory -- this would be the last third of the MOR
>                   feature; see under:
> 
> 
> https://github.com/tianocore/tianocore.github.io/wiki/How-to-Enable-Security#
> Enabling_Trusted_Compute_Module_TPM
> 
>                   However, clearing all memory in OVMF's PlatformPei
>                   would be a *real* pain, as we are limited to the
>                   32-bit address space there (yes, even if OVMF's PEI
>                   phase is built in 64-bit mode). In physical firmware,
>                   where DRAM takes actual hardware initialization, the
>                   clearing can likely occur without entering long mode
>                   and setting up large page tables (e.g., the memory
>                   controller itself could be programmed with IO
>                   accesses), so in this case physical firmware has it
>                   easier.
> 
>                   Again, Linux doesn't care about MOR.
> 
>            (2f2c) TCG Physical Presence Interface. The OS can queue TPM
>                   operations (?) that require Physical Presence, and at
>                   next boot, OVMF's PlatformBootManagerLib (in the BDS
>                   phase) would have to dispatch those pending
>                   operations. (The queueing again happens in protected
>                   non-volatile UEFI variables -- writeable only in SMM.)
> 
>                   This is of dubious usefulness, and presents extra
>                   complication for OVMF. Said dispatching is supposed to
>                   occur *before* signaling the end-of-DXE event group
>                   (according to the Intel whitepaper mentioned above),
>                   but *after* the console is ready (according to the
>                   wiki article linked above). However, OVMF *already*
>                   signals the end-of-DXE event group in
>                   PlatformBootManagerBeforeConsole(), that is, *before*
>                   the console is ready. Many things are orchestrated
>                   around end-of-DXE, so moving around its signaling
>                   looks difficult.
> 
>                   Also, while Linux appears to be capable of using
>                   Physical Presence, it is again optional, and I suggest
>                   to ignore it at first.
> 
>      In brief, by not including these two modules, we avoid a "TPM2"
>      ACPI table duplication. We also turn off the Memory Overwrite
>      Request and Physical Presence Interface features -- which are both
>      optional, as far as I can see, and very messy for OVMF's platform
>      code.
> 
> (3) Drivers (and features) that are *not in edk2/SecurityPkg/Tcg:
> 
>     The Intel whitepaper discusses (and Peter also mentioned earlier)
>     "dTPM" versus "fTPM".
> 
>     "dTPM" is basically TPM provided in publicly specified hardware,
>     where the firmware can offer support, such as EFI_TCG2_PROTOCOL, but
>     the OS can also directly drive the hardware. This is what QEMU
>     offers with the TIS+Cancel start method (value 6). (The "Command
>     Response Buffer" start method (value 7) would also qualify as
>     "dTPM"). When the platform provides "dTPM", the _DSM method
>     described above *may* be offered, but it is not required.
> 
>     "fTPM" is where the hardware is completely hidden from the OS, and
>     is implemented fully in firmware. The corresponding start method
>     values are 2 ("ACPI") and 8 ("ACPI with CRB"). In this case, the
>     _DSM method is *required*.
> 
>     To my understanding, edk2 contains no "fTPM" implementation. The
>     in-tree drivers recognize hardware that describes itself as
>     TIS+Cancel (6) or CRB (7). Pure ACPI variants are neither recognized
>     nor offered.
> 
>     I think TIS+Cancel / dTPM is the best match: the emulated TPM has to
>     be implemented in virtual hardware (not just faked within the guest,
>     in RAM), so that QEMU can secure the sensitive stuff from guest
>     kernel level access.
> 
> I'm going to link this post from
> <https://bugzilla.tianocore.org/show_bug.cgi?id=594>; please consider
> registering in the TianoCore BZ and subscribing to that bug. Discussion
> should occur on the list(s), but it's nice to capture separate threads
> and distilled ideas in the BZ.
> 
> Thanks
> Laszlo

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] investigating TPM for OVMF-on-QEMU
  2017-07-14 18:04 [Qemu-devel] investigating TPM for OVMF-on-QEMU Laszlo Ersek
  2017-07-14 20:30 ` Peter Jones
  2017-07-17  2:03 ` [Qemu-devel] " Yao, Jiewen
@ 2017-07-17  9:04 ` Javier Martinez Canillas
  2 siblings, 0 replies; 5+ messages in thread
From: Javier Martinez Canillas @ 2017-07-17  9:04 UTC (permalink / raw)
  To: Laszlo Ersek, Jiewen Yao, Stefan Berger, Peter Jones,
	Marc-André Lureau, Amarnath Valluri
  Cc: edk2-devel-01, qemu devel list

Hello Laszlo,

Thanks a lot for the great summary.

On 07/14/2017 08:04 PM, Laszlo Ersek wrote:

[snip]

> 
>      Here I should mention some ACPI and hardware aspects. Under TPM1
>      (whose ACPI table was called "TCPA"), the TPM events (measurements
>      I think) were logged in a reserved memory area described by the
>      TCPA table. Under TPM2, the "TPM2" ACPI table does no such thing,
>      it only helps identify the communication characteristics of the
>      device, and the event log itself is accessible to the OS boot
>      loader via the EFI_TCG2_PROTOCOL.
> 
>      (If you are curious how a legacy BIOS boot loader is supposed to
>      read the event log from a TPM2-only device (no "TCPA" table): I
>      don't have the slightest clue.)
>

The latest "TCG ACPI Specification" draft from February 27, 2017 mentions that
the TPM2 table contains the LAML and LASA fields for the TPM event logs memory
area. But as Stefan pointed out this is just a draft, and has this disclaimer:

"Work in Progress:
This document is an intermediate draft for comment only and is subject to change
without notice. Readers should not design products based on this document."

So I think that will be supported in the future (if the draft doesn't change and
is published).
 
>      I'm not sure about the exact characteristics of the virtual TPM
>      that Stefan's swtpm project:
> 
>        https://github.com/stefanberger/swtpm
> 
>      combined with Amarnath's pending QEMU patches:
> 
>        http://mid.mail-archive.com/1496666711-14630-1-git-send-email-amarnath.valluri@intel.com
> 
>      will expose to the guest. What I do know is that the current QEMU
>      solution, which mostly forwards a physical (host) TPM to the guest,
>      produces a "TPM2" ACPI table if said host TPM device is TPM2. The
>      "TPM2" table is exposed to the guest OS with OVMF's help, and has
>      the following fields:
> 
>      - address of control area: zero
>      - start method: 6 (TIS plus Cancel)
>      - platform specific params: none.
> 
>      This implies that neither ACPI activation (method 2) nor Command
>      Response Buffer activation (method 7) nor a combination of these
>      two (method 8) is available in QEMU.
> 

Even when QEMU always exposes a start method 6 (TIS + cancel) in its TPM2 table
to the guest, pass-through works when the host TPM advertises a different start
method.

For example I've a laptop with an Intel PTT fTPM and the start method is 2, but
I'm able to access the host TPM2 from the guest using the Linux tpm_tis driver.

> 
>      In brief, by not including these two modules, we avoid a "TPM2"
>      ACPI table duplication. We also turn off the Memory Overwrite
>      Request and Physical Presence Interface features -- which are both
>      optional, as far as I can see, and very messy for OVMF's platform
>      code.
> 

Agreed.

> (3) Drivers (and features) that are *not in edk2/SecurityPkg/Tcg:
> 
>     The Intel whitepaper discusses (and Peter also mentioned earlier)
>     "dTPM" versus "fTPM".
> 
>     "dTPM" is basically TPM provided in publicly specified hardware,
>     where the firmware can offer support, such as EFI_TCG2_PROTOCOL, but
>     the OS can also directly drive the hardware. This is what QEMU
>     offers with the TIS+Cancel start method (value 6). (The "Command
>     Response Buffer" start method (value 7) would also qualify as
>     "dTPM"). When the platform provides "dTPM", the _DSM method
>     described above *may* be offered, but it is not required.
> 
>     "fTPM" is where the hardware is completely hidden from the OS, and
>     is implemented fully in firmware. The corresponding start method
>     values are 2 ("ACPI") and 8 ("ACPI with CRB"). In this case, the
>     _DSM method is *required*.
> 
>     To my understanding, edk2 contains no "fTPM" implementation. The
>     in-tree drivers recognize hardware that describes itself as
>     TIS+Cancel (6) or CRB (7). Pure ACPI variants are neither recognized
>     nor offered.
> 

That's my understanding as well. I see that the Valley View 2 / Minnowboard Max
platform pkg (Vlv2TbltDevicePkg) as references to fTPM and a FTPM_ENABLE var to
enable it, but IIUC the fTPM driver is distributed as proprietary binary files:

https://firmware.intel.com/projects/minnowboard-max

>     I think TIS+Cancel / dTPM is the best match: the emulated TPM has to
>     be implemented in virtual hardware (not just faked within the guest,
>     in RAM), so that QEMU can secure the sensitive stuff from guest
>     kernel level access.
> 

Agreed.

Best regards,
-- 
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-07-17  9:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-14 18:04 [Qemu-devel] investigating TPM for OVMF-on-QEMU Laszlo Ersek
2017-07-14 20:30 ` Peter Jones
2017-07-14 21:31   ` [Qemu-devel] [edk2] " Laszlo Ersek
2017-07-17  2:03 ` [Qemu-devel] " Yao, Jiewen
2017-07-17  9:04 ` Javier Martinez Canillas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.