1 /*****************************************************************************
4 * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
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.
10 * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
12 *****************************************************************************
14 * This file is part of loclass. It is a reconstructon of the cipher engine
15 * used in iClass, and RFID techology.
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".
21 * Copyright (C) 2014 Martin Holst Swende
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, or, at your option, any later version.
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.
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/>.
36 ****************************************************************************/
43 #include "util_posix.h"
44 #include "cipherutils.h"
47 #include "elite_crack.h"
48 #include "fileutils.h"
49 #include "mbedtls/des.h"
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
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.
72 void permutekey(uint8_t key
[8], uint8_t dest
[8])
76 for(i
= 0 ; i
< 8 ; i
++)
78 dest
[i
] = (((key
[7] & (0x80 >> i
)) >> (7-i
)) << 7) |
79 (((key
[6] & (0x80 >> i
)) >> (7-i
)) << 6) |
80 (((key
[5] & (0x80 >> i
)) >> (7-i
)) << 5) |
81 (((key
[4] & (0x80 >> i
)) >> (7-i
)) << 4) |
82 (((key
[3] & (0x80 >> i
)) >> (7-i
)) << 3) |
83 (((key
[2] & (0x80 >> i
)) >> (7-i
)) << 2) |
84 (((key
[1] & (0x80 >> i
)) >> (7-i
)) << 1) |
85 (((key
[0] & (0x80 >> i
)) >> (7-i
)) << 0);
91 * Permutes a key from iclass specific format to NIST format
92 * @brief permutekey_rev
96 void permutekey_rev(uint8_t key
[8], uint8_t dest
[8])
99 for(i
= 0 ; i
< 8 ; i
++)
101 dest
[7-i
] = (((key
[0] & (0x80 >> i
)) >> (7-i
)) << 7) |
102 (((key
[1] & (0x80 >> i
)) >> (7-i
)) << 6) |
103 (((key
[2] & (0x80 >> i
)) >> (7-i
)) << 5) |
104 (((key
[3] & (0x80 >> i
)) >> (7-i
)) << 4) |
105 (((key
[4] & (0x80 >> i
)) >> (7-i
)) << 3) |
106 (((key
[5] & (0x80 >> i
)) >> (7-i
)) << 2) |
107 (((key
[6] & (0x80 >> i
)) >> (7-i
)) << 1) |
108 (((key
[7] & (0x80 >> i
)) >> (7-i
)) << 0);
113 * Helper function for hash1
118 uint8_t rr(uint8_t val
)
120 return val
>> 1 | (( val
& 1) << 7);
123 * Helper function for hash1
128 uint8_t rl(uint8_t val
)
130 return val
<< 1 | (( val
& 0x80) >> 7);
133 * Helper function for hash1
138 uint8_t swap(uint8_t val
)
140 return ((val
>> 4) & 0xFF) | ((val
&0xFF) << 4);
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
149 void hash1(uint8_t csn
[] , uint8_t k
[])
151 k
[0] = csn
[0]^csn
[1]^csn
[2]^csn
[3]^csn
[4]^csn
[5]^csn
[6]^csn
[7];
152 k
[1] = csn
[0]+csn
[1]+csn
[2]+csn
[3]+csn
[4]+csn
[5]+csn
[6]+csn
[7];
153 k
[2] = rr(swap( csn
[2]+k
[1] ));
154 k
[3] = rl(swap( csn
[3]+k
[0] ));
155 k
[4] = ~rr( csn
[4]+k
[2] )+1;
156 k
[5] = ~rl( csn
[5]+k
[3] )+1;
157 k
[6] = rr( csn
[6]+(k
[4]^0x3c) );
158 k
[7] = rl( csn
[7]+(k
[5]^0xc3) );
160 for(i
= 7; i
>=0; i
--)
164 Definition 14. Define the rotate key function rk : (F 82 ) 8 × N → (F 82 ) 8 as
165 rk(x [0] . . . x [7] , 0) = x [0] . . . x [7]
166 rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n)
168 void rk(uint8_t *key
, uint8_t n
, uint8_t *outp_key
)
171 memcpy(outp_key
, key
, 8);
176 for(j
=0; j
< 8 ; j
++)
177 outp_key
[j
] = rl(outp_key
[j
]);
182 static mbedtls_des_context ctx_enc
= { {0} };
183 static mbedtls_des_context ctx_dec
= { {0} };
185 void desdecrypt_iclass(uint8_t *iclass_key
, uint8_t *input
, uint8_t *output
)
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
);
192 void desencrypt_iclass(uint8_t *iclass_key
, uint8_t *input
, uint8_t *output
)
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
);
201 * @brief Insert uint8_t[8] custom master key to calculate hash2 and return key_select.
202 * @param key unpermuted custom key
204 * @param key_sel output key_sel=h[hash1[i]]
206 void hash2(uint8_t *key64
, uint8_t *outp_keytable
)
210 * High Security Key Table
212 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
213 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
214 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
215 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
216 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
217 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
218 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
219 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
221 **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ******/
222 uint8_t key64_negated
[8] = {0};
223 uint8_t z
[8][8]={{0},{0}};
224 uint8_t temp_output
[8]={0};
225 //calculate complement of key
228 key64_negated
[i
]= ~key64
[i
];
230 // Once again, key is on iclass-format
231 desencrypt_iclass(key64
, key64_negated
, z
[0]);
233 prnlog("\nHigh security custom key (Kcus):");
234 printvar("z0 ", z
[0],8);
236 uint8_t y
[8][8]={{0},{0}};
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);
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] )
250 desdecrypt_iclass(temp_output
,z
[i
-1], z
[i
]);
251 desencrypt_iclass(temp_output
,y
[i
-1], y
[i
]);
254 if(outp_keytable
!= NULL
)
256 for(i
= 0 ; i
< 8 ; i
++)
258 memcpy(outp_keytable
+i
*16,y
[i
],8);
259 memcpy(outp_keytable
+8+i
*16,z
[i
],8);
263 printarr_human_readable("hash2", outp_keytable
,128);
268 * @brief Reads data from the iclass-reader-attack dump file.
269 * @param dump, data from a iclass reader attack dump. The format of the dumpdata is expected to be as follows:
270 * <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC><8 byte HASH1><1 byte NUM_BYTES_TO_RECOVER><3 bytes BYTES_TO_RECOVER>
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
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...
283 int _readFromDump(uint8_t dump
[], dumpdata
* item
, uint8_t i
)
285 size_t itemsize
= sizeof(dumpdata
);
286 //dumpdata item = {0};
287 memcpy(item
,dump
+i
*itemsize
, itemsize
);
290 printvar("csn", item
->csn
,8);
291 printvar("cc_nr", item
->cc_nr
,12);
292 printvar("mac", item
->mac
,4);
297 static uint32_t startvalue
= 0;
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.
305 * @param dump The dumpdata from iclass reader attack.
306 * @param keytable where to write found values.
309 int bruteforceItem(dumpdata item
, uint16_t keytable
[]) {
311 uint8_t key_sel_p
[8] = { 0 };
312 uint8_t div_key
[8] = {0};
314 uint8_t key_sel
[8] = {0};
315 uint8_t calculated_MAC
[4] = { 0 };
317 //Get the key index (hash1)
318 uint8_t key_index
[8] = {0};
319 hash1(item
.csn
, key_index
);
321 printvar("CSN ", item
.csn
, 8);
322 printvar("HASH1", key_index
, 8);
325 * Determine which bytes to retrieve. A hash is typically
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...)
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.
336 uint8_t bytes_to_recover
[3] = {0};
337 uint8_t numbytes_to_recover
= 0;
339 for (int i
= 0; i
< 8; i
++) {
340 if (keytable
[key_index
[i
]] & (CRACKED
| BEING_CRACKED
)) continue;
341 if (numbytes_to_recover
== 3) {
342 prnlog("The CSN requires > 3 byte bruteforce, not supported");
343 //Before we exit, reset the 'BEING_CRACKED' to zero
344 keytable
[bytes_to_recover
[0]] &= ~BEING_CRACKED
;
345 keytable
[bytes_to_recover
[1]] &= ~BEING_CRACKED
;
346 keytable
[bytes_to_recover
[2]] &= ~BEING_CRACKED
;
349 bytes_to_recover
[numbytes_to_recover
++] = key_index
[i
];
350 keytable
[key_index
[i
]] |= BEING_CRACKED
;
355 *A uint32 has room for 4 bytes, we'll only need 24 of those bits to bruteforce up to three bytes,
357 uint32_t brute
= startvalue
;
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
366 uint32_t endmask
= 1 << 8*numbytes_to_recover
;
368 for (int i
= 0; i
< numbytes_to_recover
; i
++) {
369 prnlog("Bruteforcing byte %d", bytes_to_recover
[i
]);
372 while (!found
&& !(brute
& endmask
)) {
374 //Update the keytable with the brute-values
375 for(int i
= 0 ; i
< numbytes_to_recover
; i
++) {
376 keytable
[bytes_to_recover
[i
]] &= 0xFF00;
377 keytable
[bytes_to_recover
[i
]] |= ((brute
>> (i
*8)) & 0xFF);
380 // Piece together the key
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;
390 //Permute from iclass format to standard format
391 permutekey_rev(key_sel
,key_sel_p
);
393 diversifyKey(item
.csn
, key_sel_p
, div_key
);
395 doMAC(item
.cc_nr
, div_key
,calculated_MAC
);
397 if (memcmp(calculated_MAC
, item
.mac
, 4) == 0) {
398 for (int i
= 0; i
< numbytes_to_recover
; i
++)
399 prnlog("=> %d: 0x%02x", bytes_to_recover
[i
], 0xFF & keytable
[bytes_to_recover
[i
]]);
404 if((brute
& 0xFFFF) == 0)
406 printf("%d",(brute
>> 16) & 0xFF);
412 prnlog("\nFailed to recover %d bytes", numbytes_to_recover
);
414 //Before we exit, reset the 'BEING_CRACKED' to zero
415 for (int i
= 0; i
< numbytes_to_recover
; i
++) {
416 keytable
[bytes_to_recover
[i
]] &= ~BEING_CRACKED
;
419 for (int i
= 0; i
< numbytes_to_recover
; i
++) {
420 keytable
[bytes_to_recover
[i
]] &= ~BEING_CRACKED
;
421 keytable
[bytes_to_recover
[i
]] |= CRACKED
;
431 * From dismantling iclass-paper:
432 * Assume that an adversary somehow learns the first 16 bytes of hash2(K_cus ), i.e., y [0] and z [0] .
433 * Then he can simply recover the master custom key K_cus by computing
434 * K_cus = ~DES(z[0] , y[0] ) .
436 * Furthermore, the adversary is able to verify that he has the correct K cus by
437 * checking whether z [0] = DES enc (K_cus , ~K_cus ).
438 * @param keytable an array (128 bytes) of hash2(kcus)
439 * @param master_key where to put the master key
440 * @return 0 for ok, 1 for failz
442 int calculateMasterKey(uint8_t first16bytes
[], uint64_t master_key
[] )
444 mbedtls_des_context ctx_e
= { {0} };
446 uint8_t z_0
[8] = {0};
447 uint8_t y_0
[8] = {0};
448 uint8_t z_0_rev
[8] = {0};
449 uint8_t key64
[8] = {0};
450 uint8_t key64_negated
[8] = {0};
451 uint8_t result
[8] = {0};
453 // y_0 and z_0 are the first 16 bytes of the keytable
454 memcpy(y_0
,first16bytes
,8);
455 memcpy(z_0
,first16bytes
+8,8);
457 // Our DES-implementation uses the standard NIST
458 // format for keys, thus must translate from iclass
459 // format to NIST-format
460 permutekey_rev(z_0
, z_0_rev
);
462 // ~K_cus = DESenc(z[0], y[0])
463 mbedtls_des_setkey_enc( &ctx_e
, z_0_rev
);
464 mbedtls_des_crypt_ecb(&ctx_e
, y_0
, key64_negated
);
467 for(i
= 0; i
< 8 ; i
++)
469 key64
[i
] = ~key64_negated
[i
];
472 // Can we verify that the key is correct?
473 // Once again, key is on iclass-format
474 uint8_t key64_stdformat
[8] = {0};
475 permutekey_rev(key64
, key64_stdformat
);
477 mbedtls_des_setkey_enc( &ctx_e
, key64_stdformat
);
478 mbedtls_des_crypt_ecb(&ctx_e
, key64_negated
, result
);
479 prnlog("\nHigh security custom key (Kcus):");
480 printvar("Std format ", key64_stdformat
,8);
481 printvar("Iclass format", key64
,8);
483 if(master_key
!= NULL
)
484 memcpy(master_key
, key64
, 8);
486 if(memcmp(z_0
,result
,4) != 0)
488 prnlog("Failed to verify calculated master key (k_cus)! Something is wrong.");
491 prnlog("Key verified ok!\n");
496 * @brief Same as bruteforcefile, but uses a an array of dumpdata instead
502 int bruteforceDump(uint8_t dump
[], size_t dumpsize
, uint16_t keytable
[])
506 size_t itemsize
= sizeof(dumpdata
);
507 uint64_t t1
= msclock();
509 dumpdata
* attack
= (dumpdata
* ) malloc(itemsize
);
511 for(i
= 0 ; i
* itemsize
< dumpsize
; i
++ )
513 memcpy(attack
,dump
+i
*itemsize
, itemsize
);
514 errors
+= bruteforceItem(*attack
, keytable
);
518 float diff
= (float)t1
/ 1000.0;
519 prnlog("\nPerformed full crack in %f seconds", diff
);
521 // Pick out the first 16 bytes of the keytable.
522 // The keytable is now in 16-bit ints, where the upper 8 bits
523 // indicate crack-status. Those must be discarded for the
524 // master key calculation
525 uint8_t first16bytes
[16] = {0};
527 for (int i
= 0; i
< 16; i
++) {
528 first16bytes
[i
] = keytable
[i
] & 0xFF;
529 if (!(keytable
[i
] & CRACKED
)) {
530 prnlog("Error, we are missing byte %d, cannot calculate custom key.", i
);
534 errors
+= calculateMasterKey(first16bytes
, NULL
);
538 * Perform a bruteforce against a file which has been saved by pm3
540 * @brief bruteforceFile
544 int bruteforceFile(const char *filename
, uint16_t keytable
[])
547 FILE *f
= fopen(filename
, "rb");
549 prnlog("Failed to read from file '%s'", filename
);
553 fseek(f
, 0, SEEK_END
);
554 long fsize
= ftell(f
);
555 fseek(f
, 0, SEEK_SET
);
558 prnlog("Error, when getting fsize");
563 uint8_t *dump
= malloc(fsize
);
564 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
567 if (bytes_read
< fsize
) {
568 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
571 uint8_t res
= bruteforceDump(dump
,fsize
,keytable
);
577 * @brief Same as above, if you don't care about the returned keytable (results only printed on screen)
581 int bruteforceFileNoKeys(const char *filename
)
583 uint16_t keytable
[128] = {0};
584 return bruteforceFile(filename
, keytable
);
587 // ---------------------------------------------------------------------------------
588 // ALL CODE BELOW THIS LINE IS PURELY TESTING
589 // ---------------------------------------------------------------------------------
590 // ----------------------------------------------------------------------------
592 // ----------------------------------------------------------------------------
594 int _testBruteforce()
599 prnlog("[+] Testing crack from dumpfile...");
602 Expected values for the dumpfile:
603 High Security Key Table
605 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
606 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
607 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
608 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
609 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
610 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
611 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
612 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
614 **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
616 uint16_t keytable
[128] = {0};
618 //Test a few variants
619 if(fileExists("iclass_dump.bin"))
621 errors
|= bruteforceFile("iclass_dump.bin",keytable
);
622 }else if(fileExists("loclass/iclass_dump.bin")){
623 errors
|= bruteforceFile("loclass/iclass_dump.bin",keytable
);
624 }else if(fileExists("client/loclass/iclass_dump.bin")){
625 errors
|= bruteforceFile("client/loclass/iclass_dump.bin",keytable
);
627 prnlog("Error: The file iclass_dump.bin was not found!");
633 int _test_iclass_key_permutation()
635 uint8_t testcase
[8] = {0x6c,0x8d,0x44,0xf9,0x2a,0x2d,0x01,0xbf};
636 uint8_t testcase_output
[8] = {0};
637 uint8_t testcase_output_correct
[8] = {0x8a,0x0d,0xb9,0x88,0xbb,0xa7,0x90,0xea};
638 uint8_t testcase_output_rev
[8] = {0};
639 permutekey(testcase
, testcase_output
);
640 permutekey_rev(testcase_output
, testcase_output_rev
);
643 if(memcmp(testcase_output
, testcase_output_correct
,8) != 0)
645 prnlog("Error with iclass key permute!");
646 printarr("testcase_output", testcase_output
, 8);
647 printarr("testcase_output_correct", testcase_output_correct
, 8);
651 if(memcmp(testcase
, testcase_output_rev
, 8) != 0)
653 prnlog("Error with reverse iclass key permute");
654 printarr("testcase", testcase
, 8);
655 printarr("testcase_output_rev", testcase_output_rev
, 8);
659 prnlog("[+] Iclass key permutation OK!");
664 uint8_t csn
[8]= {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0};
667 uint8_t expected
[8] = {0x7E,0x72,0x2F,0x40,0x2D,0x02,0x51,0x42};
668 if(memcmp(k
,expected
,8) != 0)
670 prnlog("Error with hash1!");
671 printarr("calculated", k
, 8);
672 printarr("expected", expected
, 8);
680 prnlog("[+] Testing iClass Elite functinality...");
681 prnlog("[+] Testing hash2");
682 uint8_t k_cus
[8] = {0x5B,0x7C,0x62,0xC4,0x91,0xC1,0x1B,0x39};
686 * High Security Key Table
688 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
689 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
690 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
691 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
692 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
693 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
694 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
695 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
699 **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
701 uint8_t keytable
[128] = {0};
702 hash2(k_cus
, keytable
);
703 printarr_human_readable("Hash2", keytable
, 128);
704 if(keytable
[3] == 0xA1 && keytable
[0x30] == 0xA3 && keytable
[0x6F] == 0x95)
706 prnlog("[+] Hash2 looks fine...");
710 prnlog("[+] Testing hash1...");
711 errors
+= _testHash1();
712 prnlog("[+] Testing key diversification ...");
713 errors
+=_test_iclass_key_permutation();
714 errors
+= _testBruteforce();