text
[RRG-proxmark3.git] / common / generator.c
blobf7a53ed1ee8d2c6c045329fee146afad829b76b5
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
28 #include "util.h"
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"
37 #ifndef ON_DEVICE
38 #include "ui.h"
39 # define prnt(args...) PrintAndLogEx(DEBUG, ## args );
40 #else
41 # include "dbprint.h"
42 # define prnt Dbprintf
43 #endif
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
52 // Amiibo
53 // Lego Dimension
54 // XYZ 3D printing
55 // Vinglock
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
67 //Transform
68 uint8_t i;
69 uint8_t p = 0;
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++];
77 tempA = t1 ^ t2;
78 v1 = PM3_ROTL(tempA, t2 & 0x1F) + c_D[p++];
79 tempB = t2 ^ v1;
80 v2 = PM3_ROTL(tempB, v1 & 0x1F) + c_D[p++];
83 //Re-use ru
84 ru[0] = v1 & 0xFF;
85 ru[1] = (v1 >> 8) & 0xFF;
86 ru[2] = (v1 >> 16) & 0xFF;
87 ru[3] = (v1 >> 24) & 0xFF;
88 ru[4] = v2 & 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) {
133 uint32_t pwd = 0;
134 uint32_t base[] = {
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) {
152 uint8_t i;
153 // rotation offset
154 uint8_t r = (uid[1] + uid[3] + uid[5]) & 7;
156 // rotated UID
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];
161 transform_D(ru);
163 // offset
164 r = (ru[0] + ru[2] + ru[4] + ru[6]) & 3;
166 // calc key
167 uint32_t pwd = 0;
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);
178 uint32_t pwd = 0;
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 ]);
183 return pwd;
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);
190 uint32_t pwd = 0;
191 pwd |= hash[0] << 24;
192 pwd |= hash[1] << 16;
193 pwd |= hash[2] << 8;
194 pwd |= hash[3];
195 return pwd;
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);
204 // UID
205 uint32_t crc1 = crc16_philips(uid, 7);
206 // MFG string
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);
215 return pack;
217 uint16_t ul_ev1_packgenB(const uint8_t *uid) {
218 return 0x8080;
220 uint16_t ul_ev1_packgenC(const uint8_t *uid) {
221 return 0xaa55;
223 uint16_t ul_ev1_packgenD(const uint8_t *uid) {
224 uint8_t i;
225 //Rotate
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];
231 transform_D(ru);
233 //Calc pack
234 uint32_t p = 0;
235 for (i = 0; i < 8; i++)
236 p += ru[i] * 13;
238 p ^= 0x5555;
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);
249 // UID
250 uint32_t crc1 = crc16_philips(uid, 7);
251 // MFG string
252 uint32_t crc2 = crc16_fast(mfg, 10, crc1, false, false);
253 // PWD
254 uint32_t pwd = (BSWAP_16(crc2) << 16 | BSWAP_16(crc1));
256 uint8_t pb[4];
257 num_to_bytes(pwd, 4, pb);
258 return BSWAP_16(crc16_fast(pb, 4, crc2, false, false));
262 // default shims
263 uint32_t ul_ev1_pwdgen_def(const uint8_t *uid) {
264 return 0xFFFFFFFF;
266 uint16_t ul_ev1_packgen_def(const uint8_t *uid) {
267 return 0x0000;
270 // MIFARE ULTRALIGHT OTP generators
271 uint32_t ul_c_otpgenA(const uint8_t *uid) {
272 return 0x534C544F;
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 //------------------------------------
286 // Vinglock
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;
290 *key = 0;
291 return PM3_SUCCESS;
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++) {
297 uint64_t key = 0;
298 mfc_algo_ving_one(uid, sector, keytype, &key);
299 num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6));
302 return PM3_SUCCESS;
305 // Yale Doorman
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;
310 *key = 0;
311 return PM3_SUCCESS;
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++) {
317 uint64_t key = 0;
318 mfc_algo_yale_one(uid, sector, keytype, &key);
319 num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6));
322 return PM3_SUCCESS;
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;
331 if (keytype == 1) {
332 *key = 0xFFFFFFFFFFFF;
333 return PM3_SUCCESS;
336 if (keytype == 0 && sector == 1) {
337 *key = 0x2a2c13cc242a;
338 return PM3_SUCCESS;
341 if (((sector == 2) || (sector == 3)) && (keytype == 0)) {
342 *key = 0xFFFFFFFFFFFF;
343 return PM3_SUCCESS;
346 if (keytype == 0) {
347 uint64_t lut[16] = {
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);
356 h += uid[0] & 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;
364 return PM3_SUCCESS;
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++) {
372 uint64_t key = 0;
373 mfc_algo_saflok_one(uid, sector, keytype, &key);
374 num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6));
377 return PM3_SUCCESS;
380 // MIZIP algo
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;
386 if (sector == 0) {
387 // A
388 if (keytype == 0)
389 *key = 0xA0A1A2A3A4A5U;
390 else // B
391 *key = 0xB4C132439eef;
393 } else {
395 uint8_t xor[6];
397 if (keytype == 0) {
399 uint64_t xor_tbl_a[] = {
400 0x09125a2589e5,
401 0xAB75C937922F,
402 0xE27241AF2C09,
403 0x317AB72F4490,
406 num_to_bytes(xor_tbl_a[sector - 1], 6, xor);
408 *key =
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])
417 } else {
418 uint64_t xor_tbl_b[] = {
419 0xF12C8453D821,
420 0x73E799FE3241,
421 0xAA4D137656AE,
422 0xB01327272DFD
425 // B
426 num_to_bytes(xor_tbl_b[sector - 1], 6, xor);
428 *key =
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])
439 return PM3_SUCCESS;
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++) {
448 uint64_t key = 0;
449 mfc_algo_mizip_one(uid, sector, keytype, &key);
450 num_to_bytes(key, 6, keys + (keytype * 5 * 6) + (sector * 6));
453 return PM3_SUCCESS;
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;
461 uint8_t hash[64];
462 uint8_t input[] = {
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);
472 *key = (
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 |
478 hash[6]
481 return PM3_SUCCESS;
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++) {
487 uint64_t key = 0;
488 mfc_algo_di_one(uid, sector, keytype, &key);
489 num_to_bytes(key, 6, keys + (keytype * 5 * 6) + (sector * 6));
492 return PM3_SUCCESS;
495 // Skylanders
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;
503 return result;
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;
514 return PM3_SUCCESS;
516 if (keytype == 1) {
517 *key = 0x000000000000;
518 return PM3_SUCCESS;
521 // hash UID
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;
529 return PM3_SUCCESS;
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++) {
535 uint64_t key = 0;
536 mfc_algo_sky_one(uid, sector, keytype, &key);
537 num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6));
540 return PM3_SUCCESS;
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);
549 return pwd;
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");
556 return PM3_EINVARG;
559 int len = 0;
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)) {
564 return PM3_EINVARG;
567 memcpy(kdfInputOut, uid, uidLen);
568 len += uidLen;
569 } else if (*kdfInputLen < 4) {
570 return PM3_EINVARG;
573 kdfInputOut[len++] = keyNo;
575 kdfInputOut[len++] = aid & 0xff;
576 kdfInputOut[len++] = (aid >> 8) & 0xff;
577 kdfInputOut[len++] = (aid >> 16) & 0xff;
579 *kdfInputLen = len;
581 return PM3_SUCCESS;
584 int mfc_generate4b_nuid(uint8_t *uid, uint8_t *nuid) {
585 uint16_t crc;
586 uint8_t b1 = 0, b2 = 0;
588 compute_crc(CRC_14443_A, uid, 3, &b1, &b2);
589 nuid[0] = (b2 & 0xE0) | 0xF;
590 nuid[1] = b1;
591 crc = b1;
592 crc |= b2 << 8;
593 crc = crc16_fast(&uid[3], 4, reflect16(crc), true, true);
594 nuid[2] = (crc >> 8) & 0xFF ;
595 nuid[3] = crc & 0xFF;
596 return PM3_SUCCESS;
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;
603 *key = (
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 |
608 (uint64_t)0 << 8 |
609 (uint64_t)0
611 return PM3_SUCCESS;
614 //------------------------------------
615 // Self tests
616 //------------------------------------
618 int generator_selftest(void) {
619 #ifndef ON_DEVICE
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);
630 if (success)
631 testresult++;
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);
638 if (success)
639 testresult++;
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);
645 if (success)
646 testresult++;
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);
652 if (success)
653 testresult++;
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);
659 if (success)
660 testresult++;
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);
666 if (success)
667 testresult++;
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);
674 if (success)
675 testresult++;
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};
685 uint64_t key8 = 0;
686 mfc_algo_sky_one(uid8, 15, 0, &key8);
687 success = (key8 == 0x82c7e64bc565);
688 if (success)
689 testresult++;
690 PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid8, 4), key8, success ? _GREEN_("ok") : "->82C7E64BC565<--");
692 // MFC SAFLOK
693 uint8_t uid9[] = {0x11, 0x22, 0x33, 0x44};
694 uint64_t key9 = 0;
695 mfc_algo_saflok_one(uid9, 0, 0, &key9);
696 success = (key9 == 0xD1E2AA68E39A);
697 if (success)
698 testresult++;
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);
703 if (success)
704 testresult++;
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"));
709 #endif
710 return PM3_SUCCESS;