Skip to content

Svc/Ccsds: sequential SDLS IVs and configurable anti-replay window for AES-GCM - #5933

Open
lestarch-autobot wants to merge 1 commit into
nasa:develfrom
JPL-Devin:devin/1789079852-sdls-sequential-iv-anti-replay
Open

lestarch-autobot wants to merge 1 commit into
nasa:develfrom
JPL-Devin:devin/1789079852-sdls-sequential-iv-anti-replay

Conversation

@lestarch-autobot

Copy link
Copy Markdown
Collaborator
Related Issue(s) Follow-on to #5795 (no issue filed; requested by @LeStarch)
Has Unit Tests (y/n) y
Documentation Included (y/n) y
Generative AI was used in this contribution (y/n) AI

Change Description

Aligns the SDLS AES-GCM components with YAMCS's IV handling, where the 12-byte IV is a big-endian sequence number (IvSeqNum) incremented per frame and, optionally, checked against a forward window on receive (verifySeqNum / seqNumWindow, default 10).

Svc.Ccsds.AesGcmEncryptor — the IV is now a 96-bit sequence instead of RAND_bytes:

void setNextIv(const SdlsIv& iv);   // seed; defaults to all zeros
// per frame, after the key/size/busy checks and before the cipher runs:
SdlsIvSequence::toBytes(m_nextIv, iv);
SdlsIvSequence::increment(m_nextIv);   // wraps 0xFF..FF -> 0

A frame refused before the cipher (key error, oversize, busy store) draws no IV, so the sequence stays gap-free; a frame that fails inside the cipher still retires its IV.

Svc.Ccsds.AesGcmDecryptor — configurable anti-replay, evaluated only after AES-GCM authentication succeeds:

static constexpr U32 DEFAULT_ANTI_REPLAY_WINDOW = 10;
void configureAntiReplay(bool enabled, U32 window);   // disabled until called
void setLastAcceptedIv(const SdlsIv& iv);              // defaults to all ones, so 0 is the first accepted IV

Accepted iff received - lastAccepted (mod 2^96) is in [1, window]; then lastAccepted = received. Otherwise the frame is dropped with new status SdlsStatus.ANTI_REPLAY_FAILURE and the new WARNING_HI event IvReplayed(sa, received, lastAccepted) (throttle 5). MAC/key failures never touch the window, so a forged frame cannot desynchronize it. CcsdsSdlsDeframer already drops any non-SUCCESS status, so no downstream change is needed.

SharedSvc.Ccsds.SdlsIv (array [12] U8) in Types.fpp, and header-only Svc/Ccsds/Utils/SdlsIvSequence.hpp with fromBytes/toBytes/increment/isInWindow (fixed 12-iteration loops, no allocation).

Rationale

Requested behavior for interoperability with YAMCS: with random IVs the ground segment cannot apply its sequence-number window, and the flight side had no defense against replay of a captured, authenticated uplink frame. The sequence is component-wide (not per SA), matching a receiver that tracks one sequence per decryptor instance; the in-tree SdlsFileKeyManager already serves one key to all SAs.

Testing/Review Recommendations

  • Svc_Ccsds_AesGcmDecryptor_ut_exe: 23 tests (7 new: disabled mode, next-IV, window edge and overflow, exact reuse, 96-bit wrap and upper-byte carry, state only on accept, event throttle). Svc_Ccsds_AesGcmEncryptor_ut_exe: 15 tests (sequential IVs, wrap, refused frames draw no IV). All 18 Svc_Ccsds_* UTs pass; full UT tree builds (OpenSSL 3.5.1).
  • Review focus: SdlsIvSequence::isInWindow borrow arithmetic; configureAntiReplay asserts window > 0; the decryptor returns the original, un-advanced buffer on ANTI_REPLAY_FAILURE.
  • Both SDDs and docs/reference/system-functional/ccsds-protocol.md updated. Note the encryptor SDD's new operational caveat: the sequence lives in process memory, so a key that outlives a restart needs setNextIv() restored from persistent state (or a key rotation) to avoid IV reuse.

