qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/26] arm: Run Arm CCA VMs with KVM
@ 2024-11-25 19:55 Jean-Philippe Brucker
  2024-11-25 19:56 ` [PATCH v3 01/26] kvm: Merge kvm_check_extension() and kvm_vm_check_extension() Jean-Philippe Brucker
                   ` (26 more replies)
  0 siblings, 27 replies; 71+ messages in thread
From: Jean-Philippe Brucker @ 2024-11-25 19:55 UTC (permalink / raw)
  To: peter.maydell
  Cc: richard.henderson, philmd, qemu-arm, qemu-devel, alex.bennee,
	Jean-Philippe Brucker, Matias Ezequiel Vara Larsen, Paolo Bonzini,
	Peter Gonda, Stefan Berger

This series enables running confidential VMs on Arm CCA. The host KVM
support is progressing but still under discussion [1], so there is no
urgency to upstream this series. I'm sending this new version to give a
status update, and also to discuss remote attestation below.

Since v2 [2] I addressed comments on the QAPI patches. The support for
running Linux in a Realm will be in Linux v6.13 [3], so the guest-facing
interface is now stable. One important change since v2 is the requirement
to initialize the whole GPA space in RMM before boot, which we do in patch
9. The 'earlycon' kernel parameter now requires an unprotected address
parameter (see Documentation/arch/arm64/arm-cca.rst in Linux v6.13).

Documentation to try this series out:
https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/Building+an+RME+stack+for+QEMU

The new RFC patches 21-26 are ideas to make remote attestation easier.
They're all optional, and in order to understand which patches should be
kept and what should be standardized, we'd like feedback from people who
will provide hosting and verification services, and also from people
working on other VMMs, who will be faced with the same problems.


QEMU and Realm attestation
==========================

Confidential computing wouldn't be complete without the ability to attest
that a remote VM you own is running your software on the correct hardware.
There are many components in enabling remote attestation, but I'd like to
discuss specifically how to independently reconstruct the initial state of
the VM created by QEMU.

We can illustrate this problem using the keybroker attestation demo [4]:

          ┌──────┬───────────────┐                           
          │  NS  │    REALM      │            RELYING PARTY 
      ┌───┼──────┼───────────────┤     (b)    (you are here) 
      │   │      │               │  evidence  ┌────────────┐ 
      │EL0│ QEMU │ keybroker-app ┼────────────► keybroker- │ 
      │   │   │  │      ▲        ◄────────────┼   server   │ 
      ├───┼───┼──┼──────┼────────┤   secret   └─────▲──────┘ 
      │   │   │  │      │        │     (d)          │ (c)    
      │EL1│   │  │ guest kernel  │              ┌───▼────┐   
      │   │   │  │      ▲        │              │veraison│   
      │   │   │  ├──────┼────────┤              └────────┘   
      │   │   ▼  │ (a)  │        │               VERIFIER    
      │EL2│  KVM ┼───► RMM       │                           
      │   │      │               │                           
      └───┴──────┴───────────────┘                           
                ATTESTER                                       

QEMU and KVM load data into the VM memory (kernel, initrd, firmware, etc),
before activating it and sealing its initial state (a). The initial state
is recorded by the RMM as the Realm Initial Measurement (RIM). Additional
data may be loaded at runtime, for example a bootloader loading an initrd
from untrusted storage. Those are recorded in Realm Extensible
Measurements (REM).

Now say you want the VM to run an application, keybroker-app, that
downloads a secret from your keybroker-server, for example a private key
to open an encrypted archive.

  keybroker-server -e http://10.0.2.2 -vv
  keybroker-app -e http://10.0.2.2:8088 -v <key> 

keybroker-app obtains signed evidence using Linux configfs-tsm, sends it
to keybroker-server (b). The evidence contains a platform token describing
the platform state (host hardware, firmware and RMM), and a realm token.
The signature and platform verification, proving that the VM is running in
a confidential environment, is offloaded to a trusted third party in this
example (c), though you could of course run veraison yourself.
keybroker-server then checks the RIM and REMs contained in the realm
token, to ensure the Realm is running the correct payload, and sends the
secret key (d).


