Skip to content

Commit

Permalink
Added support for Polo (and hopefully Skoda Fabia 6Y) clusters runnin…
Browse files Browse the repository at this point in the history
…g VQMJ07 software. Added GetSKC support for Audi TT 8N1919880E clusters.
  • Loading branch information
gmenounos committed Apr 4, 2024
1 parent 44d1fad commit 8d65a3b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 17 deletions.
1 change: 1 addition & 0 deletions Cluster/MarelliCluster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ private bool WriteMarelliBlockAndReadAck(byte[] data)
"1C0920921", // Beetle 1C0920921G M73 V08
"1C0920941", // Beetle 1C0920941LX M73 V03
"1C0920951", // Beetle 1C0920951A M73 V02
"8N1919880", // Audi TT 8N1919880E M73 D26 (actually Immo2 but has the larger EEPROM)
"8N1920980", // Audi TT 8N1920980E M73 D14
"8N2920930", // Audi TT 8N2920930C M73 D55
"8N2920980", // Audi TT 8N2920980A M73 D14
Expand Down
20 changes: 13 additions & 7 deletions Cluster/VdoCluster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ internal class VdoCluster : ICluster
{
public void UnlockForEepromReadWrite()
{
if (!Unlock())
var (isUnlocked, softwareVersion) = Unlock();
if (!isUnlocked)
{
Log.WriteLine("Unknown cluster software version. EEPROM access will likely fail.");
}
Expand All @@ -24,7 +25,7 @@ public void UnlockForEepromReadWrite()
return;
}

SeedKeyAuthenticate();
SeedKeyAuthenticate(softwareVersion);
if (RequiresSeedKey())
{
Log.WriteLine("Failed to unlock cluster.");
Expand Down Expand Up @@ -199,13 +200,13 @@ private List<Block> SendCustom(List<byte> blockCustomBytes)
return _kwp1281.ReceiveBlocks();
}

public bool Unlock()
public (bool succeeded, string? softwareVersion) Unlock()
{
var versionBlocks = CustomReadSoftwareVersion();
if (versionBlocks.Count == 0)
{
Log.WriteLine("Cluster did not return software version.");
return false;
return (succeeded: false, softwareVersion: null);
}

// Now we need to send an unlock code that is unique to each ROM version
Expand Down Expand Up @@ -240,12 +241,16 @@ public bool Unlock()
$"Received non-ACK/NAK ${unlockResponse[0].Title:X2} from unlock request.");
}
}
return unlocked;
return (unlocked, softwareVersion);
}

private const int MaxAccessLevel = 7;

