Skip to content

Add optional TPM 2.0 emulation for QEMU nodes (swtpm + QEMU tpm-tis) #5

Description

@klogg

Motivation

Some guest OS / automotive stacks increasingly expect a TPM 2.0 for:

  • measured boot / attestation experiments
  • disk encryption sealing (e.g., LUKS keys sealed to TPM)
  • secure key storage and policy-based key release
  • future compliance / OEM security requirements

We want optional TPM 2.0 emulation per node in aos-unit, without turning the project into a full “VM platform”.

Scope

  • Add an opt-in TPM 2.0 device to selected nodes.
  • Default remains no TPM.
  • Keep implementation systemd-native and consistent with current transient-unit approach.

Proposed approach (emulation)

Use swtpm as the backend and QEMU TPM device:

  • swtpm: swtpm socket ...
  • QEMU: -chardev socket,id=chrtpm,path=<...> + -tpmdev emulator,id=tpm0,chardev=chrtpm + -device tpm-tis,tpmdev=tpm0

(Alternative tpm-crb can be evaluated, but tpm-tis is widely compatible.)

Configuration (initial proposal)

In /etc/aos-unit/unit_config.yaml, per-node optional section:

unit:
  node_configs:
    node1:
      tpm2:
        enabled: true
        state: persistent   # persistent|volatile

Notes:

  • persistent: store TPM state under StateDirectory= (survives reboots)
  • volatile: store under RuntimeDirectory= (reset on reboot/stop)

System design / implementation notes

  • Runner creates a per-node swtpm unit (transient or templated) and ensures:
    • socket path under /run/aos-unit/<node>.tpm.sock (or instance scoped)
    • state path under /var/lib/aos-unit/tpm/<node>/ when persistent
  • VM transient unit:
    • After= (and/or BindsTo=) swtpm unit so stop/start ties together cleanly
    • Adds QEMU args only when TPM is enabled

Security / hardening considerations

  • Ensure swtpm runs with a locked-down sandbox:
    • NoNewPrivileges=yes
    • PrivateTmp=yes
    • ProtectSystem=strict (as feasible)
    • limit FS access to the specific TPM state dir
  • Revisit DevicePolicy=closed allowlist when enabling TPM:
    • identify and document any additional device nodes QEMU/swtpm require
  • Keep TPM state directory permissions tight (owned by aos-unit, mode 0700).

Packaging / dependencies

  • Add package dependency on swtpm (and possibly swtpm-tools) only if TPM is enabled is difficult in Debian packaging; likely add as a normal dependency, or document it as required when using TPM.
  • Document host kernel/module expectations (if any).

Testing / validation

  • Guest detects TPM 2.0:
    • Linux: dmesg | grep -i tpm, ls /dev/tpm*, tpm2_getcap properties-fixed
  • TPM state persistence:
    • persistent mode: state survives VM restart and host reboot
    • volatile mode: state resets after service stop/restart
  • Failure mode:
    • if swtpm fails to start, VM start fails with clear logs

Acceptance criteria

  • Per-node TPM 2.0 enablement works reliably.
  • No TPM changes for default users.
  • Clear documentation + troubleshooting section.
  • No unnecessary weakening of existing security hardening.

Open questions

  • Prefer tpm-tis vs tpm-crb as default?
  • Should TPM state be per-node or per-image (node feels correct)?
  • How to surface TPM-related logs cleanly (journal + optional log file)?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions