thibauts / node-castv2

An implementation of the Chromecast CASTV2 protocol
MIT License
765 stars 99 forks source link

How does Device Authentication work ? #2

Open thibauts opened 10 years ago

thibauts commented 10 years ago

I'm trying to understand device authentication right now and will post progress in this issue.

thibauts commented 10 years ago

The culprit is the VerifyCredentials function in cast_auth_util_nss.cc.

The Chromecast uses 2 certificates. The first one is used for the TLS connection, is self-signed and expires every 24 hours (let's call it the peer certificate). The second one is used to validate the first in the device authentication process (let's call it the platform certificate).

I added a few tools in the bin directory to help dumping and inspecting the various files.

The process seems to go as follows.

  1. Every 24 hours the dongle generates a new self-signed TLS peer certificate.
  2. A client sends a DeviceAuth challenge.
  3. The dongle generates a signature of its current peer certificate using the platform certificate private key and returns both the platform certificate and the signature to the client.
  4. First the client verifies that the platform certificate is signed by a trusted CA using its embedded public key (kCAPublicKeyDER)
  5. The client then extracts the platform certificate public key and uses it to check that the returned signature matches the peer certificate signed with the platform certificate.

Long story short, I'm not an expert in cryptography but it seems that without the platform certificate private key used to produce the signature, not much can be done.

luke commented 10 years ago

I stumbled across this repo. It seems to have tools related to the certs on the chromecast. Thought it migth be of some help. https://github.com/EiNSTeiN-/chromecast-widevine-tools

thibauts commented 10 years ago

Looks good indeed. Thanks a lot !

leo-labs commented 9 years ago

Are there some updates on this? :)

thibauts commented 9 years ago

Nothing yet. I don't have time nor interest in searching this direction but I'll help if I can.

leo-labs commented 9 years ago

Am I rigth that the only way to get authentiation is work is buying a chromecast and root it?

thibauts commented 9 years ago

I can't say for sure. A first step would be understanding the auth scheme and looking at the chromium source code.

emersion commented 9 years ago

Somme guys managed to make it work in a Python project: https://github.com/dz0ny/leapcast I will try to add this to node-castv2 soon :-)

thibauts commented 9 years ago

Hmm, where exactly is the code that does it ?

emersion commented 9 years ago

I think sign_data is very interesting here: https://github.com/dz0ny/leapcast/blob/master/leapcast/services/dial.py

leo-labs commented 9 years ago

I do not think, that this is related to chromecast v2 protocol;

thibauts commented 9 years ago

I think @leo-labs is right, it doesn't look like the same process at all. Probably only relevant to the DIAL protocol.

Afterster commented 9 years ago

The chromecast protocol is new to me so sorry if this is a dummy question :). If the 24h-generated certificate is only used for Chromecast device legacy authentication, an "authentication proxy" replaying the authentication request to a real Chromecast should work isn't it?

thibauts commented 9 years ago

This looks like it should work in principle, but in effect I fear the Chrome browser will be too sensitive. During discovery the browser does an mDNS lookup and immediately connects to and authenticates the devices it found. I'm not sure two devices with the same credentials will be accepted.

I may even have tried this and failed, can't remember exactly. I may have messed something up during my tests, too.

JumpLink commented 9 years ago

Did someone just ask google to get an certificate for custom applications? Google seems to allow chromecast devices from other manufacturers, like smartTV's or speakers, for example this: http://www.xperiablog.net/2015/01/07/sony-announces-speakers-with-google-cast-for-audio-support/ Maybe this is not as problematic as we think?

thibauts commented 9 years ago

I doubt they took the burden of creating an auth system only to deliver free keys later. But well, you should ask !

JumpLink commented 9 years ago

Okay Post on Google+ Developer Group Issue on Google Code

HomerSp commented 9 years ago

I've done some looking into this, and noticed that the AuthResponse structure of cast_channel.proto is slightly wrong. There is an additional repeated field at index 3 that contains the CA certificates that's used for verifying the client_auth_certificate on the client-side (on Android it's done through CertPathValidator). So the correct struct would look like this: message AuthResponse { required bytes signature = 1; required bytes client_auth_certificate = 2; repeated bytes ca_certs = 3; }

thibauts commented 9 years ago

Interesting. I have no immediate interest in pursuing that but I'll gladly accept PRs.

friscoMad commented 9 years ago

Checking the last version of the sources it is clear that there are several CAs and that now that field is repeated as a CA chain can be sent. The legacy flow (only one CA) just checks agains the same CA public key and if a chain is sent then it seeks for the CA cert hast and check against the proper certificate (¿kPublicKeyICA1 and kPublicKeyICA2 are the same cert with different hash?) .

So to make all this work we need a device cert signed with one of those CAs or use a Chrome client that skips that validation. I am no aware of anyone but it should be simple to create one.

Probably there is one CA cert for every vendor, so they have to pay the fees to be included in the SDK and future ChromeCast clients. Rooting any authorized device will provide us a valid cert, and unless they want to disable a lot of official devices they will not be able to revoke that cert, so that seems the only way to go if Google don't want to give a cert to the public and we want a server that works with any client.

emersion commented 9 years ago

Has anyone tried to install this XPosed module to be able to skip Device Authentication?

https://github.com/HomerSp/XposedCastClientFix

(Source: http://forum.xda-developers.com/hardware-hacking/chromecast/app-cast-receiver-app-android-t2900726)

katlogic commented 9 years ago

@Afterster Indeed that appears to be the case. Simplest course of action would be to expose public internet service providing signatures via libGtvCa (ie everyone would essentialy see the very same device) running on a rooted dongle.

This is both simplest implementation and works against the worst case when signatures are provided by DRM hardware in the dongle (ie extracting root key will be very difficult).

EDIT: According to XDA, v2 proto seems to use widevine hardware DRM for key provisioning. Hey google, you promised to not be evil :/

leo-labs commented 9 years ago

@JumpLink I pushed your qquestion into the chromecast help forum. Maybe this is the right forum. https://productforums.google.com/forum/#!category-topic/chromecast/discuss-and-give-feedback/setting-up-chromecast/other-os/hXZAvdvjk_w

friscoMad commented 8 years ago

It seems Google does not want receivers outside the oficial one A XDA Developer managed to get a receiver working but Google sent a Cease & Desist http://forum.xda-developers.com/hardware-hacking/chromecast/app-youmap-chromecast-receiver-android-t316185

xmikos commented 8 years ago

@frisco82 I have looked into YouMap Receiver apk and I don't blame Google for this Cease & Desist too much. That apk included big parts of proprietary Google Cast Receiver apk (and it was paid app on Google Play! Very daring and reckless...).

Also there was no magic, there has been only drm.json file in the apk full of pregenerated daily Chromecast V2 protocol keys (for one month period). I think author of YouMap Receiver just pregenerated them on rooted Chromecast. Maybe this can be solution for opensource implementation - someone with rooted Chromecast can pregenerate daily keys for a long period (something like many many years) and publish them anonymously on net.

JumpLink commented 8 years ago

@leo-labs thank you!

lhartmann commented 7 years ago

Do android senders check the receiver devices against a hardcoded CA certificate in the apk, or do the senders check against the trusted CA certificates on the device?

friscoMad commented 7 years ago

As it is explained in the first message, the platform certificate is needed for generating valid signatures. Yes you could hack an application to avoid that validation, maybe it is even in the system part of Android then it will work for all apps, in fact this was done before, the problem is requiring root for this hack and then maintaining it, as there is no open source code and this part uses native code. Here we wanted to be able to create open node servers, and it seems it is not so easy unless the platform certificate is leaked or Google authorizes this usage.

milankragujevic commented 7 years ago

Hi all. I'm interested in making my own server implementation to run on a Orange Pi or something similar, and would like to know where to start? Is there a Wiki of some sorts on the server component?

cretz commented 6 years ago

For anyone looking for cert validation code and root CA pub keys, they are now here (or here in the code browser).

fghfghff commented 6 years ago

@thibauts Just dumped these from the factory partition, not sure if any good though, look to be outdated. They are signed by the Chromecast CA though, and are provisioned for TLS signing. https://gist.github.com/anonymous/d530375d7dc67b2edaddb79b17a8a0d9

milankragujevic commented 6 years ago

@fghfghff Archived at https://via.hypothes.is/https://gist.github.com/anonymous/d530375d7dc67b2edaddb79b17a8a0d9

fghfghff commented 6 years ago

👍

eloydegen commented 6 years ago

@katlogic Would it still be possible to achieve this, even with the DRM hardware you mentioned?

So, with the help of the libGtvCa.so library a rooted Chromecast would generate a lot of peer certificates with different timestamps, and sign them against the platform certificate. Then, we can answer the challenge-response for all the clients requesting authentication. It seems that Google did not implemented any revocation mechanism for the platform certificates, am I correct about that?

If this would actually work it would probably require some form of clustering because a single Chromecast TPM wouldn't be able to answer all the signing requests within a required timeframe.

sashahilton00 commented 6 years ago

@eloydegen first you have to find a rooted chromecast, which is harder to do these days :/

sorryusernameisalreadytaken commented 6 years ago

@sashahilton00 Is is still possible to downgrade a gen1 chromecast: https://youtu.be/MFP_0tw90tM

sashahilton00 commented 6 years ago

hmmm, might see if I can get my hands on one of them then, and poke around to see if generating certs is possible/feasible.

sorryusernameisalreadytaken commented 6 years ago

I can get a gen1 g-cast stick, never used, buyed middle of 2015....

sashahilton00 commented 6 years ago

up to you. I've no experience with libgtvca and all that, but my guess is that it's just an interface to trustzone?

cretz commented 6 years ago

I wrote a toy server impl in Go that does the auth if it helps anyone. Of course, it fails here (I think based on debug cert fail event count in chrome logs) because the auth cert wasn't gen'd from Google's CA key. I am unsure if I got everything right of course, and I didn't include the gen'd protobuf files, but I figure it could be good reading for anyone landing here.

sashahilton00 commented 6 years ago

@cretz you might be able to give the keys @fghfghff posted a go, just manually set your time back to when the certs were valid

cretz commented 6 years ago

@sashahilton00 - Oh, I have a full blown auth'd impl now at https://github.com/cretz/owncast. I actually patch a chrome binary to put my own CA in there so it auths with mine. I create the needed intermediate cert, solve the auth request w/ signature and everything, but casting using the cast v2 protocol is not yet implemented in Chrome. I don't have anything documented, and I won't resume work until https://bugs.chromium.org/p/chromium/issues/detail?id=809249 is complete (it's coming along).

forlayo commented 5 years ago

@cretz can you guide me on how to set Chrome to expose the log which says the cert have failed? I'm doing tests trying to get a valid certificate and this can be a really good point for validate :)

cretz commented 5 years ago

@forlayo - This worked for me: https://www.chromium.org/for-testers/enable-logging. You'll have to turn that v number up high (there's lots of noise) and may want to use canary w/ better cast support. Note, even with cast auth succeeding, cast protocol is not implemented completely in Chrome yet. But w/ the Chrome CA patched, I can get my device to appear in the list of Chromecast devices in the browser.

forlayo commented 5 years ago

Thanks a lot, I've been doing google-chrome --enable-logging=stderr --v=1

I'm playing a bit around, as should be a way to avoid or to fake ( or to provide a valid one ) with the authentication.

I've seen that demo application of Reflector 3 (http://www.airsquirrels.com/reflector/) and AirServer (http://www.airserver.com/) supports doing it, and it works :/

sashahilton00 commented 5 years ago

@forlayo any further progress on this? I'm guessing you have a Gen 1 and were looking to just create a signing service for peer certificates?

treblam commented 5 years ago

@forlayo Have you succeed in faking with the authentication?

forlayo commented 5 years ago

I've been able to extract the certificates they use to authenticate but not the primary key which is needed; by the way I am not working on this at the minute and I am unsure if going to work again in the future.

If I've a couple of hours at home I will try again, if success I will share here. I am pretty sure that someone with experience doing reversing can do this authentication bit :/

sashahilton00 commented 5 years ago

Fair enough. Extracting the device certificate is not practical in all likelihood; i can't remember whether it uses a coprocessor to do the crypto stuff, or if it is a TrustZone implementation, either way, it's unlikely that we'll be able to pull the keys out, short of someone exploiting TrustZone (though it has been done before). IIRC, the device key is burned in via UART during manufacture then the device is sealed.

The optimum solution is likely a lightweight API server that runs directly on a rooted chromecast, whereby one feeds in parameters/signing requests, and the Chromecast returns signed certificates. One could then create a batch of signed certificates for the next 5 years or something, write a simple API of the form /certificate/latest, which would return the presigned certificates, the valid from/valid to dates, which people could use in various open source projects.

forlayo commented 5 years ago

The weird thing is these applications I'm talking about (reflector and airserver) works even being installed on a computer without access to internet (I've tried that, and I've tried installing the application that I've downloaded few days ago).

So, or they've a bunch of these certificates you're talking about somehow into. Or they've the primary key of certificate somehow into..

I've been able to get the certificates used, but not the primary key that's obviously needed for sign the challenge