1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
17 //-----------------------------------------------------------------------------
18 #include "generator.h"
23 #include <sys/types.h>
26 #include "commonutil.h" //BSWAP_16
27 #include "common.h" //BSWAP_32/64
30 #include "crc16.h" // crc16 ccitt
31 #include "mbedtls/sha1.h"
32 #include "mbedtls/md5.h"
33 #include "mbedtls/cmac.h"
34 #include "mbedtls/cipher.h"
35 #include "mbedtls/md.h"
39 # define prnt(args...) PrintAndLogEx(DEBUG, ## args );
42 # define prnt Dbprintf
45 // Implementation tips:
46 // For each implementation of the algos, I recommend adding a self test for easy "simple unit" tests when Travis CI / Appveyor runs.
47 // See special note for MFC based algos.
49 //------------------------------------
50 // MFU/NTAG PWD/PACK generation stuff
51 // Italian transport system
56 //------------------------------------
57 static void transform_D(uint8_t *ru
) {
59 const uint32_t c_D
[] = {
60 0x6D835AFC, 0x7D15CD97, 0x0942B409, 0x32F9C923, 0xA811FB02, 0x64F121E8,
61 0xD1CC8B4E, 0xE8873E6F, 0x61399BBB, 0xF1B91926, 0xAC661520, 0xA21A31C9,
62 0xD424808D, 0xFE118E07, 0xD18E728D, 0xABAC9E17, 0x18066433, 0x00E18E79,
63 0x65A77305, 0x5AE9E297, 0x11FC628C, 0x7BB3431F, 0x942A8308, 0xB2F8FD20,
64 0x5728B869, 0x30726D5A
70 uint32_t v1
= ((ru
[3] << 24) | (ru
[2] << 16) | (ru
[1] << 8) | ru
[0]) + c_D
[p
++];
71 uint32_t v2
= ((ru
[7] << 24) | (ru
[6] << 16) | (ru
[5] << 8) | ru
[4]) + c_D
[p
++];
72 for (i
= 0; i
< 12; i
+= 2) {
73 uint32_t tempA
= v1
^ v2
;
74 uint32_t t1
= PM3_ROTL(tempA
, v2
& 0x1F) + c_D
[p
++];
75 uint32_t tempB
= v2
^ t1
;
76 uint32_t t2
= PM3_ROTL(tempB
, t1
& 0x1F) + c_D
[p
++];
78 v1
= PM3_ROTL(tempA
, t2
& 0x1F) + c_D
[p
++];
80 v2
= PM3_ROTL(tempB
, v1
& 0x1F) + c_D
[p
++];
85 ru
[1] = (v1
>> 8) & 0xFF;
86 ru
[2] = (v1
>> 16) & 0xFF;
87 ru
[3] = (v1
>> 24) & 0xFF;
89 ru
[5] = (v2
>> 8) & 0xFF;
90 ru
[6] = (v2
>> 16) & 0xFF;
91 ru
[7] = (v2
>> 24) & 0xFF;
94 // Transport system (IT) pwd generation algo nickname A.
95 uint32_t ul_ev1_pwdgenA(const uint8_t *uid
) {
97 uint8_t pos
= (uid
[3] ^ uid
[4] ^ uid
[5] ^ uid
[6]) % 32;
99 uint32_t xortable
[] = {
100 0x4f2711c1, 0x07D7BB83, 0x9636EF07, 0xB5F4460E, 0xF271141C, 0x7D7BB038, 0x636EF871, 0x5F4468E3,
101 0x271149C7, 0xD7BB0B8F, 0x36EF8F1E, 0xF446863D, 0x7114947A, 0x7BB0B0F5, 0x6EF8F9EB, 0x44686BD7,
102 0x11494fAF, 0xBB0B075F, 0xEF8F96BE, 0x4686B57C, 0x1494F2F9, 0xB0B07DF3, 0xF8F963E6, 0x686B5FCC,
103 0x494F2799, 0x0B07D733, 0x8F963667, 0x86B5F4CE, 0x94F2719C, 0xB07D7B38, 0xF9636E70, 0x6B5F44E0
106 uint8_t entry
[] = {0x00, 0x00, 0x00, 0x00};
107 uint8_t pwd
[] = {0x00, 0x00, 0x00, 0x00};
109 num_to_bytes(xortable
[pos
], 4, entry
);
111 pwd
[0] = entry
[0] ^ uid
[1] ^ uid
[2] ^ uid
[3];
112 pwd
[1] = entry
[1] ^ uid
[0] ^ uid
[2] ^ uid
[4];
113 pwd
[2] = entry
[2] ^ uid
[0] ^ uid
[1] ^ uid
[5];
114 pwd
[3] = entry
[3] ^ uid
[6];
116 return (uint32_t)bytes_to_num(pwd
, 4);
119 // Amiibo pwd generation algo nickname B. (very simple)
120 uint32_t ul_ev1_pwdgenB(const uint8_t *uid
) {
122 uint8_t pwd
[] = {0x00, 0x00, 0x00, 0x00};
124 pwd
[0] = uid
[1] ^ uid
[3] ^ 0xAA;
125 pwd
[1] = uid
[2] ^ uid
[4] ^ 0x55;
126 pwd
[2] = uid
[3] ^ uid
[5] ^ 0xAA;
127 pwd
[3] = uid
[4] ^ uid
[6] ^ 0x55;
128 return (uint32_t)bytes_to_num(pwd
, 4);
131 // Lego Dimension pwd generation algo nickname C.
132 uint32_t ul_ev1_pwdgenC(const uint8_t *uid
) {
135 0xffffffff, 0x28ffffff,
136 0x43202963, 0x7279706f,
137 0x74686769, 0x47454c20,
138 0x3032204f, 0xaaaa3431
141 memcpy(base
, uid
, 7);
143 for (int i
= 0; i
< 8; i
++) {
144 pwd
= base
[i
] + ROTR(pwd
, 25) + ROTR(pwd
, 10) - pwd
;
146 return BSWAP_32(pwd
);
149 // XYZ 3d printing pwd generation algo nickname D.
150 uint32_t ul_ev1_pwdgenD(const uint8_t *uid
) {
154 uint8_t r
= (uid
[1] + uid
[3] + uid
[5]) & 7;
157 uint8_t ru
[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
158 for (i
= 0; i
< 7; i
++)
159 ru
[(i
+ r
) & 7] = uid
[i
];
164 r
= (ru
[0] + ru
[2] + ru
[4] + ru
[6]) & 3;
168 for (i
= 0; i
< 4; i
++)
169 pwd
= ru
[i
+ r
] + (pwd
<< 8);
171 return BSWAP_32(pwd
);
174 // AIR purifier Xiaomi
175 uint32_t ul_ev1_pwdgenE(const uint8_t *uid
) {
176 uint8_t hash
[20] = {0};
177 mbedtls_sha1(uid
, 7, hash
);
179 pwd
|= (hash
[ hash
[0] % 20 ]) << 24 ;
180 pwd
|= (hash
[(hash
[0] + 5) % 20 ]) << 16;
181 pwd
|= (hash
[(hash
[0] + 13) % 20 ]) << 8;
182 pwd
|= (hash
[(hash
[0] + 17) % 20 ]);
186 // NDEF tools format password generator
187 uint32_t ul_ev1_pwdgenF(const uint8_t *uid
) {
188 uint8_t hash
[16] = {0};;
189 mbedtls_md5(uid
, 7, hash
);
191 pwd
|= hash
[0] << 24;
192 pwd
|= hash
[1] << 16;
198 // Solution from @atc1441
199 // https://gist.github.com/atc1441/41af75048e4c22af1f5f0d4c1d94bb56
200 // Philips Sonicare toothbrush NFC head
201 uint32_t ul_ev1_pwdgenG(const uint8_t *uid
, const uint8_t *mfg
) {
203 init_table(CRC_PHILIPS
);
205 uint32_t crc1
= crc16_philips(uid
, 7);
207 uint32_t crc2
= crc16_fast(mfg
, 10, crc1
, false, false);
209 return (BSWAP_16(crc2
) << 16 | BSWAP_16(crc1
));
212 // pack generation for algo 1-3
213 uint16_t ul_ev1_packgenA(const uint8_t *uid
) {
214 uint16_t pack
= (uid
[0] ^ uid
[1] ^ uid
[2]) << 8 | (uid
[2] ^ 8);
217 uint16_t ul_ev1_packgenB(const uint8_t *uid
) {
220 uint16_t ul_ev1_packgenC(const uint8_t *uid
) {
223 uint16_t ul_ev1_packgenD(const uint8_t *uid
) {
226 uint8_t r
= (uid
[2] + uid
[5]) & 7; //Rotation offset
227 uint8_t ru
[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Rotated UID
228 for (i
= 0; i
< 7; i
++)
229 ru
[(i
+ r
) & 7] = uid
[i
];
235 for (i
= 0; i
< 8; i
++)
239 return BSWAP_16(p
& 0xFFFF);
241 uint16_t ul_ev1_packgenE(const uint8_t *uid
) {
243 uint32_t pwd
= ul_ev1_pwdgenE(uid
);
244 return (0xAD << 8 | ((pwd
>> 24) & 0xFF));
247 uint16_t ul_ev1_packgenG(const uint8_t *uid
, const uint8_t *mfg
) {
248 init_table(CRC_PHILIPS
);
250 uint32_t crc1
= crc16_philips(uid
, 7);
252 uint32_t crc2
= crc16_fast(mfg
, 10, crc1
, false, false);
254 uint32_t pwd
= (BSWAP_16(crc2
) << 16 | BSWAP_16(crc1
));
257 num_to_bytes(pwd
, 4, pb
);
258 return BSWAP_16(crc16_fast(pb
, 4, crc2
, false, false));
263 uint32_t ul_ev1_pwdgen_def(const uint8_t *uid
) {
266 uint16_t ul_ev1_packgen_def(const uint8_t *uid
) {
270 // MIFARE ULTRALIGHT OTP generators
271 uint32_t ul_c_otpgenA(const uint8_t *uid
) {
276 //------------------------------------
277 // MFC key generation stuff
278 // Each algo implementation should offer two key generation functions.
279 // 1. function that returns all keys
280 // 2. function that returns one key, target sector | block
281 //------------------------------------
283 //------------------------------------
284 // MFC keyfile generation stuff
285 //------------------------------------
287 int mfc_algo_ving_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
288 if (sector
> 15) return PM3_EINVARG
;
289 if (key
== NULL
) return PM3_EINVARG
;
293 int mfc_algo_ving_all(uint8_t *uid
, uint8_t *keys
) {
294 if (keys
== NULL
) return PM3_EINVARG
;
295 for (int keytype
= 0; keytype
< 2; keytype
++) {
296 for (int sector
= 0; sector
< 16; sector
++) {
298 mfc_algo_ving_one(uid
, sector
, keytype
, &key
);
299 num_to_bytes(key
, 6, keys
+ (keytype
* 16 * 6) + (sector
* 6));
306 int mfc_algo_yale_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
307 if (sector
> 15) return PM3_EINVARG
;
308 if (key
== NULL
) return PM3_EINVARG
;
309 if (keytype
> 2) return PM3_EINVARG
;
313 int mfc_algo_yale_all(uint8_t *uid
, uint8_t *keys
) {
314 if (keys
== NULL
) return PM3_EINVARG
;
315 for (int keytype
= 0; keytype
< 2; keytype
++) {
316 for (int sector
= 0; sector
< 16; sector
++) {
318 mfc_algo_yale_one(uid
, sector
, keytype
, &key
);
319 num_to_bytes(key
, 6, keys
+ (keytype
* 16 * 6) + (sector
* 6));
325 // Saflok / Maid UID to key.
326 int mfc_algo_saflok_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
327 if (sector
> 15) return PM3_EINVARG
;
328 if (key
== NULL
) return PM3_EINVARG
;
332 *key
= 0xFFFFFFFFFFFF;
336 if (keytype
== 0 && sector
== 1) {
337 *key
= 0x2a2c13cc242a;
341 if (((sector
== 2) || (sector
== 3)) && (keytype
== 0)) {
342 *key
= 0xFFFFFFFFFFFF;
348 0xf057b39ee3d8ULL
, 0x969d954ac157ULL
, 0x8f43580d2c9dULL
, 0xffcce0050c43ULL
,
349 0x341b15a690ccULL
, 0x89585612e71bULL
, 0xbb74b0953658ULL
, 0xfb97f84b5b74ULL
,
350 0xc9d188359f92ULL
, 0x8f92e97f5897ULL
, 0x166ca2b09fd1ULL
, 0x27dd93101c6cULL
,
351 0xda3e3fd649ddULL
, 0x58dded078e3eULL
, 0x5cd005cfd907ULL
, 0x118dd00187d0ULL
354 uint8_t h
= ((uid
[3] >> 4) & 0xF);
355 h
+= ((uid
[2] >> 4) & 0xF);
358 uint64_t m
= lut
[h
& 0xF];
360 uint64_t id
= (bytes_to_num(uid
, 4) << 8);
362 *key
= (h
+ (id
+ m
+ ((uint64_t)h
<< 40ULL))) & 0xFFFFFFFFFFFFULL
;
367 int mfc_algo_saflok_all(uint8_t *uid
, uint8_t *keys
) {
368 if (keys
== NULL
) return PM3_EINVARG
;
370 for (int keytype
= 0; keytype
< 2; keytype
++) {
371 for (int sector
= 0; sector
< 16; sector
++) {
373 mfc_algo_saflok_one(uid
, sector
, keytype
, &key
);
374 num_to_bytes(key
, 6, keys
+ (keytype
* 16 * 6) + (sector
* 6));
381 int mfc_algo_mizip_one(const uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
382 if (sector
> 4) return PM3_EINVARG
;
383 if (key
== NULL
) return PM3_EINVARG
;
384 if (keytype
> 2) return PM3_EINVARG
;
389 *key
= 0xA0A1A2A3A4A5U
;
391 *key
= 0xB4C132439eef;
399 uint64_t xor_tbl_a
[] = {
406 num_to_bytes(xor_tbl_a
[sector
- 1], 6, xor);
409 (uint64_t)(uid
[0] ^ xor[0]) << 40 |
410 (uint64_t)(uid
[1] ^ xor[1]) << 32 |
411 (uint64_t)(uid
[2] ^ xor[2]) << 24 |
412 (uint64_t)(uid
[3] ^ xor[3]) << 16 |
413 (uint64_t)(uid
[0] ^ xor[4]) << 8 |
414 (uint64_t)(uid
[1] ^ xor[5])
418 uint64_t xor_tbl_b
[] = {
426 num_to_bytes(xor_tbl_b
[sector
- 1], 6, xor);
429 (uint64_t)(uid
[2] ^ xor[0]) << 40 |
430 (uint64_t)(uid
[3] ^ xor[1]) << 32 |
431 (uint64_t)(uid
[0] ^ xor[2]) << 24 |
432 (uint64_t)(uid
[1] ^ xor[3]) << 16 |
433 (uint64_t)(uid
[2] ^ xor[4]) << 8 |
434 (uint64_t)(uid
[3] ^ xor[5])
441 // returns all Mifare Mini (MFM) 10 keys.
442 // keys must have 5*2*6 = 60bytes space
443 int mfc_algo_mizip_all(uint8_t *uid
, uint8_t *keys
) {
444 if (keys
== NULL
) return PM3_EINVARG
;
446 for (int keytype
= 0; keytype
< 2; keytype
++) {
447 for (int sector
= 0; sector
< 5; sector
++) {
449 mfc_algo_mizip_one(uid
, sector
, keytype
, &key
);
450 num_to_bytes(key
, 6, keys
+ (keytype
* 5 * 6) + (sector
* 6));
456 // Disney Infinity algo
457 int mfc_algo_di_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
458 if (sector
> 4) return PM3_EINVARG
;
459 if (key
== NULL
) return PM3_EINVARG
;
463 0x0A, 0x14, 0xFD, 0x05, 0x07, 0xFF, 0x4B, 0xCD,
464 0x02, 0x6B, 0xA8, 0x3F, 0x0A, 0x3B, 0x89, 0xA9,
465 uid
[0], uid
[1], uid
[2], uid
[3], uid
[4], uid
[5], uid
[6],
466 0x28, 0x63, 0x29, 0x20, 0x44, 0x69, 0x73, 0x6E,
467 0x65, 0x79, 0x20, 0x32, 0x30, 0x31, 0x33
470 mbedtls_sha1(input
, sizeof(input
), hash
);
473 (uint64_t)hash
[3] << 40 |
474 (uint64_t)hash
[2] << 32 |
475 (uint64_t)hash
[1] << 24 |
476 (uint64_t)hash
[0] << 16 |
477 (uint64_t)hash
[7] << 8 |
483 int mfc_algo_di_all(uint8_t *uid
, uint8_t *keys
) {
484 if (keys
== NULL
) return PM3_EINVARG
;
485 for (int keytype
= 0; keytype
< 2; keytype
++) {
486 for (int sector
= 0; sector
< 5; sector
++) {
488 mfc_algo_di_one(uid
, sector
, keytype
, &key
);
489 num_to_bytes(key
, 6, keys
+ (keytype
* 5 * 6) + (sector
* 6));
496 static uint64_t sky_crc64_like(uint64_t result
, uint8_t sector
) {
497 #define SKY_POLY UINT64_C(0x42f0e1eba9ea3693)
498 #define SKY_TOP UINT64_C(0x800000000000)
499 result
^= (uint64_t)sector
<< 40;
500 for (int i
= 0; i
< 8; i
++) {
501 result
= (result
& SKY_TOP
) ? (result
<< 1) ^ SKY_POLY
: result
<< 1;
505 int mfc_algo_sky_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
507 #define SKY_KEY_MASK 0xFFFFFFFFFFFF
509 if (sector
> 15) return PM3_EINVARG
;
510 if (key
== NULL
) return PM3_EINVARG
;
512 if (sector
== 0 && keytype
== 0) {
513 *key
= 0x4B0B20107CCB;
517 *key
= 0x000000000000;
522 uint64_t hash
= 0x9AE903260CC4;
523 for (int i
= 0; i
< 4; i
++) {
524 hash
= sky_crc64_like(hash
, uid
[i
]);
527 uint64_t sectorhash
= sky_crc64_like(hash
, sector
);
528 *key
= BSWAP_64(sectorhash
& SKY_KEY_MASK
) >> 16;
531 int mfc_algo_sky_all(uint8_t *uid
, uint8_t *keys
) {
532 if (keys
== NULL
) return PM3_EINVARG
;
533 for (int keytype
= 0; keytype
< 2; keytype
++) {
534 for (int sector
= 0; sector
< 16; sector
++) {
536 mfc_algo_sky_one(uid
, sector
, keytype
, &key
);
537 num_to_bytes(key
, 6, keys
+ (keytype
* 16 * 6) + (sector
* 6));
543 // LF T55x7 White gun cloner algo
544 uint32_t lf_t55xx_white_pwdgen(uint32_t id
) {
545 uint32_t r1
= rotl(id
& 0x000000ec, 8);
546 uint32_t r2
= rotl(id
& 0x86000000, 16);
547 uint32_t pwd
= 0x10303;
548 pwd
+= ((id
& 0x86ee00ec) ^ r1
^ r2
);
552 // Gallagher Desfire Key Diversification Input for Cardax Card Data Application
553 int mfdes_kdf_input_gallagher(uint8_t *uid
, uint8_t uidLen
, uint8_t keyNo
, uint32_t aid
, uint8_t *kdfInputOut
, uint8_t *kdfInputLen
) {
554 if (uid
== NULL
|| (uidLen
!= 4 && uidLen
!= 7) || keyNo
> 2 || kdfInputOut
== NULL
|| kdfInputLen
== NULL
) {
555 prnt("Invalid arguments");
560 // If the keyNo == 1 or the aid is 000000, then omit the UID.
561 // On the other hand, if the aid is 1f81f4 (config card) always include the UID.
562 if ((keyNo
!= 1 && aid
!= 0x000000) || (aid
== 0x1f81f4)) {
563 if (*kdfInputLen
< (4 + uidLen
)) {
567 memcpy(kdfInputOut
, uid
, uidLen
);
569 } else if (*kdfInputLen
< 4) {
573 kdfInputOut
[len
++] = keyNo
;
575 kdfInputOut
[len
++] = aid
& 0xff;
576 kdfInputOut
[len
++] = (aid
>> 8) & 0xff;
577 kdfInputOut
[len
++] = (aid
>> 16) & 0xff;
584 int mfc_generate4b_nuid(uint8_t *uid
, uint8_t *nuid
) {
586 uint8_t b1
= 0, b2
= 0;
588 compute_crc(CRC_14443_A
, uid
, 3, &b1
, &b2
);
589 nuid
[0] = (b2
& 0xE0) | 0xF;
593 crc
= crc16_fast(&uid
[3], 4, reflect16(crc
), true, true);
594 nuid
[2] = (crc
>> 8) & 0xFF ;
595 nuid
[3] = crc
& 0xFF;
599 int mfc_algo_touch_one(uint8_t *uid
, uint8_t sector
, uint8_t keytype
, uint64_t *key
) {
600 if (uid
== NULL
) return PM3_EINVARG
;
601 if (key
== NULL
) return PM3_EINVARG
;
604 (uint64_t)(uid
[1] ^ uid
[2] ^ uid
[3]) << 40 |
605 (uint64_t)uid
[1] << 32 |
606 (uint64_t)uid
[2] << 24 |
607 (uint64_t)(((uid
[0] + uid
[1] + uid
[2] + uid
[3]) % 0x100) ^ uid
[3]) << 16 |
614 //------------------------------------
616 //------------------------------------
618 int generator_selftest(void) {
620 #define NUM_OF_TEST 10
622 PrintAndLogEx(INFO
, "PWD / KEY generator selftest");
623 PrintAndLogEx(INFO
, "----------------------------");
625 uint8_t testresult
= 0;
627 uint8_t uid1
[] = {0x04, 0x11, 0x12, 0x11, 0x12, 0x11, 0x10};
628 uint32_t pwd1
= ul_ev1_pwdgenA(uid1
);
629 bool success
= (pwd1
== 0x8432EB17);
633 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid1
, 7), pwd1
, success
? _GREEN_("ok") : "->8432EB17<-");
635 uint8_t uid2
[] = {0x04, 0x1f, 0x98, 0xea, 0x1e, 0x3e, 0x81};
636 uint32_t pwd2
= ul_ev1_pwdgenB(uid2
);
637 success
= (pwd2
== 0x5fd37eca);
640 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid2
, 7), pwd2
, success
? _GREEN_("ok") : "->5fd37eca<--");
642 uint8_t uid3
[] = {0x04, 0x62, 0xB6, 0x8A, 0xB4, 0x42, 0x80};
643 uint32_t pwd3
= ul_ev1_pwdgenC(uid3
);
644 success
= (pwd3
== 0x5a349515);
647 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid3
, 7), pwd3
, success
? _GREEN_("ok") : "->5a349515<--");
649 uint8_t uid4
[] = {0x04, 0xC5, 0xDF, 0x4A, 0x6D, 0x51, 0x80};
650 uint32_t pwd4
= ul_ev1_pwdgenD(uid4
);
651 success
= (pwd4
== 0x72B1EC61);
654 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid4
, 7), pwd4
, success
? _GREEN_("ok") : "->72B1EC61<--");
656 uint8_t uid5
[] = {0x04, 0xA0, 0x3C, 0xAA, 0x1E, 0x70, 0x80};
657 uint32_t pwd5
= ul_ev1_pwdgenE(uid5
);
658 success
= (pwd5
== 0xCD91AFCC);
661 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid5
, 7), pwd5
, success
? _GREEN_("ok") : "->CD91AFCC<--");
663 uint8_t uid6
[] = {0x04, 0x77, 0x42, 0xAB, 0xEF, 0x42, 0x70};
664 uint32_t pwd6
= ul_ev1_pwdgenF(uid6
);
665 success
= (pwd6
== 0xA9C4C3C0);
668 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid6
, 7), pwd6
, success
? _GREEN_("ok") : "->A9C4C3C0<--");
670 uint8_t uid7
[] = {0x04, 0x0D, 0x4B, 0x5A, 0xC5, 0x71, 0x81};
671 uint8_t mfg
[] = {0x32, 0x31, 0x30, 0x36, 0x32, 0x38, 0x20, 0x35, 0x32, 0x4D};
672 uint32_t pwd7
= ul_ev1_pwdgenG(uid7
, mfg
);
673 success
= (pwd7
== 0xFBCFACC1);
676 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %08X - %s", sprint_hex(uid7
, 7), pwd7
, success
? _GREEN_("ok") : "->FBCFACC1<--");
679 // uint8_t uid5[] = {0x11, 0x22, 0x33, 0x44};
680 // uint64_t key1 = mfc_algo_a(uid5);
681 // success = (key1 == 0xD1E2AA68E39A);
682 // PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid5, 4), key1, success ? _GREEN_("ok") : "->D1E2AA68E39A<--");
684 uint8_t uid8
[] = {0x74, 0x57, 0xCA, 0xA9};
686 mfc_algo_sky_one(uid8
, 15, 0, &key8
);
687 success
= (key8
== 0x82c7e64bc565);
690 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %"PRIx64
" - %s", sprint_hex(uid8
, 4), key8
, success
? _GREEN_("ok") : "->82C7E64BC565<--");
693 uint8_t uid9
[] = {0x11, 0x22, 0x33, 0x44};
695 mfc_algo_saflok_one(uid9
, 0, 0, &key9
);
696 success
= (key9
== 0xD1E2AA68E39A);
699 PrintAndLogEx(success
? SUCCESS
: WARNING
, "UID | %s | %"PRIX64
" - %s", sprint_hex(uid9
, 4), key9
, success
? _GREEN_("ok") : _RED_(">> D1E2AA68E39A <<"));
701 uint32_t lf_id
= lf_t55xx_white_pwdgen(0x00000080);
702 success
= (lf_id
== 0x00018383);
705 PrintAndLogEx(success
? SUCCESS
: WARNING
, "ID | 0x00000080 | %08"PRIx32
" - %s", lf_id
, success
? _GREEN_("ok") : "->00018383<--");
707 PrintAndLogEx(SUCCESS
, "------------------- Selftest %s", (testresult
== NUM_OF_TEST
) ? _GREEN_("ok") : _RED_("fail"));