{"id":29356860,"url":"https://github.com/uhi22/tesla-crc","last_synced_at":"2026-02-25T21:38:09.097Z","repository":{"id":286074642,"uuid":"960274881","full_name":"uhi22/tesla-crc","owner":"uhi22","description":"analyzing the CRC used in (not only) Tesla vehicles' CAN communication","archived":false,"fork":false,"pushed_at":"2025-04-28T07:44:31.000Z","size":971,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-09T05:40:40.712Z","etag":null,"topics":["can","crc","e2e","end-to-end-protection"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uhi22.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-04T06:41:02.000Z","updated_at":"2025-05-07T06:18:30.000Z","dependencies_parsed_at":"2025-04-04T07:34:57.573Z","dependency_job_id":"205707cd-3624-46a9-a3f0-7757fc6d40a0","html_url":"https://github.com/uhi22/tesla-crc","commit_stats":null,"previous_names":["uhi22/tesla-crc"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/uhi22/tesla-crc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhi22%2Ftesla-crc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhi22%2Ftesla-crc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhi22%2Ftesla-crc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhi22%2Ftesla-crc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uhi22","download_url":"https://codeload.github.com/uhi22/tesla-crc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhi22%2Ftesla-crc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29841604,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T21:18:31.832Z","status":"ssl_error","status_checked_at":"2026-02-25T21:18:29.265Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["can","crc","e2e","end-to-end-protection"],"created_at":"2025-07-09T05:35:22.151Z","updated_at":"2026-02-25T21:38:09.083Z","avatar_url":"https://github.com/uhi22.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tesla (and others) CRC Analysis\n\n## Status \u0026 News\n\n### 2025-04-28: Added sub-folder for Volkswagen analysis\n\nCRC calculation of MQBs ESP_21 message works.\n\n### 2025-04-06: CRC for 0x229 also fits\n\nThe tesla-crc-filereader.c reads the 870 samples of the message 0x249 plus 178 samples of the message 0x229 (both from Ref2), calculates the CRC of each message and compares it with the CRC from the log. No deviation, all CRCs are correctly calculated.\n\nThe algorithm for transmitting the end-to-end protected message:\n\n* In the example, we use a 4 byte CAN message. Other length are also possible.\n* Use a buffer which is one byte bigger than the CAN message. So 5 bytes in the example. We use index 0 to 4 for them.\n* Fill the complete message with 0x00. This is especially needed for byte 0 (later to be filled with the CRC), the byte 1 (later to be filled with the alive counter, and byte 4 (the virtual extra byte).\n* Fill the payload data into the message. This will be in the higher nibble of byte 1, and the full bytes 2 and 3.\n* Calculate the CRC (using the OPENSAFETY CRC-8, function generateCrc8Opensafety()) starting at byte 1 and length 4. So it sees the virtual extra byte as last input data.\n* Calculate the magic byte by using the current alive counter as index in the magic byte table.\n* Fill into byte 0 the XOR of the CRC and the magic byte.\n* Fill into the lower nibble of byte 1 the alive counter.\n* Transmit the bytes 0 to 3 to CAN.\n* Increment the alive counter. If it reaches 16, set it to zero.\n\nThe table of magic bytes is individual for each CAN identifier. It can be created based on the observed log files. The magic byte is the value of byte 0 of the message, when all payload bits are zero. We have 16 possible values for the alive counter, so the table of magic bytes has 16 entries.\n\n### 2025-04-05: CRC for 0x249 fully verified\n\nThe tesla-crc-filereader.c reads the 870 samples from Ref2, calculates the CRC of each message and compares it with the CRC from the log. No deviation, all CRCs are correctly calculated.\n\n```\nLooped over 870 lines.\nCRC ok: 870,  CRC fail: 0\n```\n\nThis confirms the approach:\n* It is a CRC8 with polynom 2F, like CRC-8/OPENSAFETY.\n* Alive counter is not included into CRC. Instead, alive counter is index into a 16-byte-table with magic bytes, which are individual for each ID.\n\n### 2025-04-04: Polynom for 0x249 found\n\nsee below. The CRC is using the \"12F\" polynom of OPENSAFETY (or AUTOSAR).\n\n### 2025-04-04: Calculation for the 0x229 works\n\nWe use a table of magic patterns, this is 16 bytes long, and the alive counter is the index in this table.\nWe simply fill the table with the known CRC values in idle position.\nAs soon as a button is actuated, the CRC changes by a specific XOR delta. Each button has a specific delta. The delta is the same for all possible 16 message counter values. This behavior is typical for a CRC. So it could be possible, to replace the currently implemented `if button then xorPattern = something` by a real CRC calculation.\n\nTest result: The program gives the same numbers as listed in https://openinverter.org/forum/viewtopic.php?p=81258#p81258\n\n```\nuwemi@DESKTOP-OKFJ35V MINGW64 /c/UwesTechnik/tesla-crc\n$ gcc tesla-crc.c\n\nuwemi@DESKTOP-OKFJ35V MINGW64 /c/UwesTechnik/tesla-crc\n$ ./a.exe\nTesla CRC analysis\nIdle position\n0x46 0x00 0x00\n0x44 0x01 0x00\n0x52 0x02 0x00\n0x6d 0x03 0x00\n0x43 0x04 0x00\n0x41 0x05 0x00\n0xdd 0x06 0x00\n0xf9 0x07 0x00\n0x4c 0x08 0x00\n0xa5 0x09 0x00\n0xf6 0x0a 0x00\n0x8c 0x0b 0x00\n0x49 0x0c 0x00\n0x2f 0x0d 0x00\n0x31 0x0e 0x00\n0x3b 0x0f 0x00\nFull down\n0xb7 0x40 0x00\n0xb5 0x41 0x00\n0xa3 0x42 0x00\n0x9c 0x43 0x00\n0xb2 0x44 0x00\n0xb0 0x45 0x00\n0x2c 0x46 0x00\n0x08 0x47 0x00\n0xbd 0x48 0x00\n0x54 0x49 0x00\n0x07 0x4a 0x00\n0x7d 0x4b 0x00\n0xb8 0x4c 0x00\n0xde 0x4d 0x00\n0xc0 0x4e 0x00\n0xca 0x4f 0x00\npark button\n0xaf 0x00 0x01\n0xad 0x01 0x01\n0xbb 0x02 0x01\n0x84 0x03 0x01\n0xaa 0x04 0x01\n0xa8 0x05 0x01\n0x34 0x06 0x01\n0x10 0x07 0x01\n0xa5 0x08 0x01\n0x4c 0x09 0x01\n0x1f 0x0a 0x01\n0x65 0x0b 0x01\n0xa0 0x0c 0x01\n0xc6 0x0d 0x01\n0xd8 0x0e 0x01\n0xd2 0x0f 0x01\nFull up\n0xa9 0x20 0x00\n0xab 0x21 0x00\n0xbd 0x22 0x00\n0x82 0x23 0x00\n0xac 0x24 0x00\n0xae 0x25 0x00\n0x32 0x26 0x00\n0x16 0x27 0x00\n0xa3 0x28 0x00\n0x4a 0x29 0x00\n0x19 0x2a 0x00\n0x63 0x2b 0x00\n0xa6 0x2c 0x00\n0xc0 0x2d 0x00\n0xde 0x2e 0x00\n0xd4 0x2f 0x00\nHalf down\n0x49 0x30 0x00\n0x4b 0x31 0x00\n0x5d 0x32 0x00\n0x62 0x33 0x00\n0x4c 0x34 0x00\n0x4e 0x35 0x00\n0xd2 0x36 0x00\n0xf6 0x37 0x00\n0x43 0x38 0x00\n0xaa 0x39 0x00\n0xf9 0x3a 0x00\n0x83 0x3b 0x00\n0x46 0x3c 0x00\n0x20 0x3d 0x00\n0x3e 0x3e 0x00\n0x34 0x3f 0x00\n\n```\n\n\n## Checking the 0x249\n\n```\nStarting with the log data (Ref2), extracting messages which shift a single bit:\n9B 00 00 00\nED 10 00 00\n77 20 00 00\n6C 40 00 00\n5A 80 00 00\n\nCalculating the XOR difference between the \"zero\" and the bit:\ndata       0    1    2    4    8\ncrc       9B   ED   77   6C   5A\nxor          76\n                 EC\n                      F7\n                          C1\n\nAccording to Ref4, looking whether this sequence 76 EC F7 C1 fits either to \"just shifted\" or to \"shifted and Xored\".\n\n76 \u003c\u003c 1 = EC  -\u003e just shifted.\nEC \u003c\u003c 1 = D8 but we see F7. This will reveal the polynom.\n    (EC \u003c\u003c 1) XOR F7 = 12F --\u003e 1 0010 1111 --\u003e Polynom is x^8 + x^5 + x^3 + x^2 + x^1 + x^0.\nF7 \u003c\u003c 1 = EE but we see C1. This will reveal the polynom.\n     (F7 \u003c\u003c 1) XOR C1 = 12F. As above. Polynom confirmed.\n\n\nTrying the same procedure with an other part of the data:\n9B 00 00 00\n87 00 02 00\nA3 00 04 00\nEB 00 08 00\n\ndata    0      2    4   8  \ncrc     9B     87  A3   EB\nxor         1C\n                 38\n                      70\n\n1C \u003c\u003c 1 = 38 --\u003e just shifted\n38 \u003c\u003c 1 = 70 --\u003e just shifted\n\n```\n\nThe polynom 12F (or just 2F if looking to 8 bits) is used in two \"official\" configurations according to Ref5: CRC-8/OPENSAFETY and CRC-8/AUTOSAR.\n\nTry with CRC-8/OPENSAFETY (Ref5):\n```\n10 00 00 00 gives 76\n20 00 00 00 gives EC\n40 00 00 00 gives F7\n80 00 00 00 gives C1\n\n00 02 00 00 gives 1C\n00 04 00 00 gives 38\n00 08 00 00 gives 70\n```\n\nThis fits perfectly to the above calculated XOR values.\n\nIntermediate calculation algorithm:\n* Input: Inputbuffer[4]. Byte0 will later contain the CRC. Byte1 contains the counter in lower nibble. Treat as zero.\n* copy inputbuffer[1...3] into temporaryBuffer[0...2]\n* set temporaryBuffer[3] = 0\n* calculate CRC over temporaryBuffer[0...3], using \"CRC-8/OPENSAFETY with poly=2F\".\n* xor the CRC with 9B (magicByte, depending on alive counter)\n* write the result into Inputbuffer[0]\n* write the alive counter into lower nibble of Inputbuffer[1]\n\n## Open Todos\n\n(none)\n\n## References\n\n* Ref1: Data of the 0x229 stalk: https://openinverter.org/forum/viewtopic.php?p=81258#p81258\n* Ref2: Logs with many combinations, for left and right stalk: https://openinverter.org/forum/viewtopic.php?p=81331#p81331\n* Ref3: Simple addition for 0x313: https://openinverter.org/forum/viewtopic.php?p=77694#p77694\n* Ref4: How to calculate the CRC polynom out of observed data: https://knx-user-forum.de/forum/%C3%B6ffentlicher-bereich/knx-eib-forum/diy-do-it-yourself/34358-ekey-fingerscanner-per-rs485-auslesen-protokollanalyse?p=626281#post626281\n* Ref5: CRC online calculator https://crccalc.com/?crc=00%2000%2001\u0026method=CRC-8/AUTOSAR\u0026datatype=hex\u0026outtype=hex\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuhi22%2Ftesla-crc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuhi22%2Ftesla-crc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuhi22%2Ftesla-crc/lists"}