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