net/srtp: EKT hardening — MKI exclusivity and key-lifetime limits - #448
Merged
Conversation
An EKT-ingested key installs an MKI-less crypto context, so a context that also emits or parses an MKI trailer would misparse packets once a Full EKT field is ingested. The two key-management mechanisms are alternatives; guard against combining them: adding an MKI crypto context fails once EKT is configured, and adding an EKTKey fails once an MKI context exists, both with R_SRTP_ERROR_INVAL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
An EKTKey must not wrap keys indefinitely (RFC 8870 4.5 / 5.2.2). Track a per-key wrap count and an optional lifetime (r_srtp_set_ekt_key_ttl, measured from first use); once either the AES Key Wrap cap (2^48) or the TTL is reached the sender stops emitting Full fields under that key -- they degrade to Short, so the key is never used beyond its limits. The application rolls to a fresh EKTKey (a new SPI) before then. TTL defaults to unlimited, preserving prior behaviour. Also note in the receiver anti-replay path that the 16-bit epoch is treated as strictly increasing: a wrap past 0xffff (2^16 rekeys of one SPI, unreachable in practice) stalls re-keying rather than accepting a replay. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Two follow-on hardening fixes for the EKT (RFC 8870) implementation, found while auditing it.
EKT and MKI mutual exclusivity
An EKT-ingested key installs an MKI-less crypto context, so a context that also emits or parses an MKI trailer would misparse packets once a Full EKT field is ingested. They are alternative key-management mechanisms; the two
_with_mkiconstructors now fail once EKT is configured, andr_srtp_add_ekt_keyfails once an MKI context exists, both withR_SRTP_ERROR_INVAL. Documented on the affected entry points.EKT key lifetime and usage limit (RFC 8870 §4.5 / §5.2.2)
An EKTKey must not wrap keys indefinitely. Each EKTKey now tracks a wrap count and an optional lifetime (
r_srtp_set_ekt_key_ttl, measured from first use). Once either the AES Key Wrap cap (2^48) or the TTL is reached, the sender stops emitting Full fields under that key — they degrade to Short, so the key is never used beyond its limits; the application rolls to a fresh EKTKey (a new SPI) before then. TTL defaults to unlimited, preserving prior behaviour.The wrap is counted only when a Full field is actually emitted, so a protect that fails after sizing neither burns usage nor starts the TTL clock. Also documents that the 16-bit receiver epoch is treated as strictly increasing (a wrap past
0xffff, unreachable in practice, stalls re-keying rather than accepting a replay).Testing
New tests: EKT/MKI mutual exclusion (both orders, ssrc + filter), TTL cutting the startup burst short (load-bearing — neutering the gate restores the full burst), and TTL setter argument validation. Full suite 2348 passed / 0 failed on the linux and ASan tiers (both warning-free). Reviewed with a two-agent adversarial audit (logic/safety + docs); its findings — accounting a wrap on attempt rather than emission, and a
first_used == 0sentinel ambiguity — are fixed in this branch.🤖 Generated with Claude Code