Use the raw FairPlay key for legacy receivers (#17) - #23
Conversation
ekey wraps the raw fpAesKey, and on a legacy receiver that is the only key material it ever sees, so it decrypts the stream with that key directly. A HAP-paired receiver additionally mixes in the pair-verify secret. The condition chose between them on whether a shared secret existed. rawPairVerify stores one even though it deliberately leaves the channel unencrypted, so the mixing fired on the legacy path too: the sender encrypted with SHA-512(fpAesKey || shared) while the receiver decrypted with fpAesKey. Pairing, /fp-setup, SETUP and RECORD all succeed, frames flow, and the picture stays black -- the symptom reported in omarroth#17. Select on c.encrypted instead, which PairVerify sets and rawPairVerify deliberately does not. HAP-paired receivers keep exactly the bytes they get today. Extracts the derivation into deriveStreamMasterKey so it can be tested without a handshake, and adds three tests: the four legacy/HAP-by-secret-presence combinations, a control that the two branches genuinely differ, and a guard that fails if rawPairVerify ever starts setting c.encrypted -- which would silently switch legacy receivers back to the mixed key. Diagnosed from 3rd3's fork patch in omarroth#17, which reached the same key by switching unconditionally; that would have dropped the mixing on HAP receivers too. 3rd3 confirmed this conditional version works against an AppleTV3,2 on AirTunes/220.68.
2e20cc3 to
dbc11dc
Compare
|
No rush on this at all — but a question that would help me, and I'd rather ask it than keep guessing. I opened three PRs here yesterday (#22, #23, #24) without checking first whether outside contributions are actually wanted. That was the wrong order, and I'd like to correct it: is this the kind of thing you want, and in what form? A "not right now" or "smaller PRs please" is a genuinely useful answer and I won't take it badly. Asking partly because I have more prepared and would rather not add to a queue uninvited. Some performance work on For context on why I'm in this code at all: my own FairPlay implementation now uses your Of the three open PRs, this one is the only one where someone else has a stake: @3rd3 confirmed the change fixes their AppleTV3,2 on real hardware, which I couldn't test myself. |
Fixes the black-screen half of #17. @3rd3 has confirmed this exact change works against an AppleTV3,2 on AirTunes/220.68.
The bug
ekeywraps the rawfpAesKey. On a legacy receiver that is the only key material it ever sees, so it decrypts the stream with that key directly. A HAP-paired receiver additionally mixes in the pair-verify secret:The condition chose between them on whether a shared secret existed:
But
rawPairVerifystores a shared secret too, immediately under its own comment saying it does not enable HAP encryption. So the mixing fired on the legacy path as well: the sender encrypted withSHA-512(fpAesKey ‖ shared), the receiver decrypted withfpAesKey.That matches the reported symptom exactly — pairing,
/fp-setup,SETUPandRECORDall succeed, frames flow, picture stays black.The change
Select on
c.encrypted, whichPairVerifysets andrawPairVerifydeliberately does not. HAP-paired receivers keep exactly the bytes they get today.This is the conditional form of 3rd3's fork patch, which reached the same key by switching unconditionally — correct for AppleTV3, but it would have dropped the mixing on HAP receivers too.
Tests
The derivation is extracted into
deriveStreamMasterKeyso it can be tested without a handshake:rawPairVerifyever starts settingc.encrypted, since that would silently switch legacy receivers back to the mixed keyI checked the tests actually catch the bug: reverting the discriminator fails
legacy pairing, secret presentand the branches-differ control, and nothing else.go test ./...is green.Not included
@3rd3 also needed
video/x-raw,format=I420added incapture.goon their XFCE/X11 setup. That looks like a separate capture-side issue, possibly already addressed by e9a395a, and I have no way to test a GStreamer pipeline against an Apple TV — so I've left it alone rather than guess.