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