Skip to content

Commit 12338d3

Browse files
committed
Add VDOSecurityAlgo, 221 definitions
Anonymous contributor, unverified. Matches single test case at #69
1 parent 03fb9ba commit 12338d3

2 files changed

Lines changed: 4919 additions & 0 deletions

File tree

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace UnlockECU
8+
{
9+
/// <summary>
10+
/// Very similar implementation to Mattwmaster58's IC204, except this splits out the key expansion level
11+
/// </summary>
12+
class VDOSecurityAlgo : SecurityProvider
13+
{
14+
public override bool GenerateKey(byte[] inSeed, byte[] outKey, int accessLevel, List<Parameter> parameters)
15+
{
16+
byte[] kc = GetParameterBytearray(parameters, "K");
17+
int keyExpansionLevel = GetParameterInteger(parameters, "InternalLevel");
18+
19+
if ((inSeed.Length != 8) || (outKey.Length != 8))
20+
{
21+
return false;
22+
}
23+
24+
byte[] result = GenerateKey(keyExpansionLevel, inSeed, kc);
25+
Array.ConstrainedCopy(result, 0, outKey, 0, inSeed.Length);
26+
return true;
27+
}
28+
29+
public override string GetProviderName()
30+
{
31+
return "VDOSecurityAlgo";
32+
}
33+
34+
private byte[] GenerateKey(int keyExpansionLevel, byte[] seed, byte[] kc, int tpcScramblerLevel = -1)
35+
{
36+
if (tpcScramblerLevel == -1)
37+
{
38+
tpcScramblerLevel = keyExpansionLevel;
39+
}
40+
41+
byte[] tp = new byte[]
42+
{
43+
seed[7], seed[4], seed[3], seed[6],
44+
seed[5], seed[1], seed[0], seed[2],
45+
};
46+
byte[] ik = ExpandAndTransformKey(keyExpansionLevel, tp, kc); // sp[8-f]
47+
48+
byte[] tpc = new byte[] { tp[0], tp[1], tp[2], tp[3], tp[4], tp[5], tp[6], tp[7] }; // sp[0-7]
49+
50+
for (int cipherIter = 0; cipherIter < 2; cipherIter++)
51+
{
52+
for (int i = 0; i < 4; i++)
53+
{
54+
tp[i] ^= tp[4 + i];
55+
}
56+
57+
int rotateCount = tpc[tpcScramblerLevel] & 3;
58+
rotateCount++;
59+
60+
byte[] lowerRotateBytes = new byte[] { tp[0], tp[1], tp[2], tp[3] };
61+
62+
for (int i = 0; i < rotateCount; i++)
63+
{
64+
RotateBits(lowerRotateBytes);
65+
}
66+
tp[0] = lowerRotateBytes[0];
67+
tp[1] = lowerRotateBytes[1];
68+
tp[2] = lowerRotateBytes[2];
69+
tp[3] = lowerRotateBytes[3];
70+
71+
72+
uint tpSum = tp[0];
73+
tpSum |= (uint)(tp[1] << 8);
74+
tpSum |= (uint)(tp[2] << 16);
75+
tpSum |= (uint)(tp[3] << 24);
76+
77+
uint ikSum = ik[0];
78+
ikSum |= (uint)(ik[1] << 8);
79+
ikSum |= (uint)(ik[2] << 16);
80+
ikSum |= (uint)(ik[3] << 24);
81+
82+
unchecked
83+
{
84+
tpSum += ikSum;
85+
}
86+
tp[0] = (byte)((tpSum >> 0) & 0xFF);
87+
tp[1] = (byte)((tpSum >> 8) & 0xFF);
88+
tp[2] = (byte)((tpSum >> 16) & 0xFF);
89+
tp[3] = (byte)((tpSum >> 24) & 0xFF);
90+
91+
tp[4] = tpc[0];
92+
tp[5] = tpc[1];
93+
tp[6] = tpc[2];
94+
tp[7] = tpc[3];
95+
96+
Array.ConstrainedCopy(tp, 0, tpc, 0, 8);
97+
98+
for (int i = 0; i < 4; i++)
99+
{
100+
tp[i] ^= tp[4 + i];
101+
}
102+
103+
int rotateCount2 = tpc[tpcScramblerLevel] & 3;
104+
rotateCount2++;
105+
106+
byte[] lowerRotateBytes2 = new byte[] { tp[0], tp[1], tp[2], tp[3] };
107+
108+
for (int i = 0; i < rotateCount2; i++)
109+
{
110+
RotateBits(lowerRotateBytes2);
111+
}
112+
tp[0] = lowerRotateBytes2[0];
113+
tp[1] = lowerRotateBytes2[1];
114+
tp[2] = lowerRotateBytes2[2];
115+
tp[3] = lowerRotateBytes2[3];
116+
117+
uint tpSum2 = tp[0];
118+
tpSum2 |= (uint)(tp[1] << 8);
119+
tpSum2 |= (uint)(tp[2] << 16);
120+
tpSum2 |= (uint)(tp[3] << 24);
121+
122+
uint ikSum2 = ik[4];
123+
ikSum2 |= (uint)(ik[5] << 8);
124+
ikSum2 |= (uint)(ik[6] << 16);
125+
ikSum2 |= (uint)(ik[7] << 24);
126+
127+
unchecked
128+
{
129+
tpSum2 += ikSum2;
130+
}
131+
tp[0] = (byte)((tpSum2 >> 0) & 0xFF);
132+
tp[1] = (byte)((tpSum2 >> 8) & 0xFF);
133+
tp[2] = (byte)((tpSum2 >> 16) & 0xFF);
134+
tp[3] = (byte)((tpSum2 >> 24) & 0xFF);
135+
136+
tp[4] = tpc[0];
137+
tp[5] = tpc[1];
138+
tp[6] = tpc[2];
139+
tp[7] = tpc[3];
140+
141+
Array.ConstrainedCopy(tp, 0, tpc, 0, 8);
142+
}
143+
144+
byte[] key = new byte[] {
145+
tpc[3], tpc[5], tpc[6], tpc[1],
146+
tpc[0], tpc[7], tpc[4], tpc[2],
147+
};
148+
return key;
149+
}
150+
151+
private byte[] ExpandAndTransformKey(int accessLevel, byte[] transposedSeed, byte[] kc)
152+
{
153+
int morphCount = (transposedSeed[accessLevel] & 7) + 2;
154+
ExpandFullKey(kc);
155+
156+
byte[] mKey = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
157+
Array.ConstrainedCopy(kc, 0, mKey, 0, 8);
158+
159+
for (int i = 0; i < morphCount; i++)
160+
{
161+
byte[] ek = new byte[]
162+
{
163+
mKey[0], mKey[1], mKey[2], mKey[3],
164+
mKey[4], mKey[5], mKey[6], mKey[7]
165+
};
166+
167+
byte xorIntermediate = 0;
168+
169+
ek[0] &= 8;
170+
ek[0] >>= 3;
171+
172+
xorIntermediate ^= ek[0];
173+
174+
ek[1] &= 1;
175+
ek[1] >>= 0;
176+
177+
xorIntermediate ^= ek[1];
178+
179+
ek[2] &= 2;
180+
ek[2] >>= 1;
181+
182+
xorIntermediate ^= ek[2];
183+
184+
ek[3] &= 0x80;
185+
ek[3] >>= 7;
186+
187+
xorIntermediate ^= ek[3];
188+
189+
ek[4] &= 0x20;
190+
ek[4] >>= 5;
191+
192+
xorIntermediate ^= ek[4];
193+
194+
ek[5] &= 4;
195+
ek[5] >>= 2;
196+
197+
xorIntermediate ^= ek[5];
198+
199+
ek[6] &= 0x40;
200+
ek[6] >>= 6;
201+
202+
xorIntermediate ^= ek[6];
203+
204+
byte snapshot = ek[7];
205+
ek[7] &= 0x10;
206+
ek[7] >>= 4;
207+
208+
xorIntermediate ^= ek[7];
209+
210+
byte finalByteTransformed = (byte)(xorIntermediate << 7);
211+
finalByteTransformed |= (byte)(snapshot & 0x7F);
212+
213+
mKey[7] = finalByteTransformed;
214+
RotateBits(mKey);
215+
216+
}
217+
return mKey;
218+
}
219+
220+
private void ExpandFullKey(byte[] keyConstant)
221+
{
222+
byte[] keyLower = new byte[] { keyConstant[0], keyConstant[1], keyConstant[2], keyConstant[3] };
223+
byte[] keyUpper = new byte[] { keyConstant[4], keyConstant[5], keyConstant[6], keyConstant[7] };
224+
Expand32BitKey(keyLower);
225+
Expand32BitKey(keyUpper);
226+
Array.ConstrainedCopy(keyLower, 0, keyConstant, 0, keyLower.Length);
227+
Array.ConstrainedCopy(keyUpper, 0, keyConstant, 4, keyUpper.Length);
228+
}
229+
230+
private void Expand32BitKey(byte[] key)
231+
{
232+
byte[] keyA = new byte[] { key[0], key[1], key[2], key[3] };
233+
byte[] keyP = new byte[] { key[1], key[3], key[0], key[2] };
234+
235+
int rotateCountP = (key[2] & 0xF) + 1;
236+
RotateBits(keyP, rotateCountP);
237+
238+
int rotateCountA = (key[3] & 0xF) + 1;
239+
RotateBits(keyA, rotateCountA);
240+
241+
for (int i = 0; i < key.Length; i++)
242+
{
243+
key[i] = (byte)(keyA[i] ^ keyP[i]);
244+
}
245+
}
246+
private void RotateBits(byte[] inBytes, int count)
247+
{
248+
for (int i = 0; i < count; i++)
249+
{
250+
RotateBits(inBytes);
251+
}
252+
}
253+
private void RotateBits(byte[] inBytes)
254+
{
255+
byte[] tempBuffer = new byte[inBytes.Length];
256+
for (int i = 0; i < tempBuffer.Length; i++)
257+
{
258+
if ((inBytes[i] & 1) > 0)
259+
{
260+
tempBuffer[i] = 0x80;
261+
}
262+
}
263+
for (int i = 0; i < tempBuffer.Length; i++)
264+
{
265+
int rIndex = i - 1;
266+
if (rIndex < 0)
267+
{
268+
rIndex = tempBuffer.Length - 1;
269+
}
270+
inBytes[i] = (byte)(inBytes[i] >> 1);
271+
inBytes[i] |= tempBuffer[rIndex];
272+
}
273+
}
274+
}
275+
}

0 commit comments

Comments
 (0)