Computing the Realm Initial Measurement
---------------------------------------

The simplest way to obtain the RIM is to run the payload once on a trusted
machine, extract the reference values and provision keybroker-server with
them. On the first run the demo tells you how to do this:

  INFO Known-good RIM values are missing. If you trust the client that
    submitted evidence for challenge 352278775, you should restart the
    keybroker-server with the following command-line option to populate it
    with known-good RIM values:
    --reference-values <(echo '{ "reference-values": [ "Up9LS4jrkX002..." ] }')

This is fine for testing, but does not scale well. For one thing you may
not have access to a trusted machine to run the payload. Also, the RIM is
relatively unstable: it depends on the host features (eg. SVE vector
length), the VM configuration (eg. amount of RAM) and the images loaded
into the Realm. Since the DTB/ACPI tables are included in the
measurements, changing the number of CPUs or MMIO devices will also
produce a different RIM. Some VMMs even have unstable IRQ allocation.

To pre-calculate the RIM for a set of VM parameters, rather than running
the workload once you can use the realm-measurements tool [5]:

  realm-measurements --print-b64
    -c configs/qemu-max-8.2.conf -c configs/kvm.conf  # host caps
    -k <kernel> -i <initrd>                           # payload
    qemu <qemu command-line parameters>

  RIM: Up9LS4jrkX002...

Internally realm-measurements generates a DTB for the given machine
configuration and uses it to calculate the RIM. This means that QEMU must
be run with the same generated DTB, which can be obtained by running
realm-measurements with `--output-dtb qemu.dtb --no-measurements` on the
host. See patch 21, which enables loading this DTB.

I've also experimented with reproducing the DTB generated by QEMU,
from a template obtained with `-M dumpdtb=<tpl.dtb>` [6]. It's rather
fragile due to phandle allocation, property names and libfdt internals.
You can try this mode by passing `--input-dtb <tpl.dtb>`, in which case
there is no need to pass a DTB to QEMU. But this solution will probably
remain experimental.


An event log from the VMM
-------------------------

Reconstructing the RIM this way requires a strict specification of the VMM
behavior [7]. To relax this, the VMM could provide an event log,
describing the different operations that contributed to the RIM: Realm
parameters, images loaded into RAM, initial CPU registers. The Trusted
Computing Group (TCG) defines a log format that describes things measured
by a TPM. Since this format will probably be reused to describe images
measured into the REM, it would make sense to adopt it for the RIM as
well. UEFI normally creates this log in RAM and passes it to the OS via
firmware table (CCEL for ACPI, TBD [8] for device tree)

Patches 23-26 show how we could load such event log into Realm memory.
Something to improve is the image identifiers passed in the log, that
allow the verifier to locate the image in its store of known-good images.
At the moment we use a hash function for this, but it would be useful to
either let the host pass the pre-calculated hash, or we could extend RMM
to return the hashes that it already computes when measuring data
granules.

