Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Google Find My #51

Open
biemster opened this issue Apr 10, 2024 · 25 comments
Open

Implement Google Find My #51

biemster opened this issue Apr 10, 2024 · 25 comments
Assignees
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@biemster
Copy link
Owner

Google just activated their own Find My network on Android this weekend. Details are still scarce, so let's collect all technical info needed to send the BLE advertisement and subsequently query this network here.
The BLE part can then be implemented here: https://github.com/biemster/st17h66_RF (and I will also finally put the Apple FindMy advertisement there then as well, so the chip can do both)

@darthnithin
Copy link

For anybody working on this the specification seems to be here (https://developers.google.com/nearby/fast-pair/specifications/extensions/fmdn)

@trep-kalkyl
Copy link

trep-kalkyl commented Apr 11, 2024

This is very interesting.

  1. Are there any indications that Google will release an API or documentation for this, or will a similar investigation like Haystack be needed?
  2. Is there documentation on how the hardware is supposed to function and can it in that case be usefull for us?

Note:
Some interesting blogpost:
https://security.googleblog.com/2024/04/find-my-device-network-security-privacy-protections.html

@darthnithin
Copy link

not sure yet. From that page, device manufacturers at least have to do a google NDA to ship a find my device compatible device, but that's pretty normal right?

@humpataa
Copy link

My question is if Google / Android phones are now reporting Apple's FindMy devices to their (or even Apple's) server as well. If Google isn't releasing info on how to request the data from their server, it probably needs to be hacked like it was done with Apple before. If Android now sends location reports to Apple's server it would enlarge the FindMy network instantly without the need to make any changes for Apple and us.

@darthnithin
Copy link

Yea I'm fairly certain that's not happening. The google Find my Device network is separate. There are some architectural changes too.
I think the only crossover between the networks is individual devices detecting unwanted trackers.
image

@mrx23dot
Copy link

This new standard has some details on the protocol
https://datatracker.ietf.org/doc/draft-detecting-unwanted-location-trackers/01/

also there is a spec
https://developers.google.com/nearby/fast-pair/specifications/extensions/fmdn
there are a lot more GATT services/characteristics required like Get_Accessory_Category_Response

flipper guys also planning it
MatthewKuKanich/FindMyFlipper#43

not sure if fast pair is relevant
.. _Fast Pair: https://developers.google.com/nearby/fast-pair/specifications/introduction
.. _Fast Pair roles: https://developers.google.com/nearby/fast-pair/specifications/configuration#roles
.. _Fast Pair Model Registration: https://developers.google.com/nearby/fast-pair/specifications/service/modelregistration
.. _Fast Pair TX power: https://developers.google.com/nearby/fast-pair/specifications/configuration#transmit_power
.. _Fast Pair Advertising: https://developers.google.com/nearby/fast-pair/specifications/service/provider
.. _Fast Pair GATT Characteristics: https://developers.google.com/nearby/fast-pair/specifications/characteristics
.. _Fast Pair Procedure: https://developers.google.com/nearby/fast-pair/specifications/service/gatt
.. _Verifying Fast Pair: https://developers.google.com/nearby/fast-pair/help#verifying_fast_pair
.. _Fast Pair Personalized Name extension: https://developers.google.com/nearby/fast-pair/specifications/extensions/personalizedname
.. _Fast Pair Certification Guidelines for Personalized Name: https://developers.google.com/nearby/fast-pair/certification-guideline#2_personalized_name
.. _Fast Pair Battery Notification extension: https://developers.google.com/nearby/fast-pair/specifications/extensions/batterynotification
.. _Fast Pair Find My Device Network extension: https://developers.google.com/nearby/fast-pair/specifications/extensions/fmdn
.. _Fast Pair FMDN advertising: https://developers.google.com/nearby/fast-pair/specifications/extensions/fmdn#advertised-frames
.. _Fast Pair Locator Tag Specific Guidelines: https://developers.google.com/nearby/fast-pair/specifications/extensions/fmdn#locator-tag
.. _Fast Pair Unwanted Tracking Prevention Guidelines: https://developers.google.com/nearby/fast-pair/specifications/extensions/fmdn#unwanted-tracking-prevention

@Cassander313
Copy link

More info that people have started collecting here: seemoo-lab/openhaystack#210

@rena2019
Copy link

Maybe helpful: from Nordic Semiconductor (manufacturer of nRF52840 - Multiprotocol Bluetooth 5.4 SoC supporting Bluetooth Low Energy, Bluetooth mesh, NFC, Thread and Zigbee)
Bluetooth Fast Pair: Locator tag (doc) https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/samples/bluetooth/fast_pair/locator_tag/README.html
Bluetooth: Fast Pair locator tag (zephyr source code) https://github.com/NordicBuilder/sdk-nrf/tree/0e99b70bcb259379b2faa87f9e2abcaf5de1e7a0/samples/bluetooth/fast_pair/locator_tag
Fast Pair Validator (exclusively for manufacturers of bluetooth devices) https://play.google.com/store/apps/details?id=com.google.location.nearby.apps.fastpair.validator

