R&Y: Added DAY RTA Tapp Card and Additional BKK BEM Stored Value Card AIDs to `aid_de...
[RRG-proxmark3.git] / common / generator.c
blob8e6d049191265cec4ab7c06c909d524c49adb89a
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
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.
8 //
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 //-----------------------------------------------------------------------------
16 // Generator commands
17 //-----------------------------------------------------------------------------
18 #include "generator.h"
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #include <inttypes.h>
25 #include <string.h>
26 #include "commonutil.h" //BSWAP_16
27 #include "common.h" //BSWAP_32/64
29 #include "pm3_cmd.h"
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"
36 #include "mbedtls/hkdf.h"
38 #ifndef ON_DEVICE
39 #include "ui.h"
40 #include "util.h"
41 # define prnt(args...) PrintAndLogEx(DEBUG, ## args );
42 #else
43 # include "dbprint.h"
44 # define prnt Dbprintf
45 #endif
47 // Implementation tips:
48 // For each implementation of the algos, I recommend adding a self test for easy "simple unit" tests when Travis CI / Appveyor runs.
49 // See special note for MFC based algos.
51 //------------------------------------
52 // MFU/NTAG PWD/PACK generation stuff
53 // Italian transport system
54 // Amiibo
55 // Lego Dimension
56 // XYZ 3D printing
57 // Vinglock
58 //------------------------------------
59 static void transform_D(uint8_t *ru) {
61 const uint32_t c_D[] = {
62 0x6D835AFC, 0x7D15CD97, 0x0942B409, 0x32F9C923, 0xA811FB02, 0x64F121E8,
63 0xD1CC8B4E, 0xE8873E6F, 0x61399BBB, 0xF1B91926, 0xAC661520, 0xA21A31C9,
64 0xD424808D, 0xFE118E07, 0xD18E728D, 0xABAC9E17, 0x18066433, 0x00E18E79,
65 0x65A77305, 0x5AE9E297, 0x11FC628C, 0x7BB3431F, 0x942A8308, 0xB2F8FD20,
66 0x5728B869, 0x30726D5A
69 //Transform
70 uint8_t i;
71 uint8_t p = 0;
72 uint32_t v1 = ((ru[3] << 24) | (ru[2] << 16) | (ru[1] << 8) | ru[0]) + c_D[p++];
73 uint32_t v2 = ((ru[7] << 24) | (ru[6] << 16) | (ru[5] << 8) | ru[4]) + c_D[p++];
74 for (i = 0; i < 12; i += 2) {
75 uint32_t tempA = v1 ^ v2;
76 uint32_t t1 = PM3_ROTL(tempA, v2 & 0x1F) + c_D[p++];
77 uint32_t tempB = v2 ^ t1;
78 uint32_t t2 = PM3_ROTL(tempB, t1 & 0x1F) + c_D[p++];
79 tempA = t1 ^ t2;
80 v1 = PM3_ROTL(tempA, t2 & 0x1F) + c_D[p++];
81 tempB = t2 ^ v1;
82 v2 = PM3_ROTL(tempB, v1 & 0x1F) + c_D[p++];
85 //Re-use ru
86 ru[0] = v1 & 0xFF;
87 ru[1] = (v1 >> 8) & 0xFF;
88 ru[2] = (v1 >> 16) & 0xFF;
89 ru[3] = (v1 >> 24) & 0xFF;
90 ru[4] = v2 & 0xFF;
91 ru[5] = (v2 >> 8) & 0xFF;
92 ru[6] = (v2 >> 16) & 0xFF;
93 ru[7] = (v2 >> 24) & 0xFF;
96 // Transport system (IT) pwd generation algo nickname A.
97 uint32_t ul_ev1_pwdgenA(const uint8_t *uid) {
99 uint8_t pos = (uid[3] ^ uid[4] ^ uid[5] ^ uid[6]) % 32;
101 uint32_t xortable[] = {
102 0x4f2711c1, 0x07D7BB83, 0x9636EF07, 0xB5F4460E, 0xF271141C, 0x7D7BB038, 0x636EF871, 0x5F4468E3,
103 0x271149C7, 0xD7BB0B8F, 0x36EF8F1E, 0xF446863D, 0x7114947A, 0x7BB0B0F5, 0x6EF8F9EB, 0x44686BD7,
104 0x11494fAF, 0xBB0B075F, 0xEF8F96BE, 0x4686B57C, 0x1494F2F9, 0xB0B07DF3, 0xF8F963E6, 0x686B5FCC,
105 0x494F2799, 0x0B07D733, 0x8F963667, 0x86B5F4CE, 0x94F2719C, 0xB07D7B38, 0xF9636E70, 0x6B5F44E0
108 uint8_t entry[] = {0x00, 0x00, 0x00, 0x00};
109 uint8_t pwd[] = {0x00, 0x00, 0x00, 0x00};
111 num_to_bytes(xortable[pos], 4, entry);
113 pwd[0] = entry[0] ^ uid[1] ^ uid[2] ^ uid[3];
114 pwd[1] = entry[1] ^ uid[0] ^ uid[2] ^ uid[4];
115 pwd[2] = entry[2] ^ uid[0] ^ uid[1] ^ uid[5];
116 pwd[3] = entry[3] ^ uid[6];
118 return (uint32_t)bytes_to_num(pwd, 4);
121 // Amiibo pwd generation algo nickname B. (very simple)
122 uint32_t ul_ev1_pwdgenB(const uint8_t *uid) {
124 uint8_t pwd[] = {0x00, 0x00, 0x00, 0x00};
126 pwd[0] = uid[1] ^ uid[3] ^ 0xAA;
127 pwd[1] = uid[2] ^ uid[4] ^ 0x55;
128 pwd[2] = uid[3] ^ uid[5] ^ 0xAA;
129 pwd[3] = uid[4] ^ uid[6] ^ 0x55;
130 return (uint32_t)bytes_to_num(pwd, 4);
133 // Lego Dimension pwd generation algo nickname C.
134 uint32_t ul_ev1_pwdgenC(const uint8_t *uid) {
135 uint32_t pwd = 0;
136 uint32_t base[] = {
137 0xffffffff, 0x28ffffff,
138 0x43202963, 0x7279706f,
139 0x74686769, 0x47454c20,
140 0x3032204f, 0xaaaa3431
143 memcpy(base, uid, 7);
145 for (int i = 0; i < 8; i++) {
146 pwd = base[i] + ROTR(pwd, 25) + ROTR(pwd, 10) - pwd;
148 return BSWAP_32(pwd);
151 // XYZ 3d printing pwd generation algo nickname D.
152 uint32_t ul_ev1_pwdgenD(const uint8_t *uid) {
154 uint8_t i;
155 // rotation offset
156 uint8_t r = (uid[1] + uid[3] + uid[5]) & 7;
158 // rotated UID
159 uint8_t ru[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
160 for (i = 0; i < 7; i++)
161 ru[(i + r) & 7] = uid[i];
163 transform_D(ru);
165 // offset
166 r = (ru[0] + ru[2] + ru[4] + ru[6]) & 3;
168 // calc key
169 uint32_t pwd = 0;
170 for (i = 0; i < 4; i++)
171 pwd = ru[i + r] + (pwd << 8);
173 return BSWAP_32(pwd);
176 // AIR purifier Xiaomi
177 uint32_t ul_ev1_pwdgenE(const uint8_t *uid) {
178 uint8_t hash[20] = {0};
179 mbedtls_sha1(uid, 7, hash);
180 uint32_t pwd = 0;
181 pwd |= (hash[ hash[0] % 20 ]) << 24 ;
182 pwd |= (hash[(hash[0] + 5) % 20 ]) << 16;
183 pwd |= (hash[(hash[0] + 13) % 20 ]) << 8;
184 pwd |= (hash[(hash[0] + 17) % 20 ]);
185 return pwd;
188 // NDEF tools format password generator
189 uint32_t ul_ev1_pwdgenF(const uint8_t *uid) {
190 uint8_t hash[16] = {0};;
191 mbedtls_md5(uid, 7, hash);
192 uint32_t pwd = 0;
193 pwd |= hash[0] << 24;
194 pwd |= hash[1] << 16;
195 pwd |= hash[2] << 8;
196 pwd |= hash[3];
197 return pwd;
200 // Solution from @atc1441
201 // https://gist.github.com/atc1441/41af75048e4c22af1f5f0d4c1d94bb56
202 // Philips Sonicare toothbrush NFC head
203 uint32_t ul_ev1_pwdgenG(const uint8_t *uid, const uint8_t *mfg) {
205 init_table(CRC_PHILIPS);
206 // UID
207 uint32_t crc1 = crc16_philips(uid, 7);
208 // MFG string
209 uint32_t crc2 = crc16_fast(mfg, 10, crc1, false, false);
211 return (BSWAP_16(crc2) << 16 | BSWAP_16(crc1));
214 // pack generation for algo 1-3
215 uint16_t ul_ev1_packgenA(const uint8_t *uid) {
216 uint16_t pack = (uid[0] ^ uid[1] ^ uid[2]) << 8 | (uid[2] ^ 8);
217 return pack;
219 uint16_t ul_ev1_packgenB(const uint8_t *uid) {
220 return 0x8080;
222 uint16_t ul_ev1_packgenC(const uint8_t *uid) {
223 return 0xaa55;
225 uint16_t ul_ev1_packgenD(const uint8_t *uid) {
226 uint8_t i;
227 //Rotate
228 uint8_t r = (uid[2] + uid[5]) & 7; //Rotation offset
229 uint8_t ru[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Rotated UID
230 for (i = 0; i < 7; i++)
231 ru[(i + r) & 7] = uid[i];
233 transform_D(ru);
235 //Calc pack
236 uint32_t p = 0;
237 for (i = 0; i < 8; i++)
238 p += ru[i] * 13;
240 p ^= 0x5555;
241 return BSWAP_16(p & 0xFFFF);
243 uint16_t ul_ev1_packgenE(const uint8_t *uid) {
245 uint32_t pwd = ul_ev1_pwdgenE(uid);
246 return (0xAD << 8 | ((pwd >> 24) & 0xFF));
249 uint16_t ul_ev1_packgenG(const uint8_t *uid, const uint8_t *mfg) {
250 init_table(CRC_PHILIPS);
251 // UID
252 uint32_t crc1 = crc16_philips(uid, 7);
253 // MFG string
254 uint32_t crc2 = crc16_fast(mfg, 10, crc1, false, false);
255 // PWD
256 uint32_t pwd = (BSWAP_16(crc2) << 16 | BSWAP_16(crc1));
258 uint8_t pb[4];
259 num_to_bytes(pwd, 4, pb);
260 return BSWAP_16(crc16_fast(pb, 4, crc2, false, false));
264 // default shims
265 uint32_t ul_ev1_pwdgen_def(const uint8_t *uid) {
266 return 0xFFFFFFFF;
268 uint16_t ul_ev1_packgen_def(const uint8_t *uid) {
269 return 0x0000;
272 // MIFARE ULTRALIGHT OTP generators
273 uint32_t ul_c_otpgenA(const uint8_t *uid) {
274 return 0x534C544F;
278 //------------------------------------
279 // MFC key generation stuff
280 // Each algo implementation should offer two key generation functions.
281 // 1. function that returns all keys
282 // 2. function that returns one key, target sector | block
283 //------------------------------------
285 //------------------------------------
286 // MFC keyfile generation stuff
287 //------------------------------------
288 // Vinglock
289 int mfc_algo_ving_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
290 if (sector > 15) return PM3_EINVARG;
291 if (key == NULL) return PM3_EINVARG;
292 *key = 0;
293 return PM3_SUCCESS;
295 int mfc_algo_ving_all(uint8_t *uid, uint8_t *keys) {
296 if (keys == NULL) return PM3_EINVARG;
297 for (int keytype = 0; keytype < 2; keytype++) {
298 for (int sector = 0; sector < 16; sector++) {
299 uint64_t key = 0;
300 mfc_algo_ving_one(uid, sector, keytype, &key);
301 num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6));
304 return PM3_SUCCESS;
307 // Yale Doorman
308 int mfc_algo_yale_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
309 if (sector > 15) return PM3_EINVARG;
310 if (key == NULL) return PM3_EINVARG;
311 if (keytype > 2) return PM3_EINVARG;
312 *key = 0;
313 return PM3_SUCCESS;
315 int mfc_algo_yale_all(uint8_t *uid, uint8_t *keys) {
316 if (keys == NULL) return PM3_EINVARG;
317 for (int keytype = 0; keytype < 2; keytype++) {
318 for (int sector = 0; sector < 16; sector++) {
319 uint64_t key = 0;
320 mfc_algo_yale_one(uid, sector, keytype, &key);
321 num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6));
324 return PM3_SUCCESS;
327 // Saflok / Maid UID to key.
328 int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
329 if (sector > 15) return PM3_EINVARG;
330 if (key == NULL) return PM3_EINVARG;
333 if (keytype == 1) {
334 *key = 0xFFFFFFFFFFFF;
335 return PM3_SUCCESS;
338 if (keytype == 0 && sector == 1) {
339 *key = 0x2a2c13cc242a;
340 return PM3_SUCCESS;
343 if (((sector == 2) || (sector == 3)) && (keytype == 0)) {
344 *key = 0xFFFFFFFFFFFF;
345 return PM3_SUCCESS;
348 if (keytype == 0) {
349 uint64_t lut[16] = {
350 0xf057b39ee3d8ULL, 0x969d954ac157ULL, 0x8f43580d2c9dULL, 0xffcce0050c43ULL,
351 0x341b15a690ccULL, 0x89585612e71bULL, 0xbb74b0953658ULL, 0xfb97f84b5b74ULL,
352 0xc9d188359f92ULL, 0x8f92e97f5897ULL, 0x166ca2b09fd1ULL, 0x27dd93101c6cULL,
353 0xda3e3fd649ddULL, 0x58dded078e3eULL, 0x5cd005cfd907ULL, 0x118dd00187d0ULL
356 uint8_t h = (NIBBLE_HIGH(uid[3]) & 0xF);
357 h += (NIBBLE_HIGH(uid[2]) & 0xF);
358 h += uid[0] & 0xF;
360 uint64_t m = lut[h & 0xF];
361 uint64_t id = (bytes_to_num(uid, 4) << 8);
363 *key = (h + (id + m + ((uint64_t)h << 40ULL))) & 0xFFFFFFFFFFFFULL;
365 return PM3_SUCCESS;
368 int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys) {
369 if (keys == NULL) return PM3_EINVARG;
371 for (int keytype = 0; keytype < 2; keytype++) {
372 for (int sector = 0; sector < 16; sector++) {
373 uint64_t key = 0;
374 mfc_algo_saflok_one(uid, sector, keytype, &key);
375 num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6));
378 return PM3_SUCCESS;
381 // MIZIP algo
382 int mfc_algo_mizip_one(const uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
383 if (sector > 4) return PM3_EINVARG;
384 if (key == NULL) return PM3_EINVARG;
385 if (keytype > 2) return PM3_EINVARG;
387 if (sector == 0) {
388 // A
389 if (keytype == 0)
390 *key = 0xA0A1A2A3A4A5U;
391 else // B
392 *key = 0xB4C132439eef;
394 } else {
396 uint8_t xor[6];
398 if (keytype == 0) {
400 uint64_t xor_tbl_a[] = {
401 0x09125a2589e5,
402 0xAB75C937922F,
403 0xE27241AF2C09,
404 0x317AB72F4490,
407 num_to_bytes(xor_tbl_a[sector - 1], 6, xor);
409 *key =
410 (uint64_t)(uid[0] ^ xor[0]) << 40 |
411 (uint64_t)(uid[1] ^ xor[1]) << 32 |
412 (uint64_t)(uid[2] ^ xor[2]) << 24 |
413 (uint64_t)(uid[3] ^ xor[3]) << 16 |
414 (uint64_t)(uid[0] ^ xor[4]) << 8 |
415 (uint64_t)(uid[1] ^ xor[5])
418 } else {
419 uint64_t xor_tbl_b[] = {
420 0xF12C8453D821,
421 0x73E799FE3241,
422 0xAA4D137656AE,
423 0xB01327272DFD
426 // B
427 num_to_bytes(xor_tbl_b[sector - 1], 6, xor);
429 *key =
430 (uint64_t)(uid[2] ^ xor[0]) << 40 |
431 (uint64_t)(uid[3] ^ xor[1]) << 32 |
432 (uint64_t)(uid[0] ^ xor[2]) << 24 |
433 (uint64_t)(uid[1] ^ xor[3]) << 16 |
434 (uint64_t)(uid[2] ^ xor[4]) << 8 |
435 (uint64_t)(uid[3] ^ xor[5])
440 return PM3_SUCCESS;
442 // returns all Mifare Mini (MFM) 10 keys.
443 // keys must have 5*2*6 = 60bytes space
444 int mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) {
445 if (keys == NULL) return PM3_EINVARG;
447 for (int keytype = 0; keytype < 2; keytype++) {
448 for (int sector = 0; sector < 5; sector++) {
449 uint64_t key = 0;
450 mfc_algo_mizip_one(uid, sector, keytype, &key);
451 num_to_bytes(key, 6, keys + (keytype * 5 * 6) + (sector * 6));
454 return PM3_SUCCESS;
457 // Disney Infinity algo
458 int mfc_algo_di_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
459 if (sector > 4) return PM3_EINVARG;
460 if (key == NULL) return PM3_EINVARG;
462 uint8_t hash[64];
463 uint8_t input[] = {
464 0x0A, 0x14, 0xFD, 0x05, 0x07, 0xFF, 0x4B, 0xCD,
465 0x02, 0x6B, 0xA8, 0x3F, 0x0A, 0x3B, 0x89, 0xA9,
466 uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6],
467 0x28, 0x63, 0x29, 0x20, 0x44, 0x69, 0x73, 0x6E,
468 0x65, 0x79, 0x20, 0x32, 0x30, 0x31, 0x33
471 mbedtls_sha1(input, sizeof(input), hash);
473 *key = (
474 (uint64_t)hash[3] << 40 |
475 (uint64_t)hash[2] << 32 |
476 (uint64_t)hash[1] << 24 |
477 (uint64_t)hash[0] << 16 |
478 (uint64_t)hash[7] << 8 |
479 hash[6]
482 return PM3_SUCCESS;
484 int mfc_algo_di_all(uint8_t *uid, uint8_t *keys) {
485 if (keys == NULL) return PM3_EINVARG;
486 for (int keytype = 0; keytype < 2; keytype++) {
487 for (int sector = 0; sector < 5; sector++) {
488 uint64_t key = 0;
489 mfc_algo_di_one(uid, sector, keytype, &key);
490 num_to_bytes(key, 6, keys + (keytype * 5 * 6) + (sector * 6));
493 return PM3_SUCCESS;
496 // Skylanders
497 static uint64_t sky_crc64_like(uint64_t result, uint8_t sector) {
498 #define SKY_POLY UINT64_C(0x42f0e1eba9ea3693)
499 #define SKY_TOP UINT64_C(0x800000000000)
500 result ^= (uint64_t)sector << 40;
501 for (int i = 0; i < 8; i++) {
502 result = (result & SKY_TOP) ? (result << 1) ^ SKY_POLY : result << 1;
504 return result;
506 int mfc_algo_sky_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
508 #define SKY_KEY_MASK 0xFFFFFFFFFFFF
510 if (sector > 15) return PM3_EINVARG;
511 if (key == NULL) return PM3_EINVARG;
513 if (sector == 0 && keytype == 0) {
514 *key = 0x4B0B20107CCB;
515 return PM3_SUCCESS;
517 if (keytype == 1) {
518 *key = 0x000000000000;
519 return PM3_SUCCESS;
522 // hash UID
523 uint64_t hash = 0x9AE903260CC4;
524 for (int i = 0; i < 4; i++) {
525 hash = sky_crc64_like(hash, uid[i]);
528 uint64_t sectorhash = sky_crc64_like(hash, sector);
529 *key = BSWAP_64(sectorhash & SKY_KEY_MASK) >> 16;
530 return PM3_SUCCESS;
532 int mfc_algo_sky_all(uint8_t *uid, uint8_t *keys) {
533 if (keys == NULL) return PM3_EINVARG;
534 for (int keytype = 0; keytype < 2; keytype++) {
535 for (int sector = 0; sector < 16; sector++) {
536 uint64_t key = 0;
537 mfc_algo_sky_one(uid, sector, keytype, &key);
538 num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6));
541 return PM3_SUCCESS;
545 static const uint8_t bambu_salt[] = { 0x9a, 0x75, 0x9c, 0xf2, 0xc4, 0xf7, 0xca, 0xff, 0x22, 0x2c, 0xb9, 0x76, 0x9b, 0x41, 0xbc, 0x96 };
546 static const uint8_t bambu_context_a[] = "RFID-A";
547 static const uint8_t bambu_context_b[] = "RFID-B";
549 int mfc_algo_bambu_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
550 if (uid == NULL) return PM3_EINVARG;
551 if (key == NULL) return PM3_EINVARG;
553 uint8_t keys[16 * 6] = {0};
555 // prepare hmac context
556 const mbedtls_md_info_t *info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
558 if (keytype == 0) {
559 mbedtls_hkdf(info, bambu_salt, sizeof(bambu_salt), uid, 4, bambu_context_a, sizeof(bambu_context_a), keys, sizeof(keys));
560 } else {
561 mbedtls_hkdf(info, bambu_salt, sizeof(bambu_salt), uid, 4, bambu_context_b, sizeof(bambu_context_b), keys, sizeof(keys));
564 *key = bytes_to_num(keys + (sector * 6), 6);
565 return PM3_SUCCESS;
568 int mfc_algo_bambu_all(uint8_t *uid, uint8_t *keys) {
569 if (uid == NULL) return PM3_EINVARG;
570 if (keys == NULL) return PM3_EINVARG;
572 // prepare hmac context
573 const mbedtls_md_info_t *info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
574 mbedtls_hkdf(info, bambu_salt, sizeof(bambu_salt), uid, 4, bambu_context_a, sizeof(bambu_context_a), keys, (16 * 6));
575 mbedtls_hkdf(info, bambu_salt, sizeof(bambu_salt), uid, 4, bambu_context_b, sizeof(bambu_context_b), keys + (16 * 6), (16 * 6));
576 return PM3_SUCCESS;
579 // LF T55x7 White gun cloner algo
580 uint32_t lf_t55xx_white_pwdgen(uint32_t id) {
581 uint32_t r1 = rotl(id & 0x000000ec, 8);
582 uint32_t r2 = rotl(id & 0x86000000, 16);
583 uint32_t pwd = 0x10303;
584 pwd += ((id & 0x86ee00ec) ^ r1 ^ r2);
585 return pwd;
588 // Gallagher Desfire Key Diversification Input for Cardax Card Data Application
589 int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen) {
590 if (uid == NULL || (uidLen != 4 && uidLen != 7) || keyNo > 2 || kdfInputOut == NULL || kdfInputLen == NULL) {
591 prnt("Invalid arguments");
592 return PM3_EINVARG;
595 int len = 0;
596 // If the keyNo == 1 or the aid is 000000, then omit the UID.
597 // On the other hand, if the aid is 1f81f4 (config card) always include the UID.
598 if ((keyNo != 1 && aid != 0x000000) || (aid == 0x1f81f4)) {
599 if (*kdfInputLen < (4 + uidLen)) {
600 return PM3_EINVARG;
603 memcpy(kdfInputOut, uid, uidLen);
604 len += uidLen;
605 } else if (*kdfInputLen < 4) {
606 return PM3_EINVARG;
609 kdfInputOut[len++] = keyNo;
611 kdfInputOut[len++] = aid & 0xff;
612 kdfInputOut[len++] = (aid >> 8) & 0xff;
613 kdfInputOut[len++] = (aid >> 16) & 0xff;
615 *kdfInputLen = len;
617 return PM3_SUCCESS;
620 int mfc_generate4b_nuid(uint8_t *uid, uint8_t *nuid) {
621 uint16_t crc;
622 uint8_t b1 = 0, b2 = 0;
624 compute_crc(CRC_14443_A, uid, 3, &b1, &b2);
625 nuid[0] = (b2 & 0xE0) | 0xF;
626 nuid[1] = b1;
627 crc = b1;
628 crc |= b2 << 8;
629 crc = crc16_fast(&uid[3], 4, reflect16(crc), true, true);
630 nuid[2] = (crc >> 8) & 0xFF ;
631 nuid[3] = crc & 0xFF;
632 return PM3_SUCCESS;
635 int mfc_algo_touch_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
636 if (uid == NULL) return PM3_EINVARG;
637 if (key == NULL) return PM3_EINVARG;
639 *key = (
640 (uint64_t)(uid[1] ^ uid[2] ^ uid[3]) << 40 |
641 (uint64_t)uid[1] << 32 |
642 (uint64_t)uid[2] << 24 |
643 (uint64_t)(((uid[0] + uid[1] + uid[2] + uid[3]) % 0x100) ^ uid[3]) << 16 |
644 (uint64_t)0 << 8 |
645 (uint64_t)0
647 return PM3_SUCCESS;
650 //------------------------------------
651 // Self tests
652 //------------------------------------
654 int generator_selftest(void) {
655 #ifndef ON_DEVICE
656 #define NUM_OF_TEST 11
658 PrintAndLogEx(INFO, "------- " _CYAN_("PWD / KEY generator self tests") " --------");
660 uint8_t testresult = 0;
662 uint8_t uid1[] = {0x04, 0x11, 0x12, 0x11, 0x12, 0x11, 0x10};
663 uint32_t pwd1 = ul_ev1_pwdgenA(uid1);
664 bool success = (pwd1 == 0x8432EB17);
665 if (success)
666 testresult++;
667 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid1, 7), pwd1, success ? _GREEN_("ok") : "->8432EB17<-");
669 uint8_t uid2[] = {0x04, 0x1f, 0x98, 0xea, 0x1e, 0x3e, 0x81};
670 uint32_t pwd2 = ul_ev1_pwdgenB(uid2);
671 success = (pwd2 == 0x5fd37eca);
672 if (success)
673 testresult++;
674 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid2, 7), pwd2, success ? _GREEN_("ok") : "->5fd37eca<--");
676 uint8_t uid3[] = {0x04, 0x62, 0xB6, 0x8A, 0xB4, 0x42, 0x80};
677 uint32_t pwd3 = ul_ev1_pwdgenC(uid3);
678 success = (pwd3 == 0x5a349515);
679 if (success)
680 testresult++;
681 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid3, 7), pwd3, success ? _GREEN_("ok") : "->5a349515<--");
683 uint8_t uid4[] = {0x04, 0xC5, 0xDF, 0x4A, 0x6D, 0x51, 0x80};
684 uint32_t pwd4 = ul_ev1_pwdgenD(uid4);
685 success = (pwd4 == 0x72B1EC61);
686 if (success)
687 testresult++;
688 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid4, 7), pwd4, success ? _GREEN_("ok") : "->72B1EC61<--");
690 uint8_t uid5[] = {0x04, 0xA0, 0x3C, 0xAA, 0x1E, 0x70, 0x80};
691 uint32_t pwd5 = ul_ev1_pwdgenE(uid5);
692 success = (pwd5 == 0xCD91AFCC);
693 if (success)
694 testresult++;
695 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid5, 7), pwd5, success ? _GREEN_("ok") : "->CD91AFCC<--");
697 uint8_t uid6[] = {0x04, 0x77, 0x42, 0xAB, 0xEF, 0x42, 0x70};
698 uint32_t pwd6 = ul_ev1_pwdgenF(uid6);
699 success = (pwd6 == 0xA9C4C3C0);
700 if (success)
701 testresult++;
702 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid6, 7), pwd6, success ? _GREEN_("ok") : "->A9C4C3C0<--");
704 uint8_t uid7[] = {0x04, 0x0D, 0x4B, 0x5A, 0xC5, 0x71, 0x81};
705 uint8_t mfg[] = {0x32, 0x31, 0x30, 0x36, 0x32, 0x38, 0x20, 0x35, 0x32, 0x4D};
706 uint32_t pwd7 = ul_ev1_pwdgenG(uid7, mfg);
707 success = (pwd7 == 0xFBCFACC1);
708 if (success)
709 testresult++;
710 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid7, 7), pwd7, success ? _GREEN_("ok") : "->FBCFACC1<--");
713 // uint8_t uid5[] = {0x11, 0x22, 0x33, 0x44};
714 // uint64_t key1 = mfc_algo_a(uid5);
715 // success = (key1 == 0xD1E2AA68E39A);
716 // PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid5, 4), key1, success ? _GREEN_("ok") : "->D1E2AA68E39A<--");
718 uint8_t uid8[] = {0x74, 0x57, 0xCA, 0xA9};
719 uint64_t key8 = 0;
720 mfc_algo_sky_one(uid8, 15, 0, &key8);
721 success = (key8 == 0x82c7e64bc565);
722 if (success)
723 testresult++;
724 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %012"PRIx64" - %s", sprint_hex(uid8, 4), key8, success ? _GREEN_("ok") : "->82C7E64BC565<--");
726 // MFC SAFLOK
727 uint8_t uid9[] = {0x11, 0x22, 0x33, 0x44};
728 uint64_t key9 = 0;
729 mfc_algo_saflok_one(uid9, 0, 0, &key9);
730 success = (key9 == 0xD1E2AA68E39A);
731 if (success)
732 testresult++;
733 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %012"PRIX64" - %s", sprint_hex(uid9, 4), key9, success ? _GREEN_("ok") : _RED_(">> D1E2AA68E39A <<"));
735 uint32_t lf_id = lf_t55xx_white_pwdgen(0x00000080);
736 success = (lf_id == 0x00018383);
737 if (success)
738 testresult++;
739 PrintAndLogEx(success ? SUCCESS : WARNING, "ID | 0x00000080 | %08"PRIx32 " - %s", lf_id, success ? _GREEN_("ok") : ">> 00018383 <<");
741 // MFC Bambu
742 uint64_t key13 = 0;
743 mfc_algo_bambu_one(uid9, 0, 0, &key13);
744 success = (key13 == 0x0729F3B2D37A);
745 if (success)
746 testresult++;
747 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %012"PRIX64" - %s", sprint_hex(uid9, 4), key13, success ? _GREEN_("ok") : _RED_(">> 0729F3B2D37A <<"));
750 PrintAndLogEx(SUCCESS, "------------------- Selftest %s", (testresult == NUM_OF_TEST) ? _GREEN_("ok") : _RED_("fail"));
752 #endif
753 return PM3_SUCCESS;