Skip to content

net/srtp: EKT hardening — MKI exclusivity and key-lifetime limits - #448

Merged
haaspors merged 2 commits into
masterfrom
srtp-ekt-hardening
Aug 3, 2026
Merged

net/srtp: EKT hardening — MKI exclusivity and key-lifetime limits#448
haaspors merged 2 commits into
masterfrom
srtp-ekt-hardening

Conversation

@haaspors

@haaspors haaspors commented Aug 3, 2026

Copy link
Copy Markdown
Owner

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_mki constructors now fail once EKT is configured, and r_srtp_add_ekt_key fails once an MKI context exists, both with R_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 == 0 sentinel ambiguity — are fixed in this branch.

🤖 Generated with Claude Code

haaspors and others added 2 commits August 3, 2026 17:45
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>
@haaspors
haaspors merged commit 84cd79f into master Aug 3, 2026
18 checks passed
@haaspors
haaspors deleted the srtp-ekt-hardening branch August 3, 2026 16:11
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