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