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)?
Motivation
Some guest OS / automotive stacks increasingly expect a TPM 2.0 for:
We want optional TPM 2.0 emulation per node in aos-unit, without turning the project into a full “VM platform”.
Scope
Proposed approach (emulation)
Use swtpm as the backend and QEMU TPM device:
swtpm socket ...-chardev socket,id=chrtpm,path=<...>+-tpmdev emulator,id=tpm0,chardev=chrtpm+-device tpm-tis,tpmdev=tpm0(Alternative
tpm-crbcan be evaluated, buttpm-tisis widely compatible.)Configuration (initial proposal)
In
/etc/aos-unit/unit_config.yaml, per-node optional section:Notes:
persistent: store TPM state under StateDirectory= (survives reboots)volatile:store under RuntimeDirectory= (reset on reboot/stop)System design / implementation notes
/run/aos-unit/<node>.tpm.sock(or instance scoped)/var/lib/aos-unit/tpm/<node>/when persistentAfter=(and/orBindsTo=) swtpm unit so stop/start ties together cleanlySecurity / hardening considerations
NoNewPrivileges=yesPrivateTmp=yesProtectSystem=strict(as feasible)DevicePolicy=closedallowlist when enabling TPM:aos-unit, mode 0700).Packaging / dependencies
swtpm(and possiblyswtpm-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.Testing / validation
dmesg | grep -i tpm,ls /dev/tpm*,tpm2_getcap properties-fixedAcceptance criteria
Open questions
tpm-tisvstpm-crbas default?