Open joerg-krause opened 4 years ago
@joerg-krause Which version iTunes do you use ? Apple-Challenge refers to RSA Authentication, which is not allowed for AP2
iTunes version is 12.10.7.3. This is the log:
$ python ap2-receiver.py -m myap2 -n wlp5s0
Interface: wlp5s0
IPv4: 192.168.178.118
IPv6: fd00::89a1:4d7b:fa87:7be0
mDNS service registered
Starting RSTP server, press Ctrl-C to exit...
serving at port 7000
Got connection with 192.168.178.33:49339
CSeq: 1
User-Agent: iTunes/12.10.7 (Windows; Microsoft Windows 7 Service Pack 1 x64 Professional Edition (Build 7601); x64) (dt:2)
Client-Instance: 8E6AFF7283B34602
DACP-ID: 8E6AFF7283B34602
Active-Remote: 222309246
Apple-Challenge: 3zeVCckh56X+LikSee2wQg
Thanks @joerg-krause , Windows version of iTunes does not support FairPlay authentication. It either uses RSA authentication (regular raop devices) or MFi authentication with AP2 devices. I don't know if windows version of iTunes can accept RSA authentication for AP2 (mac version/ios devices does not), and I was actually interested in checking that (branch-RSA..) but it is still pending work.
Thanks @ckdo for sharing the RSA branch. Actually, iTunes on Windows does support FairPlay v2 authentication. I've tested in by advertising the AP2 device as an AP1 device using only the _raop._tcp service. However, if I re-enable the _airplay._tcp service, iTunes sends the "Apple-Challenge" in the OPTIONS
request stead of sending an fp-setup
request.
@joerg-krause RSA branch is updated to compute Apple-Response correctly. Apple-Response is accepted for _raop._tcp service, but for _airplay._tcp the dialog is stopping, so I guess RSA auth cannot be used on AP2 devices. In addition, windows version does not seems to support real Airplay2, protocol used is raop (ANNOUNCE for instance does not exist anymore with AP2 protocol) with previous MFi authentication.
Thanks @ckdo ! I wonder, why iTunes on Windows sends the Apple-Challenge. What authentication algorithm does it expect, if not RSA? Looks like an unsolved mystery for now...
@ckdo I managed to get iTunes on Windows to try to connect with the AirPlay 2 receiver using FairPlay v2. The features needs to be set to 0x3004A5D5A00
(The magic bit in the features is bit 25). iTunes needs several seconds before it sends the fp-setup
request (so I guess some settings are not optimal yet):
Got connection with 192.168.178.136:49791
CSeq: 1
Content-Type: application/octet-stream
Content-Length: 16
User-Agent: iTunes/12.10.7 (Windows; Microsoft Windows 10 x64 Professional Edition (Build 19041); x64) (dt:2)
Client-Instance: 61A9F4C15E5B4DD7
DACP-ID: 61A9F4C15E5B4DD7
Active-Remote: 616789066
POST /fp-setup
00000000: 46 50 4C 59 02 01 01 00 00 00 00 04 02 00 00 BB FPLY............
As you can see, the fifth byte send in the request is 02
, which is FairPlay v2. As the current code only implements FairPlay v3, further processing fails with an exception...
Interesting findings ! Once authenticated, unfortunately it will not use Airplay2 protocol: 192.168.128.227 - - [03/Jul/2020 15:58:49] code 501, message Unsupported method ('ANNOUNCE')
Like said in this case ANNOUNCE method is used, so it means raop/ap1. But... it can be interesting to know that for instance to ensure backward compatibility with ap1 with a device publishing only a _airplay._tcp service.
The ANNOUNCE
method is advertised as supported method in the OPTIONS
request even in AP2 devices. What makes you think the ANNOUNCE
is an AP1 method?
Yes so that AP2 devices ensure AP1 backward compatibility since there is one single enpoint for both protocols. Invano documented the methods used for AP2 here: https://emanuelecozzi.net/docs/airplay2/protocols
You can also quite easily check rtsp streams with a tcpdump since for iTunes/Windows they are not encrypted.
I see!
As I am far more experienced with C than with Python, I fiddled around with the FairPlay v2 feature using shairplay. This is my experimental FP2 branch: https://github.com/joerg-krause/shairplay/tree/fairplay_v2.
iTunes on Windows successfully connects to the AirPlay device, but shairport aborts, while buffering. Something is wrong with the audio decryption. Maybe the audio is not encrypted using AES 128 CBC?
I hope, that adding FairPlay v2 support can be used as a backward compatibility for iTunes on Windows...
Nice work I will check that... about encryption with Fairplayv2 I don't know but with MFi auth there's no particular change with encryption. Actually my initial goal for this project is to understand the "player" part of AP2... to implement in pulseaudio ( https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/194 ), with all benefits of AP2 and not only in AP1 compatibility mode as this MR does. So having "C" contributions is very welcome :)
Is your latest code pushed onto shairplay branch ? There are several points I don't understand (only fply_2 is used, fply_header and payload are not used in response)
The branch is named fairplay_v2. It is a single commit https://github.com/joerg-krause/shairplay/commit/d5f0953d2380502366592e30a0a59fe3879f3c59. fply_header
and fply_2
are used in fairplay_setup()
.
Yes, but I mean there https://github.com/joerg-krause/shairplay/blob/d5f0953d2380502366592e30a0a59fe3879f3c59/src/lib/fairplay_playfair.c#L93-L97 : res only rely on fply_2, which does not use neither fply_header nor payload . Is it normal ?
You're right! The reply needs to be distinguished whether by the request data. Depending on one byte set in the request, the header and payload data are needed for the response. That part is missing. I will add it soon, right now I am quite busy. Thanks for looking into it!
Update: The missing part is not relevant for the fairplay v2 handshake. The main problem seems to be the decryption. I guess, there is a difference between v2 and v3 decryption.
I think the best approach is to use legacy RSA, for iTunes on Windows.
EDIT: RSA is only working when using the _raop._tcp
bonjour service. When using the _airplay,_tcp
service, it fails. However, if I first use the _raop._tcp
service to connect iTunes on Windows with the AP device and then restart AP with the _airplay._tcp
service instead of _raop._tcp
, the authentification works, too.
I took a stab at getting the framework in place for RSA and perhaps also FP. The bits remaining to fix are decryption. There is a nice FP decryptor [1] available in C, so until that gets ported to Python, it's lib time. Was there anything interesting that you discovered when you tried to fix compatibility?
[1] https://github.com/juhovh/shairplay/tree/master/src/lib/playfair
I've pushed commits to master https://github.com/openairplay/airplay2-receiver/ which implement ANNOUNCE. This means you can receive audio encrypted using rsaaeskey. If I run:
python3 ap2-receiver.py -m myap2 -n en0 -ftxor 12
things seem to work out. But occasionally, (probably some mDNS record lurking around) I need to run python3 ap2-receiver.py -m myap2 -n en0 -ftxor 12 25
and then python3 ap2-receiver.py -m myap2 -n en0 -ftxor 12
again to get iTunes to stop sending:
Apple-Challenge
headers. But my iTunes for Windows never accepts those using your branch here. Perhaps Apple changed what is expected in the Apple-Response? I tried your approach in the RSA branch, using PKCS1_OAEP, with and without hardware ID. Maybe I didn't try every combo. Don't like black-box crypto stuff so much :shrug:
Any ideas @ckdo ?
The FairPlay authentification works fine with iOS, but fails with iTunes: The AirPlay device "myap2" is not compatible with this version of iTunes.
Something i noticed: iTunes sends an OPTION request with an "Apple-Challenge".