Move TC uplink security onto upstream F Prime SDLS interfaces - #513
Move TC uplink security onto upstream F Prime SDLS interfaces#513nateinaction wants to merge 1 commit into
Conversation
Replace Components::TcSecurityDeframer, a project-local pass-through component from before F Prime had a security hook, with Components::TcSecurityDecryptor: a decryptor implementing Svc.Ccsds.CcsdsSdlsDecrypt behind the upstream Svc::Ccsds::CcsdsSdlsDeframer introduced in F Prime 4.3.0. The security association index is now supplied by the deframer rather than parsed from the frame, so MAC verification moves to the PSA multipart API to keep the SA index inside the authenticated span. Wire format, authenticated-flag policy, and all command opcodes are unchanged; no SdlsSaRouter or SdlsFileKeyManager adopted (documented in the component SDD). Verified: host unit tests, a full Zephyr build (opcodes/telemetry channels confirmed in the topology dictionary), and a bench integration run on the flight control board showing a clean authenticated round-trip and the anti-replay path rejecting a duplicate frame without advancing the counter.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
nateinaction
left a comment
There was a problem hiding this comment.
Code review
Reviewed the rename and re-platforming onto Svc.Ccsds.CcsdsSdlsDeframer / CcsdsSdlsDecrypt. The substance is correct. Verified:
- Wire format compatibility holds.
authenticateFrameMACssaIndex(2, BE) || [SeqNum|Data], which matchesFraming/src/authenticate_plugin.py'sHMAC(SPI|SeqNum|Data)exactly. - Test vectors are right. Recomputed both new vectors in
test_TcSecurityDecryptor_Authenticator.cpp. - Opcodes preserved.
ReferenceDeploymentTopologyDictionary.jsonshows0x2100B000/0x2200B000forGET_SEQ_NUM, keeping theBypasser.cppliterals valid;CurrentSequenceNumberexists on both links. - Buffer ownership is sound on both the SUCCESS and
DECRYPTION_FAILUREpaths. Dropping the un-slice in the return handler is safe:BufferManager::bufferSendIn_handleronly asserts the pointer is inside the allocation and that the size did not grow. - Truncated MAC works in the multipart PSA path —
psa_mac_finalize_alg_and_key_validationonly rejects< 4bytes, and the imported key'sPSA_KEY_USAGE_VERIFY_MESSAGEis the flagpsa_mac_verify_setuprequires. No fallback needed. - No base-id collisions. The new
sdlsDeframerbase id+0x0C000is clear in all three subtopologies;logOut/logTextOut/timeCallerare auto-connected, and the unconnectederrorNotifyis guarded upstream.
Three inline findings below, plus one that is not anchorable because the file is not in the diff:
Stale debug configs — .vscode/launch.json:38 (low)
Three debug configurations still point at build-gtest/test_TcSecurityDeframer_{Authenticator,Parser,Validator}. After this rename make test-unit produces test_TcSecurityDecryptor_*, so all three fail to launch. This file was missed by the rename fan-out.
| // drops the frame and returns the buffer for deallocation. | ||
| this->log_WARNING_HI_ParsingFailed(static_cast<PacketParserStatus::T>(parseResult.status)); | ||
| this->dataReturnOut_out(0, data, contextOut); | ||
| this->decryptOut_out(0, Svc::Ccsds::SdlsStatus::DECRYPTION_FAILURE, data, contextOut); |
There was a problem hiding this comment.
medium — unthrottled event amplification from the uplink
Routing the parse-failure drop through decryptOut_out(DECRYPTION_FAILURE, ...) makes the upstream deframer emit Svc.Ccsds.CcsdsSdlsDeframer.DecryptionFailed, which is declared with no throttle, in addition to the local ParsingFailed (throttle 2).
Producing a droppable frame requires no secret — only a well-formed TC primary header and a correct FECF CRC16. So anyone transmitting on the LoRa/UART link can emit one unthrottled WARNING_HI event per frame indefinitely, crowding real events out of the ComQueue.
The interface offers a quieter drop: bufferReturnOut is documented as "Port for returning the incoming iv/data buffer for deallocation". Calling
this->bufferReturnOut_out(0, data, contextOut);reaches CcsdsSdlsDeframer::bufferReturnIn_handler -> dataReturnOut_out -> TcDeframer, returning the buffer with no upstream event.
| @ downstream by the router. | ||
| passive component TcSecurityDecryptor { | ||
|
|
||
| import Svc.Ccsds.CcsdsSdlsDecrypt |
There was a problem hiding this comment.
low — recursive acquisition of the guarded-port mutex
import Svc.Ccsds.CcsdsSdlsDecrypt makes both decryptIn and decryptReturnIn guarded; the generated TcSecurityDecryptorComponentAc.cpp (lines 1038 and 1066) confirms both call the same this->lock().
The whole downstream chain is synchronous (spacePacketDeframer -> ProvesRouter::dataIn_handler, which calls dataReturnOut_out on the same stack), so decryptReturnIn_handler re-enters m_guardedPortMutex while decryptIn_handler still holds it. This only works because Zephyr's k_mutex is recursive — the removed component deliberately declared sync input port dataReturnIn to avoid exactly this.
On any POSIX host build, Os::Posix::Mutex uses PTHREAD_MUTEX_ERRORCHECK and would FW_ASSERT, which will block re-enabling the commented-out component UT in CMakeLists.txt:52. Worth an explicit comment at minimum, or overriding lock() / unLock().
|
|
||
| //! CCSDS 355.0-B-2 Section E2.2 | ||
| //! The Security Parameter Index is stripped by the upstream Svc.Ccsds.CcsdsSdlsDeframer before | ||
| //! this component sees the frame; kSpiSize is kept only for the MAC-prefix fallback in Authenticator. |
There was a problem hiding this comment.
low — comment refers to code that does not exist
This says kSpiSize is "kept only for the MAC-prefix fallback in Authenticator", but no such fallback was implemented: Authenticator.cpp:113 hardcodes const uint8_t saIndexBytes[2]. kSpiSize is now referenced nowhere, so the comment points a future reader at code that is not there.
Summary
Components::TcSecurityDeframer(a project-local pass-through component written before F Prime had a security hook) withComponents::TcSecurityDecryptor, a decryptor implementingSvc.Ccsds.CcsdsSdlsDecryptbehind the upstreamSvc::Ccsds::CcsdsSdlsDeframerintroduced in F Prime 4.3.0.psa_mac_verify_setup/update/update/psa_mac_verify_finish) to keep the SA index inside the authenticated span.authenticated-flag policy design, ground-side Framing plugin, and all command opcodes are unchanged. NoSdlsSaRouterorSdlsFileKeyManageradopted — both rejections are documented in the component SDD, along with the seam Move HMAC auth key off firmware image onto internal-flash key store #472 (key store) and feat(TcSecurityDeframer): expose active key SPIs and fingerprints #490 (key fingerprints) can land through.Test plan
make test-unit— all 8 host gtest suites pass (added coverage that the SA index participates in the MAC)make generate build— clean full Zephyr flight build;GET_SEQ_NUMopcodes confirmed unchanged (0x2100B000/0x2200B000) andCurrentSequenceNumberchannels present in the topology dictionary for UART/LoRamake check-console-disabledsync_sequence_numberthen the broader integration suite (11 passed, 0 failed); event log shows the anti-replay path organically rejecting a duplicate frame (SequenceNumberInvalid) without advancing the counter, noAuthenticationFailed/ParsingFailed/DecryptionFailedevents,commsBufferManagerhigh-water stable