Tesla Signaling/Hermes Protocol to send vehicle commands #769
Replies: 8 comments 10 replies
-
I also tried a lot here and I managed to register my public key in my tesla using the Tesla App. But when I try to send a command using the cli I get this error: But the Account is registered I can access the vehicle data. Any ideas on this? |
Beta Was this translation helpful? Give feedback.
-
Yesterday I was able to begin writing a .proto file to make some first sense of the captured network traffic. I'm able to manually find the field types and descriptors in the decompiled android app, so I think this protocol is completely feasible to re-implement.
|
Beta Was this translation helpful? Give feedback.
-
I send my first command successfully with just owner API access and the Hermes protocol! I will write up the details and provide the code (golang as im leveraging the vehicle SDK) as time allows. |
Beta Was this translation helpful? Give feedback.
-
I can send commands to the vehicle via hermes by reusing the official golang vehicle-sdk. Here is a go package and example: https://github.com/lotharbach/tesla-hermes-signaling All of the encryption details, session setup and command message encoding is done in vehicle-sdk, and I can only give a high level explaination right now. You need a private key that is authorized in the vehicle, which I have done with the tesla-command tool from the vehicle-sdk via Bluetooth. As described above, two tokens are fetched from the owner API, and a websocket channel is established with the users hermes token. Binary messages are send and received, in the following format
(I have not yet seen subscribeMessage/unsubscribeMessage being used in the App so far) You need send a CLIENT_ACK for every message you receive, requestTxid set to the txid of the incoming message, and the same topic.
Messages to the car need to be send to the topic "vehicle_device..cmds", and need to have a valid hermes vehicle token (as described above). The payload is a binary RoutableMessage protobuf.
You need to first setup a session, for each domain you want to send commands, by sending your public key.
The vehicle will then send back a message with its own public key and session info, basically an encrypted message channel. I did not dive deeper into this, but again the vehicle-sdk contains all the details to either reuse or reverse in another language. Now command messages can be send, the payload is an encrypted/signed VehicleAction or RKEAction. The vehicle responds with a COMMAND_TYPE_SIGNED_COMMAND_RESPONSE. |
Beta Was this translation helpful? Give feedback.
-
@lotharbach thank you for your work! I think this is the right direction to go, considering the heavy limitations of the Fleet API. |
Beta Was this translation helpful? Give feedback.
-
I have a proof of concept patch to tesla-http-proxy that sends commands via hermes, and proxies other API requests to the owner api: https://github.com/lotharbach/tesla-command-proxy/tree/owner-proxy Run the modified proxy:
Get vehicle_data and send command:
|
Beta Was this translation helpful? Give feedback.
-
I just came across this project and looks interesting, thanks for sharing your research. I just wanted to share that I’ve built a Home Assistant addon which implements the keygen, http proxy, and oauth flow. My goal was to make it as easy as possible for users. https://github.com/llamafilm/tesla-http-proxy-addon |
Beta Was this translation helpful? Give feedback.
-
@lotharbach Thanks for your work. I have a question: How to get the In the fleet api document, we query the token from the |
Beta Was this translation helpful? Give feedback.
-
Related to #763 I began looking into how the Tesla App now sends signed commands to the vehicle. I would like to share what I have found by intercepting the App network traffic, which is very easy to do with a rooted phone as there is no certificate pinning, and hope for more research to happen. I hope we will someday be able to properly document what I would call the "Tesla Signaling/Hermes Protocol" as part of this project.
First of all, the owner API is still heavily used by the app. There is no reason to suspect the owner API in its entirety will go away anytime soon, as I have read so many times. It will "just" loose all "api/1/vehicle/../command/.." REST endpoints, as vehicles require end-to-end signed commands which is a thousand times more secure and to the benefit of all vehicle owners! The wake_up and vehicle_data endpoint is used by the app every few seconds, and pure data loggers will continue to work just fine!
The Tesla App can not send commands without also being registered as a phone key. For the phone key function it generates a private key on the phone and likely transfer that public key to the vehicle via Bluetooth. Details about generating and transfering such a key is also found in teslas vehicle-sdk. The SDK also contains all there we kneed to know about generating signed commands and can send them via the Fleet API or via Bluetooth. Since we likely won't have access to the Fleet API as vehicle owners, I was interested how the App continues to function.
The App performs a POST on HERMES_AUTHORIZATION endpoint,
https://owner-api.teslamotors.com/api/1/users/jwt/hermes
There is also a second POST on HERMES_VEHICLE_AUTHORIZATION endpoint,
https://owner-api.teslamotors.com/api/1/vehicles/:vehicle-id/jwt/hermes
With the first token, a WebSocket connection is opened on HERMES_URI wss://signaling.vn.teslamotors.com/v1/mobile with
Header "X-Jwt: <jwt to talk to hermes>
And they now exchange some sort of protobuf based binary packets. A command in the App very clearly generates a new exchange on that WebSocket channel and nothing else on the network. Decoding the protobuf shows strings like
vehicle_device.<my VIN>.cmds
and what I guess is a wrapped message in the same signed command protobuf layout that the vehicle-sdk is generating to send via BLE or to the Fleet-API's signed_command endpoint.This is the end of my knowledge so far. More revesing of the protobuf message description is required to generated what I guess is first some "handshake" and then the command messsages. I unfortunately can't/won't share my full binary capture as it contains private information and credentials.
This is how one can talk to hermes on the command line:
Without a valid token there is a "authorization denied" message.
Beta Was this translation helpful? Give feedback.
All reactions