https://objective-see.org/oftw/v4.html
alright, wrapping this up: what have we learned?
- the pairing has improved and enforces physical presence now!
- we have dynamic keys!
- cryptography remains very difficult π
- maybe the ECDSA keys will do something in a future update?
- talking to vendors helps! getting publicity helps!
also, what i'm seeing here looks a little similar to what i described in a somewhat exasperated mail to Xplora in November, although with a certain came-back-wrong vibe to it
10/10, thanks for joining β¨
... this shiny new function is apparently only ever used to encrypt the S/N and IMEI values from above, using the random string from step 3 as a key. which then, of course, is sent in the same request as the encrypted value?? they're essentially sending key || AES-GCM(SHA256(key), data), which is a cool way to spend ~76 bytes doing a cryptographic NOP
a similar thing applies to the ECDSA signatures: yes, they're proving ownership of the public key by including a signature over some values, but from what i can tell, this key is never used again?
we're generating expensive elliptic curve points, enrolling them into the AndroidKeyStore, serializing the public key into base64, generating a signature to prove to the server that we control the private key β and then we just pour it all down the drain?
to be clear: i don't think this is exploitable, which is why i'm talking about it here. simplifying these NOPs still yields a secure-ish looking protocol. but still π³
9/x
now, when i say 'encrypted', i'm referring to this new function here (code simplified by me).
it does AES-GCM, and it's the best cryptographic code i've seen from Xplora so far! sure, it calls the key a nonce for some reason, but it does authenticated encryption, hashes the key string before use (doesn't even use md5!), and uses a securely random IV every single time! π€―
however...
8/x
...okay, i *think* this is still in the realms where i can just post about it, so strap in π§π»
(disclaimer: this is all at a glance, i may well be wrong about something)
high-level, the process to get credentials from the server looks like this:
1. send our encrypted* S/N to the server to get a QR code with a random identifier (as seen in #6)
2. user scans code, gets 6-digit pin from server, enters it on the watch
3. we build a request containing a random string, our encrypted* S/N and IMEI, the 6-digit pin, a timestamp, our ECDSA public key, and a matching ECDSA signature*
4. the server validates this request somehow, and sends us INIT_SECRET and INIT_KEY values in response
7/x
the watch is still paired using a QR code, but it looks a little different and no longer contains the device IMEI but what looks like a 6-byte random value (good!)
previously, just scanning the code was enough, but now users have to enter a 6-digit code on the watch to confirm the pairing. i'm not sure if that additional interaction actually adds security (scanning a code containing unpredictable (!) data should already be enough to establish physical presence), but it certainly doesn't hurt.
with that, attackers can no longer activate arbitrary watches from a distance. small wins! yay β¨
6/x