SDD stores diagnostic configuration in EXML files — JLR’s proprietary encrypted XML format. These files define every DID, IOControl, routine, and security parameter for each ECU. They are the Rosetta Stone.
Cracking EXML Encryption
EXML files have a distinctive 8-byte magic header:
F1 22 C4 66 2C 2B 2F F2
A GitHub tool (smartgauges/exml) decrypts them. Running it against our 2,033 EXML files revealed:
- Security.exml (62KB) — The master key database. Every ECU’s security key, organized by platform and module. This is where we found the RLM’s DC0031/DC0032 keys.
- CCF_DATA_L319.exml (299KB) — Car Configuration File with feature flags and options. Confirms Discovery 3s have
ASUS_4_CORNER(4-corner air suspension) as option 7. - RLM.exml and MDX_RLM.exml — The actual RLM diagnostic data. Disappointingly, these were mostly stubs labelled “MANUALLY CREATED”. JLR never fully populated the L319 RLM diagnostic data in SDD 130.
The Triple DES Discovery
How is EXML encrypted? We decompiled sdd-tools-1_0.jar from the SDD web application. The cipher class reveals:
// CipherStreamFactory.java
SecretKeyFactory.getInstance("DESede") // Triple DES
Cipher.getInstance("DESede") // 3DES cipher
setSecretKeySeed(byte[] aSeed) // Key from byte array
The encryption is standard Java Cryptography Extension Triple DES. The key seed is set at runtime by IdsRuntime.class. The CipherTool class provides command-line encrypt/decrypt:
java -cp sdd-tools-1_0.jar com.jlr.sdd.cipher.CipherTool -decrypt file.exml
The Calibration Question: Amplitude vs Offset
Our ultimate goal: understand whether the RLM calibration includes amplitude (gain/slope) in addition to offset (zero point).
From the SA DLL strings and the known D3 calibration heights (466mm front, 488mm rear at normal ride height), the calibration flow appears to be:
1. Place vehicle at known reference height
2. Read raw height sensor counts via ReadDID (0x22)
3. Compare to expected values
4. Write calibration offset via IOControl (0x2F)
5. Store in ECU non-volatile memory
The DIDs for calibration data are in the 0xF1xx and 0xE4xx ranges. The IOControl IDs for valve actuation (needed to position the suspension) are referenced by the @J_I_* tokens we extracted earlier.
What we still don’t know — and what the J2534 proxy will reveal — is whether the calibration writes a single offset per corner or includes gain/scaling parameters. If the suspension is over-compensating, it could be a gain error (wrong mm-per-count ratio) not just an offset error (wrong zero point).
Current Status
| Component | Status |
|---|---|
| CAN capture | ✅ Working (30+ fps) |
| CAN transmit | ✅ Fixed (GPIO16+GPIO23) |
| Security algorithm | ✅ Implemented |
| RLM keys | ✅ Extracted |
| UDS diagnostic tool | ✅ Built |
| DID/IOControl IDs | 🔴 Still hunting |
| J2534 proxy (VM) | 🟡 Compiled, needs deployment |
| Calibration sequence | 🔴 Capture from SDD |
What’s Next
- Deploy the J2534 proxy in the SDD VM — capture exact UDS commands
- Complete the UDS scan on the vehicle — find the RLM’s CAN ID
- Read calibration DIDs — discover the amplitude/offset parameters
- Build calibration tool — replay the sequence, verify against physical measurements
- Diagnose the over-compensation — determine if it’s gain, offset, or mechanical
This series will continue as each milestone is reached. The code is open-source at github.com/jcian/discovery-3.
Series index: Part 1-5 — OBD pins, LilyGO setup, capturing frames, finding height values. Part 6 — Reverse Engineering JLR SDD. Part 7 — Cracking Ford Security. Part 8 — LilyGO CAN TX Fix. Part 9 — Building a UDS Diagnostic Tool. Part 10 — EXML Files and Calibration Goals (this article).
Disclaimer: This series documents reverse engineering for educational and research purposes. JLR SDD and its components are proprietary software. EXML encryption details are discussed in the context of interoperability research. All testing is performed on a bench ECU, not a road-registered vehicle.
Leave a Reply