Files
KAT/docs/porsche_touareg.md
T
KaraZajac 48ee413c9b v1.2.0: Add 4 new protocols, fix 5 existing, port Kia V6 encoder
New protocols (from ProtoPirate):
- Mazda V0: 433MHz, pair-based decoding, XOR deobfuscation
- Mitsubishi V0: 868MHz, PWM, bit negation + XOR unscrambling
- Porsche Touareg: 433/868MHz, sync preamble, 24-bit rotate cipher
- Fiat V1 (Magneti Marelli BSI): 433MHz, auto-detected timing variants

Protocol fixes aligned with ProtoPirate reference:
- Kia V1: Fix Manchester level mapping (inverted convention), off-by-one
  bit count, CRC4 simplified to 7 bytes + offset 1
- Kia V2: Fix CRC byte layout (was double-counting nibbles), off-by-one
  bit count, preamble short-HIGH handling
- Fiat V0: Fix endbyte transform (remove (<<1)|1), standard Manchester
  encoder (was differential), 7 btn bits (was 6), gap path fallback
- PSA: Fix modified TEA (XTEA-like dynamic key selection), XOR decrypt
  byte mapping, critical key2_low construction bug, encoder polarity and
  preamble, add key1_high nibble validation, dual preamble patterns
- Ford V0: Add calculate_checksum (sums all serial+count bytes) for encoder

Kia V6 encoder ported:
- Forward AES-128 (SubBytes, ShiftRows, MixColumns, encrypt)
- encrypt_payload: build plaintext, AES encrypt, pack into 3 parts
- Two-pass Manchester upload (640 + 38 preamble pairs)
- fx_field extraction stored in DecodedSignal.extra for encode roundtrip

Updated README, protocol docs, and version bump to 1.2.0.
2026-03-22 12:05:01 -04:00

73 lines
2.4 KiB
Markdown

---
layout: default
---
# Porsche Touareg Protocol
**Rust module:** `src/protocols/porsche_touareg.rs`
**Reference:** `REFERENCES/ProtoPirate/protocols/porsche_touareg.c`
## Overview
Porsche Touareg uses PWM encoding with very long timing (1680/3370 us). 64-bit frame with a sync preamble (at least 15 sync pulses at 3370 us). Counter is recovered via brute-force using a 24-bit rotation cipher. Originally designed for the Porsche Cayenne.
## Timing
| Parameter | Value | Notes |
|------------|----------|--------------|
| Short | 1680 us | +/-500 us |
| Long | 3370 us | +/-500 us |
| Sync | 3370 us | Same as long |
| Gap | 5930 us | +/-500 us |
| Sync min | 15 pulses| |
| Min bits | 64 | |
## PWM Bit Encoding
| Pair (LOW, HIGH) | Bit |
|------------------|-----|
| Short LOW + Long HIGH | 0 |
| Long LOW + Short HIGH | 1 |
## Frame Layout (64 bits = 8 bytes)
| Byte | Content |
|------|---------|
| pkt[0] | (button << 4) \| (frame_type & 0x07) |
| pkt[1] | serial bits [23:16] |
| pkt[2] | serial bits [15:8] |
| pkt[3] | serial bits [7:0] |
| pkt[4..7] | Encrypted counter/rolling code |
- **Serial**: 24 bits from pkt[1..3]
- **Button**: 4 bits (pkt[0] >> 4)
- **Frame type**: 3 bits (pkt[0] & 0x07): 0x02=First, 0x01=Cont, 0x04=Final
## Counter Recovery (Brute-Force)
Counter is not in plaintext. The decoder tries counter values 1-256, calling `compute_frame()` for each, and checks if computed bytes [4..7] match received bytes [4..7].
### Compute Frame Algorithm (24-bit Rotate Cipher)
1. Initialize 24-bit rotate register from serial bytes: r_h=b3, r_m=b1, r_l=b2.
2. ROTATE24: circular left shift across 3 bytes (h<-m, m<-l, l<-h).
3. Rotate 4 times + counter_low more times.
4. Compute encrypted bytes a9a/a9b/a9c from rotated values XOR'd with inverted counter bits.
5. Assemble pkt[4..7] using bitfield packing.
## Decoder Steps
1. **Reset** -- Wait for LOW pulse matching sync (3370 us).
2. **Sync** -- Count sync pulses (both HIGH and LOW). When count >= 15 and gap detected (5930 us), transition to GapHigh or GapLow.
3. **GapHigh** -- Expect HIGH gap (5930 us); init data on match.
4. **GapLow** -- Expect LOW gap (5930 us); init data on match.
5. **Data** -- Decode bit pairs (LOW saved, HIGH completes). At 64 bits, parse data and brute-force counter.
## Encoder
Not supported (decode-only).
## Frequencies
433.92 MHz, 868.35 MHz.