1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2019 iceman <iceman at iuse.se>
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
9 //-----------------------------------------------------------------------------
10 #include "generator.h"
15 #include <sys/types.h>
18 #include "commonutil.h" //BSWAP_16
19 #include "common.h" //BSWAP_32/64
23 #include "mbedtls/sha1.h"
24 #include "crc16.h" // crc16 ccitt
26 // Implemetation tips:
27 // For each implementation of the algos, I recommend adding a self test for easy "simple unit" tests when Travic CI / Appveyour runs.
28 // See special note for MFC based algos.
30 //------------------------------------
31 // MFU/NTAG PWD/PACK generation stuff
32 // Italian transport system
37 //------------------------------------
38 static void transform_D(uint8_t *ru
) {
40 const uint32_t c_D
[] = {
41 0x6D835AFC, 0x7D15CD97, 0x0942B409, 0x32F9C923, 0xA811FB02, 0x64F121E8,
42 0xD1CC8B4E, 0xE8873E6F, 0x61399BBB, 0xF1B91926, 0xAC661520, 0xA21A31C9,
43 0xD424808D, 0xFE118E07, 0xD18E728D, 0xABAC9E17, 0x18066433, 0x00E18E79,
44 0x65A77305, 0x5AE9E297, 0x11FC628C, 0x7BB3431F, 0x942A8308, 0xB2F8FD20,
45 0x5728B869, 0x30726D5A
51 uint32_t v1
= ((ru
[3] << 24) | (ru
[2] << 16) | (ru
[1] << 8) | ru
[0]) + c_D
[p
++];
52 uint32_t v2
= ((ru
[7] << 24) | (ru
[6] << 16) | (ru
[5] << 8) | ru
[4]) + c_D
[p
++];
53 for (i
= 0; i
< 12; i
+= 2) {
54 uint32_t tempA
= v1
^ v2
;
55 uint32_t t1
= PM3_ROTL(tempA
, v2
& 0x1F) + c_D
[p
++];
56 uint32_t tempB
= v2
^ t1
;
57 uint32_t t2
= PM3_ROTL(tempB
, t1
& 0x1F) + c_D
[p
++];
59 v1
= PM3_ROTL(tempA
, t2
& 0x1F) + c_D
[p
++];
61 v2
= PM3_ROTL(tempB
, v1
& 0x1F) + c_D
[p
++];
66 ru
[1] = (v1
>> 8) & 0xFF;
67 ru
[2] = (v1
>> 16) & 0xFF;
68 ru
[3] = (v1
>> 24) & 0xFF;
70 ru
[5] = (v2
>> 8) & 0xFF;
71 ru
[6] = (v2
>> 16) & 0xFF;
72 ru
[7] = (v2
>> 24) & 0xFF;
75 // Transport system (IT) pwd generation algo nickname A.
76 uint32_t ul_ev1_pwdgenA(uint8_t *uid
) {
78 uint8_t pos
= (uid
[3] ^ uid
[4] ^ uid
[5] ^ uid
[6]) % 32;
80 uint32_t xortable
[] = {
81 0x4f2711c1, 0x07D7BB83, 0x9636EF07, 0xB5F4460E, 0xF271141C, 0x7D7BB038, 0x636EF871, 0x5F4468E3,
82 0x271149C7, 0xD7BB0B8F, 0x36EF8F1E, 0xF446863D, 0x7114947A, 0x7BB0B0F5, 0x6EF8F9EB, 0x44686BD7,
83 0x11494fAF, 0xBB0B075F, 0xEF8F96BE, 0x4686B57C, 0x1494F2F9, 0xB0B07DF3, 0xF8F963E6, 0x686B5FCC,
84 0x494F2799, 0x0B07D733, 0x8F963667, 0x86B5F4CE, 0x94F2719C, 0xB07D7B38, 0xF9636E70, 0x6B5F44E0
87 uint8_t entry
[] = {0x00, 0x00, 0x00, 0x00};
88 uint8_t pwd
[] = {0x00, 0x00, 0x00, 0x00};
90 num_to_bytes(xortable
[pos
], 4, entry
);
92 pwd
[0] = entry
[0] ^ uid
[1] ^ uid
[2] ^ uid
[3];
93 pwd
[1] = entry
[1] ^ uid
[0] ^ uid
[2] ^ uid
[4];
94 pwd
[2] = entry
[2] ^ uid
[0] ^ uid
[1] ^ uid
[5];
95 pwd
[3] = entry
[3] ^ uid
[6];
97 return (uint32_t)bytes_to_num(pwd
, 4);
100 // Amiibo pwd generation algo nickname B. (very simple)
101 uint32_t ul_ev1_pwdgenB(uint8_t *uid
) {
103 uint8_t pwd
[] = {0x00, 0x00, 0x00, 0x00};
105 pwd
[0] = uid
[1] ^ uid
[3] ^ 0xAA;
106 pwd
[1] = uid
[2] ^ uid
[4] ^ 0x55;
107 pwd
[2] = uid
[3] ^ uid
[5] ^ 0xAA;
108 pwd
[3] = uid
[4] ^ uid
[6] ^ 0x55;
109 return (uint32_t)bytes_to_num(pwd
, 4);
112 // Lego Dimension pwd generation algo nickname C.
113 uint32_t ul_ev1_pwdgenC(uint8_t *uid
) {
116 0xffffffff, 0x28ffffff,
117 0x43202963, 0x7279706f,
118 0x74686769, 0x47454c20,
119 0x3032204f, 0xaaaa3431
122 memcpy(base
, uid
, 7);
124 for (int i
= 0; i
< 8; i
++) {
125 pwd
= base
[i
] + ROTR(pwd
, 25) + ROTR(pwd
, 10) - pwd
;
127 return BSWAP_32(pwd
);
130 // XYZ 3d printing pwd generation algo nickname D.
131 uint32_t ul_ev1_pwdgenD(uint8_t *uid
) {
135 uint8_t r
= (uid
[1] + uid
[3] + uid
[5]) & 7;
138 uint8_t ru
[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
139 for (i
= 0; i
< 7; i
++)
140 ru
[(i
+ r
) & 7] = uid
[i
];
145 r
= (ru
[0] + ru
[2] + ru
[4] + ru
[6]) & 3;
149 for (i
= 0; i
< 4; i
++)
150 pwd
= ru
[i
+ r
] + (pwd
<< 8);
152 return BSWAP_32(pwd
);
155 // pack generation for algo 1-3
156 uint16_t ul_ev1_packgenA(uint8_t *uid
) {
157 uint16_t pack
= (uid
[0] ^ uid
[1] ^ uid
[2]) << 8 | (uid
[2] ^ 8);
160 uint16_t ul_ev1_packgenB(uint8_t *uid
) {
163 uint16_t ul_ev1_packgenC(uint8_t *uid
) {
166 uint16_t ul_ev1_packgenD(uint8_t *uid
) {
169 uint8_t r
= (uid
[2] + uid
[5]) & 7; //Rotation offset
170 uint8_t ru
[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Rotated UID
171 for (i
= 0; i
< 7; i
++)
172 ru
[(i
+ r
) & 7] = uid
[i
];
178 for (i
= 0; i
< 8; i
++)
182 return BSWAP_16(p
& 0xFFFF);
185 uint32_t ul_ev1_pwdgen_def(uint8_t *uid
) {
188 uint16_t ul_ev1_packgen_def(uint8_t *uid
) {
192 //------------------------------------
193 // MFC key generation stuff
194 // Each algo implementation should offer two key generation functions.
195 // 1. function that returns all keys
196 // 2. function that returns one key, target sector | block
197 //------------------------------------
199 //------------------------------------
200 // MFC keyfile generation stuff
201 //------------------------------------
203 int mfc_algo_ving_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
204 if (sector
> 15) return PM3_EINVARG
;
205 if (key
== NULL
) return PM3_EINVARG
;
209 int mfc_algo_ving_all(uint8_t *uid
, uint8_t *keys
) {
210 if (keys
== NULL
) return PM3_EINVARG
;
211 for (int keytype
= 0; keytype
< 2; keytype
++) {
212 for (int sector
= 0; sector
< 16; sector
++) {
214 mfc_algo_ving_one(uid
, sector
, keytype
, &key
);
215 num_to_bytes(key
, 6, keys
+ (keytype
* 16 * 6) + (sector
* 6));
222 int mfc_algo_yale_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
223 if (sector
> 15) return PM3_EINVARG
;
224 if (key
== NULL
) return PM3_EINVARG
;
225 if (keytype
> 2) return PM3_EINVARG
;
229 int mfc_algo_yale_all(uint8_t *uid
, uint8_t *keys
) {
230 if (keys
== NULL
) return PM3_EINVARG
;
231 for (int keytype
= 0; keytype
< 2; keytype
++) {
232 for (int sector
= 0; sector
< 16; sector
++) {
234 mfc_algo_yale_one(uid
, sector
, keytype
, &key
);
235 num_to_bytes(key
, 6, keys
+ (keytype
* 16 * 6) + (sector
* 6));
241 // Saflok / Maid UID to key.
242 int mfc_algo_saflok_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
243 if (sector
> 15) return PM3_EINVARG
;
244 if (key
== NULL
) return PM3_EINVARG
;
245 if (keytype
> 2) return PM3_EINVARG
;
249 int mfc_algo_saflok_all(uint8_t *uid
, uint8_t *keys
) {
250 if (keys
== NULL
) return PM3_EINVARG
;
252 for (int keytype
= 0; keytype
< 2; keytype
++) {
253 for (int sector
= 0; sector
< 16; sector
++) {
255 mfc_algo_saflok_one(uid
, sector
, keytype
, &key
);
256 num_to_bytes(key
, 6, keys
+ (keytype
* 16 * 6) + (sector
* 6));
263 int mfc_algo_mizip_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
264 if (sector
> 4) return PM3_EINVARG
;
265 if (key
== NULL
) return PM3_EINVARG
;
266 if (keytype
> 2) return PM3_EINVARG
;
271 *key
= 0xA0A1A2A3A4A5U
;
273 *key
= 0xB4C132439eef;
281 uint64_t xor_tbl_a
[] = {
288 num_to_bytes(xor_tbl_a
[sector
- 1], 6, xor);
291 (uint64_t)(uid
[0] ^ xor[0]) << 40 |
292 (uint64_t)(uid
[1] ^ xor[1]) << 32 |
293 (uint64_t)(uid
[2] ^ xor[2]) << 24 |
294 (uint64_t)(uid
[3] ^ xor[3]) << 16 |
295 (uint64_t)(uid
[0] ^ xor[4]) << 8 |
296 (uint64_t)(uid
[1] ^ xor[5])
300 uint64_t xor_tbl_b
[] = {
308 num_to_bytes(xor_tbl_b
[sector
- 1], 6, xor);
311 (uint64_t)(uid
[2] ^ xor[0]) << 40 |
312 (uint64_t)(uid
[3] ^ xor[1]) << 32 |
313 (uint64_t)(uid
[0] ^ xor[2]) << 24 |
314 (uint64_t)(uid
[1] ^ xor[3]) << 16 |
315 (uint64_t)(uid
[2] ^ xor[4]) << 8 |
316 (uint64_t)(uid
[3] ^ xor[5])
323 // returns all Mifare Mini (MFM) 10 keys.
324 // keys must have 5*2*6 = 60bytes space
325 int mfc_algo_mizip_all(uint8_t *uid
, uint8_t *keys
) {
326 if (keys
== NULL
) return PM3_EINVARG
;
328 for (int keytype
= 0; keytype
< 2; keytype
++) {
329 for (int sector
= 0; sector
< 5; sector
++) {
331 mfc_algo_mizip_one(uid
, sector
, keytype
, &key
);
332 num_to_bytes(key
, 6, keys
+ (keytype
* 5 * 6) + (sector
* 6));
338 // Disney Infinity algo
339 int mfc_algo_di_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
340 if (sector
> 4) return PM3_EINVARG
;
341 if (key
== NULL
) return PM3_EINVARG
;
345 0x0A, 0x14, 0xFD, 0x05, 0x07, 0xFF, 0x4B, 0xCD,
346 0x02, 0x6B, 0xA8, 0x3F, 0x0A, 0x3B, 0x89, 0xA9,
347 uid
[0], uid
[1], uid
[2], uid
[3], uid
[4], uid
[5], uid
[6],
348 0x28, 0x63, 0x29, 0x20, 0x44, 0x69, 0x73, 0x6E,
349 0x65, 0x79, 0x20, 0x32, 0x30, 0x31, 0x33
352 mbedtls_sha1(input
, sizeof(input
), hash
);
355 (uint64_t)hash
[3] << 40 |
356 (uint64_t)hash
[2] << 32 |
357 (uint64_t)hash
[1] << 24 |
358 (uint64_t)hash
[0] << 16 |
359 (uint64_t)hash
[7] << 8 |
365 int mfc_algo_di_all(uint8_t *uid
, uint8_t *keys
) {
366 if (keys
== NULL
) return PM3_EINVARG
;
367 for (int keytype
= 0; keytype
< 2; keytype
++) {
368 for (int sector
= 0; sector
< 5; sector
++) {
370 mfc_algo_di_one(uid
, sector
, keytype
, &key
);
371 num_to_bytes(key
, 6, keys
+ (keytype
* 5 * 6) + (sector
* 6));
378 static uint64_t sky_crc64_like(uint64_t result
, uint8_t sector
) {
379 #define SKY_POLY UINT64_C(0x42f0e1eba9ea3693)
380 #define SKY_TOP UINT64_C(0x800000000000)
381 result
^= (uint64_t)sector
<< 40;
382 for (int i
= 0; i
< 8; i
++) {
383 result
= (result
& SKY_TOP
) ? (result
<< 1) ^ SKY_POLY
: result
<< 1;
387 int mfc_algo_sky_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
389 #define SKY_KEY_MASK 0xFFFFFFFFFFFF
391 if (sector
> 15) return PM3_EINVARG
;
392 if (key
== NULL
) return PM3_EINVARG
;
394 if (sector
== 0 && keytype
== 0) {
395 *key
= 0x4B0B20107CCB;
399 *key
= 0x000000000000;
404 uint64_t hash
= 0x9AE903260CC4;
405 for (int i
= 0; i
< 4; i
++) {
406 hash
= sky_crc64_like(hash
, uid
[i
]);
409 uint64_t sectorhash
= sky_crc64_like(hash
, sector
);
410 *key
= BSWAP_64(sectorhash
& SKY_KEY_MASK
) >> 16;
413 int mfc_algo_sky_all(uint8_t *uid
, uint8_t *keys
) {
414 if (keys
== NULL
) return PM3_EINVARG
;
415 for (int keytype
= 0; keytype
< 2; keytype
++) {
416 for (int sector
= 0; sector
< 16; sector
++) {
418 mfc_algo_sky_one(uid
, sector
, keytype
, &key
);
419 num_to_bytes(key
, 6, keys
+ (keytype
* 16 * 6) + (sector
* 6));
425 // LF T55x7 White gun cloner algo
426 uint32_t lf_t55xx_white_pwdgen(uint32_t id
) {
427 uint32_t r1
= rotl(id
& 0x000000ec, 8);
428 uint32_t r2
= rotl(id
& 0x86000000, 16);
429 uint32_t pwd
= 0x10303;
430 pwd
+= ((id
& 0x86ee00ec) ^ r1
^ r2
);
434 // Gallagher Desfire Key Diversification Input for Cardax Card Data Application
435 int mfdes_kdf_input_gallagher(uint8_t *uid
, uint8_t uidLen
, uint8_t keyNo
, uint32_t aid
, uint8_t *kdfInputOut
, uint8_t *kdfInputLen
) {
436 if (uid
== NULL
|| (uidLen
!= 4 && uidLen
!= 7) || keyNo
> 2 || kdfInputOut
== NULL
|| kdfInputLen
== NULL
) {
438 PrintAndLogEx(WARNING
, "Invalid arguments");
443 // Verify the AppID is a valid Gallagher AppID
444 if ((aid
& 0xF0FFFF) != 0x2081F4) {
446 PrintAndLogEx(WARNING
, "Invalid Gallagher AID %06X", aid
);
452 // If the keyNo == 1, then omit the UID.
454 if (*kdfInputLen
< (4 + uidLen
)) {
458 memcpy(kdfInputOut
, uid
, uidLen
);
460 } else if (*kdfInputLen
< 4) {
464 kdfInputOut
[len
++] = keyNo
;
466 kdfInputOut
[len
++] = aid
& 0xff;
467 kdfInputOut
[len
++] = (aid
>> 8) & 0xff;
468 kdfInputOut
[len
++] = (aid
>> 16) & 0xff;
475 int mfc_generate4b_nuid(uint8_t *uid
, uint8_t *nuid
) {
479 compute_crc(CRC_14443_A
, uid
, 3, &b1
, &b2
);
480 nuid
[0] = (b2
& 0xE0) | 0xF;
484 crc
= crc16_fast(&uid
[3], 4, reflect16(crc
), true, true);
485 nuid
[2] = (crc
>> 8) & 0xFF ;
486 nuid
[3] = crc
& 0xFF;
490 int mfc_algo_touch_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
491 if (uid
== NULL
) return PM3_EINVARG
;
492 if (key
== NULL
) return PM3_EINVARG
;
495 (uint64_t)(uid
[1] ^ uid
[2] ^ uid
[3]) << 40 |
496 (uint64_t)uid
[1] << 32 |
497 (uint64_t)uid
[2] << 24 |
498 (uint64_t)(((uid
[0] + uid
[1] + uid
[2] + uid
[3]) % 0x100) ^ uid
[3]) << 16 |
505 //------------------------------------
507 //------------------------------------
508 int generator_selftest(void) {
510 #define NUM_OF_TEST 6
512 PrintAndLogEx(INFO
, "PWD / KEY generator selftest");
513 PrintAndLogEx(INFO
, "----------------------------");
515 uint8_t testresult
= 0;
517 uint8_t uid1
[] = {0x04, 0x11, 0x12, 0x11, 0x12, 0x11, 0x10};
518 uint32_t pwd1
= ul_ev1_pwdgenA(uid1
);
519 bool success
= (pwd1
== 0x8432EB17);
523 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid1
, 7), pwd1
, success
? "OK" : "->8432EB17<-");
525 uint8_t uid2
[] = {0x04, 0x1f, 0x98, 0xea, 0x1e, 0x3e, 0x81};
526 uint32_t pwd2
= ul_ev1_pwdgenB(uid2
);
527 success
= (pwd2
== 0x5fd37eca);
530 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid2
, 7), pwd2
, success
? "OK" : "->5fd37eca<--");
532 uint8_t uid3
[] = {0x04, 0x62, 0xB6, 0x8A, 0xB4, 0x42, 0x80};
533 uint32_t pwd3
= ul_ev1_pwdgenC(uid3
);
534 success
= (pwd3
== 0x5a349515);
537 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid3
, 7), pwd3
, success
? "OK" : "->5a349515<--");
539 uint8_t uid4
[] = {0x04, 0xC5, 0xDF, 0x4A, 0x6D, 0x51, 0x80};
540 uint32_t pwd4
= ul_ev1_pwdgenD(uid4
);
541 success
= (pwd4
== 0x72B1EC61);
544 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid4
, 7), pwd4
, success
? "OK" : "->72B1EC61<--");
546 // uint8_t uid5[] = {0x11, 0x22, 0x33, 0x44};
547 // uint64_t key1 = mfc_algo_a(uid5);
548 // success = (key1 == 0xD1E2AA68E39A);
549 // PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid5, 4), key1, success ? "OK" : "->D1E2AA68E39A<--");
551 uint8_t uid6
[] = {0x74, 0x57, 0xCA, 0xA9};
553 mfc_algo_sky_one(uid6
, 15, 0, &key6
);
554 success
= (key6
== 0x82c7e64bc565);
557 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %"PRIx64
" - %s", sprint_hex(uid6
, 4), key6
, success
? "OK" : "->82C7E64BC565<--");
560 uint32_t lf_id
= lf_t55xx_white_pwdgen(0x00000080);
561 success
= (lf_id
== 0x00018383);
564 PrintAndLogEx(success
? SUCCESS
: WARNING
, "ID | 0x00000080 | %08"PRIx32
" - %s", lf_id
, success
? "OK" : "->00018383<--");
566 PrintAndLogEx(SUCCESS
, "------------------- Selftest %s", (testresult
== NUM_OF_TEST
) ? "OK" : "fail");