public void SeedKeyAuthenticate()
/// <summary>
/// Tries to perform seed/key authentication with cluster.
/// </summary>
/// <param name="softwareVersion">Software version string like "VQMJ07LM 09.00"</param>
public void SeedKeyAuthenticate(string? softwareVersion)
{
// Perform Seed/Key authentication
Log.WriteLine("Sending Custom \"Seed request\" block");
Expand All @@ -256,7 +261,8 @@ public void SeedKeyAuthenticate()
{
Log.WriteLine($"Block: {Utils.Dump(customBlock.Body)}");

var keyBytes = VdoKeyFinder.FindKey(customBlock.Body.ToArray(), MaxAccessLevel);
var keyBytes = VdoKeyFinder.FindKey(
customBlock.Body.ToArray(), MaxAccessLevel, softwareVersion);

Log.WriteLine("Sending Custom \"Key response\" block");

Expand Down
28 changes: 24 additions & 4 deletions Cluster/VdoKeyFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ namespace BitFab.KW1281Test.Cluster
public static class VdoKeyFinder
{
/// <summary>
/// Takes a 10-byte seed block and desired access level and generates an 8-byte key block.
/// Takes a 10-byte seed block, desired access level and optional cluster software version and generates an
/// 8-byte key block.
/// </summary>
public static byte[] FindKey(byte[] seed, int accessLevel)
public static byte[] FindKey(
byte[] seed, int accessLevel, string? softwareVersion)
{
if (seed.Length != 10)
{
Expand All @@ -23,6 +25,9 @@ public static byte[] FindKey(byte[] seed, int accessLevel)
case 0x01 when seed[9] == 0x00:
secret = VWK501Secrets[accessLevel];
break;
case 0x09 when seed[9] == 0x00 && (softwareVersion ?? "").StartsWith("VQMJ07"):
secret = VQMJ07Secrets[accessLevel];
break;
case 0x03 when seed[9] == 0x00:
case 0x09 when seed[9] == 0x00:
secret = VSQX01Secrets[accessLevel];
Expand All @@ -40,7 +45,7 @@ public static byte[] FindKey(byte[] seed, int accessLevel)
[seed[1], seed[3], seed[5], seed[7]],
secret);

return [(byte)accessLevel, key[0], key[1], 0x00, key[2], 0x00, key[3], 0x00, 0x00];
return [(byte)accessLevel, key[0], key[1], 0x00, key[2], 0x00, key[3], 0x00];
}

/// <summary>
Expand Down Expand Up @@ -72,7 +77,22 @@ public static byte[] FindKey(byte[] seed, int accessLevel)
[0xac, 0xfc, 0x5e, 0x6c],
[0x98, 0xe1, 0x56, 0x5f] // AccessLevel 7
];


/// <summary>
/// Table of secrets, one for each access level.
/// </summary>
private static readonly byte[][] VQMJ07Secrets =
[
[0xa7, 0xd2, 0xe9, 0x8d], // AccessLevel 0
[0xe6, 0xfa, 0x9e, 0xba],
[0x63, 0x92, 0xe3, 0x08],
[0x55, 0x3e, 0x68, 0x24],
[0x03, 0x2a, 0x70, 0xdc],
[0xe7, 0xb4, 0x71, 0x86],
[0x4f, 0x58, 0xcd, 0x81],
[0xfd, 0x8e, 0x31, 0x96] // AccessLevel 7
];

/// <summary>
/// Takes a 4-byte seed and calculates a 4-byte key.
/// </summary>
Expand Down
12 changes: 9 additions & 3 deletions Tester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,8 @@ private void UnlockControllerForEepromReadWrite()
case ControllerAddress.Cluster:
// TODO:UnlockCluster() is only needed for EEPROM read, not memory read
var cluster = new VdoCluster(_kwp1281);
if (!cluster.Unlock())
var (isUnlocked, softwareVersion) = cluster.Unlock();
if (!isUnlocked)
{
Log.WriteLine("Unknown cluster software version. EEPROM access will likely fail.");
}
Expand All @@ -969,7 +970,7 @@ private void UnlockControllerForEepromReadWrite()
return;
}

cluster.SeedKeyAuthenticate();
cluster.SeedKeyAuthenticate(softwareVersion);
if (cluster.RequiresSeedKey())
{
Log.WriteLine("Failed to unlock cluster.");
Expand Down Expand Up @@ -1064,7 +1065,12 @@ private void DumpClusterMem(uint startAddress, uint length, string? filename)
}
else
{
cluster.SeedKeyAuthenticate();
var (isUnlocked, softwareVersion) = cluster.Unlock();
if (!isUnlocked)
{
Log.WriteLine("Unknown cluster software version. Memory access will likely fail.");
}
cluster.SeedKeyAuthenticate(softwareVersion);
}

var dumpFileName = filename ?? $"cluster_mem_${startAddress:X6}.bin";
Expand Down
6 changes: 3 additions & 3 deletions kw1281test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>BitFab.KW1281Test</RootNamespace>
<LangVersion>latest</LangVersion>
<AssemblyVersion>0.96.0.0</AssemblyVersion>
<FileVersion>0.96.0.0</FileVersion>
<Version>0.96.0-beta</Version>
<AssemblyVersion>0.97.0.0</AssemblyVersion>
<FileVersion>0.97.0.0</FileVersion>
<Version>0.97.0-beta</Version>
<Copyright>Copyright © 2024 Greg Menounos</Copyright>
<DebugType>embedded</DebugType>
<DebugSymbols>true</DebugSymbols>
Expand Down

0 comments on commit 8d65a3b

Please sign in to comment.