Add replay protection to encrypted commands (MJ-11)#5
Open
balloob wants to merge 1 commit into
Open
Conversation
The inbound encrypted-command path only verified session liveness and the CCM tag, never the nonce counter. An attacker who captured any encrypted command frame in a live session could replay it verbatim and the device would re-execute it. The replay-window fields already existed in the session struct but were unused on the inbound path. Port the nRF firmware's verifyNonceReplay sliding-window check to Silabs and wire it into decrypt_encrypted_payload at the point the CCM tag is verified, mirroring nRF's decryptCommand semantics so both firmwares behave identically against the same client: reject replays (already-seen or below the +/-32 window), advance last_seen_counter/replay_window on accept, and clear the session after repeated integrity failures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012g2e8mr132vcizx92WsgiR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Silabs inbound encrypted-command path performs no replay protection.
decrypt_encrypted_payloadonly checkedsession_alive()and the CCM tag; the replay-window fields in the session struct (last_seen_counter,replay_window,replay_idx) were never consulted on the inbound path. An attacker who captures any encrypted command frame in a live session can replay it verbatim and the device re-executes it.The nRF firmware already validates a sliding nonce-counter window (
encryption.cverifyNonceReplay, called fromdecryptCommand), so the two firmwares diverged in security behavior.Fix (mirrors nRF)
Port nRF's
verifyNonceReplayto Silabs asverify_nonce_replayand wire it intodecrypt_encrypted_payloadat the point the CCM tag is verified, matching nRF'sdecryptCommandsemantics so both firmwares behave identically against the same client:last_seen_counterand already present in the 64-entryreplay_window.last_seen_counterwhen the counter is newer, and record the counter in the circularreplay_window.integrity_failuresand clear the session after 3, mirroring nRF; resetintegrity_failuresto 0 on a successful decrypt.This uses the existing nonce counter only — the nonce direction-bit change (MJ-12) is a separate breaking change handled elsewhere and is intentionally not touched here. No other command handling is modified.
Testing
Full SLC/Simplicity firmware build could not be run in this environment (no
arm-none-eabi-gcc/slctoolchain available). Verification done:EncryptionSessionwith host GCC (-Wall -Wextra -std=c11): clean, no warnings; all referenced struct fields exist and types match.verifyNonceReplayaccept/reject decisions: fresh counter accepted, out-of-order replay below the window rejected, counter far outside the +/-32 window rejected, session_id mismatch rejected. The one nRF quirk (a replay of the exact currentlast_seen_counter, diff==0, is accepted until a newer counter arrives) is reproduced identically, keeping the two firmwares in lockstep.🤖 Generated with Claude Code
https://claude.ai/code/session_012g2e8mr132vcizx92WsgiR