Using a modified keybroker-demo that supports the event log [10], you can
pass a list of known-good images loaded into the realm:

  sha512sum path/to/images/* > checksums.txt
  keybroker-server -e http://10.0.2.2 -vv --images checksums.txt

Now when receiving evidence, the server can reconstruct the RIM and REMs
by parsing the event log. To reduce bandwidth use, the server caches the
computed reference values, and only requires an event log when reference
values are absent.

Note that the PoC is incomplete, because it trusts the log too much when
constructing the RIM: although data loaded into the Realm is correctly
verified, some events aren't properly checked by the policy at the moment.
In particular the REC event (vCPU initial state) must have sane initial
registers (which can be predicted from the DTB, KERNEL and FIRMWARE log
events, so should be easy to fix). The kernel parameters, contained in the
DTB, will also need to be validated by the policy.

The server reconstructs the DTB using a few VM properties passed in the
log (number of CPUs, RAM size). Another possible extension is to send the
DTB/ACPI tables in the log, so the tool can verify their content rather
than generate them, but I'm not sure it's even worth attempting.


Loading IGVM payload 
--------------------

IGVM [9] packs the payload along with instructions for creating the VM,
into a file that is fed to QEMU. We'll likely want to support it on Arm in
order to load complex payloads like COCONUT-SVSM, but probably not for
lightweight container payloads where firmware would be unnecessary
overhead.

If the IGVM file describes all operations leading to a RIM, then a strict
VM specification isn't needed in this case either. However to get more
flexibility it may be useful to combine IGVM with an event log: the host
packs the IGVM file including an event log, and the relying party only
needs the event log to reconstruct the RIM, it doesn't need to upload a
pack for each different configuration.



[1] [PATCH v5] arm64: Support for Arm CCA in KVM
    https://lore.kernel.org/all/20241004152804.72508-1-steven.price@arm.com/

[2] [PATCH v2] arm: Run CCA VMs with KVM
    https://lore.kernel.org/all/20240419155709.318866-2-jean-philippe@linaro.org/

[3] [PATCH v7] arm64: Support for running as a guest in Arm CCA
    https://lore.kernel.org/all/172967739783.1412028.8494484908145931121.b4-ty@arm.com/

[4] Veraison keybroker demo
    https://github.com/veraison/keybroker-demo/

[5] Realm measurements tool
    https://github.com/veraison/cca-realm-measurements
    https://docs.rs/cca-realm-measurements/0.1.0/cca_realm_measurements/

[6] DTB modification and libfdt changes
    https://github.com/veraison/cca-realm-measurements/commit/4b7aa3cbd7ae7ce114726979367329f57b8ef2c6
    https://git.codelinaro.org/linaro/dcap/buildroot-external-cca/-/commit/28f4afa6120b467cadab9bc0af67e7bab239797b

[7] VM specification
    https://github.com/veraison/cca-realm-measurements/blob/main/docs/realm-vm.md

[8] Confidential computing event log for device-tree
    https://jpbrucker.net/git/linux/log/?h=cca/ccel-dt

[9] IGVM in QEMU, COCONUT-SVSM
    https://lore.kernel.org/qemu-devel/cover.1727341768.git.roy.hopkins@suse.com/
    https://github.com/coconut-svsm/svsm/blob/main/Documentation/docs/installation/INSTALL.md

[10] keybroker-demo with event log support
     https://github.com/jpbrucker/keybroker-demo/commits/event-log/

Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Matias Ezequiel Vara Larsen <mvaralar@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Gonda <pgonda@google.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Philippe Mathieu-Daudé <philmd@linaro.org>
Cc: Richard Henderson <richard.henderson@linaro.org>
Cc: Stefan Berger <stefanb@linux.vnet.ibm.com>

Jean-Philippe Brucker (26):
  kvm: Merge kvm_check_extension() and kvm_vm_check_extension()
  target/arm: Add confidential guest support
  target/arm/kvm: Return immediately on error in kvm_arch_init()
  target/arm/kvm-rme: Initialize realm
  target/arm/kvm: Split kvm_arch_get/put_registers
  target/arm/kvm-rme: Initialize vCPU
  target/arm/kvm: Create scratch VM as Realm if necessary
  hw/core/loader: Add ROM loader notifier
  target/arm/kvm-rme: Initialize Realm memory
  target/arm/kvm-rme: Add Realm Personalization Value parameter
  target/arm/kvm-rme: Add measurement algorithm property
  target/arm/cpu: Set number of breakpoints and watchpoints in KVM
  target/arm/cpu: Set number of PMU counters in KVM
  target/arm/cpu: Inform about reading confidential CPU registers
  hw/arm/virt: Add support for Arm RME
  hw/arm/virt: Disable DTB randomness for confidential VMs
  hw/arm/virt: Reserve one bit of guest-physical address for RME
  hw/arm/boot: Mark all guest memory as RIPAS_RAM.
  hw/arm/virt: Move virt_flash_create() to machvirt_init()
  hw/arm/virt: Use RAM instead of flash for confidential guest firmware
  hw/arm/boot: Load DTB as is for confidential VMs
  hw/arm/boot: Skip bootloader for confidential guests
  hw/tpm: Add TPM event log
  hw/core/loader: Add fields to RomLoaderNotify
  target/arm/kvm-rme: Add measurement log
  hw/arm/virt: Add measurement log for confidential boot

 docs/system/arm/virt.rst                   |   9 +-
 docs/system/confidential-guest-support.rst |   1 +
 qapi/qom.json                              |  40 +
 qapi/tpm.json                              |  14 +
 include/hw/arm/boot.h                      |  18 +
 include/hw/arm/virt.h                      |   3 +-
 include/hw/loader.h                        |  17 +
 include/hw/tpm/tpm_log.h                   |  89 +++
 include/sysemu/kvm.h                       |   2 -
 include/sysemu/kvm_int.h                   |   1 +
 target/arm/cpu.h                           |  10 +
 target/arm/kvm_arm.h                       |  98 +++
 accel/kvm/kvm-all.c                        |  41 +-
 hw/arm/boot.c                              | 115 ++-
 hw/arm/virt.c                              | 143 +++-
 hw/core/loader.c                           |  17 +
 hw/tpm/tpm_log.c                           | 325 ++++++++
 target/arm/arm-qmp-cmds.c                  |   1 +
 target/arm/cpu.c                           |   5 +
 target/arm/cpu64.c                         | 118 +++
 target/arm/kvm-rme.c                       | 843 +++++++++++++++++++++
 target/arm/kvm.c                           | 201 ++++-
 target/i386/kvm/kvm.c                      |   6 +-
 target/ppc/kvm.c                           |  36 +-
 hw/tpm/Kconfig                             |   4 +
 hw/tpm/meson.build                         |   1 +
 target/arm/Kconfig                         |   1 +
 target/arm/meson.build                     |   7 +-
 28 files changed, 2075 insertions(+), 91 deletions(-)
 create mode 100644 include/hw/tpm/tpm_log.h
 create mode 100644 hw/tpm/tpm_log.c
 create mode 100644 target/arm/kvm-rme.c

-- 
2.47.0



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

end of thread, other threads:[~2025-02-07 16:02 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-25 19:55 [PATCH v3 00/26] arm: Run Arm CCA VMs with KVM Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 01/26] kvm: Merge kvm_check_extension() and kvm_vm_check_extension() Jean-Philippe Brucker
2024-11-26 12:29   ` Daniel P. Berrangé
2024-12-04 19:07     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 02/26] target/arm: Add confidential guest support Jean-Philippe Brucker
2024-11-26 12:37   ` Daniel P. Berrangé
2024-12-04 19:07     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 03/26] target/arm/kvm: Return immediately on error in kvm_arch_init() Jean-Philippe Brucker
2024-12-05 21:47   ` Philippe Mathieu-Daudé
2024-12-10 19:06     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 04/26] target/arm/kvm-rme: Initialize realm Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 05/26] target/arm/kvm: Split kvm_arch_get/put_registers Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 06/26] target/arm/kvm-rme: Initialize vCPU Jean-Philippe Brucker
2025-02-04  5:02   ` Gavin Shan
2025-02-07 15:56     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 07/26] target/arm/kvm: Create scratch VM as Realm if necessary Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 08/26] hw/core/loader: Add ROM loader notifier Jean-Philippe Brucker
2024-12-05 21:59   ` Philippe Mathieu-Daudé
2024-12-10 19:07     ` Jean-Philippe Brucker
2025-02-04  5:33   ` Gavin Shan
2025-02-07 15:57     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 09/26] target/arm/kvm-rme: Initialize Realm memory Jean-Philippe Brucker
2025-02-04  5:30   ` Gavin Shan
2025-02-07 15:59     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 10/26] target/arm/kvm-rme: Add Realm Personalization Value parameter Jean-Philippe Brucker
2024-11-26  7:20   ` Markus Armbruster
2024-11-26 12:47     ` Daniel P. Berrangé
2024-12-04 19:11       ` Jean-Philippe Brucker
2024-12-04 19:10     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 11/26] target/arm/kvm-rme: Add measurement algorithm property Jean-Philippe Brucker
2024-11-26 12:57   ` Daniel P. Berrangé
2024-11-26 15:11     ` Markus Armbruster
2024-11-26 15:17       ` Daniel P. Berrangé
2024-11-25 19:56 ` [PATCH v3 12/26] target/arm/cpu: Set number of breakpoints and watchpoints in KVM Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 13/26] target/arm/cpu: Set number of PMU counters " Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 14/26] target/arm/cpu: Inform about reading confidential CPU registers Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 15/26] hw/arm/virt: Add support for Arm RME Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 16/26] hw/arm/virt: Disable DTB randomness for confidential VMs Jean-Philippe Brucker
2024-12-05 22:03   ` Philippe Mathieu-Daudé
2024-11-25 19:56 ` [PATCH v3 17/26] hw/arm/virt: Reserve one bit of guest-physical address for RME Jean-Philippe Brucker
2024-12-13 12:03   ` Gavin Shan
2025-01-22 14:56     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 18/26] hw/arm/boot: Mark all guest memory as RIPAS_RAM Jean-Philippe Brucker
2025-02-04  7:27   ` Gavin Shan
2025-02-07 16:02     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 19/26] hw/arm/virt: Move virt_flash_create() to machvirt_init() Jean-Philippe Brucker
2024-11-25 19:56 ` [PATCH v3 20/26] hw/arm/virt: Use RAM instead of flash for confidential guest firmware Jean-Philippe Brucker
2024-11-25 19:56 ` [RFC PATCH v3 21/26] hw/arm/boot: Load DTB as is for confidential VMs Jean-Philippe Brucker
2024-11-25 19:56 ` [RFC PATCH v3 22/26] hw/arm/boot: Skip bootloader for confidential guests Jean-Philippe Brucker
2024-11-25 19:56 ` [RFC PATCH v3 23/26] hw/tpm: Add TPM event log Jean-Philippe Brucker
2024-12-05 22:13   ` Philippe Mathieu-Daudé
2024-12-09 22:34   ` Stefan Berger
2024-12-13 14:31     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [RFC PATCH v3 24/26] hw/core/loader: Add fields to RomLoaderNotify Jean-Philippe Brucker
2024-12-05 22:21   ` Philippe Mathieu-Daudé
2024-12-10 19:04     ` Jean-Philippe Brucker
2024-11-25 19:56 ` [RFC PATCH v3 25/26] target/arm/kvm-rme: Add measurement log Jean-Philippe Brucker
2024-11-25 22:23   ` Stefan Berger
2024-11-26 13:45     ` Daniel P. Berrangé
2024-11-26 16:21       ` Jean-Philippe Brucker
2024-12-02 15:58         ` Stefan Berger
2024-12-05 12:33           ` Jean-Philippe Brucker
2024-12-09 20:22             ` Stefan Berger
2024-12-09 22:08   ` Stefan Berger
2024-12-13 14:21     ` Jean-Philippe Brucker
2024-12-13 16:51       ` Stefan Berger
2024-11-25 19:56 ` [RFC PATCH v3 26/26] hw/arm/virt: Add measurement log for confidential boot Jean-Philippe Brucker
2024-12-05 22:23   ` Philippe Mathieu-Daudé
2024-12-10 19:05     ` Jean-Philippe Brucker
2024-12-11  3:01 ` [PATCH v3 00/26] arm: Run Arm CCA VMs with KVM Gavin Shan
2024-12-11  8:01   ` Gavin Shan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).