Skip to content

[atak] Android-side PQC sidecar for ML-KEM session decrypt #69

Description

@jdev-02

Lane: atak · Owner: P4 (Ben) · Phase: stretch · Priority: P2 · Pair: P2 (signer/KEM)

Why

ATAK does not natively speak liboqs. To realize the ML-KEM-768 session encryption (sister stretch issue) end-to-end, the Android side needs a process that:

  1. Runs the peer half of the ML-KEM handshake with the Jetson agent
  2. Decrypts the AEAD-sealed CoT stream
  3. Forwards the plaintext (still ML-DSA-signed) CoT to ATAK on a loopback port

This is the actual hard half of the encrypted-tunnel stretch. Without it, the server-side encryption (other stretch issue) has no peer.

Two viable approaches — pick at kickoff

Approach 1: Phone-side sidecar app (preferred)

  • Standalone Android app written in Kotlin or Termux-Python
  • Listens on a TCP port for the encrypted stream from Jetson (USB-tethered)
  • Performs ML-KEM-768 handshake via liboqs-java (or Python via Termux + liboqs-python)
  • Decrypts, forwards plaintext signed CoT to ATAK on 127.0.0.1:4242
  • Pro: no ATAK plugin contract to satisfy, ATAK just sees normal CoT on loopback
  • Con: extra process to keep alive

Approach 2: Native ATAK plugin (Java)

  • Implements ATAK's plugin SDK
  • Same KEM + AEAD logic but inside the ATAK process
  • Pro: cleaner integration, no extra app on the phone
  • Con: ATAK plugin SDK is heavy; signing + sideload complications; takes longer

Decision: start with Approach 1. Approach 2 is post-hackathon.

Acceptance criteria

  • Android app/Termux script accepts a TCP connection on (configurable) port 4243 from the Jetson over USB tether
  • Performs ML-KEM-768 + X25519 hybrid handshake matching the protocol spec from sister issue (docs/contracts/pqc_session.md)
  • Successfully decrypts AEAD-sealed CoT messages emitted by Jetson agent
  • Forwards plaintext signed CoT to 127.0.0.1:4242 (where ATAK is configured to listen)
  • Verifies replay counters match the spec
  • Demo: Jetson on USB tether, encrypted stream flows, ATAK draws the route, tcpdump on the wire shows ciphertext only
  • If sidecar dies, ATAK doesn't see anything (fail-closed). On restart, fresh handshake re-establishes.

File pointers

  • atak/sidecar/ (new directory)
  • atak/sidecar/README.md (build + sideload instructions)
  • Either: atak/sidecar/app/ (Android Studio project) or atak/sidecar/termux/ (Python script)

Dependencies

  • Hard prerequisite: sister issue (server-side ML-KEM session) for the wire format spec
  • Hard prerequisite: USB tether POC working with plaintext signed CoT (proves the link)
  • Hardware: Kyle's HDMI-to-USB tether adapter for Jetson↔Samsung physical link
  • Tooling: liboqs-java if Approach 2; liboqs-python + Termux if Approach 1

Defer condition

This is the integration point that determines whether the encrypted-tunnel stretch ships at all. If at Sun 0700 go/no-go we don't have a clear path to one of the two approaches working in 2-3 hours, drop both stretch issues and pitch the architecture as roadmap-only (PRD §8.5 deferred). The ML-DSA signed CoT (already shipping) is enough for the security beat by itself.

Refs PRD §7.2 (mesh stretch row), §8.2 step 5, §8.5.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions