Skip to content

avformat/whip: require remote DTLS fingerprint in SDP answer#78

Open
JackLau1222 wants to merge 1 commit into
workflowsfrom
michaelni-ff-tmp-half-a-whip
Open

avformat/whip: require remote DTLS fingerprint in SDP answer#78
JackLau1222 wants to merge 1 commit into
workflowsfrom
michaelni-ff-tmp-half-a-whip

Conversation

@JackLau1222

Copy link
Copy Markdown
Collaborator

WHIP relies on the SDP a=fingerprint to bind the peer identity to the SRTP keying material (RFC 8842 §§ 5.1, 5.3). parse_answer() walks the SDP body looking for a=ice-lite, a=ice-ufrag:, a=ice-pwd:, and a=candidate: lines and ignores everything else, including a=fingerprint. WHIP intentionally runs the OpenSSL DTLS backend with s->verify=0 (DTLS-SRTP uses self-signed certs by design, so a CA chain check would be meaningless); the peer cert is accepted regardless of identity. The spec's compensating identity control — verifying the DTLS peer cert against the SDP a=fingerprint hash — is missing, so the SRTP keys are derived from a session whose peer identity was never authenticated. Any on-path attacker, or a malicious WHIP server URL, can substitute their own DTLS material and the publisher's RTP stream will be encrypted to them.

The full fix is a two-step process:
(a) Require a=fingerprint to be present in the SDP answer
(RFC 8842 § 5.3 MUST).
(b) After DTLS handshake, compute the peer-cert hash and compare
against the stored fingerprint (RFC 8842 § 5.1 MUST); tear
down the session on mismatch.
This patch implements step (a) only; step (b) requires plumbing the cert hash out of dtls_start() through the openssl TLS context and is left as a follow-up.

Add a remote_fingerprint field to WHIPContext, extract the a=fingerprint value from the SDP answer in parse_answer(), and return AVERROR(EINVAL) when it is absent. This raises the bar from "no fingerprint required" to "any fingerprint required"; the follow-up patch will raise it again to "fingerprint MUST hash-match the DTLS peer cert."

Found-by: Claude (Anthropic). Human-verified and reported by Omkhar Arasaratnam omkhar@linkedin.com.

WHIP relies on the SDP a=fingerprint to bind the peer identity to
the SRTP keying material (RFC 8842 §§ 5.1, 5.3). parse_answer()
walks the SDP body looking for `a=ice-lite`, `a=ice-ufrag:`,
`a=ice-pwd:`, and `a=candidate:` lines and ignores everything else,
including `a=fingerprint`. WHIP intentionally runs the OpenSSL DTLS
backend with s->verify=0 (DTLS-SRTP uses self-signed certs by
design, so a CA chain check would be meaningless); the peer cert is
accepted regardless of identity. The spec's compensating identity
control — verifying the DTLS peer cert against the SDP a=fingerprint
hash — is missing, so the SRTP keys are derived from a session
whose peer identity was never authenticated. Any on-path attacker,
or a malicious WHIP server URL, can substitute their own DTLS
material and the publisher's RTP stream will be encrypted to them.

The full fix is a two-step process:
  (a) Require a=fingerprint to be present in the SDP answer
      (RFC 8842 § 5.3 MUST).
  (b) After DTLS handshake, compute the peer-cert hash and compare
      against the stored fingerprint (RFC 8842 § 5.1 MUST); tear
      down the session on mismatch.
This patch implements step (a) only; step (b) requires plumbing
the cert hash out of dtls_start() through the openssl TLS context
and is left as a follow-up.

Add a remote_fingerprint field to WHIPContext, extract the
a=fingerprint value from the SDP answer in parse_answer(), and
return AVERROR(EINVAL) when it is absent. This raises the bar from
"no fingerprint required" to "any fingerprint required"; the
follow-up patch will raise it again to "fingerprint MUST hash-match
the DTLS peer cert."

Found-by: Claude (Anthropic). Human-verified and reported by
Omkhar Arasaratnam <omkhar@linkedin.com>.
Signed-off-by: Omkhar Arasaratnam <omkhar@linkedin.com>
@github-actions
github-actions Bot force-pushed the workflows branch 7 times, most recently from f7516d1 to 7079d5b Compare June 3, 2026 00:54
@github-actions
github-actions Bot force-pushed the workflows branch 8 times, most recently from 3a21f63 to 78e6b5b Compare June 11, 2026 00:48
@github-actions
github-actions Bot force-pushed the workflows branch 7 times, most recently from f3a2fa0 to 0a5ee51 Compare June 18, 2026 00:51
@github-actions
github-actions Bot force-pushed the workflows branch 7 times, most recently from df9a9de to 3eeac0d Compare June 25, 2026 00:45
@github-actions
github-actions Bot force-pushed the workflows branch 7 times, most recently from 4ac1629 to e0056c5 Compare July 2, 2026 00:44
@github-actions
github-actions Bot force-pushed the workflows branch 7 times, most recently from 79431fe to 842e45a Compare July 9, 2026 02:36
@github-actions
github-actions Bot force-pushed the workflows branch 8 times, most recently from 9fc4947 to 6e3be90 Compare July 17, 2026 02:20
@github-actions
github-actions Bot force-pushed the workflows branch 6 times, most recently from cf51801 to f17ab0c Compare July 24, 2026 02:22
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