]> git.zerfleddert.de Git - proxmark3-svn/blame - client/loclass/elite_crack.c
Fix Tune Samples (broken in commit 12/31 by me)
[proxmark3-svn] / client / loclass / elite_crack.c
CommitLineData
3ad48540
MHS
1#include <stdint.h>
2#include <stdbool.h>
3#include <string.h>
4#include <stdio.h>
5#include <time.h>
6#include "cipherutils.h"
7#include "cipher.h"
8#include "ikeys.h"
9#include "elite_crack.h"
10#include "fileutils.h"
11#include "des.h"
12
13/**
14 * @brief Permutes a key from standard NIST format to Iclass specific format
15 * from http://www.proxmark.org/forum/viewtopic.php?pid=11220#p11220
16 *
17 * If you permute [6c 8d 44 f9 2a 2d 01 bf] you get [8a 0d b9 88 bb a7 90 ea] as shown below.
18 *
19 * 1 0 1 1 1 1 1 1 bf
20 * 0 0 0 0 0 0 0 1 01
21 * 0 0 1 0 1 1 0 1 2d
22 * 0 0 1 0 1 0 1 0 2a
23 * 1 1 1 1 1 0 0 1 f9
24 * 0 1 0 0 0 1 0 0 44
25 * 1 0 0 0 1 1 0 1 8d
26 * 0 1 1 0 1 1 0 0 6c
27 *
28 * 8 0 b 8 b a 9 e
29 * a d 9 8 b 7 0 a
30 *
31 * @param key
32 * @param dest
33 */
34void permutekey(uint8_t key[8], uint8_t dest[8])
35{
36
37 int i;
38 for(i = 0 ; i < 8 ; i++)
39 {
40 dest[i] = (((key[7] & (0x80 >> i)) >> (7-i)) << 7) |
41 (((key[6] & (0x80 >> i)) >> (7-i)) << 6) |
42 (((key[5] & (0x80 >> i)) >> (7-i)) << 5) |
43 (((key[4] & (0x80 >> i)) >> (7-i)) << 4) |
44 (((key[3] & (0x80 >> i)) >> (7-i)) << 3) |
45 (((key[2] & (0x80 >> i)) >> (7-i)) << 2) |
46 (((key[1] & (0x80 >> i)) >> (7-i)) << 1) |
47 (((key[0] & (0x80 >> i)) >> (7-i)) << 0);
48 }
49
50 return;
51}
52/**
53 * Permutes a key from iclass specific format to NIST format
54 * @brief permutekey_rev
55 * @param key
56 * @param dest
57 */
58void permutekey_rev(uint8_t key[8], uint8_t dest[8])
59{
60 int i;
61 for(i = 0 ; i < 8 ; i++)
62 {
63 dest[7-i] = (((key[0] & (0x80 >> i)) >> (7-i)) << 7) |
64 (((key[1] & (0x80 >> i)) >> (7-i)) << 6) |
65 (((key[2] & (0x80 >> i)) >> (7-i)) << 5) |
66 (((key[3] & (0x80 >> i)) >> (7-i)) << 4) |
67 (((key[4] & (0x80 >> i)) >> (7-i)) << 3) |
68 (((key[5] & (0x80 >> i)) >> (7-i)) << 2) |
69 (((key[6] & (0x80 >> i)) >> (7-i)) << 1) |
70 (((key[7] & (0x80 >> i)) >> (7-i)) << 0);
71 }
72}
73
74/**
75 * Helper function for hash1
76 * @brief rr
77 * @param val
78 * @return
79 */
80uint8_t rr(uint8_t val)
81{
82 return val >> 1 | (( val & 1) << 7);
83}
84/**
85 * Helper function for hash1
86 * @brief rl
87 * @param val
88 * @return
89 */
90uint8_t rl(uint8_t val)
91{
92 return val << 1 | (( val & 0x80) >> 7);
93}
94/**
95 * Helper function for hash1
96 * @brief swap
97 * @param val
98 * @return
99 */
100uint8_t swap(uint8_t val)
101{
102 return ((val >> 4) & 0xFF) | ((val &0xFF) << 4);
103}
104
105/**
106 * Hash1 takes CSN as input, and determines what bytes in the keytable will be used
107 * when constructing the K_sel.
108 * @param csn the CSN used
109 * @param k output
110 */
111void hash1(uint8_t csn[] , uint8_t k[])
112{
113 k[0] = csn[0]^csn[1]^csn[2]^csn[3]^csn[4]^csn[5]^csn[6]^csn[7];
114 k[1] = csn[0]+csn[1]+csn[2]+csn[3]+csn[4]+csn[5]+csn[6]+csn[7];
115 k[2] = rr(swap( csn[2]+k[1] ));
0eea34a2
MHS
116 k[3] = rl(swap( csn[3]+k[0] ));
117 k[4] = ~rr( csn[4]+k[2] )+1;
118 k[5] = ~rl( csn[5]+k[3] )+1;
3ad48540
MHS
119 k[6] = rr( csn[6]+(k[4]^0x3c) );
120 k[7] = rl( csn[7]+(k[5]^0xc3) );
121 int i;
122 for(i = 7; i >=0; i--)
123 k[i] = k[i] & 0x7F;
124}
aa41c605
MHS
125/**
126Definition 14. Define the rotate key function rk : (F 82 ) 8 Ɨ N ā†’ (F 82 ) 8 as
127rk(x [0] . . . x [7] , 0) = x [0] . . . x [7]
128rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n)
129**/
130void rk(uint8_t *key, uint8_t n, uint8_t *outp_key)
131{
132
133 memcpy(outp_key, key, 8);
134
135 uint8_t j;
136
137 while(n-- > 0)
138 for(j=0; j < 8 ; j++)
139 outp_key[j] = rl(outp_key[j]);
140
141 return;
142}
143
144static des_context ctx_enc = {DES_ENCRYPT,{0}};
145static des_context ctx_dec = {DES_DECRYPT,{0}};
146
147void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output)
148{
149 uint8_t key_std_format[8] = {0};
150 permutekey_rev(iclass_key, key_std_format);
151 des_setkey_dec( &ctx_dec, key_std_format);
152 des_crypt_ecb(&ctx_dec,input,output);
153}
154void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output)
155{
156 uint8_t key_std_format[8] = {0};
157 permutekey_rev(iclass_key, key_std_format);
158 des_setkey_enc( &ctx_enc, key_std_format);
159 des_crypt_ecb(&ctx_enc,input,output);
160}
161
162/**
163 * @brief Insert uint8_t[8] custom master key to calculate hash2 and return key_select.
164 * @param key unpermuted custom key
165 * @param hash1 hash1
166 * @param key_sel output key_sel=h[hash1[i]]
167 */
168void hash2(uint8_t *key64, uint8_t *outp_keytable)
169{
170 /**
171 *Expected:
172 * High Security Key Table
173
17400 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
17510 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
17620 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
17730 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
17840 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
17950 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
18060 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
18170 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
182
183**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ******/
184 uint8_t key64_negated[8] = {0};
185 uint8_t z[8][8]={{0},{0}};
186 uint8_t temp_output[8]={0};
187 //calculate complement of key
188 int i;
189 for(i=0;i<8;i++)
190 key64_negated[i]= ~key64[i];
191
192 // Once again, key is on iclass-format
193 desencrypt_iclass(key64, key64_negated, z[0]);
194
195 prnlog("\nHigh security custom key (Kcus):");
196 printvar("z0 ", z[0],8);
197
198 uint8_t y[8][8]={{0},{0}};
199
200 // y[0]=DES_dec(z[0],~key)
201 // Once again, key is on iclass-format
202 desdecrypt_iclass(z[0], key64_negated, y[0]);
203 printvar("y0 ", y[0],8);
204
205 for(i=1; i<8; i++)
206 {
3ad48540 207
aa41c605
MHS
208 // z [i] = DES dec (rk(K cus , i), z [iāˆ’1] )
209 rk(key64, i, temp_output);
210 //y [i] = DES enc (rk(K cus , i), y [iāˆ’1] )
211
212 desdecrypt_iclass(temp_output,z[i-1], z[i]);
213 desencrypt_iclass(temp_output,y[i-1], y[i]);
214
215 }
216 if(outp_keytable != NULL)
217 {
218 for(i = 0 ; i < 8 ; i++)
219 {
220 memcpy(outp_keytable+i*16,y[i],8);
221 memcpy(outp_keytable+8+i*16,z[i],8);
222 }
223 }else
224 {
225 printarr_human_readable("hash2", outp_keytable,128);
226 }
227}
3ad48540
MHS
228
229/**
230 * @brief Reads data from the iclass-reader-attack dump file.
231 * @param dump, data from a iclass reader attack dump. The format of the dumpdata is expected to be as follows:
232 * <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC><8 byte HASH1><1 byte NUM_BYTES_TO_RECOVER><3 bytes BYTES_TO_RECOVER>
233 * .. N times...
234 *
235 * So the first attack, with 3 bytes to recover would be : ... 03000145
236 * And a later attack, with 1 byte to recover (byte 0x5)would be : ...01050000
237 * And an attack, with 2 bytes to recover (byte 0x5 and byte 0x07 )would be : ...02050700
238 *
239 * @param cc_nr an array to store cc_nr into (12 bytes)
240 * @param csn an arracy ot store CSN into (8 bytes)
241 * @param received_mac an array to store MAC into (4 bytes)
242 * @param i the number to read. Should be less than 127, or something is wrong...
243 * @return
244 */
245int _readFromDump(uint8_t dump[], dumpdata* item, uint8_t i)
246{
247 size_t itemsize = sizeof(dumpdata);
248 //dumpdata item = {0};
249 memcpy(item,dump+i*itemsize, itemsize);
250 if(true)
251 {
252 printvar("csn", item->csn,8);
253 printvar("cc_nr", item->cc_nr,12);
254 printvar("mac", item->mac,4);
255 }
256 return 0;
257}
258
259static uint32_t startvalue = 0;
260/**
261 * @brief Performs brute force attack against a dump-data item, containing csn, cc_nr and mac.
262 *This method calculates the hash1 for the CSN, and determines what bytes need to be bruteforced
263 *on the fly. If it finds that more than three bytes need to be bruteforced, it aborts.
264 *It updates the keytable with the findings, also using the upper half of the 16-bit ints
265 *to signal if the particular byte has been cracked or not.
266 *
267 * @param dump The dumpdata from iclass reader attack.
268 * @param keytable where to write found values.
269 * @return
270 */
271int bruteforceItem(dumpdata item, uint16_t keytable[])
272{
273 int errors = 0;
274 uint8_t key_sel_p[8] = { 0 };
275 uint8_t div_key[8] = {0};
276 int found = false;
277 uint8_t key_sel[8] = {0};
278 uint8_t calculated_MAC[4] = { 0 };
279
280 //Get the key index (hash1)
281 uint8_t key_index[8] = {0};
282 hash1(item.csn, key_index);
283
284
285 /*
286 * Determine which bytes to retrieve. A hash is typically
287 * 01010000454501
288 * We go through that hash, and in the corresponding keytable, we put markers
289 * on what state that particular index is:
290 * - CRACKED (this has already been cracked)
291 * - BEING_CRACKED (this is being bruteforced now)
292 * - CRACK_FAILED (self-explaining...)
293 *
294 * The markers are placed in the high area of the 16 bit key-table.
295 * Only the lower eight bits correspond to the (hopefully cracked) key-value.
296 **/
297 uint8_t bytes_to_recover[3] = {0};
298 uint8_t numbytes_to_recover = 0 ;
299 int i;
300 for(i =0 ; i < 8 ; i++)
301 {
302 if(keytable[key_index[i]] & (CRACKED | BEING_CRACKED)) continue;
303 bytes_to_recover[numbytes_to_recover++] = key_index[i];
304 keytable[key_index[i]] |= BEING_CRACKED;
305
306 if(numbytes_to_recover > 3)
307 {
308 prnlog("The CSN requires > 3 byte bruteforce, not supported");
309 printvar("CSN", item.csn,8);
310 printvar("HASH1", key_index,8);
311
312 //Before we exit, reset the 'BEING_CRACKED' to zero
313 keytable[bytes_to_recover[0]] &= ~BEING_CRACKED;
314 keytable[bytes_to_recover[1]] &= ~BEING_CRACKED;
315 keytable[bytes_to_recover[2]] &= ~BEING_CRACKED;
316
317 return 1;
318 }
319 }
320
321 /*
322 *A uint32 has room for 4 bytes, we'll only need 24 of those bits to bruteforce up to three bytes,
323 */
324 uint32_t brute = startvalue;
325 /*
326 Determine where to stop the bruteforce. A 1-byte attack stops after 256 tries,
327 (when brute reaches 0x100). And so on...
328 bytes_to_recover = 1 --> endmask = 0x0000100
329 bytes_to_recover = 2 --> endmask = 0x0010000
330 bytes_to_recover = 3 --> endmask = 0x1000000
331 */
332
333 uint32_t endmask = 1 << 8*numbytes_to_recover;
334
335 for(i =0 ; i < numbytes_to_recover && numbytes_to_recover > 1; i++)
336 prnlog("Bruteforcing byte %d", bytes_to_recover[i]);
337
338 while(!found && !(brute & endmask))
339 {
340
341 //Update the keytable with the brute-values
342 for(i =0 ; i < numbytes_to_recover; i++)
343 {
344 keytable[bytes_to_recover[i]] &= 0xFF00;
345 keytable[bytes_to_recover[i]] |= (brute >> (i*8) & 0xFF);
346 }
347
348 // Piece together the key
349 key_sel[0] = keytable[key_index[0]] & 0xFF;key_sel[1] = keytable[key_index[1]] & 0xFF;
350 key_sel[2] = keytable[key_index[2]] & 0xFF;key_sel[3] = keytable[key_index[3]] & 0xFF;
351 key_sel[4] = keytable[key_index[4]] & 0xFF;key_sel[5] = keytable[key_index[5]] & 0xFF;
352 key_sel[6] = keytable[key_index[6]] & 0xFF;key_sel[7] = keytable[key_index[7]] & 0xFF;
353
354 //Permute from iclass format to standard format
355 permutekey_rev(key_sel,key_sel_p);
356 //Diversify
357 diversifyKey(item.csn, key_sel_p, div_key);
358 //Calc mac
aa41c605 359 doMAC(item.cc_nr,12, div_key,calculated_MAC);
3ad48540
MHS
360
361 if(memcmp(calculated_MAC, item.mac, 4) == 0)
362 {
363 for(i =0 ; i < numbytes_to_recover; i++)
364 prnlog("=> %d: 0x%02x", bytes_to_recover[i],0xFF & keytable[bytes_to_recover[i]]);
365 found = true;
366 break;
367 }
368 brute++;
369 if((brute & 0xFFFF) == 0)
370 {
371 printf("%d",(brute >> 16) & 0xFF);
372 fflush(stdout);
373 }
374 }
375 if(! found)
376 {
377 prnlog("Failed to recover %d bytes using the following CSN",numbytes_to_recover);
378 printvar("CSN",item.csn,8);
379 errors++;
380 //Before we exit, reset the 'BEING_CRACKED' to zero
381 for(i =0 ; i < numbytes_to_recover; i++)
382 {
383 keytable[bytes_to_recover[i]] &= 0xFF;
384 keytable[bytes_to_recover[i]] |= CRACK_FAILED;
385 }
386
387 }else
388 {
389 for(i =0 ; i < numbytes_to_recover; i++)
390 {
391 keytable[bytes_to_recover[i]] &= 0xFF;
392 keytable[bytes_to_recover[i]] |= CRACKED;
393 }
394
395 }
396 return errors;
397}
398
399
400/**
401 * From dismantling iclass-paper:
402 * Assume that an adversary somehow learns the first 16 bytes of hash2(K_cus ), i.e., y [0] and z [0] .
403 * Then he can simply recover the master custom key K_cus by computing
404 * K_cus = ~DES(z[0] , y[0] ) .
405 *
406 * Furthermore, the adversary is able to verify that he has the correct K cus by
407 * checking whether z [0] = DES enc (K_cus , ~K_cus ).
408 * @param keytable an array (128 bytes) of hash2(kcus)
409 * @param master_key where to put the master key
410 * @return 0 for ok, 1 for failz
411 */
412int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] )
413{
414 des_context ctx_e = {DES_ENCRYPT,{0}};
415
416 uint8_t z_0[8] = {0};
417 uint8_t y_0[8] = {0};
418 uint8_t z_0_rev[8] = {0};
419 uint8_t key64[8] = {0};
420 uint8_t key64_negated[8] = {0};
421 uint8_t result[8] = {0};
422
423 // y_0 and z_0 are the first 16 bytes of the keytable
424 memcpy(y_0,first16bytes,8);
425 memcpy(z_0,first16bytes+8,8);
426
427 // Our DES-implementation uses the standard NIST
428 // format for keys, thus must translate from iclass
429 // format to NIST-format
430 permutekey_rev(z_0, z_0_rev);
431
432 // ~K_cus = DESenc(z[0], y[0])
433 des_setkey_enc( &ctx_e, z_0_rev );
434 des_crypt_ecb(&ctx_e, y_0, key64_negated);
435
436 int i;
437 for(i = 0; i < 8 ; i++)
438 {
439 key64[i] = ~key64_negated[i];
440 }
441
442 // Can we verify that the key is correct?
443 // Once again, key is on iclass-format
444 uint8_t key64_stdformat[8] = {0};
445 permutekey_rev(key64, key64_stdformat);
446
447 des_setkey_enc( &ctx_e, key64_stdformat );
448 des_crypt_ecb(&ctx_e, key64_negated, result);
449 prnlog("\nHigh security custom key (Kcus):");
450 printvar("Std format ", key64_stdformat,8);
451 printvar("Iclass format", key64,8);
452
453 if(master_key != NULL)
454 memcpy(master_key, key64, 8);
455
456 if(memcmp(z_0,result,4) != 0)
457 {
458 prnlog("Failed to verify calculated master key (k_cus)! Something is wrong.");
459 return 1;
460 }else{
461 prnlog("Key verified ok!\n");
462 }
463 return 0;
464}
465/**
466 * @brief Same as bruteforcefile, but uses a an array of dumpdata instead
467 * @param dump
468 * @param dumpsize
469 * @param keytable
470 * @return
471 */
472int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[])
473{
474 uint8_t i;
475 int errors = 0;
476 size_t itemsize = sizeof(dumpdata);
477 clock_t t1 = clock();
478
479 dumpdata* attack = (dumpdata* ) malloc(itemsize);
480
481 for(i = 0 ; i * itemsize < dumpsize ; i++ )
482 {
483 memcpy(attack,dump+i*itemsize, itemsize);
484 errors += bruteforceItem(*attack, keytable);
485 }
486 free(attack);
487 clock_t t2 = clock();
488 float diff = (((float)t2 - (float)t1) / CLOCKS_PER_SEC );
489 prnlog("\nPerformed full crack in %f seconds",diff);
490
491 // Pick out the first 16 bytes of the keytable.
492 // The keytable is now in 16-bit ints, where the upper 8 bits
493 // indicate crack-status. Those must be discarded for the
494 // master key calculation
495 uint8_t first16bytes[16] = {0};
496
497 for(i = 0 ; i < 16 ; i++)
498 {
499 first16bytes[i] = keytable[i] & 0xFF;
500 if(!(keytable[i] & CRACKED))
501 {
502 prnlog("Error, we are missing byte %d, custom key calculation will fail...", i);
503 }
504 }
505 errors += calculateMasterKey(first16bytes, NULL);
506 return errors;
507}
508/**
509 * Perform a bruteforce against a file which has been saved by pm3
510 *
511 * @brief bruteforceFile
512 * @param filename
513 * @return
514 */
515int bruteforceFile(const char *filename, uint16_t keytable[])
516{
517
518 FILE *f = fopen(filename, "rb");
519 if(!f) {
520 prnlog("Failed to read from file '%s'", filename);
521 return 1;
522 }
523
524 fseek(f, 0, SEEK_END);
525 long fsize = ftell(f);
526 fseek(f, 0, SEEK_SET);
527
528 uint8_t *dump = malloc(fsize);
6f101995 529 size_t bytes_read = fread(dump, 1, fsize, f);
3ad48540
MHS
530
531 fclose(f);
532 if (bytes_read < fsize)
533 {
534 prnlog("Error, could only read %d bytes (should be %d)",bytes_read, fsize );
535 }
536 return bruteforceDump(dump,fsize,keytable);
537}
538/**
539 *
540 * @brief Same as above, if you don't care about the returned keytable (results only printed on screen)
541 * @param filename
542 * @return
543 */
544int bruteforceFileNoKeys(const char *filename)
545{
546 uint16_t keytable[128] = {0};
547 return bruteforceFile(filename, keytable);
548}
549
550// ---------------------------------------------------------------------------------
551// ALL CODE BELOW THIS LINE IS PURELY TESTING
552// ---------------------------------------------------------------------------------
553// ----------------------------------------------------------------------------
554// TEST CODE BELOW
555// ----------------------------------------------------------------------------
556
557int _testBruteforce()
558{
559 int errors = 0;
560 if(true){
561 // First test
562 prnlog("[+] Testing crack from dumpfile...");
563
564 /**
565 Expected values for the dumpfile:
566 High Security Key Table
567
568 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
569 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
570 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
571 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
572 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
573 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
574 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
575 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
576
577 **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
578 **/
579 uint16_t keytable[128] = {0};
6f101995
MHS
580
581 //Test a few variants
582 if(fileExists("iclass_dump.bin"))
583 {
584 errors |= bruteforceFile("iclass_dump.bin",keytable);
585 }else if(fileExists("loclass/iclass_dump.bin")){
586 errors |= bruteforceFile("loclass/iclass_dump.bin",keytable);
587 }else if(fileExists("client/loclass/iclass_dump.bin")){
588 errors |= bruteforceFile("client/loclass/iclass_dump.bin",keytable);
589 }else{
590 prnlog("Error: The file iclass_dump.bin was not found!");
591 }
3ad48540
MHS
592 }
593 return errors;
594}
595
596int _test_iclass_key_permutation()
597{
598 uint8_t testcase[8] = {0x6c,0x8d,0x44,0xf9,0x2a,0x2d,0x01,0xbf};
599 uint8_t testcase_output[8] = {0};
600 uint8_t testcase_output_correct[8] = {0x8a,0x0d,0xb9,0x88,0xbb,0xa7,0x90,0xea};
601 uint8_t testcase_output_rev[8] = {0};
602 permutekey(testcase, testcase_output);
603 permutekey_rev(testcase_output, testcase_output_rev);
604
605
606 if(memcmp(testcase_output, testcase_output_correct,8) != 0)
607 {
608 prnlog("Error with iclass key permute!");
609 printarr("testcase_output", testcase_output, 8);
610 printarr("testcase_output_correct", testcase_output_correct, 8);
611 return 1;
612
613 }
614 if(memcmp(testcase, testcase_output_rev, 8) != 0)
615 {
616 prnlog("Error with reverse iclass key permute");
617 printarr("testcase", testcase, 8);
618 printarr("testcase_output_rev", testcase_output_rev, 8);
619 return 1;
620 }
621
622 prnlog("[+] Iclass key permutation OK!");
623 return 0;
624}
625
626int testElite()
627{
628 prnlog("[+] Testing iClass Elite functinality...");
aa41c605
MHS
629 prnlog("[+] Testing hash2");
630 uint8_t k_cus[8] = {0x5B,0x7C,0x62,0xC4,0x91,0xC1,0x1B,0x39};
631
632 /**
633 *Expected:
634 * High Security Key Table
635
63600 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
63710 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
63820 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
63930 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
64040 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
64150 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
64260 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
64370 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
644
645
646
647**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
648 */
649 uint8_t keytable[128] = {0};
650 hash2(k_cus, keytable);
651 printarr_human_readable("Hash2", keytable, 128);
652 if(keytable[3] == 0xA1 && keytable[0x30] == 0xA3 && keytable[0x6F] == 0x95)
653 {
654 prnlog("[+] Hash2 looks fine...");
655 }
656
657 prnlog("[+] Testing key diversification ...");
3ad48540
MHS
658
659 int errors = 0 ;
660 errors +=_test_iclass_key_permutation();
661 errors += _testBruteforce();
662 return errors;
663
664}
665
Impressum, Datenschutz