@biemster
Copy link
Owner Author

I added an esp32 micropython script that sends the FMDN advertisement as detailed in https://developers.google.com/nearby/fast-pair/specifications/extensions/fmdn#advertised-frames table 8. I have no clue yet how to compute the ephemeral id or how to retrieve the reports through the google api's yet, but it's a start!

nRF Connect reports this as an Eddystone, with the ephemeral id as the data field.

@dylanmazurek
Copy link

I added an esp32 micropython script that sends the FMDN advertisement as detailed in https://developers.google.com/nearby/fast-pair/specifications/extensions/fmdn#advertised-frames table 8. I have no clue yet how to compute the ephemeral id or how to retrieve the reports through the google api's yet, but it's a start!

nRF Connect reports this as an Eddystone, with the ephemeral id as the data field.

I just got some Chipolo tags, if you need me to scrape some data that might help, happy to do so.

@biemster
Copy link
Owner Author

I just got some Chipolo tags, if you need me to scrape some data that might help, happy to do so.

That would be great! Are you able to mitm proxy an android with the account your chipolos are registered on?
(and confirming they advertise as an eddystone with a 20 byte data field would already be of huge help)

@mrx23dot
Copy link

chipolo review, https://youtu.be/3EAu08m5Lbc?feature=shared&t=285
currently worse than Samsung's, which is closer to Apple's, but hopefully will change with time.

@X-Ryl669
Copy link

X-Ryl669 commented Nov 14, 2024

I have no clue yet how to compute the ephemeral id or how to retrieve the reports through the google api's yet, but it's a start!

I don't know if they improved meanwhile, but it's described here

As I understand the specifications, the Ephemeral Key is just a random 32 bytes generated by the tag once. It doesn't have to be known by the smartphone or tag owner. It's then used as an AES key (ECB mode!) for encrypting a dumb message. This makes a pseudo random number (s) that's used in the later crypto operations.

I'm not sure I'm getting the logic here, it seems so stupid, I'm missing something. The dumb message (which is doubled to fit in 256 bits) is made of only 22 bits of actual changing data. There's seconds' timer counter whose 10 low bits are cleared (so only 22 bits useful in theory, but since it counts from 0, those are guessable quite easily). Technically, the counter actually update ~4 times per hour.

Then you AES ECB encrypt it and get r'. There's a small micmac to build a 160 bits's X coordinate of the number on the curve using the usual ECC computations.

As for the ephemeral identity key, they say this, meaning that it's possible to fetch it if the tracker is not provisioned. In that case, everything is deterministic.

If you ever intend to make a fully featured device (one that does support the provisioning process), then it means implementing this (which is, AFAIU, not very complex to compute, but probably more to implement the persistent state in flash, in your reversed engineered firmware)

@mrx23dot
Copy link

wow, thank you for your analysis!

As it's done with the airtags it should be kept as simple as possible, ie

  • hard coding rotating stuff, (precompute everything in python)
  • no random content
  • and fetching directly from the google network without provisioning.

My guess is that they use randomness as IV during provisioning, just to prevent same bytes showing up in the air.

ECB is normal if data is less than block size/packets are infrequent and they don't want to worry about keeping last state/losing packets.

@leonboe1
Copy link

leonboe1 commented Nov 14, 2024

This could be interesting to you as well:

Note: I have not been able to query location reports from the server yet. This will be the hardest part, since it requires HTTPS and Firebase authentication with a private API from Google.

@X-Ryl669
Copy link

