Files
loader/_docs/02_tasks/done/AZ-182_tpm_security_provider.md
T
Oleksandr Bezdieniezhnykh 9a0248af72 [AZ-185][AZ-186] Batch 2
Made-with: Cursor
2026-04-15 07:32:37 +03:00

6.1 KiB

TPM-Based Security Provider

Task: AZ-182_tpm_security_provider Name: TPM Security Provider Description: Introduce SecurityProvider abstraction with TPM detection and FAPI integration, wrapping existing security logic in LegacySecurityProvider for backward compatibility Complexity: 5 points Dependencies: None Component: 02 Security Tracker: AZ-182 Epic: AZ-181

Problem

The loader's security code (key derivation, encryption, hardware fingerprinting) is hardcoded for the binary-split scheme. On fused Jetson Orin Nano devices with fTPM, this scheme is unnecessary — full-disk encryption protects data at rest, and the fleet update system (AZ-185) handles encrypted artifact delivery with per-artifact keys. However, the loader still needs a clean abstraction to:

  1. Detect whether it's running on a TPM-equipped device or a legacy environment
  2. Provide TPM seal/unseal capability as infrastructure for defense-in-depth (sealed credentials, future key wrapping)
  3. Preserve the legacy code path for non-TPM deployments

Outcome

  • Loader detects TPM availability at startup and selects the appropriate security provider
  • SecurityProvider abstraction cleanly separates TPM and legacy code paths
  • TpmSecurityProvider establishes FAPI connection and provides seal/unseal operations
  • LegacySecurityProvider wraps existing security.pyx unchanged
  • Foundation in place for fTPM-sealed credentials (future) and per-artifact key decryption integration

Scope

Included

  • SecurityProvider abstraction (ABC) with TpmSecurityProvider and LegacySecurityProvider
  • Runtime TPM detection (/dev/tpm0 + SECURITY_PROVIDER env var override)
  • tpm2-pytss FAPI integration: connect, create_seal, unseal
  • LegacySecurityProvider wrapping existing security.pyx (encrypt, decrypt, key derivation)
  • Auto-detection and provider selection at startup with logging
  • Docker compose device mounts for /dev/tpm0 and /dev/tpmrm0
  • Dockerfile changes: install tpm2-tss native library + tpm2-pytss
  • Tests using TPM simulator (swtpm)

Excluded

  • Resource download/upload changes (handled by AZ-185 Update Manager with per-artifact keys)
  • Docker unlock flow changes (handled by AZ-185 Update Manager)
  • fTPM provisioning pipeline (manufacturing-time, separate from code)
  • Remote attestation via EK certificates
  • fTPM-sealed device credentials (future enhancement, not v1)
  • Changes to the Azaion admin API server

Acceptance Criteria

AC-1: SecurityProvider auto-detection Given a Jetson device with provisioned fTPM and /dev/tpm0 accessible When the loader starts Then TpmSecurityProvider is selected and logged

AC-2: TPM seal/unseal round-trip Given TpmSecurityProvider is active When data is sealed via FAPI create_seal and later unsealed Then the unsealed data matches the original

AC-3: Legacy path unchanged Given no TPM is available (/dev/tpm0 absent) When the loader starts and processes resource requests Then LegacySecurityProvider is selected and all behavior is identical to the current scheme

AC-4: Env var override Given SECURITY_PROVIDER=legacy is set When the loader starts on a device with /dev/tpm0 present Then LegacySecurityProvider is selected regardless of TPM availability

AC-5: Graceful fallback Given /dev/tpm0 exists but FAPI connection fails When the loader starts Then it falls back to LegacySecurityProvider with a warning log

AC-6: Docker container TPM access Given docker-compose.yml with /dev/tpm0 and /dev/tpmrm0 device mounts When the loader container starts on a fused Jetson Then TpmSecurityProvider can connect to fTPM via FAPI

Non-Functional Requirements

Performance

  • TPM seal/unseal latency must be under 500ms per operation

Compatibility

  • Must work on ARM64 Jetson Orin Nano with JetPack 6.1+
  • Must work inside Docker containers with --device mounts
  • tpm2-pytss must be compatible with Python 3.11 and Cython compilation

Reliability

  • Graceful fallback to LegacySecurityProvider on any TPM initialization failure
  • No crash on /dev/tpm0 absence — clean detection and fallback

Unit Tests

AC Ref What to Test Required Outcome
AC-1 SecurityProvider factory with /dev/tpm0 mock present TpmSecurityProvider selected
AC-2 FAPI create_seal + unseal via swtpm Data matches round-trip
AC-3 SecurityProvider factory without /dev/tpm0 LegacySecurityProvider selected
AC-4 SECURITY_PROVIDER=legacy env var with /dev/tpm0 present LegacySecurityProvider selected
AC-5 /dev/tpm0 exists but FAPI raises exception LegacySecurityProvider selected, warning logged

Blackbox Tests

AC Ref Initial Data/Conditions What to Test Expected Behavior NFR References
AC-3 No TPM device available POST /load/{filename} (split resource) Existing binary-split behavior, all current tests pass Compatibility
AC-6 TPM simulator in Docker Container starts with device mounts FAPI connects, seal/unseal works Compatibility

Constraints

  • tpm2-pytss requires tpm2-tss >= 2.4.0 native library in the Docker image
  • Tests require swtpm (software TPM simulator) — must be added to test infrastructure
  • fTPM provisioning is out of scope — this task assumes a provisioned TPM exists
  • PCR-based policy binding intentionally not used (known persistence issues on Orin Nano)

Risks & Mitigation

Risk 1: fTPM FAPI stability on Jetson Orin Nano

  • Risk: FAPI seal/unseal may have undocumented issues on Orin Nano (similar to PCR/NV persistence bugs)
  • Mitigation: Design intentionally avoids PCR policies and NV indexes; uses SRK hierarchy only. Hardware validation required before production deployment.

Risk 2: swtpm test fidelity

  • Risk: Software TPM simulator may not reproduce all fTPM behaviors
  • Mitigation: Integration tests on actual Jetson hardware as part of acceptance testing (outside CI).

Risk 3: tpm2-tss native library in Docker image

  • Risk: tpm2-tss may not be available in python:3.11-slim base image; ARM64 build may need compilation
  • Mitigation: Add tpm2-tss to Dockerfile build step; verify ARM64 compatibility early.