Audi C7 (4G) Component Protection — full firmware RE of the HVAC + Gateway, a captured ODIS/GeKo session, and the ONE piece I still needI've been doing Component Protection research on my own C7 for a while and I'm close to an offline solution — but I need community help on the last piece. Full write-up, captured data, firmware analysis, keys and tooling below. Everything is open-source (links at the bottom). This is all on my own car, going back to my ORIGINAL part — pure right-to-repair.
The backstory2013 Audi A6 C7, 3.0T TFSI (CGWB), VIN
WAUGGAFC7DN120188. I swapped my 2-zone Climatronic for a 4-zone unit and used ODIS + GeKo (dealer session, Feb 2024) to clear CP. A week later I swapped in matching heated/cooled seats and ran ODIS again — CP cleared, all good. Now I want to put my ORIGINAL 2-zone HVAC back in, and of course it's CP-locked. My ODIS VM wiped itself between sessions, so I only captured ONE diagnostic protocol (DPROT) file. That file has the handshakes and the resulting key blob — but the GeKo-side derivation is masked. So I went into the firmware to understand the whole thing. Here's what I found.
═══ 1. THE CAPTURED ODIS/GeKo SESSION (Feb 27, 2024) ═══Tool: ODIS-S Patch 23.0.1, VAS 6154A VCI over USB
Dealer: 17483 (importer 219), Tester AGJ1E
Car: 2013 A6 C7, 3.0T TFSI CGWB, built Neckarsulm
Result: 12 modules CP-cleared in one atomic session
The 12 modules cleared together (CP is car-wide, not per-module):
J136 seat memory, J518 Kessy, J255 Climatronic, J519 BCM, J234 airbag, J285 cluster, J525 sound, R radio, J794 MMI, J854 + J855 belt tensioners, J533 gateway.
What ODIS read and sent to GeKo (the token request inputs):F190 VIN WAUGGAFC7DN120188
F17C J518 FAZIT HLH-W41 / 21.02.13 / 1003 / 1126
F191 J518 HW 4H0907064CR
J533 FAZIT LAK-000 / 22.02.13 / 2009 / 7162
+ key-fob transponder challenge-response via J518 TrainICA (MASKED ****** in log)
The one IKA key blob that logged UNMASKED (J136 seat, DID 0x00BE, 34 bytes):E6 2B 41 D1 1C 44 AF 20 21 77 FB 1F 27 4B 0A C2
D1 5B D2 62 E4 FD 27 AB 61 D1 23 C2 F1 5A 2C 93 26 00
(J136 variant SVF6000, FAZIT CU5-SIB 21.03.11 0002 0968)
Every other module's IKA was masked ****** — they went through the masked TrainICA KWP service; J136's went through a direct WriteDataByIdentifier so it logged verbatim.
Gateway constellation write (J533, DID 0x04A3):Before: FD A1 E9 0C FE 62 64 8D 00 00
After: FD A1 E8 0C FE 62 60 0D 00 00
Procedure flow (reconstructed):1. Read J518 FAZIT + HW, read J533 FAZIT
2. GeKo <- VIN + J518_FAZIT + J533_FAZIT + transponder data
3. GeKo -> IKA blob per component (THIS is the masked secret)
4. KWP modules: TrainICA(blob) -> TrainGVA(blob) -> confirm
5. UDS modules: WriteDataByIdentifier(0x00BE, blob)
6. J533 constellation (0x04A3) updated
═══ 2. HOW CP ACTUALLY WORKS — TWO LAYERS ═══People conflate these, which is why "just write the IKA" or "just zero the constellation" alone never works.
Layer 1 — Gateway enrollment (J533, 4G0907468AC SW 0037, LEAR, Renesas uPD70F3433 V850)The gateway keeps the constellation (0x04A3) and each module's IKA. Critically,
the gateway does NOT enforce CP — I confirmed this on the live car:
0x04A3 Constellation: FD A1 E8 0C FE 62 60 0D 00 00
0x2A26 Present bitmap: FD A1 E8 0C FE 62 60 0D 00 00 <- IDENTICAL
0x0439 Auth-incorrect: 00 00 00 00 00 00 00 00 00 00 <- ALL ZEROS
Constellation == present bitmap, and "auth incorrect" is all zeros even with J255 throwing U1101. So the gateway just tracks an install list;
each module self-polices its own CP. Clearing the constellation will NOT fix it.
The gateway's own integrity self-check (firmware RE) turned out to be a
fixed-key AES-128 known-answer test over a PUBLIC sentinel — no per-vehicle secret:
key = "LEAR D4 Gateway." (ASCII, 16 bytes, in flash)
sentinel = 01 02 03 04 05 06 07 08 08 07 06 05 04 03 02 01
valid record = AES-ENC(sentinel, key)
= 6D 08 45 31 99 C6 FF A0 A0 56 FB 72 0C 02 9B 07
So the gateway side is forgeable 100% offline. That layer is solved.
Layer 2 — The per-module credential (the actual lock)On every self-policing CP module I tore down (HVAC J255 V850, driver seat J136 V850, BCM1 J519), the IKA is verified by a
LOCAL symmetric-AES known-answer test:
pass <=> stored_block0 == AES-128(challenge, K)
-
K is on the module — module-fixed AES-128 keys baked in flash. Seat J136, verified in the binary:
K5 = 16F45463BB3DB44EEB35DF537F8DFD6B
K6 = C93E58A121F00277912580785E1AD506
K7 = 2D508AB80B42AEF16E2335A70811C67D
(a second AES path keys off the IKA's own block1)
-
stored_block0 (the "answer") is per-vehicle, in owner-writable data-flash (seat record @0x03FF9000). On the seat the write path is wide open: UDS 0x3B LID 0xBE -> TrainICA -> stored unconditionally,
no SecurityAccess, default session.
-
challenge arrives over the bus in the 0x00BE/0x00BD exchange.
No RSA, no ECC, no online check in the verify itself — it's a symmetric KAT. Fail -> DTC (U1101 / 0xEA6x) -> limp (Climatronic drops to defrost-only). The J525 amp is a "dumb endpoint" — stores the IKA, self-reports a flag, no cipher at all.