The former repository is really useful, I didn't know it was possible to write crypto code over finite field that simply with python, always did it with C++ (and a not that simple interface). I've hard time figuring out what the second repo is actually doing (except making an HTTP request to https://android.googleapis.com/nova/nbe_list_devices).

I think this line is wrong however.
They say in the documentation that you should clear the 10 low bits of the second / timestamp counter. That's because they are using a fixed key for encrypting the eid and user fetching the report should be able to query the expected report, so she must guess the content of r and thus the timestamp. By zeroing the 10 low bits, you have to guess a timestamp by steps of 1024 second, which is much easier that trying to guess a timestamp by step of 1 second.

While requesting location report is useful per se, it can be done actually with an Android phone meanwhile. Being able to have a tag that's speaking the right protocol so that an unmodified Android phone fills the location report's database at Google would confirm the protocol implementation in the tag is working. That would probably solve many problems already.

@leonboe1
Copy link

leonboe1 commented Nov 15, 2024

Hey there, I verified the EID calculation with real trackers. It should be correct.

What you seem to forget is that the timestamp and padding is not the EID. The EID is calculated by encryption using AES-ECB with the EIK and then projecting the result to the elliptic curve. Then, the EID is the x coordinate of this calculation, just like in my code.

@X-Ryl669
Copy link

X-Ryl669 commented Nov 15, 2024

Ok, I don't know in fact what the tracker are doing, I don't have any. Here they say: 12 - 15 | TS[0]...TS[3] | Beacon time counter, in 32-bit big-endian format. The K lowest bits are cleared.
The part I was referring to is The K lowest bits are cleared.

Seems like, to me that the beacon time counter should be TS & ~1023, since K is 10. So it should only have 22 bits of actual data, and incrementing every 1024 seconds.
They say:
Note: The device is assumed to have a 32-bit time counter in seconds.
Note: Rotation period exponent is fixed and set to 10, corresponding to 1024 seconds.

Once you know it, you can recreate this EID just by knowing the time distance with the last or first provisioning (since everything is known in the algorithm). So you can compute Rx from both side (tracker & consumer's smartphone) which is required for encrypting and decrypting the EID, as described here (since you can deduce Ry from Rx).

So if you don't mask the low bits, you'll not find the expected Rx from the consumer's smartphone that'll mask them out. (It'll only be correct once every 1024 seconds, but since the clock are unlikely to be synchronized, I don't think the tracker will emit a report that'll be captured by a nearby phone at the exact moment when its time counter is 0 for the 10 low bits).

@leonboe1
Copy link

leonboe1 commented Nov 15, 2024

Ah, now I know what you mean. It's true that the counter for the EID calculation only counts in multiples of 1024.

Since all other code only called the EID calculation with multiples of 1024 as the offset value, this was not a problem. But you are right, this should be made more explicit in the code.

@X-Ryl669
Copy link

Well, I think we talk about different acronyms (in their immense wisdom, they used E for both ephemeral and encrypted).
The Ephemeral ID computation, which I've found in your code here maps to this, right ? (It looks like it does)

Yet, it's missing the part that's masking the low 10 bits, as specified.

It's not the encrypted ID yet, but it's required to compute the encrypted ID

@leonboe1
Copy link

leonboe1 commented Nov 15, 2024

I've updated the file to make it more clear that only multiples of 1024 can be used. The file does specify the complete EID calculation. If you have more questions, please open an issue in my repository.

@KieronQuinn
Copy link

I've done some digging into how the API works, perhaps it could be useful to you all.

The reason that there's no data in the response to requests to the nbe_execute_action endpoint is that they come as push notifications. The push data contains a payload (com.google.android.apps.adm.FCM_PAYLOAD), which is the actual response. This is as far as I got on this route, but the payload is in Protobuf format and seems to contain the encrypted location for a refresh action.

However, this may make using the API difficult. Libraries like push-receiver do allow for subscribing to push notifications for a FCM project, so might be useful here. A quick test using that library shows that using the app ID, project ID and API key from the Find Device app results in a push token, but this is only half the battle - the token still has to be sent to the server, which is a gRPC call that would need to be reverse engineered too.

As for getting an auth token for the server in the first place, you'll need an AAS token and to make a request using the right scopes using this token. The token can only be obtained via the embedded setup, there's various implementations of this (such as Aurora Store's authenticator, Revanced's MicroG-RE, or my own Google Wallet plugin)

My original intention for working with the API was to do some basic location history logging to compare it to Samsung's network. In the end, I just made an Xposed module that intercepts the data after the app has handled it.

I've also done a lot of work in reversing Samsung's API, which is much easier to work with, that I'll write documentation for (useful for #65) when I release the project it's for - an app/mod that allows using Samsung's tags on non-Samsung devices.

@leonboe1
Copy link

Hi Kieron,

Thanks for your report! I've also looked into querying the location reports for the last week. I'll have to agree that working with Google's implementation is indeed very annoying. Nevertheless, I'm happy to report that I made a breakthrough yesterday.

I am now able to log in with Firebase, get the required tokens, and receive the push notifications for the encrypted location reports in my own app. Root is not needed.

To make everything work, I used microG as a base, and added rudimentary support for the Spot API to it. My plan is to now to extract only the needed parts from microG. The project is very large, it can take up to 40mins to compile 😅

If I have compiled a more simple version, I'll post it on my GitHub. I'll keep you updated.

@leonboe1
Copy link

leonboe1 commented Dec 22, 2024

Just in case you haven’t noticed already: The whole location querying process is now implemented in my repository https://github.com/leonboe1/GoogleFindMyTools

I’ve also implemented an iOS app which does the same thing. If anyone is interested in testing this app, write me a message.

@trep-kalkyl
Copy link

This is fantastic and a breakthrough. Could you please share some more information of this achievement?

Just in case you haven’t noticed already: The whole location querying process is now implemented in my repository https://github.com/leonboe1/GoogleFindMyTools

I’ve also implemented an iOS app which does the same thing. If anyone is interested in testing this app, write me a message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests