F tpm support 3 20#484
Conversation
xtest -t regression 1008 xtest -t regression 1033 The above test cases were failing due to not being able to open the corrupt TA for test 1008 (searches locally on TA_DIR make flag), and it was missing the plugin needed for 1033. This change formalizes the TA and the Plugin paths and adds them to the optee.supplicant service's path.
TAs and Plugins are needed for tee-supplicant. The xtest binary does require a path to the TAs for loading in the TA_DIR=$(tas) make flag, which is hard coded into the binary. This is a true runtime dependency, which nix finds with strings. We need to ensure that the TAs do not have a back reference to $out. We cannot use remove-references-to or nuke-refs in the installPhase as is typical, because the TAs are signed in the buildPhase. To achive this, a 'hook' is added into make, that creates a preSign phase, which calls nuke-refsa before signing. All xtest tests are passing.
Some packages are useful to see in the passthru for debug purposes.
Patch tee-supplicant to send READY=1 notification to systemd when initialization is complete. This allows the service to use Type=notify in systemd, enabling proper service ordering and dependency management. The implementation uses a standalone sd_notify() function from systemd's reference implementation, avoiding a dependency on libsystemd. Based on upstream commit to OP-TEE/optee_client and ported to nv-optee. Upstream commit: a5b1ffcd26e328af0bbf18ab448a38ecd558e05c Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add build infrastructure for fTPM (Firmware TPM) trusted applications: - buildFTpmHelperTa: Builds the fTPM helper TA and userspace client app (nvftpm-helper-app) that assists with fTPM initialization and EPS injection for testing - buildMsTpm20RefTa: Builds Microsoft's TPM 2.0 reference implementation TA using GCC 13. Configured with measured boot support and platform EPS The fTPM helper includes both the TA (runs in secure world) and a userspace application for configuration. The MS TPM 20 ref implements the full TPM 2.0 specification in the secure world. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Integrate fTPM trusted applications into the OP-TEE OS firmware build and add NixOS module configuration options. Module configuration: - hardware.nvidia-jetpack.firmware.optee.ftpm.enable: Enable fTPM support (default: true) - hardware.nvidia-jetpack.firmware.optee.ftpm.unsafeInjectEPS: Allow EPS injection for testing (insecure, default: false) Firmware integration: - buildOptee: Add enableFTPM parameter and conditional CFG flags for TPM event log, REE state, and fTPM helper PTA support - buildTOS: Build fTPM helper and MS TPM 2.0 ref TAs when fTPM is enabled, embed them as early TAs in the TOS image - Pass opteePatches to MS TPM TA build for consistent patching - Add passthru to expose tosArgs for downstream customization The fTPM TAs are signed and embedded in the TOS firmware image during the build process, ensuring they are available in the secure world at boot time. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add kernel driver and systemd service integration for fTPM runtime support in NixOS. Kernel configuration: - Add tpm and tpm_ftpm_tee kernel modules - Enable TCG_TPM and TCG_FTPM_TEE in kernel config as modules - Add tpm_ftpm_tee to initrd for early TPM access - Blacklist tpm_ftpm_tee at boot (loaded after tee-supplicant) Systemd integration: - Create ftpm-driver service to load tpm_ftpm_tee after tee-supplicant - Change tee-supplicant to Type=notify for proper ordering - Add optional EPS injection when unsafeInjectEPS is enabled The ftpm-driver service waits for tee-supplicant to be ready (via sd_notify), then optionally injects a random EPS for testing, and finally loads the tpm_ftpm_tee kernel driver which triggers fTPM initialization in the secure world. When unsafeInjectEPS is enabled, a persistent random EPS is generated and stored in /var/lib/unsafeInjectEPS.hex. This is insecure and should only be used for testing. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
TanelDettenborn
left a comment
There was a problem hiding this comment.
Overall, this looks good. I am keen to see fTPM upstreamed.
|
|
||
| buildMsTpm20RefTa = args: | ||
| let | ||
| gcc13Stdenv = stdenvAdapters.overrideCC stdenv gcc13; |
There was a problem hiding this comment.
I am assuming GCC 13 is used here because NVIDIA’s fTPM does not compile with newer GCC releases, and not because newer GCC versions would produce a bad binary?
If that is the case, then rather than downgrading GCC, I would prefer adding:
"NIX_CFLAGS_COMPILE = "-Wno-incompatible-pointer-types -Wno-implicit-function-declaration";"
There was a problem hiding this comment.
Correct. GCC13 is being used at the moment because of the above. I opted for GCC13 since it I wanted to confirm that the base fTPM worked.
I agree that we should use default gcc with these flags.
| Add fTPM TA and kernel modules. | ||
| ''; | ||
| }; | ||
| unsafeInjectEPS = mkEnableOption '' |
There was a problem hiding this comment.
I would argue that ESP injection isn't 'unsafe' in this context, as it’s actually the desired outcome. I suggest emphasizing that this is an insecure configuration choice, perhaps by renaming the option to unsecureInjectESP or even unsecureConfigInjectESP.
There was a problem hiding this comment.
Agree with rename to unsecureInjectESP. It's not unsafe, but is insecure. fTPM is fully compromised.
| mkdir -p "''$(dirname "''$EPS_FILE")" | ||
|
|
||
| # Generate 64 random bytes and convert to hex with 0x prefix | ||
| EPS_HEX="0x''$(${pkgs.coreutils}/bin/dd if=/dev/urandom bs=1 count=''$EPS_SIZE 2>/dev/null | ${pkgs.xxd}/bin/xxd -p -c 256)" |
There was a problem hiding this comment.
Since ESP injection is purely for testing, making it configurable via Nix options (e.g., file path or/both value) would be a cleaner and more flexible approach than hardcoding these parameters?
There was a problem hiding this comment.
Sure, good suggestion.
| in | ||
| mkIf cfg.ftpm.enable { | ||
| description = "Load fTPM driver after TEE supplicant"; | ||
| after = [ "tee-supplicant.service" ]; |
There was a problem hiding this comment.
For the robustness I would add local-fs.target (and systemd-modules-load.service").
| "OPTEE_CLIENT_EXPORT=${opteeClient}" | ||
| "OPTEE_OS_DIR=$(PWD)/optee/optee_os" | ||
| "O=$(PWD)/out" | ||
| "CFG_TA_MEASURED_BOOT=y" |
There was a problem hiding this comment.
I am wondering if CFG_TA_MEASURED_BOOT could be exposed as a separate Nix option. For example measuredBoot?
Also wondering if same option should/could include CFG_CORE_TPM_EVENT_LOG. I have not verified from OP-TEE's code, if fTPM is functional without tpm-events.
| ftpm = { | ||
| enable = mkOption { | ||
| type = types.bool; | ||
| default = true; |
There was a problem hiding this comment.
I haven't tested this yet, but does it compile for Jetson 35.x? I believe fTPM support was only released with r36.4.
| nativeBuildInputs = [ (buildPackages.python3.withPackages (p: [ p.cryptography ])) ]; | ||
| enableParallelBuilding = true; | ||
| makeFlags = [ | ||
| "-C optee/samples/ftpm-helper" |
There was a problem hiding this comment.
Nvidia has refactored fTPM compilation for Jetson 38.x. It introduces CFG_MS_TPM_20_REF-flag. Seems like it would make buildMsTpm20RefTa-derivation obsolete.
| "O=$(PWD)/out" | ||
| "CFG_TA_MEASURED_BOOT=y" | ||
| "CFG_USE_PLATFORM_EPS=y" | ||
| "CFG_TA_LOG_LEVEL=${toString args.taLogLevel}" |
There was a problem hiding this comment.
Nvidia's default value is zero, so I'm wondering if this should be a separate Nix option? It would allow users to stay consistent with the default or override it if needed.
|
@dperezzoghbi Apologies, I just merged #480, could you rebase this PR against master? Also, could you fill out the PR description? |
Description of changes
Testing