Future Work

  • Per-SA sequence state if a deployment routes several SAs with distinct keys through one decryptor and needs independent windows.
  • Wire configureAntiReplay/setNextIv into the encryption reference deployment topology.

AI Usage (see policy)

This PR was authored by Devin (Cognition AI) at the direction of Michael Starch: YAMCS source review, FPP/C++ implementation, unit tests, and documentation. A human reviewed the request and will review the result.

IAMAI

AesGcmEncryptor now emits a 96-bit big-endian IV sequence (wrapping at
2^96, seeded by setNextIv) instead of a random IV, matching YAMCS's
IvSeqNum. AesGcmDecryptor gains configureAntiReplay(enabled, window):
after AES-GCM authentication, the received IV must lie within the next
window values after the last accepted IV, or the frame is dropped with
ANTI_REPLAY_FAILURE and the throttled WARNING_HI IvReplayed event.
Anti-replay is disabled by default; the window defaults to 10.

Co-Authored-By: michael.d.starch <michael.d.starch@jpl.nasa.gov>
@thomas-bc
thomas-bc self-requested a review September 10, 2026 22:50
@github-actions

Copy link
Copy Markdown
Contributor

Coverage report — base devel

Overall (line): 84.60% → 84.62% (+0.02)
Regression threshold: 0.50% (line).

Regressions

(none over threshold)

Modules changed

Module Line Δ Function Δ Branch Δ
Os/Posix 65.49 -0.39 86.32 +0.00 46.28 -0.23
Os/Generic/Types 91.79 -0.35 92.86 +0.00 73.83 -1.87
Svc/Ccsds/TcDeframer 95.08 +0.16 100.00 +0.00 87.27 +0.48
Fw/DataStructures 97.60 +0.18 97.14 +0.19 82.12 +0.37

New modules

Module Line Function Branch
Fw/Prm 0.00 0.00 0.00

Modules without UTs

CFDP/Checksum/GTest, Drv/LinuxGpioDriver, Drv/LinuxI2cDriver, Drv/LinuxSpiDriver, Drv/Ports/DataTypes, Drv/PosixUartDriver, FppTestProject/FppTest/topology/async, FppTestProject/FppTest/topology/components/Comp, FppTestProject/FppTest/topology/components/Framework, FppTestProject/FppTest/topology/components/Receiver, FppTestProject/FppTest/topology/components/Sender, FppTestProject/FppTest/topology/guarded, FppTestProject/FppTest/topology/sync, FppTestProject/FppTest/topology/top_ports, FppTestProject/FppTest/topology/types, Fw/Com, Fw/Comp, Fw/FilePacket/GTest, Fw/Fpy, Fw/Obj, Fw/Port, Fw/Sm, Fw/Test, Fw/Types/GTest, Os/Models, Svc/Ccsds/Types, Svc/Ccsds/Utils, Svc/FatalHandler, Svc/Subtopologies/CdhCore, Svc/Subtopologies/ComCcsds, Svc/Subtopologies/ComCcsdsSdls, Svc/Subtopologies/ComFprime, Svc/Subtopologies/ComLoggerTee, Svc/Subtopologies/DataProducts, Svc/Subtopologies/DpCompression, Svc/Subtopologies/FileHandling, Svc/Subtopologies/FileHandlingCfdp, Svc/Subtopologies/FileHandlingCfdp/FileHandlingCfdpConfig, TestDeploymentsProject/Ref/DpDemo, TestDeploymentsProject/Ref/PingReceiver, TestDeploymentsProject/Ref/RecvBuffApp, TestDeploymentsProject/Ref/SendBuffApp, TestDeploymentsProject/Ref/Top, TestDeploymentsProject/Ref/TypeDemo, cmake/test/data/TestConfigDeployment, cmake/test/data/TestDeployment/TestBuildAutocoder, cmake/test/data/TestDeployment/TestHeaderAutocoder, cmake/test/data/TestDeployment/TestLinkDepends, cmake/test/data/TestDeployment/TestRelative, cmake/test/data/test-fprime-library/TestLibrary/TestComponent, cmake/test/data/test-fprime-library2/TestLibrary2/TestComponent

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