Skip to content

Harden comms pipeline and add AES-128-GCM uplink encryption#37

Merged
OrenRotaru merged 4 commits into
mainfrom
comms-hardening-aes-uplink
Jul 11, 2026
Merged

Harden comms pipeline and add AES-128-GCM uplink encryption#37
OrenRotaru merged 4 commits into
mainfrom
comms-hardening-aes-uplink

Conversation

@OrenRotaru

@OrenRotaru OrenRotaru commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

What this does

  • Adds AES-128-GCM encryption for uplink packets (note: no replay protection at this layer — that's up to the command layer)
  • Hardens the comms pipeline (better error handling and concurrency in the comms service)
  • Sends UDP passthrough from the downlink endpoint socket
  • Adds a ground station implementation guide (GROUND_STATION.md)
  • Adds config options for encryption, baud rate, and bus
  • Adds and updates tests for uplink, downlink, and concurrent handling

Fixes from the comms pipeline review:
- Make the SFP inter-fragment timeout configurable (csp.sfp_read_timeout_ms,
  default 10s) instead of a fatal 100ms read timeout
- Drain each uplink CSP port on its own poller thread feeding a channel, so
  SFP reassembly no longer starves packet-port commands
- Cap comms telemetry errors at the 100 most recent entries and recover from
  poisoned mutexes instead of panicking the read thread
- Back off 100ms on read errors instead of hot-spinning
- Stop counting UDP passthrough uplinks as downlink packets
- Set the CCSDS secondary header flag, which was always written but never set
- Validate CSP v1 node addresses (0..=31) in config
- Downlink an Error (PayloadType 2) NACK SpacePacket carrying the original
  command_id when a command cannot be serviced

New feature:
- Optional AES-128-GCM uplink encryption (csp.uplink_crypto = "aes-128" with
  a 16-byte hex csp.uplink_aes_key). Wire format is nonce(12) || ciphertext ||
  tag(16) wrapping the whole serialized SpacePacket on both uplink ports.
  Authentication failures are dropped silently and counted in telemetry.
  The key is redacted from Debug output and never exposed via GraphQL.

Documents the SpacePacket wire format, NACK behavior, and encryption usage in
the service README. Implementation by Codex from a reviewed spec.
Documents everything the ground segment needs to command the OBC over the
NXTRX4 link: CSP v1 frame layout, SFP fragment format and RDP expectations,
the SpacePacket byte contract with a worked hex example, the AES-128-GCM
uplink encryption wire format and nonce rules, size budgets per port, and
response/NACK correlation semantics.
UDP passthrough previously sent each uplinked datagram from a throwaway
ephemeral socket, so services that reply to the datagram's source address
(like shell-service) had their replies sent to a dead socket and lost.

CommsService::start now binds the downlink endpoint sockets up front and the
passthrough path sends from a clone of the first one. Replies to the source
therefore land on the downlink endpoint and are wrapped and downlinked like
any other UDP downlink. Without a configured downlink port the old ephemeral
behavior is kept.

Documents how shell-service (reply-to-source) and file-transfer-service
(configured downlink_ip/downlink_port, which must point at the comms
downlink endpoint) work over the radio link.
@OrenRotaru
OrenRotaru force-pushed the comms-hardening-aes-uplink branch from 14cf2ff to cd3ce78 Compare July 11, 2026 01:24
@OrenRotaru
OrenRotaru merged commit bb91098 into main Jul 11, 2026
0 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant