textual
[RRG-proxmark3.git] / client / src / mifare / mifarehost.c
blob5285a4d94a56e1f911cada935596a8639b632cf1
1 // Merlok, 2011, 2012, 2019
2 // people from mifare@nethemba.com, 2010
3 //
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
6 // the license.
7 //-----------------------------------------------------------------------------
8 // mifare commands
9 //-----------------------------------------------------------------------------
10 #include "mifarehost.h"
12 #include <inttypes.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
17 #include "comms.h"
18 #include "commonutil.h"
19 #include "mifare4.h"
20 #include "ui.h" // PrintAndLog...
21 #include "crapto1/crapto1.h"
22 #include "crc16.h"
23 #include "protocols.h"
24 #include "mfkey.h"
25 #include "util_posix.h" // msclock
26 #include "cmdparser.h" // detection of flash capabilities
27 #include "cmdflashmemspiffs.h" // upload to flash mem
29 int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
30 uint32_t uid = 0;
31 uint32_t nt = 0, nr = 0, ar = 0;
32 uint64_t par_list = 0, ks_list = 0;
33 uint64_t *keylist = NULL, *last_keylist = NULL;
34 bool first_run = true;
36 // message
37 PrintAndLogEx(INFO, "--------------------------------------------------------------------------------");
38 PrintAndLogEx(INFO, "Executing darkside attack. Expected execution time: 25sec on average");
39 PrintAndLogEx(INFO, "press pm3-button on the Proxmark3 device to abort both Proxmark3 and client");
40 PrintAndLogEx(INFO, "--------------------------------------------------------------------------------");
42 while (true) {
43 clearCommandBuffer();
44 struct {
45 uint8_t first_run;
46 uint8_t blockno;
47 uint8_t key_type;
48 } PACKED payload;
49 payload.first_run = first_run;
50 payload.blockno = blockno;
51 payload.key_type = key_type;
52 SendCommandNG(CMD_HF_MIFARE_READER, (uint8_t *)&payload, sizeof(payload));
54 //flush queue
55 while (kbd_enter_pressed()) {
56 return PM3_EOPABORTED;
59 PrintAndLogEx(INFO, "." NOLF);
61 // wait cycle
62 while (true) {
63 PrintAndLogEx(NORMAL, "." NOLF);
65 if (kbd_enter_pressed()) {
66 return PM3_EOPABORTED;
69 PacketResponseNG resp;
70 if (WaitForResponseTimeout(CMD_HF_MIFARE_READER, &resp, 2000)) {
71 if (resp.status == PM3_EOPABORTED) {
72 return -1;
75 struct p {
76 int32_t isOK;
77 uint8_t cuid[4];
78 uint8_t nt[4];
79 uint8_t par_list[8];
80 uint8_t ks_list[8];
81 uint8_t nr[4];
82 uint8_t ar[4];
83 } PACKED;
85 struct p *package = (struct p *) resp.data.asBytes;
87 if (package->isOK == -6) {
88 *key = 0101;
89 return 1;
92 if (package->isOK < 0)
93 return package->isOK;
96 uid = (uint32_t)bytes_to_num(package->cuid, sizeof(package->cuid));
97 nt = (uint32_t)bytes_to_num(package->nt, sizeof(package->nr));
98 par_list = bytes_to_num(package->par_list, sizeof(package->par_list));
99 ks_list = bytes_to_num(package->ks_list, sizeof(package->ks_list));
100 nr = (uint32_t)bytes_to_num(package->nr, 4);
101 ar = (uint32_t)bytes_to_num(package->ar, 4);
102 break;
105 PrintAndLogEx(NORMAL, "\n");
107 if (par_list == 0 && first_run == true) {
108 PrintAndLogEx(SUCCESS, "Parity is all zero. Most likely this card sends NACK on every authentication.");
110 first_run = false;
112 uint32_t keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist);
114 if (keycount == 0) {
115 PrintAndLogEx(FAILED, "key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
116 PrintAndLogEx(FAILED, "this is expected to happen in 25%% of all cases. Trying again with a different reader nonce...");
117 continue;
120 // only parity zero attack
121 if (par_list == 0) {
122 qsort(keylist, keycount, sizeof(*keylist), compare_uint64);
123 keycount = intersection(last_keylist, keylist);
124 if (keycount == 0) {
125 free(last_keylist);
126 last_keylist = keylist;
127 PrintAndLogEx(FAILED, "no candidates found, trying again");
128 continue;
132 PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") " candidate key%s", keycount, (keycount > 1) ? "s." : ".");
134 *key = UINT64_C(-1);
135 uint8_t keyBlock[PM3_CMD_DATA_SIZE];
136 uint32_t max_keys = KEYS_IN_BLOCK;
137 for (uint32_t i = 0; i < keycount; i += max_keys) {
139 uint8_t size = keycount - i > max_keys ? max_keys : keycount - i;
140 register uint8_t j;
141 for (j = 0; j < size; j++) {
142 if (par_list == 0) {
143 num_to_bytes(last_keylist[i * max_keys + j], 6, keyBlock + (j * 6));
144 } else {
145 num_to_bytes(keylist[i * max_keys + j], 6, keyBlock + (j * 6));
149 if (mfCheckKeys(blockno, key_type - 0x60, false, size, keyBlock, key) == PM3_SUCCESS) {
150 break;
154 if (*key != UINT64_C(-1)) {
155 break;
156 } else {
157 PrintAndLogEx(FAILED, "all key candidates failed. Restarting darkside attack");
158 free(last_keylist);
159 last_keylist = keylist;
160 first_run = true;
163 free(last_keylist);
164 free(keylist);
165 return PM3_SUCCESS;
168 int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) {
169 *key = -1;
170 clearCommandBuffer();
171 uint8_t data[PM3_CMD_DATA_SIZE] = {0};
172 data[0] = keyType;
173 data[1] = blockNo;
174 data[2] = clear_trace;
175 data[3] = 0;
176 data[4] = keycnt;
177 memcpy(data + 5, keyBlock, 6 * keycnt);
178 SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (5 + 6 * keycnt));
180 PacketResponseNG resp;
181 if (!WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2500)) return PM3_ETIMEOUT;
182 if (resp.status != PM3_SUCCESS) return resp.status;
184 struct kr {
185 uint8_t key[6];
186 bool found;
187 } PACKED;
188 struct kr *keyresult = (struct kr *)&resp.data.asBytes;
189 if (!keyresult->found) return PM3_ESOFT;
190 *key = bytes_to_num(keyresult->key, sizeof(keyresult->key));
191 return PM3_SUCCESS;
194 // Sends chunks of keys to device.
195 // 0 == ok all keys found
196 // 1 ==
197 // 2 == Time-out, aborting
198 int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy,
199 uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory) {
201 uint64_t t2 = msclock();
203 // send keychunk
204 clearCommandBuffer();
205 SendCommandOLD(CMD_HF_MIFARE_CHKKEYS_FAST, (sectorsCnt | (firstChunk << 8) | (lastChunk << 12)), ((use_flashmemory << 8) | strategy), size, keyBlock, 6 * size);
206 PacketResponseNG resp;
208 uint32_t timeout = 0;
209 while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
211 PrintAndLogEx((timeout == 0) ? INFO : NORMAL, "." NOLF);
212 fflush(stdout);
214 timeout++;
216 // max timeout for one chunk of 85keys, 60*3sec = 180seconds
217 // s70 with 40*2 keys to check, 80*85 = 6800 auth.
218 // takes about 97s, still some margin before abort
219 if (timeout > 180) {
220 PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
221 return PM3_ETIMEOUT;
224 t2 = msclock() - t2;
226 if (timeout) {
227 PrintAndLogEx(NORMAL, "");
230 // time to convert the returned data.
231 uint8_t curr_keys = resp.oldarg[0];
233 PrintAndLogEx(INFO, "Chunk: %.1fs | found %u/%u keys (%u)", (float)(t2 / 1000.0), curr_keys, (sectorsCnt << 1), size);
235 // all keys?
236 if (curr_keys == sectorsCnt * 2 || lastChunk) {
238 // success array. each byte is status of key
239 uint8_t arr[80];
240 uint64_t foo = 0;
241 uint16_t bar = 0;
242 foo = bytes_to_num(resp.data.asBytes + 480, 8);
243 bar = (resp.data.asBytes[489] << 8 | resp.data.asBytes[488]);
245 for (uint8_t i = 0; i < 64; i++)
246 arr[i] = (foo >> i) & 0x1;
248 for (uint8_t i = 0; i < 16; i++)
249 arr[i + 64] = (bar >> i) & 0x1;
251 // initialize storage for found keys
252 icesector_t *tmp = calloc(sectorsCnt, sizeof(icesector_t));
253 if (tmp == NULL)
254 return PM3_EMALLOC;
256 memcpy(tmp, resp.data.asBytes, sectorsCnt * sizeof(icesector_t));
258 for (int i = 0; i < sectorsCnt; i++) {
259 // key A
260 if (!e_sector[i].foundKey[0]) {
261 e_sector[i].Key[0] = bytes_to_num(tmp[i].keyA, 6);
262 e_sector[i].foundKey[0] = arr[(i * 2) ];
264 // key B
265 if (!e_sector[i].foundKey[1]) {
266 e_sector[i].Key[1] = bytes_to_num(tmp[i].keyB, 6);
267 e_sector[i].foundKey[1] = arr[(i * 2) + 1 ];
270 free(tmp);
272 if (curr_keys == sectorsCnt * 2)
273 return PM3_SUCCESS;
274 if (lastChunk)
275 return PM3_ESOFT;
277 return PM3_ESOFT;
280 // Trigger device to use a binary file on flash mem as keylist for mfCheckKeys.
281 // As of now, 255 keys possible in the file
282 // 6 * 255 = 1500 bytes
283 int mfCheckKeys_file(uint8_t *destfn, uint64_t *key) {
284 *key = -1;
285 clearCommandBuffer();
287 struct {
288 uint8_t filename[32];
289 } PACKED payload_file;
291 memcpy(payload_file.filename, destfn, sizeof(payload_file.filename) - 1);
293 PacketResponseNG resp;
294 clearCommandBuffer();
295 SendCommandNG(CMD_HF_MIFARE_CHKKEYS_FILE, (uint8_t *)&payload_file, sizeof(payload_file));
297 uint8_t retry = 10;
299 while (!WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2000)) {
301 //flush queue
302 while (kbd_enter_pressed()) {
303 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
304 return PM3_EOPABORTED;
307 retry--;
308 if (retry == 0) {
309 PrintAndLogEx(WARNING, "Chk keys file, timeouted");
310 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
311 return PM3_ETIMEOUT;
315 if (resp.status != PM3_SUCCESS) return resp.status;
317 struct kr {
318 uint8_t key[6];
319 bool found;
320 } PACKED;
321 struct kr *keyresult = (struct kr *)&resp.data.asBytes;
322 if (!keyresult->found) return PM3_ESOFT;
324 *key = bytes_to_num(keyresult->key, sizeof(keyresult->key));
325 return PM3_SUCCESS;
328 // PM3 imp of J-Run mf_key_brute (part 2)
329 // ref: https://github.com/J-Run/mf_key_brute
330 int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey) {
332 uint64_t key64;
333 uint8_t found = false;
334 uint8_t candidates[CANDIDATE_SIZE] = {0x00};
335 uint8_t keyBlock[KEYBLOCK_SIZE] = {0x00};
337 memset(candidates, 0, sizeof(candidates));
338 memset(keyBlock, 0, sizeof(keyBlock));
340 // Generate all possible keys for the first two unknown bytes.
341 for (uint16_t i = 0; i < 0xFFFF; ++i) {
342 uint32_t j = i * 6;
343 candidates[0 + j] = i >> 8;
344 candidates[1 + j] = i;
345 candidates[2 + j] = key[2];
346 candidates[3 + j] = key[3];
347 candidates[4 + j] = key[4];
348 candidates[5 + j] = key[5];
350 uint32_t counter, i;
351 for (i = 0, counter = 1; i < CANDIDATE_SIZE; i += KEYBLOCK_SIZE, ++counter) {
353 key64 = 0;
355 // copy candidatekeys to test key block
356 memcpy(keyBlock, candidates + i, KEYBLOCK_SIZE);
358 // check a block of generated key candidates.
359 if (mfCheckKeys(blockNo, keyType, true, KEYS_IN_BLOCK, keyBlock, &key64) == PM3_SUCCESS) {
360 *resultkey = key64;
361 found = true;
362 break;
365 // progress
366 if (counter % 20 == 0)
367 PrintAndLogEx(SUCCESS, "tried : %s.. \t %u keys", sprint_hex(candidates + i, 6), counter * KEYS_IN_BLOCK);
369 return found;
372 // Compare 16 Bits out of cryptostate
373 inline static int Compare16Bits(const void *a, const void *b) {
374 if ((*(uint64_t *)b & 0x00ff000000ff0000) == (*(uint64_t *)a & 0x00ff000000ff0000)) return 0;
375 if ((*(uint64_t *)b & 0x00ff000000ff0000) > (*(uint64_t *)a & 0x00ff000000ff0000)) return 1;
376 return -1;
379 // wrapper function for multi-threaded lfsr_recovery32
380 static void
381 #ifdef __has_attribute
382 #if __has_attribute(force_align_arg_pointer)
383 __attribute__((force_align_arg_pointer))
384 #endif
385 #endif
386 *nested_worker_thread(void *arg) {
387 struct Crypto1State *p1;
388 StateList_t *statelist = arg;
389 statelist->head.slhead = lfsr_recovery32(statelist->ks1, statelist->nt_enc ^ statelist->uid);
391 for (p1 = statelist->head.slhead; p1->odd | p1->even; p1++) {};
393 statelist->len = p1 - statelist->head.slhead;
394 statelist->tail.sltail = --p1;
396 qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits);
398 return statelist->head.slhead;
401 int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) {
403 uint32_t uid;
404 StateList_t statelists[2];
405 struct Crypto1State *p1, *p2, *p3, *p4;
407 struct {
408 uint8_t block;
409 uint8_t keytype;
410 uint8_t target_block;
411 uint8_t target_keytype;
412 bool calibrate;
413 uint8_t key[6];
414 } PACKED payload;
415 payload.block = blockNo;
416 payload.keytype = keyType;
417 payload.target_block = trgBlockNo;
418 payload.target_keytype = trgKeyType;
419 payload.calibrate = calibrate;
420 memcpy(payload.key, key, sizeof(payload.key));
422 PacketResponseNG resp;
423 clearCommandBuffer();
424 SendCommandNG(CMD_HF_MIFARE_NESTED, (uint8_t *)&payload, sizeof(payload));
426 if (!WaitForResponseTimeout(CMD_HF_MIFARE_NESTED, &resp, 2000)) {
427 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
428 return PM3_ETIMEOUT;
431 struct p {
432 int16_t isOK;
433 uint8_t block;
434 uint8_t keytype;
435 uint8_t cuid[4];
436 uint8_t nt_a[4];
437 uint8_t ks_a[4];
438 uint8_t nt_b[4];
439 uint8_t ks_b[4];
440 } PACKED;
441 struct p *package = (struct p *)resp.data.asBytes;
443 // error during nested on device side
444 if (package->isOK != PM3_SUCCESS)
445 return package->isOK;
447 memcpy(&uid, package->cuid, sizeof(package->cuid));
449 for (uint8_t i = 0; i < 2; i++) {
450 statelists[i].blockNo = package->block;
451 statelists[i].keyType = package->keytype;
452 statelists[i].uid = uid;
455 memcpy(&statelists[0].nt_enc, package->nt_a, sizeof(package->nt_a));
456 memcpy(&statelists[0].ks1, package->ks_a, sizeof(package->ks_a));
458 memcpy(&statelists[1].nt_enc, package->nt_b, sizeof(package->nt_b));
459 memcpy(&statelists[1].ks1, package->ks_b, sizeof(package->ks_b));
461 // calc keys
462 pthread_t thread_id[2];
464 // create and run worker threads
465 for (uint8_t i = 0; i < 2; i++)
466 pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]);
468 // wait for threads to terminate:
469 for (uint8_t i = 0; i < 2; i++)
470 pthread_join(thread_id[i], (void *)&statelists[i].head.slhead);
472 // the first 16 Bits of the cryptostate already contain part of our key.
473 // Create the intersection of the two lists based on these 16 Bits and
474 // roll back the cryptostate
475 p1 = p3 = statelists[0].head.slhead;
476 p2 = p4 = statelists[1].head.slhead;
478 while (p1 <= statelists[0].tail.sltail && p2 <= statelists[1].tail.sltail) {
479 if (Compare16Bits(p1, p2) == 0) {
481 struct Crypto1State savestate;
482 savestate = *p1;
483 while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) {
484 *p3 = *p1;
485 lfsr_rollback_word(p3, statelists[0].nt_enc ^ statelists[0].uid, 0);
486 p3++;
487 p1++;
489 savestate = *p2;
490 while (Compare16Bits(p2, &savestate) == 0 && p2 <= statelists[1].tail.sltail) {
491 *p4 = *p2;
492 lfsr_rollback_word(p4, statelists[1].nt_enc ^ statelists[1].uid, 0);
493 p4++;
494 p2++;
496 } else {
497 while (Compare16Bits(p1, p2) == -1) p1++;
498 while (Compare16Bits(p1, p2) == 1) p2++;
502 p3->odd = -1;
503 p3->even = -1;
504 p4->odd = -1;
505 p4->even = -1;
506 statelists[0].len = p3 - statelists[0].head.slhead;
507 statelists[1].len = p4 - statelists[1].head.slhead;
508 statelists[0].tail.sltail = --p3;
509 statelists[1].tail.sltail = --p4;
511 // the statelists now contain possible keys. The key we are searching for must be in the
512 // intersection of both lists
513 qsort(statelists[0].head.keyhead, statelists[0].len, sizeof(uint64_t), compare_uint64);
514 qsort(statelists[1].head.keyhead, statelists[1].len, sizeof(uint64_t), compare_uint64);
515 // Create the intersection
516 statelists[0].len = intersection(statelists[0].head.keyhead, statelists[1].head.keyhead);
518 //statelists[0].tail.keytail = --p7;
519 uint32_t keycnt = statelists[0].len;
520 if (keycnt == 0) goto out;
522 PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") " key candidates", keycnt);
524 memset(resultKey, 0, 6);
525 uint64_t key64 = -1;
527 // The list may still contain several key candidates. Test each of them with mfCheckKeys
528 uint32_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt;
529 uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00};
531 for (uint32_t i = 0; i < keycnt; i += max_keys) {
533 uint64_t start_time = msclock();
535 uint8_t size = keycnt - i > max_keys ? max_keys : keycnt - i;
537 register uint8_t j;
538 for (j = 0; j < size; j++) {
539 crypto1_get_lfsr(statelists[0].head.slhead + i, &key64);
540 num_to_bytes(key64, 6, keyBlock + j * 6);
543 if (mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) {
544 free(statelists[0].head.slhead);
545 free(statelists[1].head.slhead);
546 num_to_bytes(key64, 6, resultKey);
548 PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]",
549 package->block,
550 package->keytype ? 'B' : 'A',
551 sprint_hex_inrow(resultKey, 6)
553 return PM3_SUCCESS;
556 float bruteforce_per_second = (float)(i + max_keys) / ((msclock() - start_time) / 1000.0);
557 PrintAndLogEx(INPLACE, "%6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second);
560 out:
561 PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c",
562 package->block,
563 package->keytype ? 'B' : 'A'
566 free(statelists[0].head.slhead);
567 free(statelists[1].head.slhead);
568 return PM3_ESOFT;
572 int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) {
574 uint32_t uid;
575 StateList_t statelists[1];
576 struct Crypto1State *p1, *p3;
578 struct {
579 uint8_t block;
580 uint8_t keytype;
581 uint8_t target_block;
582 uint8_t target_keytype;
583 uint8_t key[6];
584 } PACKED payload;
585 payload.block = blockNo;
586 payload.keytype = keyType;
587 payload.target_block = trgBlockNo;
588 payload.target_keytype = trgKeyType;
589 memcpy(payload.key, key, sizeof(payload.key));
591 PacketResponseNG resp;
592 clearCommandBuffer();
593 SendCommandNG(CMD_HF_MIFARE_STATIC_NESTED, (uint8_t *)&payload, sizeof(payload));
595 if (!WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NESTED, &resp, 2000))
596 return PM3_ETIMEOUT;
598 if (resp.status != PM3_SUCCESS)
599 return resp.status;
601 struct p {
602 int16_t isOK;
603 uint8_t block;
604 uint8_t keytype;
605 uint8_t cuid[4];
606 uint8_t nt[4];
607 uint8_t ks[4];
608 } PACKED;
609 struct p *package = (struct p *)resp.data.asBytes;
611 // error during collecting static nested information
612 if (package->isOK == 0) return PM3_EUNDEF;
614 memcpy(&uid, package->cuid, sizeof(package->cuid));
616 statelists[0].blockNo = package->block;
617 statelists[0].keyType = package->keytype;
618 statelists[0].uid = uid;
620 memcpy(&statelists[0].nt_enc, package->nt, sizeof(package->nt));
621 memcpy(&statelists[0].ks1, package->ks, sizeof(package->ks));
623 // calc keys
624 pthread_t t;
626 // create and run worker thread
627 pthread_create(&t, NULL, nested_worker_thread, &statelists[0]);
629 // wait for thread to terminate:
630 pthread_join(t, (void *)&statelists[0].head.slhead);
632 // the first 16 Bits of the cryptostate already contain part of our key.
633 p1 = p3 = statelists[0].head.slhead;
635 // create key candidates.
636 while (p1 <= statelists[0].tail.sltail) {
637 struct Crypto1State savestate;
638 savestate = *p1;
639 while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) {
640 *p3 = *p1;
641 lfsr_rollback_word(p3, statelists[0].nt_enc ^ statelists[0].uid, 0);
642 p3++;
643 p1++;
647 p3->odd = -1;
648 p3->even = -1;
649 statelists[0].len = p3 - statelists[0].head.slhead;
650 statelists[0].tail.sltail = --p3;
652 uint32_t keycnt = statelists[0].len;
653 if (keycnt == 0) goto out;
655 PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") " key candidates", keycnt);
657 memset(resultKey, 0, 6);
658 uint64_t key64 = -1;
660 // The list may still contain several key candidates. Test each of them with mfCheckKeys
661 uint32_t maxkeysinblock = IfPm3Flash() ? 1000 : KEYS_IN_BLOCK;
662 uint32_t max_keys_chunk = keycnt > maxkeysinblock ? maxkeysinblock : keycnt;
664 uint8_t *mem = calloc((maxkeysinblock * 6) + 5, sizeof(uint8_t));
665 if (mem == NULL) {
666 free(statelists[0].head.slhead);
667 return PM3_EMALLOC;
670 uint8_t *p_keyblock = mem + 5;
671 mem[0] = statelists[0].keyType;
672 mem[1] = statelists[0].blockNo;
673 mem[2] = 1;
674 mem[3] = ((max_keys_chunk >> 8) & 0xFF);
675 mem[4] = (max_keys_chunk & 0xFF);
677 uint8_t destfn[32];
678 strncpy((char *)destfn, "static_nested_000.bin", sizeof(destfn) - 1);
680 uint64_t start_time = msclock();
681 for (uint32_t i = 0; i < keycnt; i += max_keys_chunk) {
683 //flush queue
684 while (kbd_enter_pressed()) {
685 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
686 PrintAndLogEx(NORMAL, "");
687 free(mem);
688 return PM3_EOPABORTED;
691 int res = 0;
692 key64 = 0;
693 uint32_t chunk = keycnt - i > max_keys_chunk ? max_keys_chunk : keycnt - i;
695 // copy x keys to device.
696 for (uint32_t j = 0; j < chunk; j++) {
697 crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64);
698 num_to_bytes(key64, 6, p_keyblock + j * 6);
701 // check a block of generated key candidates.
702 if (IfPm3Flash()) {
704 mem[3] = ((chunk >> 8) & 0xFF);
705 mem[4] = (chunk & 0xFF);
707 // upload to flash.
708 res = flashmem_spiffs_load((char *)destfn, mem, 5 + (chunk * 6));
709 if (res != PM3_SUCCESS) {
710 PrintAndLogEx(WARNING, "\nSPIFFS upload failed");
711 free(mem);
712 return res;
714 res = mfCheckKeys_file(destfn, &key64);
715 } else {
716 res = mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, chunk, mem, &key64);
719 if (res == PM3_SUCCESS) {
720 p_keyblock = NULL;
721 free(statelists[0].head.slhead);
722 free(mem);
724 num_to_bytes(key64, 6, resultKey);
726 PrintAndLogEx(NORMAL, "");
727 PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]",
728 package->block,
729 package->keytype ? 'B' : 'A',
730 sprint_hex_inrow(resultKey, 6)
732 return PM3_SUCCESS;
733 } else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) {
734 PrintAndLogEx(NORMAL, "");
735 free(mem);
736 return res;
739 float bruteforce_per_second = (float)(i + max_keys_chunk) / ((msclock() - start_time) / 1000.0);
740 PrintAndLogEx(INPLACE, "%6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds", i, keycnt, bruteforce_per_second, (keycnt - i) / bruteforce_per_second);
743 p_keyblock = NULL;
744 free(mem);
746 out:
747 PrintAndLogEx(SUCCESS, "\ntarget block:%3u key type: %c",
748 package->block,
749 package->keytype ? 'B' : 'A'
752 free(statelists[0].head.slhead);
753 return PM3_ESOFT;
756 // MIFARE
757 int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) {
759 clearCommandBuffer();
760 SendCommandMIX(CMD_HF_MIFARE_READSC, sectorNo, keyType, 0, key, 6);
761 PacketResponseNG resp;
762 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
763 uint8_t isOK = resp.oldarg[0] & 0xff;
765 if (isOK) {
766 memcpy(data, resp.data.asBytes, mfNumBlocksPerSector(sectorNo) * 16);
767 return PM3_SUCCESS;
768 } else {
769 return PM3_EUNDEF;
771 } else {
772 PrintAndLogEx(DEBUG, "Command execute timeout");
773 return PM3_ETIMEOUT;
775 return PM3_SUCCESS;
778 int mfReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t *data) {
779 mf_readblock_t payload = {
780 .blockno = blockNo,
781 .keytype = keyType
783 memcpy(payload.key, key, sizeof(payload.key));
785 clearCommandBuffer();
786 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
787 PacketResponseNG resp;
788 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) {
789 memcpy(data, resp.data.asBytes, 16);
791 if (resp.status != PM3_SUCCESS) {
792 PrintAndLogEx(DEBUG, "failed reading block");
793 return PM3_ESOFT;
795 } else {
796 PrintAndLogEx(DEBUG, "Command execute timeout");
797 return PM3_ETIMEOUT;
799 return PM3_SUCCESS;
802 // EMULATOR
803 int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
805 size_t size = blocksCount * 16;
806 if (size > PM3_CMD_DATA_SIZE) {
807 return PM3_ESOFT;
810 struct {
811 uint8_t blockno;
812 uint8_t blockcnt;
813 } PACKED payload;
815 payload.blockno = blockNum;
816 payload.blockcnt = blocksCount;
818 clearCommandBuffer();
819 SendCommandNG(CMD_HF_MIFARE_EML_MEMGET, (uint8_t *)&payload, sizeof(payload));
821 PacketResponseNG resp;
822 if (WaitForResponseTimeout(CMD_HF_MIFARE_EML_MEMGET, &resp, 1500) == 0) {
823 PrintAndLogEx(WARNING, "Command execute timeout");
824 return PM3_ETIMEOUT;
827 if (resp.status == PM3_SUCCESS)
828 memcpy(data, resp.data.asBytes, size);
830 return resp.status;
833 int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
834 return mfEmlSetMem_xt(data, blockNum, blocksCount, 16);
837 int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
839 struct p {
840 uint8_t blockno;
841 uint8_t blockcnt;
842 uint8_t blockwidth;
843 uint8_t data[];
844 } PACKED;
846 size_t size = blocksCount * blockBtWidth;
847 if (size > (PM3_CMD_DATA_SIZE - sizeof(struct p))) {
848 return PM3_ESOFT;
851 size_t paylen = sizeof(struct p) + size;
852 struct p *payload = calloc(1, paylen);
854 payload->blockno = blockNum;
855 payload->blockcnt = blocksCount;
856 payload->blockwidth = blockBtWidth;
857 memcpy(payload->data, data, size);
859 clearCommandBuffer();
860 SendCommandNG(CMD_HF_MIFARE_EML_MEMSET, (uint8_t *)payload, paylen);
861 free(payload);
862 return PM3_SUCCESS;
865 // "MAGIC" CARD
866 int mfCSetUID(uint8_t *uid, uint8_t uidlen, uint8_t *atqa, uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard) {
868 uint8_t params = MAGIC_SINGLE;
869 uint8_t block0[16];
870 memset(block0, 0x00, sizeof(block0));
872 int res = mfCGetBlock(0, block0, params);
873 if (res == 0) {
874 PrintAndLogEx(SUCCESS, "old block 0... %s", sprint_hex_inrow(block0, sizeof(block0)));
875 if (old_uid) {
876 memcpy(old_uid, block0, uidlen);
878 } else {
879 PrintAndLogEx(INFO, "couldn't get old data. Will write over the last bytes of block 0");
882 // fill in the new values
883 // UID
884 memcpy(block0, uid, uidlen);
885 // Mifare UID BCC
886 if (uidlen == 4) {
887 block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3];
889 // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed)
890 if (sak)
891 block0[5] = sak[0];
893 if (atqa) {
894 block0[6] = atqa[1];
895 block0[7] = atqa[0];
898 } else if (uidlen == 7) {
899 block0[7] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3] ^ block0[4] ^ block0[5] ^ block0[6];
901 // mifare classic SAK(byte 8) and ATQA(byte 9 and 10, reversed)
902 if (sak)
903 block0[8] = sak[0];
905 if (atqa) {
906 block0[9] = atqa[1];
907 block0[10] = atqa[0];
911 PrintAndLogEx(SUCCESS, "new block 0... %s", sprint_hex_inrow(block0, 16));
913 if (wipecard) {
914 params |= MAGIC_WIPE;
917 res = mfCSetBlock(0, block0, NULL, params);
918 if (res == PM3_SUCCESS) {
919 params = MAGIC_SINGLE;
920 memset(block0, 0, sizeof(block0));
921 res = mfCGetBlock(0, block0, params);
922 if (res == 0) {
923 if (verifed_uid) {
924 memcpy(verifed_uid, block0, uidlen);
928 return res;
931 int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) {
932 uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF};
933 uint8_t blockD[16] = {0x00};
934 uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
935 uint8_t params = MAGIC_SINGLE;
937 if (uid != NULL) {
938 memcpy(block0, uid, 4);
939 block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3];
941 if (sak != NULL)
942 block0[5] = sak[0];
944 if (atqa != NULL) {
945 block0[6] = atqa[1];
946 block0[7] = atqa[0];
948 int res;
949 for (int blockNo = 0; blockNo < 4 * 16; blockNo++) {
950 for (int retry = 0; retry < 3; retry++) {
952 PrintAndLogEx(INPLACE, "wipe block %d", blockNo);
954 if (blockNo == 0) {
955 res = mfCSetBlock(blockNo, block0, NULL, params);
956 } else {
957 if (mfIsSectorTrailer(blockNo))
958 res = mfCSetBlock(blockNo, blockK, NULL, params);
959 else
960 res = mfCSetBlock(blockNo, blockD, NULL, params);
963 if (res == PM3_SUCCESS)
964 break;
966 PrintAndLogEx(WARNING, "retry block %d ...", blockNo);
969 if (res) {
970 PrintAndLogEx(ERR, "error setting block %d (%d)", blockNo, res);
971 return res;
974 DropField();
975 PrintAndLogEx(NORMAL, "");
976 return PM3_SUCCESS;
979 int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) {
981 clearCommandBuffer();
982 SendCommandMIX(CMD_HF_MIFARE_CSETBL, params, blockNo, 0, data, 16);
983 PacketResponseNG resp;
984 if (WaitForResponseTimeout(CMD_ACK, &resp, 3500)) {
985 uint8_t isOK = resp.oldarg[0] & 0xff;
986 if (uid != NULL)
987 memcpy(uid, resp.data.asBytes, 4);
988 if (!isOK)
989 return PM3_EUNDEF;
990 } else {
991 PrintAndLogEx(WARNING, "command execute timeout");
992 return PM3_ETIMEOUT;
994 return PM3_SUCCESS;
997 int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
998 clearCommandBuffer();
999 SendCommandMIX(CMD_HF_MIFARE_CGETBL, params, blockNo, 0, NULL, 0);
1000 PacketResponseNG resp;
1001 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
1002 uint8_t isOK = resp.oldarg[0] & 0xff;
1003 if (!isOK)
1004 return PM3_EUNDEF;
1005 memcpy(data, resp.data.asBytes, 16);
1006 } else {
1007 PrintAndLogEx(WARNING, "command execute timeout");
1008 return PM3_ETIMEOUT;
1010 return PM3_SUCCESS;
1013 int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid) {
1014 clearCommandBuffer();
1015 SendCommandMIX(CMD_HF_MIFARE_GEN3UID, uidlen, 0, 0, uid, uidlen);
1016 PacketResponseNG resp;
1017 if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3UID, &resp, 3500)) {
1018 if (resp.status == PM3_SUCCESS && oldUid) {
1019 memcpy(oldUid, resp.data.asBytes, uidlen);
1021 return resp.status;
1022 } else {
1023 PrintAndLogEx(WARNING, "Command execute timeout");
1024 return PM3_ETIMEOUT;
1028 int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock) {
1029 clearCommandBuffer();
1030 SendCommandMIX(CMD_HF_MIFARE_GEN3BLK, blockLen, 0, 0, block, 16);
1031 PacketResponseNG resp;
1032 if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3BLK, &resp, 3500)) {
1033 if (resp.status == PM3_SUCCESS && newBlock) {
1034 memcpy(newBlock, resp.data.asBytes, 16);
1036 return resp.status;
1037 } else {
1038 PrintAndLogEx(WARNING, "Command execute timeout");
1039 return PM3_ETIMEOUT;
1043 int mfGen3Freeze(void) {
1044 clearCommandBuffer();
1045 SendCommandNG(CMD_HF_MIFARE_GEN3FREEZ, NULL, 0);
1046 PacketResponseNG resp;
1047 if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3FREEZ, &resp, 3500)) {
1048 return resp.status;
1049 } else {
1050 PrintAndLogEx(WARNING, "Command execute timeout");
1051 return PM3_ETIMEOUT;
1055 int mfG3GetBlock(uint8_t blockno, uint8_t *data) {
1056 struct p {
1057 uint8_t blockno;
1058 } PACKED payload;
1059 payload.blockno = blockno;
1061 clearCommandBuffer();
1062 SendCommandNG(CMD_HF_MIFARE_G3_RDBL, (uint8_t*)&payload, sizeof(payload));
1063 PacketResponseNG resp;
1064 if (WaitForResponseTimeout(CMD_HF_MIFARE_G3_RDBL, &resp, 1500)) {
1065 if (resp.status != PM3_SUCCESS)
1066 return PM3_EUNDEF;
1067 memcpy(data, resp.data.asBytes, 16);
1068 } else {
1069 PrintAndLogEx(WARNING, "command execute timeout");
1070 return PM3_ETIMEOUT;
1072 return PM3_SUCCESS;
1076 // variables
1077 uint32_t cuid = 0; // uid part used for crypto1.
1079 void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted) {
1080 if (len != 1) {
1081 for (int i = 0; i < len; i++)
1082 data[i] = crypto1_byte(pcs, 0x00, isEncrypted) ^ data[i];
1083 } else {
1084 uint8_t bt = 0;
1085 bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 0)) << 0;
1086 bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 1)) << 1;
1087 bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 2)) << 2;
1088 bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 3)) << 3;
1089 data[0] = bt;
1093 int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len) {
1094 PrintAndLogEx(SUCCESS, "encrypted data... %s", sprint_hex(data, len));
1095 struct Crypto1State *s;
1096 uint32_t ks2 = ar_enc ^ prng_successor(nt, 64);
1097 uint32_t ks3 = at_enc ^ prng_successor(nt, 96);
1098 s = lfsr_recovery64(ks2, ks3);
1099 mf_crypto1_decrypt(s, data, len, false);
1100 PrintAndLogEx(SUCCESS, "decrypted data... " _YELLOW_("%s"), sprint_hex(data, len));
1101 PrintAndLogEx(NORMAL, "");
1102 crypto1_destroy(s);
1103 return PM3_SUCCESS;
1106 /* Detect Tag Prng,
1107 * function performs a partial AUTH, where it tries to authenticate against block0, key A, but only collects tag nonce.
1108 * the tag nonce is check to see if it has a predictable PRNG.
1109 * @returns
1110 * TRUE if tag uses WEAK prng (ie Now the NACK bug also needs to be present for Darkside attack)
1111 * FALSE is tag uses HARDEND prng (ie hardnested attack possible, with known key)
1113 int detect_classic_prng(void) {
1115 PacketResponseNG resp, respA;
1116 uint8_t cmd[] = {MIFARE_AUTH_KEYA, 0x00};
1117 uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS;
1119 clearCommandBuffer();
1120 SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(cmd), 0, cmd, sizeof(cmd));
1122 if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
1123 PrintAndLogEx(WARNING, "PRNG UID: Reply timeout.");
1124 return PM3_ETIMEOUT;
1127 // if select tag failed.
1128 if (resp.oldarg[0] == 0) {
1129 PrintAndLogEx(ERR, "error: selecting tag failed, can't detect prng\n");
1130 return PM3_ERFTRANS;
1132 if (!WaitForResponseTimeout(CMD_ACK, &respA, 2500)) {
1133 PrintAndLogEx(WARNING, "PRNG data: Reply timeout.");
1134 return PM3_ETIMEOUT;
1137 // check respA
1138 if (respA.oldarg[0] != 4) {
1139 PrintAndLogEx(ERR, "PRNG data error: Wrong length: %"PRIu64, respA.oldarg[0]);
1140 return PM3_ESOFT;
1143 uint32_t nonce = bytes_to_num(respA.data.asBytes, respA.oldarg[0]);
1144 return validate_prng_nonce(nonce);
1146 /* Detect Mifare Classic NACK bug
1148 returns:
1149 0 = error during test / aborted
1150 1 = has nack bug
1151 2 = has not nack bug
1152 3 = always leak nacks (clones)
1154 int detect_classic_nackbug(bool verbose) {
1156 clearCommandBuffer();
1157 SendCommandNG(CMD_HF_MIFARE_NACK_DETECT, NULL, 0);
1158 PacketResponseNG resp;
1160 PrintAndLogEx(INFO, "Checking for NACK bug");
1162 if (verbose)
1163 PrintAndLogEx(SUCCESS, "press pm3-button on the Proxmark3 device to abort both Proxmark3 and client.\n");
1165 while (true) {
1167 PrintAndLogEx(NORMAL, "." NOLF);
1168 if (kbd_enter_pressed()) {
1169 return PM3_EOPABORTED;
1172 if (WaitForResponseTimeout(CMD_HF_MIFARE_NACK_DETECT, &resp, 500)) {
1174 PrintAndLogEx(NORMAL, "");
1176 if (resp.status == PM3_EOPABORTED) {
1177 PrintAndLogEx(WARNING, "button pressed. Aborted.");
1178 return PM3_EOPABORTED;
1181 uint8_t ok = resp.data.asBytes[0];
1182 uint8_t nacks = resp.data.asBytes[1];
1183 uint16_t auths = bytes_to_num(resp.data.asBytes + 2, 2);
1185 if (verbose) {
1186 PrintAndLogEx(SUCCESS, "num of auth requests : %u", auths);
1187 PrintAndLogEx(SUCCESS, "num of received NACK : %u", nacks);
1189 switch (ok) {
1190 case 96 :
1191 case 98 : {
1192 if (verbose)
1193 PrintAndLogEx(FAILED, "card random number generator is not predictable.");
1194 PrintAndLogEx(WARNING, "detection failed");
1195 return PM3_SUCCESS;
1197 case 97 : {
1198 if (verbose) {
1199 PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial");
1200 PrintAndLogEx(FAILED, "with 16 effective bits only, but shows unexpected behavior, try again.");
1202 return PM3_SUCCESS;
1204 case 2 :
1205 PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("always leak NACK"));
1206 return PM3_SUCCESS;
1207 case 1 :
1208 PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("detected"));
1209 return PM3_SUCCESS;
1210 case 0 :
1211 PrintAndLogEx(SUCCESS, "NACK test: " _GREEN_("no bug"));
1212 return PM3_SUCCESS;
1213 default :
1214 PrintAndLogEx(ERR, "errorcode from device " _RED_("[%i]"), ok);
1215 return PM3_EUNDEF;
1217 break;
1220 return PM3_SUCCESS;
1223 /* Detect Mifare Classic Static / Fixed nonce
1224 detects special magic cards that has a static / fixed nonce
1225 returns:
1226 0 = has normal nonce
1227 1 = has static/fixed nonce
1228 2 = cmd failed
1230 int detect_classic_static_nonce(void) {
1232 clearCommandBuffer();
1233 SendCommandNG(CMD_HF_MIFARE_STATIC_NONCE, NULL, 0);
1234 PacketResponseNG resp;
1235 if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NONCE, &resp, 1000)) {
1237 if (resp.status == PM3_ESOFT)
1238 return NONCE_FAIL;
1240 return resp.data.asBytes[0];
1242 return NONCE_FAIL;
1245 /* try to see if card responses to "Chinese magic backdoor" commands. */
1246 int detect_mf_magic(bool is_mfc) {
1248 uint8_t isGeneration = 0;
1249 PacketResponseNG resp;
1250 clearCommandBuffer();
1251 uint8_t payload[] = { is_mfc };
1252 SendCommandNG(CMD_HF_MIFARE_CIDENT, payload, sizeof(payload));
1253 if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) {
1254 if (resp.status == PM3_SUCCESS)
1255 isGeneration = resp.data.asBytes[0];
1258 switch (isGeneration) {
1259 case MAGIC_GEN_1A:
1260 PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 1a"));
1261 break;
1262 case MAGIC_GEN_1B:
1263 PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 1b"));
1264 break;
1265 case MAGIC_GEN_2:
1266 PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Gen 2 / CUID"));
1267 break;
1268 case MAGIC_GEN_3:
1269 PrintAndLogEx(SUCCESS, "Magic capabilities : possibly " _GREEN_("Gen 3 / APDU"));
1270 break;
1271 case MAGIC_GEN_UNFUSED:
1272 PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("Write Once / FUID"));
1273 break;
1274 case MAGIC_SUPER:
1275 PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("super card"));
1276 break;
1277 case MAGIC_NTAG21X:
1278 PrintAndLogEx(SUCCESS, "Magic capabilities : " _GREEN_("NTAG21x"));
1279 break;
1280 default:
1281 break;
1283 return isGeneration;
1286 int detect_mfc_ev1_signature(uint8_t *signature) {
1287 if (signature == NULL) {
1288 return PM3_EINVARG;
1290 uint8_t sign[32] = {0};
1291 uint8_t key[] = {0x4b, 0x79, 0x1b, 0xea, 0x7b, 0xcc};
1292 int res = mfReadBlock(69, 1, key, sign);
1293 if (res == PM3_SUCCESS) {
1294 res = mfReadBlock(70, 1, key, sign + 16);
1295 if (res == PM3_SUCCESS) {
1296 memcpy(signature, sign, sizeof(sign));
1299 return res;