1 //-----------------------------------------------------------------------------
2 // Borrowed initially from https://nethemba.com/tag/darkside-attack/
3 // Copyright (C) mifare@nethemba.com, 2010
4 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // See LICENSE.txt for the text of the license.
17 //-----------------------------------------------------------------------------
19 //-----------------------------------------------------------------------------
20 #include "mifarehost.h"
28 #include "commonutil.h"
30 #include "ui.h" // PrintAndLog...
31 #include "crapto1/crapto1.h"
33 #include "protocols.h"
35 #include "util_posix.h" // msclock
36 #include "cmdparser.h" // detection of flash capabilities
37 #include "cmdflashmemspiffs.h" // upload to flash mem
38 #include "mifaredefault.h" // default keys
39 #include "protocol_vigik.h" // VIGIK struct
40 #include "crypto/libpcrypto.h"
41 #include "util.h" // xor
42 #include "mbedtls/sha1.h" // SHA1
47 int mfDarkside(uint8_t blockno
, uint8_t key_type
, uint64_t *key
) {
49 uint32_t nt
= 0, nr
= 0, ar
= 0;
50 uint64_t par_list
= 0, ks_list
= 0;
51 uint64_t *keylist
= NULL
, *last_keylist
= NULL
;
52 bool first_run
= true;
55 PrintAndLogEx(INFO
, "Expected execution time is about " _YELLOW_("25") " seconds on average");
56 PrintAndLogEx(INFO
, "Press " _GREEN_("pm3 button") " to abort");
61 //TODO: Not really stopping the command in time.
63 while (kbd_enter_pressed()) {
64 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
65 PrintAndLogEx(WARNING
, "Aborted via keyboard");
66 return PM3_EOPABORTED
;
74 payload
.first_run
= first_run
;
75 payload
.blockno
= blockno
;
76 payload
.key_type
= key_type
;
77 SendCommandNG(CMD_HF_MIFARE_READER
, (uint8_t *)&payload
, sizeof(payload
));
79 PrintAndLogEx(NORMAL
, "");
80 PrintAndLogEx(INFO
, "Running darkside " NOLF
);
84 PrintAndLogEx(NORMAL
, "." NOLF
);
86 if (IsCommunicationThreadDead()) return PM3_EIO
;
88 //TODO: Not really stopping the command in time.
89 if (kbd_enter_pressed()) {
90 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
91 PrintAndLogEx(WARNING
, "\nAborted via keyboard");
92 return PM3_EOPABORTED
;
95 PacketResponseNG resp
;
96 if (WaitForResponseTimeout(CMD_HF_MIFARE_READER
, &resp
, 2000)) {
108 struct p
*package
= (struct p
*)resp
.data
.asBytes
;
110 if (resp
.status
!= PM3_SUCCESS
) {
111 PrintAndLogEx(NORMAL
, "");
113 switch (package
->isOK
) {
115 PrintAndLogEx(FAILED
, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).");
118 PrintAndLogEx(FAILED
, "Card is not vulnerable to Darkside attack (its random number generator is not predictable).");
121 PrintAndLogEx(FAILED
, "Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown");
122 PrintAndLogEx(FAILED
, "generating polynomial with 16 effective bits only, but shows unexpected behaviour.");
125 PrintAndLogEx(WARNING
, "Button pressed. aborted");
131 PrintAndLogEx(FAILED
, "Unknown error. Darkside attack failed.");
138 uid
= (uint32_t)bytes_to_num(package
->cuid
, sizeof(package
->cuid
));
139 nt
= (uint32_t)bytes_to_num(package
->nt
, sizeof(package
->nr
));
140 par_list
= bytes_to_num(package
->par_list
, sizeof(package
->par_list
));
141 ks_list
= bytes_to_num(package
->ks_list
, sizeof(package
->ks_list
));
142 nr
= (uint32_t)bytes_to_num(package
->nr
, 4);
143 ar
= (uint32_t)bytes_to_num(package
->ar
, 4);
147 PrintAndLogEx(NORMAL
, "");
149 if (par_list
== 0 && first_run
== true) {
150 PrintAndLogEx(SUCCESS
, "Parity is all zero. Most likely this card sends NACK on every authentication.");
154 uint32_t keycount
= nonce2key(uid
, nt
, nr
, ar
, par_list
, ks_list
, &keylist
);
157 PrintAndLogEx(FAILED
, "Key not found (lfsr_common_prefix list is null). Nt = %08x", nt
);
158 PrintAndLogEx(FAILED
, "This is expected to happen in 25%% of all cases.");
159 PrintAndLogEx(FAILED
, "Trying again with a different reader nonce...");
163 // only parity zero attack
165 qsort(keylist
, keycount
, sizeof(*keylist
), compare_uint64
);
166 keycount
= intersection(last_keylist
, keylist
);
169 last_keylist
= keylist
;
170 PrintAndLogEx(FAILED
, "No candidates found, trying again");
175 PrintAndLogEx(SUCCESS
, "found " _YELLOW_("%u") " candidate key%s", keycount
, (keycount
> 1) ? "s" : "");
178 uint8_t keyBlock
[PM3_CMD_DATA_SIZE
];
179 uint32_t max_keys
= KEYS_IN_BLOCK
;
180 for (uint32_t i
= 0; i
< keycount
; i
+= max_keys
) {
182 uint8_t size
= keycount
- i
> max_keys
? max_keys
: keycount
- i
;
184 for (j
= 0; j
< size
; j
++) {
186 num_to_bytes(last_keylist
[i
* max_keys
+ j
], MIFARE_KEY_SIZE
, keyBlock
+ (j
* MIFARE_KEY_SIZE
));
188 num_to_bytes(keylist
[i
* max_keys
+ j
], MIFARE_KEY_SIZE
, keyBlock
+ (j
* MIFARE_KEY_SIZE
));
192 if (mfCheckKeys(blockno
, key_type
- 0x60, false, size
, keyBlock
, key
) == PM3_SUCCESS
) {
197 if (*key
!= UINT64_C(-1)) {
200 PrintAndLogEx(FAILED
, "All key candidates failed. Restarting darkside");
202 last_keylist
= keylist
;
211 int mfCheckKeys(uint8_t blockNo
, uint8_t keyType
, bool clear_trace
, uint8_t keycnt
, uint8_t *keyBlock
, uint64_t *key
) {
215 clearCommandBuffer();
216 uint8_t data
[PM3_CMD_DATA_SIZE
] = {0};
219 data
[2] = clear_trace
;
222 memcpy(data
+ 5, keyBlock
, MIFARE_KEY_SIZE
* keycnt
);
223 SendCommandNG(CMD_HF_MIFARE_CHKKEYS
, data
, (5 + MIFARE_KEY_SIZE
* keycnt
));
225 PacketResponseNG resp
;
226 if (WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS
, &resp
, 2500) == false) {
229 if (resp
.status
!= PM3_SUCCESS
) {
234 uint8_t key
[MIFARE_KEY_SIZE
];
237 struct kr
*keyresult
= (struct kr
*)&resp
.data
.asBytes
;
238 if (keyresult
->found
== false) {
243 *key
= bytes_to_num(keyresult
->key
, sizeof(keyresult
->key
));
248 // Sends chunks of keys to device.
249 // 0 == ok all keys found
251 // 2 == Time-out, aborting
252 int mfCheckKeys_fast_ex(uint8_t sectorsCnt
, uint8_t firstChunk
, uint8_t lastChunk
, uint8_t strategy
,
253 uint32_t size
, uint8_t *keyBlock
, sector_t
*e_sector
, bool use_flashmemory
,
254 bool verbose
, bool quiet
, uint16_t singleSectorParams
) {
256 uint64_t t2
= msclock();
259 clearCommandBuffer();
260 SendCommandOLD(CMD_HF_MIFARE_CHKKEYS_FAST
, (sectorsCnt
| (firstChunk
<< 8) | (lastChunk
<< 12) | (singleSectorParams
<< 16)), ((use_flashmemory
<< 8) | strategy
), size
, keyBlock
, 6 * size
);
261 PacketResponseNG resp
;
263 uint32_t timeout
= 0;
264 while (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
266 if (quiet
== false) {
267 PrintAndLogEx((timeout
) ? NORMAL
: INFO
, "." NOLF
);
273 // max timeout for one chunk of 85keys, 60*3sec = 180seconds
274 // s70 with 40*2 keys to check, 80*85 = 6800 auth.
275 // takes about 97s, still some margin before abort
277 PrintAndLogEx(WARNING
, "\nNo response from Proxmark3. Aborting...");
283 if (timeout
&& (quiet
== false)) {
284 PrintAndLogEx(NORMAL
, "");
287 // time to convert the returned data.
288 uint8_t curr_keys
= resp
.oldarg
[0];
290 if ((singleSectorParams
>> 15) & 1) {
292 uint64_t foo
= bytes_to_num(resp
.data
.asBytes
, 6);
293 PrintAndLogEx(NORMAL
, "");
294 PrintAndLogEx(SUCCESS
, _GREEN_("Key %s for block %2i found: %012" PRIx64
), (singleSectorParams
>> 8) & 1 ? "B" : "A", singleSectorParams
& 0xFF, foo
);
300 PrintAndLogEx(INFO
, "Chunk %.1fs | found %u/%u keys (%u)", (float)(t2
/ 1000.0), curr_keys
, (sectorsCnt
<< 1), size
);
304 if (curr_keys
== sectorsCnt
* 2 || lastChunk
) {
306 // success array. each byte is status of key
310 foo
= bytes_to_num(resp
.data
.asBytes
+ 480, 8);
311 bar
= (resp
.data
.asBytes
[489] << 8 | resp
.data
.asBytes
[488]);
313 for (uint8_t i
= 0; i
< 64; i
++) {
314 arr
[i
] = (foo
>> i
) & 0x1;
317 for (uint8_t i
= 0; i
< 16; i
++) {
318 arr
[i
+ 64] = (bar
>> i
) & 0x1;
321 // initialize storage for found keys
322 icesector_t
*tmp
= calloc(sectorsCnt
, sizeof(icesector_t
));
327 memcpy(tmp
, resp
.data
.asBytes
, sectorsCnt
* sizeof(icesector_t
));
329 for (int i
= 0; i
< sectorsCnt
; i
++) {
331 if (!e_sector
[i
].foundKey
[0]) {
332 e_sector
[i
].Key
[0] = bytes_to_num(tmp
[i
].keyA
, MIFARE_KEY_SIZE
);
333 e_sector
[i
].foundKey
[0] = arr
[(i
* 2) ];
336 if (!e_sector
[i
].foundKey
[1]) {
337 e_sector
[i
].Key
[1] = bytes_to_num(tmp
[i
].keyB
, MIFARE_KEY_SIZE
);
338 e_sector
[i
].foundKey
[1] = arr
[(i
* 2) + 1 ];
343 // if all keys where found
344 if (curr_keys
== sectorsCnt
* 2) {
348 // if some keys was found
360 int mfCheckKeys_fast(uint8_t sectorsCnt
, uint8_t firstChunk
, uint8_t lastChunk
, uint8_t strategy
,
361 uint32_t size
, uint8_t *keyBlock
, sector_t
*e_sector
, bool use_flashmemory
, bool verbose
) {
362 return mfCheckKeys_fast_ex(sectorsCnt
, firstChunk
, lastChunk
, strategy
, size
, keyBlock
, e_sector
, use_flashmemory
, verbose
, false, 0);
365 // Trigger device to use a binary file on flash mem as keylist for mfCheckKeys.
366 // As of now, 255 keys possible in the file
367 // 6 * 255 = 1500 bytes
368 int mfCheckKeys_file(uint8_t *destfn
, uint64_t *key
) {
370 clearCommandBuffer();
373 uint8_t filename
[32];
374 } PACKED payload_file
;
376 memcpy(payload_file
.filename
, destfn
, sizeof(payload_file
.filename
) - 1);
378 PacketResponseNG resp
;
379 clearCommandBuffer();
380 SendCommandNG(CMD_HF_MIFARE_CHKKEYS_FILE
, (uint8_t *)&payload_file
, sizeof(payload_file
));
384 while (!WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS
, &resp
, 2000)) {
387 while (kbd_enter_pressed()) {
388 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
389 return PM3_EOPABORTED
;
394 PrintAndLogEx(WARNING
, "Chk keys file, command execution time out");
395 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
400 if (resp
.status
!= PM3_SUCCESS
) return resp
.status
;
403 uint8_t key
[MIFARE_KEY_SIZE
];
406 struct kr
*keyresult
= (struct kr
*)&resp
.data
.asBytes
;
407 if (!keyresult
->found
) return PM3_ESOFT
;
409 *key
= bytes_to_num(keyresult
->key
, sizeof(keyresult
->key
));
413 // PM3 imp of J-Run mf_key_brute (part 2)
414 // ref: https://github.com/J-Run/mf_key_brute
415 int mfKeyBrute(uint8_t blockNo
, uint8_t keyType
, const uint8_t *key
, uint64_t *resultkey
) {
418 uint8_t found
= false;
419 uint8_t candidates
[CANDIDATE_SIZE
] = {0x00};
420 uint8_t keyBlock
[KEYBLOCK_SIZE
] = {0x00};
422 memset(candidates
, 0, sizeof(candidates
));
423 memset(keyBlock
, 0, sizeof(keyBlock
));
425 // Generate all possible keys for the first two unknown bytes.
426 for (uint16_t i
= 0; i
< 0xFFFF; ++i
) {
427 uint32_t j
= i
* MIFARE_KEY_SIZE
;
428 candidates
[0 + j
] = i
>> 8;
429 candidates
[1 + j
] = i
;
430 candidates
[2 + j
] = key
[2];
431 candidates
[3 + j
] = key
[3];
432 candidates
[4 + j
] = key
[4];
433 candidates
[5 + j
] = key
[5];
436 for (i
= 0, counter
= 1; i
< CANDIDATE_SIZE
; i
+= KEYBLOCK_SIZE
, ++counter
) {
440 // copy candidatekeys to test key block
441 memcpy(keyBlock
, candidates
+ i
, KEYBLOCK_SIZE
);
443 // check a block of generated key candidates.
444 if (mfCheckKeys(blockNo
, keyType
, true, KEYS_IN_BLOCK
, keyBlock
, &key64
) == PM3_SUCCESS
) {
451 if (counter
% 20 == 0)
452 PrintAndLogEx(SUCCESS
, "tried %s.. \t %u keys", sprint_hex(candidates
+ i
, 6), counter
* KEYS_IN_BLOCK
);
457 // Compare 16 Bits out of cryptostate
458 inline static int Compare16Bits(const void *a
, const void *b
) {
459 if ((*(uint64_t *)b
& 0x00ff000000ff0000) == (*(uint64_t *)a
& 0x00ff000000ff0000)) return 0;
460 if ((*(uint64_t *)b
& 0x00ff000000ff0000) > (*(uint64_t *)a
& 0x00ff000000ff0000)) return 1;
464 // wrapper function for multi-threaded lfsr_recovery32
466 #ifdef __has_attribute
467 #if __has_attribute(force_align_arg_pointer)
468 __attribute__((force_align_arg_pointer
))
471 *nested_worker_thread(void *arg
) {
472 struct Crypto1State
*p1
;
473 StateList_t
*statelist
= arg
;
474 statelist
->head
.slhead
= lfsr_recovery32(statelist
->ks1
, statelist
->nt_enc
^ statelist
->uid
);
476 for (p1
= statelist
->head
.slhead
; p1
->odd
| p1
->even
; p1
++) {};
478 statelist
->len
= p1
- statelist
->head
.slhead
;
479 statelist
->tail
.sltail
= --p1
;
481 qsort(statelist
->head
.slhead
, statelist
->len
, sizeof(uint64_t), Compare16Bits
);
483 return statelist
->head
.slhead
;
486 int mfnested(uint8_t blockNo
, uint8_t keyType
, uint8_t *key
, uint8_t trgBlockNo
, uint8_t trgKeyType
, uint8_t *resultKey
, bool calibrate
) {
489 StateList_t statelists
[2];
490 struct Crypto1State
*p1
, *p2
, *p3
, *p4
;
495 uint8_t target_block
;
496 uint8_t target_keytype
;
500 payload
.block
= blockNo
;
501 payload
.keytype
= keyType
;
502 payload
.target_block
= trgBlockNo
;
503 payload
.target_keytype
= trgKeyType
;
504 payload
.calibrate
= calibrate
;
505 memcpy(payload
.key
, key
, sizeof(payload
.key
));
507 PacketResponseNG resp
;
508 clearCommandBuffer();
509 SendCommandNG(CMD_HF_MIFARE_NESTED
, (uint8_t *)&payload
, sizeof(payload
));
511 if (WaitForResponseTimeout(CMD_HF_MIFARE_NESTED
, &resp
, 2000) == false) {
512 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
526 struct p
*package
= (struct p
*)resp
.data
.asBytes
;
528 // error during nested on device side
529 if (package
->isOK
!= PM3_SUCCESS
)
530 return package
->isOK
;
532 memcpy(&uid
, package
->cuid
, sizeof(package
->cuid
));
534 for (uint8_t i
= 0; i
< 2; i
++) {
535 statelists
[i
].blockNo
= package
->block
;
536 statelists
[i
].keyType
= package
->keytype
;
537 statelists
[i
].uid
= uid
;
540 memcpy(&statelists
[0].nt_enc
, package
->nt_a
, sizeof(package
->nt_a
));
541 memcpy(&statelists
[0].ks1
, package
->ks_a
, sizeof(package
->ks_a
));
543 memcpy(&statelists
[1].nt_enc
, package
->nt_b
, sizeof(package
->nt_b
));
544 memcpy(&statelists
[1].ks1
, package
->ks_b
, sizeof(package
->ks_b
));
547 pthread_t thread_id
[2];
549 // create and run worker threads
550 for (uint8_t i
= 0; i
< 2; i
++)
551 pthread_create(thread_id
+ i
, NULL
, nested_worker_thread
, &statelists
[i
]);
553 // wait for threads to terminate:
554 for (uint8_t i
= 0; i
< 2; i
++)
555 pthread_join(thread_id
[i
], (void *)&statelists
[i
].head
.slhead
);
557 // the first 16 Bits of the cryptostate already contain part of our key.
558 // Create the intersection of the two lists based on these 16 Bits and
559 // roll back the cryptostate
560 p1
= p3
= statelists
[0].head
.slhead
;
561 p2
= p4
= statelists
[1].head
.slhead
;
563 while (p1
<= statelists
[0].tail
.sltail
&& p2
<= statelists
[1].tail
.sltail
) {
564 if (Compare16Bits(p1
, p2
) == 0) {
566 struct Crypto1State savestate
;
568 while (Compare16Bits(p1
, &savestate
) == 0 && p1
<= statelists
[0].tail
.sltail
) {
570 lfsr_rollback_word(p3
, statelists
[0].nt_enc
^ statelists
[0].uid
, 0);
575 while (Compare16Bits(p2
, &savestate
) == 0 && p2
<= statelists
[1].tail
.sltail
) {
577 lfsr_rollback_word(p4
, statelists
[1].nt_enc
^ statelists
[1].uid
, 0);
582 while (Compare16Bits(p1
, p2
) == -1) p1
++;
583 while (Compare16Bits(p1
, p2
) == 1) p2
++;
591 statelists
[0].len
= p3
- statelists
[0].head
.slhead
;
592 statelists
[1].len
= p4
- statelists
[1].head
.slhead
;
593 statelists
[0].tail
.sltail
= --p3
;
594 statelists
[1].tail
.sltail
= --p4
;
596 // the statelists now contain possible keys. The key we are searching for must be in the
597 // intersection of both lists
598 qsort(statelists
[0].head
.keyhead
, statelists
[0].len
, sizeof(uint64_t), compare_uint64
);
599 qsort(statelists
[1].head
.keyhead
, statelists
[1].len
, sizeof(uint64_t), compare_uint64
);
600 // Create the intersection
601 statelists
[0].len
= intersection(statelists
[0].head
.keyhead
, statelists
[1].head
.keyhead
);
603 //statelists[0].tail.keytail = --p7;
604 uint32_t keycnt
= statelists
[0].len
;
605 if (keycnt
== 0) goto out
;
607 PrintAndLogEx(SUCCESS
, "Found " _YELLOW_("%u") " key candidates", keycnt
);
609 memset(resultKey
, 0, MIFARE_KEY_SIZE
);
612 // The list may still contain several key candidates. Test each of them with mfCheckKeys
613 uint32_t max_keys
= keycnt
> KEYS_IN_BLOCK
? KEYS_IN_BLOCK
: keycnt
;
614 uint8_t keyBlock
[PM3_CMD_DATA_SIZE
] = {0x00};
616 for (uint32_t i
= 0; i
< keycnt
; i
+= max_keys
) {
618 uint64_t start_time
= msclock();
620 uint8_t size
= keycnt
- i
> max_keys
? max_keys
: keycnt
- i
;
623 for (j
= 0; j
< size
; j
++) {
624 crypto1_get_lfsr(statelists
[0].head
.slhead
+ i
, &key64
);
625 num_to_bytes(key64
, 6, keyBlock
+ j
* MIFARE_KEY_SIZE
);
628 if (mfCheckKeys(statelists
[0].blockNo
, statelists
[0].keyType
, false, size
, keyBlock
, &key64
) == PM3_SUCCESS
) {
629 free(statelists
[0].head
.slhead
);
630 free(statelists
[1].head
.slhead
);
631 num_to_bytes(key64
, 6, resultKey
);
633 if (package
->keytype
< 2) {
634 PrintAndLogEx(SUCCESS
, "\nTarget block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]",
636 package
->keytype
? 'B' : 'A',
637 sprint_hex_inrow(resultKey
, MIFARE_KEY_SIZE
)
640 PrintAndLogEx(SUCCESS
, "\nTarget block %4u key type %02x -- found valid key [ " _GREEN_("%s") " ]",
642 MIFARE_AUTH_KEYA
+ package
->keytype
,
643 sprint_hex_inrow(resultKey
, MIFARE_KEY_SIZE
)
651 float bruteforce_per_second
= (float)(i
+ max_keys
) / ((msclock() - start_time
) / 1000.0);
652 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
);
656 if (package
->keytype
< 2) {
657 PrintAndLogEx(SUCCESS
, "\nTarget block %4u key type %c",
659 package
->keytype
? 'B' : 'A'
662 PrintAndLogEx(SUCCESS
, "\nTarget block %4u key type %02x",
664 MIFARE_AUTH_KEYA
+ package
->keytype
667 free(statelists
[0].head
.slhead
);
668 free(statelists
[1].head
.slhead
);
672 int mfStaticNested(uint8_t blockNo
, uint8_t keyType
, uint8_t *key
, uint8_t trgBlockNo
, uint8_t trgKeyType
, uint8_t *resultKey
) {
675 StateList_t statelists
[2];
676 struct Crypto1State
*p1
, *p2
, *p3
, *p4
;
681 uint8_t target_block
;
682 uint8_t target_keytype
;
685 payload
.block
= blockNo
;
686 payload
.keytype
= keyType
;
687 payload
.target_block
= trgBlockNo
;
688 payload
.target_keytype
= trgKeyType
;
689 memcpy(payload
.key
, key
, sizeof(payload
.key
));
691 PacketResponseNG resp
;
692 clearCommandBuffer();
693 SendCommandNG(CMD_HF_MIFARE_STATIC_NESTED
, (uint8_t *)&payload
, sizeof(payload
));
695 if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NESTED
, &resp
, 2000) == false)
698 if (resp
.status
!= PM3_SUCCESS
)
710 struct p
*package
= (struct p
*)resp
.data
.asBytes
;
712 memcpy(&uid
, package
->cuid
, sizeof(package
->cuid
));
714 for (uint8_t i
= 0; i
< 2; i
++) {
715 statelists
[i
].blockNo
= package
->block
;
716 statelists
[i
].keyType
= package
->keytype
;
717 statelists
[i
].uid
= uid
;
720 memcpy(&statelists
[0].nt_enc
, package
->nt_a
, sizeof(package
->nt_a
));
721 memcpy(&statelists
[0].ks1
, package
->ks_a
, sizeof(package
->ks_a
));
723 memcpy(&statelists
[1].nt_enc
, package
->nt_b
, sizeof(package
->nt_b
));
724 memcpy(&statelists
[1].ks1
, package
->ks_b
, sizeof(package
->ks_b
));
727 pthread_t thread_id
[2];
729 // create and run worker threads
730 for (uint8_t i
= 0; i
< 2; i
++)
731 pthread_create(thread_id
+ i
, NULL
, nested_worker_thread
, &statelists
[i
]);
733 // wait for threads to terminate:
734 for (uint8_t i
= 0; i
< 2; i
++)
735 pthread_join(thread_id
[i
], (void *)&statelists
[i
].head
.slhead
);
737 // the first 16 Bits of the cryptostate already contain part of our key.
738 // Create the intersection of the two lists based on these 16 Bits and
739 // roll back the cryptostate
740 p1
= p3
= statelists
[0].head
.slhead
;
741 p2
= p4
= statelists
[1].head
.slhead
;
743 while (p1
<= statelists
[0].tail
.sltail
&& p2
<= statelists
[1].tail
.sltail
) {
744 if (Compare16Bits(p1
, p2
) == 0) {
746 struct Crypto1State savestate
;
748 while (Compare16Bits(p1
, &savestate
) == 0 && p1
<= statelists
[0].tail
.sltail
) {
750 lfsr_rollback_word(p3
, statelists
[0].nt_enc
^ statelists
[0].uid
, 0);
755 while (Compare16Bits(p2
, &savestate
) == 0 && p2
<= statelists
[1].tail
.sltail
) {
757 lfsr_rollback_word(p4
, statelists
[1].nt_enc
^ statelists
[1].uid
, 0);
762 while (Compare16Bits(p1
, p2
) == -1) p1
++;
763 while (Compare16Bits(p1
, p2
) == 1) p2
++;
771 statelists
[0].len
= p3
- statelists
[0].head
.slhead
;
772 statelists
[1].len
= p4
- statelists
[1].head
.slhead
;
773 statelists
[0].tail
.sltail
= --p3
;
774 statelists
[1].tail
.sltail
= --p4
;
776 // the statelists now contain possible keys. The key we are searching for must be in the
777 // intersection of both lists
778 qsort(statelists
[0].head
.keyhead
, statelists
[0].len
, sizeof(uint64_t), compare_uint64
);
779 qsort(statelists
[1].head
.keyhead
, statelists
[1].len
, sizeof(uint64_t), compare_uint64
);
780 // Create the intersection
781 statelists
[0].len
= intersection(statelists
[0].head
.keyhead
, statelists
[1].head
.keyhead
);
786 memcpy(&uid, package->cuid, sizeof(package->cuid));
788 statelists[0].blockNo = package->block;
789 statelists[0].keyType = package->keytype;
790 statelists[0].uid = uid;
792 memcpy(&statelists[0].nt_enc, package->nt, sizeof(package->nt));
793 memcpy(&statelists[0].ks1, package->ks, sizeof(package->ks));
798 // create and run worker thread
799 pthread_create(&t, NULL, nested_worker_thread, &statelists[0]);
801 // wait for thread to terminate:
802 pthread_join(t, (void *)&statelists[0].head.slhead);
804 // the first 16 Bits of the cryptostate already contain part of our key.
805 p1 = p3 = statelists[0].head.slhead;
807 // create key candidates.
808 while (p1 <= statelists[0].tail.sltail) {
809 struct Crypto1State savestate;
811 while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) {
813 lfsr_rollback_word(p3, statelists[0].nt_enc ^ statelists[0].uid, 0);
821 statelists[0].len = p3 - statelists[0].head.slhead;
822 statelists[0].tail.sltail = --p3;
825 uint32_t keycnt
= statelists
[0].len
;
830 PrintAndLogEx(SUCCESS
, "Found " _YELLOW_("%u") " key candidates", keycnt
);
832 memset(resultKey
, 0, MIFARE_KEY_SIZE
);
834 // The list may still contain several key candidates. Test each of them with mfCheckKeys
835 uint32_t maxkeysinblock
= IfPm3Flash() ? 1000 : KEYS_IN_BLOCK
;
836 uint32_t max_keys_chunk
= keycnt
> maxkeysinblock
? maxkeysinblock
: keycnt
;
839 uint8_t *p_keyblock
= NULL
;
841 // if RDV4 and more than 10 candidate keys
842 if (IfPm3Flash() && keycnt
> 70) {
844 // used for mfCheckKeys_file, which needs a header
845 mem
= calloc((maxkeysinblock
* MIFARE_KEY_SIZE
) + 5, sizeof(uint8_t));
847 free(statelists
[0].head
.slhead
);
851 mem
[0] = statelists
[0].keyType
;
852 mem
[1] = statelists
[0].blockNo
;
854 mem
[3] = ((max_keys_chunk
>> 8) & 0xFF);
855 mem
[4] = (max_keys_chunk
& 0xFF);
857 p_keyblock
= mem
+ 5;
860 // used for mfCheckKeys, which adds its own header.
861 mem
= calloc((maxkeysinblock
* MIFARE_KEY_SIZE
), sizeof(uint8_t));
863 free(statelists
[0].head
.slhead
);
869 uint8_t fn
[32] = "static_nested_000.bin";
871 uint64_t start_time
= msclock();
872 for (uint32_t i
= 0; i
< keycnt
; i
+= max_keys_chunk
) {
875 while (kbd_enter_pressed()) {
876 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
877 PrintAndLogEx(NORMAL
, "");
879 return PM3_EOPABORTED
;
884 uint32_t chunk
= keycnt
- i
> max_keys_chunk
? max_keys_chunk
: keycnt
- i
;
886 // copy x keys to device.
887 for (uint32_t j
= 0; j
< chunk
; j
++) {
888 crypto1_get_lfsr(statelists
[0].head
.slhead
+ i
+ j
, &key64
);
889 num_to_bytes(key64
, MIFARE_KEY_SIZE
, p_keyblock
+ j
* MIFARE_KEY_SIZE
);
892 // check a block of generated key candidates.
893 if (IfPm3Flash() && keycnt
> 70) {
895 mem
[3] = ((chunk
>> 8) & 0xFF);
896 mem
[4] = (chunk
& 0xFF);
899 res
= flashmem_spiffs_load((char *)fn
, mem
, 5 + (chunk
* MIFARE_KEY_SIZE
));
900 if (res
!= PM3_SUCCESS
) {
901 PrintAndLogEx(WARNING
, "\nSPIFFS upload failed");
905 res
= mfCheckKeys_file(fn
, &key64
);
907 res
= mfCheckKeys(statelists
[0].blockNo
, statelists
[0].keyType
, true, chunk
, mem
, &key64
);
910 if (res
== PM3_SUCCESS
) {
912 free(statelists
[0].head
.slhead
);
915 num_to_bytes(key64
, MIFARE_KEY_SIZE
, resultKey
);
917 if (IfPm3Flash() && keycnt
> 70)
918 PrintAndLogEx(NORMAL
, "");
920 PrintAndLogEx(SUCCESS
, "target block %4u key type %c -- found valid key [ " _GREEN_("%s") " ]",
922 package
->keytype
? 'B' : 'A',
923 sprint_hex_inrow(resultKey
, MIFARE_KEY_SIZE
)
926 } else if (res
== PM3_ETIMEOUT
|| res
== PM3_EOPABORTED
) {
927 PrintAndLogEx(NORMAL
, "");
932 float bruteforce_per_second
= (float)(i
+ max_keys_chunk
) / ((msclock() - start_time
) / 1000.0);
933 PrintAndLogEx(INPLACE
, "%6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds", i
, keycnt
, bruteforce_per_second
, (keycnt
- i
) / bruteforce_per_second
);
941 PrintAndLogEx(SUCCESS
, "\nTarget block %4u key type %c",
943 package
->keytype
? 'B' : 'A'
946 free(statelists
[0].head
.slhead
);
947 free(statelists
[1].head
.slhead
);
952 int mfReadSector(uint8_t sectorNo
, uint8_t keyType
, const uint8_t *key
, uint8_t *data
) {
954 clearCommandBuffer();
955 SendCommandMIX(CMD_HF_MIFARE_READSC
, sectorNo
, keyType
, 0, (uint8_t *)key
, MIFARE_KEY_SIZE
);
956 PacketResponseNG resp
;
957 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
958 uint8_t isOK
= resp
.oldarg
[0] & 0xFF;
961 memcpy(data
, resp
.data
.asBytes
, mfNumBlocksPerSector(sectorNo
) * MFBLOCK_SIZE
);
967 PrintAndLogEx(DEBUG
, "command execution time out");
973 int mfReadBlock(uint8_t blockNo
, uint8_t keyType
, const uint8_t *key
, uint8_t *data
) {
974 mf_readblock_t payload
= {
978 memcpy(payload
.key
, key
, sizeof(payload
.key
));
980 clearCommandBuffer();
981 SendCommandNG(CMD_HF_MIFARE_READBL
, (uint8_t *)&payload
, sizeof(mf_readblock_t
));
982 PacketResponseNG resp
;
983 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL
, &resp
, 1500)) {
984 memcpy(data
, resp
.data
.asBytes
, MFBLOCK_SIZE
);
986 if (resp
.status
!= PM3_SUCCESS
) {
987 PrintAndLogEx(DEBUG
, "failed reading block");
991 PrintAndLogEx(DEBUG
, "command execution time out");
998 int mfEmlGetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
1000 size_t size
= blocksCount
* MFBLOCK_SIZE
;
1001 if (size
> PM3_CMD_DATA_SIZE
) {
1010 payload
.blockno
= blockNum
;
1011 payload
.blockcnt
= blocksCount
;
1013 clearCommandBuffer();
1014 SendCommandNG(CMD_HF_MIFARE_EML_MEMGET
, (uint8_t *)&payload
, sizeof(payload
));
1016 PacketResponseNG resp
;
1017 if (WaitForResponseTimeout(CMD_HF_MIFARE_EML_MEMGET
, &resp
, 1500) == 0) {
1018 PrintAndLogEx(WARNING
, "command execution time out");
1019 return PM3_ETIMEOUT
;
1022 if (resp
.status
== PM3_SUCCESS
)
1023 memcpy(data
, resp
.data
.asBytes
, size
);
1028 int mfEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
1029 return mfEmlSetMem_xt(data
, blockNum
, blocksCount
, MFBLOCK_SIZE
);
1032 int mfEmlSetMem_xt(uint8_t *data
, int blockNum
, int blocksCount
, int blockBtWidth
) {
1041 size_t size
= ((size_t) blocksCount
) * blockBtWidth
;
1042 if (size
> (PM3_CMD_DATA_SIZE
- sizeof(struct p
))) {
1046 size_t paylen
= sizeof(struct p
) + size
;
1047 struct p
*payload
= calloc(1, paylen
);
1049 payload
->blockno
= blockNum
;
1050 payload
->blockcnt
= blocksCount
;
1051 payload
->blockwidth
= blockBtWidth
;
1052 memcpy(payload
->data
, data
, size
);
1054 clearCommandBuffer();
1055 SendCommandNG(CMD_HF_MIFARE_EML_MEMSET
, (uint8_t *)payload
, paylen
);
1061 int mfCSetUID(uint8_t *uid
, uint8_t uidlen
, const uint8_t *atqa
, const uint8_t *sak
, uint8_t *old_uid
, uint8_t *verifed_uid
, uint8_t wipecard
) {
1063 uint8_t params
= MAGIC_SINGLE
;
1064 uint8_t block0
[MFBLOCK_SIZE
];
1065 memset(block0
, 0x00, sizeof(block0
));
1067 int res
= mfCGetBlock(0, block0
, params
);
1069 PrintAndLogEx(SUCCESS
, "old block 0... %s", sprint_hex_inrow(block0
, sizeof(block0
)));
1071 memcpy(old_uid
, block0
, uidlen
);
1074 PrintAndLogEx(INFO
, "couldn't get old data. Will write over the last bytes of block 0");
1077 // fill in the new values
1079 memcpy(block0
, uid
, uidlen
);
1082 block0
[4] = block0
[0] ^ block0
[1] ^ block0
[2] ^ block0
[3];
1084 // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed)
1089 block0
[6] = atqa
[1];
1090 block0
[7] = atqa
[0];
1093 } else if (uidlen
== 7) {
1094 block0
[7] = block0
[0] ^ block0
[1] ^ block0
[2] ^ block0
[3] ^ block0
[4] ^ block0
[5] ^ block0
[6];
1096 // mifare classic SAK(byte 8) and ATQA(byte 9 and 10, reversed)
1101 block0
[9] = atqa
[1];
1102 block0
[10] = atqa
[0];
1106 PrintAndLogEx(SUCCESS
, "new block 0... %s", sprint_hex_inrow(block0
, sizeof(block0
)));
1109 params
|= MAGIC_WIPE
;
1112 res
= mfCSetBlock(0, block0
, NULL
, params
);
1113 if (res
== PM3_SUCCESS
) {
1114 params
= MAGIC_SINGLE
;
1115 memset(block0
, 0, sizeof(block0
));
1116 res
= mfCGetBlock(0, block0
, params
);
1119 memcpy(verifed_uid
, block0
, uidlen
);
1126 int mfCWipe(uint8_t *uid
, const uint8_t *atqa
, const uint8_t *sak
) {
1127 uint8_t block0
[MFBLOCK_SIZE
] = {0x00, 0x56, 0x78, 0xBB, 0x95, 0x08, 0x04, 0x00, 0x02, 0xB2, 0x1E, 0x24, 0x23, 0x27, 0x1E, 0x1D};
1128 // uint8_t block0[MFBLOCK_SIZE] = {0x04, 0x03, 0x02, 0x01, 0x04, 0x08, 0x04, 0x00, 0x64, 0xB9, 0x95, 0x11, 0x4D, 0x20, 0x42, 0x09};
1129 uint8_t blockD
[MFBLOCK_SIZE
] = {0x00};
1130 // default transport ACL
1131 uint8_t blockK
[MFBLOCK_SIZE
] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1132 uint8_t params
= MAGIC_SINGLE
;
1135 memcpy(block0
, uid
, 4);
1136 block0
[4] = block0
[0] ^ block0
[1] ^ block0
[2] ^ block0
[3];
1142 block0
[6] = atqa
[1];
1143 block0
[7] = atqa
[0];
1146 for (int blockNo
= 0; blockNo
< 4 * 16; blockNo
++) {
1147 for (int retry
= 0; retry
< 3; retry
++) {
1149 PrintAndLogEx(INPLACE
, "wipe block %d", blockNo
);
1152 res
= mfCSetBlock(blockNo
, block0
, NULL
, params
);
1154 if (mfIsSectorTrailer(blockNo
))
1155 res
= mfCSetBlock(blockNo
, blockK
, NULL
, params
);
1157 res
= mfCSetBlock(blockNo
, blockD
, NULL
, params
);
1160 if (res
== PM3_SUCCESS
)
1163 PrintAndLogEx(WARNING
, "retry block %d ...", blockNo
);
1167 PrintAndLogEx(ERR
, "error setting block %d (%d)", blockNo
, res
);
1172 PrintAndLogEx(NORMAL
, "");
1176 int mfCSetBlock(uint8_t blockNo
, uint8_t *data
, uint8_t *uid
, uint8_t params
) {
1177 clearCommandBuffer();
1178 SendCommandMIX(CMD_HF_MIFARE_CSETBL
, params
, blockNo
, 0, data
, MFBLOCK_SIZE
);
1179 PacketResponseNG resp
;
1180 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 3500)) {
1181 uint8_t isOK
= resp
.oldarg
[0] & 0xff;
1183 memcpy(uid
, resp
.data
.asBytes
, 4);
1190 PrintAndLogEx(WARNING
, "command execution time out");
1191 return PM3_ETIMEOUT
;
1196 int mfCGetBlock(uint8_t blockNo
, uint8_t *data
, uint8_t params
) {
1197 clearCommandBuffer();
1198 SendCommandMIX(CMD_HF_MIFARE_CGETBL
, params
, blockNo
, 0, NULL
, 0);
1199 PacketResponseNG resp
;
1200 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
1201 uint8_t isOK
= resp
.oldarg
[0] & 0xff;
1205 memcpy(data
, resp
.data
.asBytes
, MFBLOCK_SIZE
);
1207 PrintAndLogEx(WARNING
, "command execution time out");
1208 return PM3_ETIMEOUT
;
1213 int mfGen3UID(uint8_t *uid
, uint8_t uidlen
, uint8_t *oldUid
) {
1214 clearCommandBuffer();
1215 SendCommandMIX(CMD_HF_MIFARE_GEN3UID
, uidlen
, 0, 0, uid
, uidlen
);
1216 PacketResponseNG resp
;
1217 if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3UID
, &resp
, 3500)) {
1218 if (resp
.status
== PM3_SUCCESS
&& oldUid
) {
1219 memcpy(oldUid
, resp
.data
.asBytes
, uidlen
);
1223 PrintAndLogEx(WARNING
, "command execution time out");
1224 return PM3_ETIMEOUT
;
1228 int mfGen3Block(uint8_t *block
, int blockLen
, uint8_t *newBlock
) {
1229 clearCommandBuffer();
1230 SendCommandMIX(CMD_HF_MIFARE_GEN3BLK
, blockLen
, 0, 0, block
, MFBLOCK_SIZE
);
1231 PacketResponseNG resp
;
1232 if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3BLK
, &resp
, 3500)) {
1233 if (resp
.status
== PM3_SUCCESS
&& newBlock
) {
1234 memcpy(newBlock
, resp
.data
.asBytes
, MFBLOCK_SIZE
);
1238 PrintAndLogEx(WARNING
, "command execution time out");
1239 return PM3_ETIMEOUT
;
1243 int mfGen3Freeze(void) {
1244 clearCommandBuffer();
1245 SendCommandNG(CMD_HF_MIFARE_GEN3FREEZ
, NULL
, 0);
1246 PacketResponseNG resp
;
1247 if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3FREEZ
, &resp
, 3500)) {
1250 PrintAndLogEx(WARNING
, "command execution time out");
1251 return PM3_ETIMEOUT
;
1256 uint32_t cuid
= 0; // uid part used for crypto1.
1258 void mf_crypto1_decrypt(struct Crypto1State
*pcs
, uint8_t *data
, int len
, bool isEncrypted
) {
1260 for (int i
= 0; i
< len
; i
++) {
1261 data
[i
] = crypto1_byte(pcs
, 0x00, isEncrypted
) ^ data
[i
];
1265 bt
|= (crypto1_bit(pcs
, 0, isEncrypted
) ^ BIT(data
[0], 0)) << 0;
1266 bt
|= (crypto1_bit(pcs
, 0, isEncrypted
) ^ BIT(data
[0], 1)) << 1;
1267 bt
|= (crypto1_bit(pcs
, 0, isEncrypted
) ^ BIT(data
[0], 2)) << 2;
1268 bt
|= (crypto1_bit(pcs
, 0, isEncrypted
) ^ BIT(data
[0], 3)) << 3;
1273 int tryDecryptWord(uint32_t nt
, uint32_t ar_enc
, uint32_t at_enc
, uint8_t *data
, int len
) {
1275 PrintAndLogEx(SUCCESS
, "encrypted data... %s", sprint_hex(data
, len
));
1276 uint32_t ks2
= ar_enc
^ prng_successor(nt
, 64);
1277 uint32_t ks3
= at_enc
^ prng_successor(nt
, 96);
1279 struct Crypto1State
*s
= lfsr_recovery64(ks2
, ks3
);
1280 mf_crypto1_decrypt(s
, data
, len
, false);
1281 PrintAndLogEx(SUCCESS
, "decrypted data... " _YELLOW_("%s"), sprint_hex(data
, len
));
1282 PrintAndLogEx(NORMAL
, "");
1288 * function performs a partial AUTH, where it tries to authenticate against block0, key A, but only collects tag nonce.
1289 * the tag nonce is check to see if it has a predictable PRNG.
1291 * TRUE if tag uses WEAK prng (ie Now the NACK bug also needs to be present for Darkside attack)
1292 * FALSE is tag uses HARDEND prng (ie hardnested attack possible, with known key)
1294 int detect_classic_prng(void) {
1296 PacketResponseNG resp
, respA
;
1297 uint8_t cmd
[] = {MIFARE_AUTH_KEYA
, 0x00};
1298 uint32_t flags
= ISO14A_CONNECT
| ISO14A_RAW
| ISO14A_APPEND_CRC
| ISO14A_NO_RATS
;
1300 clearCommandBuffer();
1301 SendCommandMIX(CMD_HF_ISO14443A_READER
, flags
, sizeof(cmd
), 0, cmd
, sizeof(cmd
));
1303 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
1304 PrintAndLogEx(WARNING
, "PRNG UID: Reply timeout.");
1305 return PM3_ETIMEOUT
;
1308 // if select tag failed.
1309 if (resp
.oldarg
[0] == 0) {
1310 PrintAndLogEx(ERR
, "error: selecting tag failed, can't detect prng\n");
1311 return PM3_ERFTRANS
;
1313 if (WaitForResponseTimeout(CMD_ACK
, &respA
, 2500) == false) {
1314 PrintAndLogEx(WARNING
, "PRNG data: Reply timeout.");
1315 return PM3_ETIMEOUT
;
1319 if (respA
.oldarg
[0] != 4) {
1320 PrintAndLogEx(ERR
, "PRNG data error: Wrong length: %"PRIu64
, respA
.oldarg
[0]);
1324 uint32_t nonce
= bytes_to_num(respA
.data
.asBytes
, respA
.oldarg
[0]);
1325 return validate_prng_nonce(nonce
);
1327 /* Detect Mifare Classic NACK bug
1330 0 = error during test / aborted
1332 2 = has not nack bug
1333 3 = always leak nacks (clones)
1335 int detect_classic_nackbug(bool verbose
) {
1337 clearCommandBuffer();
1338 SendCommandNG(CMD_HF_MIFARE_NACK_DETECT
, NULL
, 0);
1339 PacketResponseNG resp
;
1341 PrintAndLogEx(INFO
, "Checking for NACK bug");
1344 PrintAndLogEx(SUCCESS
, "press " _GREEN_("pm3 button") " to abort both Proxmark3 and client\n");
1347 PrintAndLogEx(INFO
, "." NOLF
);
1351 PrintAndLogEx(NORMAL
, "." NOLF
);
1352 if (kbd_enter_pressed()) {
1353 return PM3_EOPABORTED
;
1356 if (WaitForResponseTimeout(CMD_HF_MIFARE_NACK_DETECT
, &resp
, 500)) {
1358 PrintAndLogEx(NORMAL
, "");
1360 if (resp
.status
== PM3_EOPABORTED
) {
1361 PrintAndLogEx(WARNING
, "button pressed. Aborted.");
1362 return PM3_EOPABORTED
;
1365 uint8_t ok
= resp
.data
.asBytes
[0];
1366 uint8_t nacks
= resp
.data
.asBytes
[1];
1367 uint16_t auths
= bytes_to_num(resp
.data
.asBytes
+ 2, 2);
1370 PrintAndLogEx(SUCCESS
, "num of auth requests : %u", auths
);
1371 PrintAndLogEx(SUCCESS
, "num of received NACK : %u", nacks
);
1377 PrintAndLogEx(FAILED
, "card random number generator is not predictable.");
1378 PrintAndLogEx(WARNING
, "detection failed");
1383 PrintAndLogEx(FAILED
, "card random number generator seems to be based on the well-known generating polynomial");
1384 PrintAndLogEx(FAILED
, "with 16 effective bits only, but shows unexpected behavior, try again.");
1389 PrintAndLogEx(SUCCESS
, "NACK test: " _GREEN_("always leak NACK"));
1392 PrintAndLogEx(SUCCESS
, "NACK test: " _GREEN_("detected"));
1395 PrintAndLogEx(SUCCESS
, "NACK test: " _GREEN_("no bug"));
1398 PrintAndLogEx(ERR
, "errorcode from device " _RED_("[%i]"), ok
);
1407 /* Detect Mifare Classic Static / Fixed nonce
1408 detects special magic cards that has a static / fixed nonce
1410 0 = has normal nonce
1411 1 = has static/fixed nonce
1414 int detect_classic_static_nonce(void) {
1416 clearCommandBuffer();
1417 SendCommandNG(CMD_HF_MIFARE_STATIC_NONCE
, NULL
, 0);
1418 PacketResponseNG resp
;
1419 if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NONCE
, &resp
, 1000)) {
1421 if (resp
.status
== PM3_ESOFT
)
1424 return resp
.data
.asBytes
[0];
1429 /* Detect Mifare Classic static encrypted nonce
1430 detects special magic cards that has a static / fixed nonce
1433 1 = has static/fixed nonce
1435 3 = has encrypted nonce
1437 int detect_classic_static_encrypted_nonce_ex(uint8_t block_no
, uint8_t key_type
, uint8_t *key
, uint8_t block_no_nested
, uint8_t key_type_nested
, uint8_t *key_nested
, uint8_t nr_nested
, bool reset
, bool hardreset
, bool addread
, bool addauth
, bool incblk2
, bool corruptnrar
, bool corruptnrarparity
, bool verbose
) {
1438 clearCommandBuffer();
1439 uint8_t cdata
[1 + 1 + MIFARE_KEY_SIZE
+ 1 + 1 + MIFARE_KEY_SIZE
+ 1 + 1 + 1 + 1 + 1 + 1 + 1] = { 0 };
1440 cdata
[0] = block_no
;
1441 cdata
[1] = key_type
;
1442 memcpy(&cdata
[2], key
, MIFARE_KEY_SIZE
);
1443 cdata
[8] = block_no_nested
;
1444 cdata
[9] = key_type_nested
;
1445 memcpy(&cdata
[10], key_nested
, MIFARE_KEY_SIZE
);
1446 cdata
[16] = nr_nested
;
1447 cdata
[17] = hardreset
<< 1 | reset
;
1448 cdata
[18] = addread
;
1449 cdata
[19] = addauth
;
1450 cdata
[20] = incblk2
;
1451 cdata
[21] = corruptnrar
;
1452 cdata
[22] = corruptnrarparity
;
1453 SendCommandNG(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE
, cdata
, sizeof(cdata
));
1454 PacketResponseNG resp
;
1455 if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE
, &resp
, 1000)) {
1457 if (resp
.status
== PM3_ESOFT
) {
1460 if (verbose
&& (resp
.data
.asBytes
[0] == NONCE_STATIC_ENC
)) {
1462 uint32_t uid
= resp
.data
.asBytes
[1] << 24 |
1463 resp
.data
.asBytes
[2] << 16 |
1464 resp
.data
.asBytes
[3] << 8 |
1465 resp
.data
.asBytes
[4];
1467 uint32_t nt
= resp
.data
.asBytes
[5] << 24 |
1468 resp
.data
.asBytes
[6] << 16 |
1469 resp
.data
.asBytes
[7] << 8 |
1470 resp
.data
.asBytes
[8];
1472 uint32_t ntenc
= resp
.data
.asBytes
[9] << 24 |
1473 resp
.data
.asBytes
[10] << 16 |
1474 resp
.data
.asBytes
[11] << 8 |
1475 resp
.data
.asBytes
[12];
1477 uint8_t ntencparenc
= resp
.data
.asBytes
[13];
1479 // recompute nt on client, just because
1480 struct Crypto1State mpcs
= {0, 0};
1481 struct Crypto1State
*pcs
;
1484 uint64_t ui64key
= bytes_to_num(key_nested
, 6);
1486 crypto1_init(pcs
, ui64key
); // key_nested
1487 uint32_t ks
= crypto1_word(pcs
, ntenc
^ uid
, 1);
1489 uint32_t mynt
= ks
^ ntenc
;
1491 PrintAndLogEx(ERR
, "Client computed nT " _YELLOW_("%08x") " does not match ARM computed nT " _YELLOW_("%08x"), mynt
, nt
);
1495 // [...] Additionally, the bit of keystream used to encrypt the parity bits is reused to encrypt the next bit of plaintext.
1496 // we can decrypt first 3 parity bits, not last one as it's using future keystream
1497 uint8_t ksp
= (((ks
>> 16) & 1) << 3) | (((ks
>> 8) & 1) << 2) | (((ks
>> 0) & 1) << 1);
1498 uint8_t ntencpar
= ntencparenc
^ ksp
;
1499 if (validate_prng_nonce(nt
)) {
1500 PrintAndLogEx(INFO
, "nTenc " _GREEN_("%08x") " par {" _YELLOW_("%i%i%i%i") "}=" _YELLOW_("%i%i%ix") " | ks " _GREEN_("%08x") " | nT " _GREEN_("%08x") " par " _YELLOW_("%i%i%i%i")" | lfsr16 index " _GREEN_("%i"),
1502 (ntencparenc
>> 3) & 1, (ntencparenc
>> 2) & 1, (ntencparenc
>> 1) & 1, ntencparenc
& 1,
1503 (ntencpar
>> 3) & 1, (ntencpar
>> 2) & 1, (ntencpar
>> 1) & 1,
1505 oddparity8((nt
>> 24) & 0xFF), oddparity8((nt
>> 16) & 0xFF), oddparity8((nt
>> 8) & 0xFF), oddparity8(nt
& 0xFF),
1506 nonce_distance(0, nt
)
1509 PrintAndLogEx(INFO
, "nTenc " _GREEN_("%08x") " par {" _YELLOW_("%i%i%i%i") "}=" _YELLOW_("%i%i%ix") " | ks " _YELLOW_("%08x") " | nT " _YELLOW_("%08x") " par " _YELLOW_("%i%i%i%i") " | " _RED_("not lfsr16") " (wrong key)",
1511 (ntencparenc
>> 3) & 1, (ntencparenc
>> 2) & 1, (ntencparenc
>> 1) & 1, ntencparenc
& 1,
1512 (ntencpar
>> 3) & 1, (ntencpar
>> 2) & 1, (ntencpar
>> 1) & 1,
1514 oddparity8((nt
>> 24) & 0xFF), oddparity8((nt
>> 16) & 0xFF), oddparity8((nt
>> 8) & 0xFF), oddparity8(nt
& 0xFF)
1518 return resp
.data
.asBytes
[0];
1523 int detect_classic_static_encrypted_nonce(uint8_t block_no
, uint8_t key_type
, uint8_t *key
) {
1524 return detect_classic_static_encrypted_nonce_ex(block_no
, key_type
, key
, block_no
, key_type
, key
, 3, false, false, false, false, false, false, false, false);
1527 // try to see if card responses to "Chinese magic backdoor" commands.
1529 uint16_t detect_mf_magic(bool is_mfc
, uint8_t key_type
, uint64_t key
) {
1531 PacketResponseNG resp
;
1532 clearCommandBuffer();
1533 uint8_t payload
[1 + 1 + MIFARE_KEY_SIZE
] = { is_mfc
, key_type
};
1534 num_to_bytes(key
, MIFARE_KEY_SIZE
, payload
+ 2);
1536 SendCommandNG(CMD_HF_MIFARE_CIDENT
, payload
, sizeof(payload
));
1537 if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT
, &resp
, 1500)) {
1538 if (resp
.status
!= PM3_SUCCESS
) {
1539 return MAGIC_FLAG_NONE
;
1543 uint16_t isMagic
= MAGIC_FLAG_NONE
;
1544 if ((resp
.status
== PM3_SUCCESS
) && resp
.length
== sizeof(uint16_t)) {
1545 isMagic
= MemLeToUint2byte(resp
.data
.asBytes
);
1549 PrintAndLogEx(NORMAL
, "");
1552 if ((isMagic
& MAGIC_FLAG_GEN_1A
) == MAGIC_FLAG_GEN_1A
) {
1553 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Gen 1a"));
1556 if ((isMagic
& MAGIC_FLAG_GEN_1B
) == MAGIC_FLAG_GEN_1B
) {
1557 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Gen 1b"));
1560 if ((isMagic
& MAGIC_FLAG_GEN_2
) == MAGIC_FLAG_GEN_2
) {
1561 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Gen 2 / CUID"));
1564 if ((isMagic
& MAGIC_FLAG_GEN_3
) == MAGIC_FLAG_GEN_3
) {
1565 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Gen 3 / APDU") " ( possibly )");
1568 if ((isMagic
& MAGIC_FLAG_GEN_4GTU
) == MAGIC_FLAG_GEN_4GTU
) {
1569 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Gen 4 GTU"));
1572 if ((isMagic
& MAGIC_FLAG_GDM_AUTH
) == MAGIC_FLAG_GDM_AUTH
) {
1573 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Magic Auth )");
1576 if ((isMagic
& MAGIC_FLAG_GDM_WUP_20
) == MAGIC_FLAG_GDM_WUP_20
) {
1577 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Gen4 Magic Wakeup )");
1580 if ((isMagic
& MAGIC_FLAG_GDM_WUP_40
) == MAGIC_FLAG_GDM_WUP_40
) {
1581 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Gen1 Magic Wakeup )");
1584 if ((isMagic
& MAGIC_FLAG_GEN_UNFUSED
) == MAGIC_FLAG_GEN_UNFUSED
) {
1585 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Write Once / FUID"));
1588 if ((isMagic
& MAGIC_FLAG_SUPER_GEN1
) == MAGIC_FLAG_SUPER_GEN1
) {
1589 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 1") _GREEN_(" )"));
1592 if ((isMagic
& MAGIC_FLAG_SUPER_GEN2
) == MAGIC_FLAG_SUPER_GEN2
) {
1593 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 2") _GREEN_(" )"));
1596 if ((isMagic
& MAGIC_FLAG_NTAG21X
) == MAGIC_FLAG_NTAG21X
) {
1597 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("NTAG21x"));
1600 if ((isMagic
& MAGIC_FLAG_QL88
) == MAGIC_FLAG_QL88
) {
1601 PrintAndLogEx(SUCCESS
, "Magic capabilities... " _GREEN_("QL88"));
1606 bool detect_mfc_ev1_signature(void) {
1608 int res
= mfCheckKeys(69, MF_KEY_B
, false, 1, (uint8_t *)g_mifare_signature_key_b
, &key
);
1609 return (res
== PM3_SUCCESS
);
1612 int read_mfc_ev1_signature(uint8_t *signature
) {
1613 if (signature
== NULL
) {
1616 uint8_t sign
[32] = {0};
1617 int res
= mfReadBlock(69, MF_KEY_B
, g_mifare_signature_key_b
, sign
);
1618 if (res
== PM3_SUCCESS
) {
1619 res
= mfReadBlock(70, MF_KEY_B
, g_mifare_signature_key_b
, sign
+ 16);
1620 if (res
== PM3_SUCCESS
) {
1621 memcpy(signature
, sign
, sizeof(sign
));
1625 res
= mfReadBlock(69, MF_KEY_B
, g_mifare_ql88_signature_key_b
, sign
);
1626 if (res
== PM3_SUCCESS
) {
1627 res
= mfReadBlock(70, MF_KEY_B
, g_mifare_ql88_signature_key_b
, sign
+ 16);
1628 if (res
== PM3_SUCCESS
) {
1629 memcpy(signature
, sign
, sizeof(sign
));
1636 int convert_mfc_2_arr(uint8_t *in
, uint16_t ilen
, uint8_t *out
, uint16_t *olen
) {
1637 if (in
== NULL
|| out
== NULL
)
1640 uint8_t blockno
= 0;
1643 if (mfIsSectorTrailer(blockno
) == false) {
1644 memcpy(out
, in
, MFBLOCK_SIZE
);
1645 out
+= MFBLOCK_SIZE
;
1646 *olen
+= MFBLOCK_SIZE
;
1650 ilen
-= MFBLOCK_SIZE
;
1655 static const vigik_pk_t vigik_rsa_pk
[] = {
1656 {"La Poste Service Universel", 0x07AA, "AB9953CBFCCD9375B6C028ADBAB7584BED15B9CA037FADED9765996F9EA1AB983F3041C90DA3A198804FF90D5D872A96A4988F91F2243B821E01C5021E3ED4E1BA83B7CFECAB0E766D8563164DE0B2412AE4E6EA63804DF5C19C7AA78DC14F608294D732D7C8C67A88C6F84C0F2E3FAFAE34084349E11AB5953AC68729D07715"},
1657 {"La Poste Service Universel", 0x07AA, "1577D02987C63A95B51AE149430834AEAF3F2E0F4CF8C6887AC6C8D732D79482604FC18DA77A9CC1F54D8063EAE6E42A41B2E04D1663856D760EABECCFB783BAE1D43E1E02C5011E823B24F2918F98A4962A875D0DF94F8098A1A30DC941303F98ABA19E6F996597EDAD7F03CAB915ED4B58B7BAAD28C0B67593CDFCCB5399AB"},
1659 {"La Poste Autres Services", 0x07AB, "A6D99B8D902893B04F3F8DE56CB6BF24338FEE897C1BCE6DFD4EBD05B7B1A07FD2EB564BB4F7D35DBFE0A42966C2C137AD156E3DAB62904592BCA20C0BC7B8B1E261EF82D53F52D203843566305A49A22062DECC38C2FE3864CAD08E79219487651E2F79F1C9392B48CAFE1BFFAFF4802AE451E7A283E55A4026AD1E82DF1A15"},
1660 {"La Poste Autres Services", 0x07AB, "151adf821ead26405ae583a2e751e42a80f4afff1bfeca482b39c9f1792f1e65879421798ed0ca6438fec238ccde6220a2495a3066358403d2523fd582ef61e2b1b8c70b0ca2bc92459062ab3d6e15ad37c1c26629a4e0bf5dd3f7b44b56ebd27fa0b1b705bd4efd6dce1b7c89ee8f3324bfb66ce58d3f4fb09328908d9bd9a6"},
1662 {"France Telecom", 0x07AC, "C44DBCD92F9DCF42F4902A87335DBB35D2FF530CDB09814CFA1F4B95A1BD018D099BC6AB69F667B4922AE1ED826E72951AA3E0EAAA7D49A695F04F8CDAAE2D18D10D25BD529CBB05ABF070DC7C041EC35C2BA7F58CC4C349983CC6E11A5CBE828FB8ECBC26F08E1094A6B44C8953C8E1BAFD214DF3E69F430A98CCC75C03669D"},
1663 {"France Telecom", 0x07AC, "9d66035cc7cc980a439fe6f34d21fdbae1c853894cb4a694108ef026bcecb88f82be5c1ae1c63c9849c3c48cf5a72b5cc31e047cdc70f0ab05bb9c52bd250dd1182daeda8c4ff095a6497daaeae0a31a95726e82ede12a92b467f669abc69b098d01bda1954b1ffa4c8109db0c53ffd235bb5d33872a90f442cf9d2fd9bc4dc4"},
1665 {"EDF-GDF", 0x07AD, "B35193DBD2F88A21CDCFFF4BF84F7FC036A991A363DCB3E802407A5E5879DC2127EECFC520779E79E911394882482C87D09A88B0711CBC2973B77FFDAE40EA0001F595072708C558B484AB89D02BCBCB971FF1B80371C0BE30CB13661078078BB68EBCCA524B9DD55EBF7D47D9355AFC95511350CC1103A5DEE847868848B235"},
1666 {"EDF-GDF", 0x07AD, "35b248888647e8dea50311cc50135195fc5a35d9477dbf5ed59d4b52cabc8eb68b0778106613cb30bec07103b8f11f97cbcb2bd089ab84b458c508270795f50100ea40aefd7fb77329bc1c71b0889ad0872c4882483911e9799e7720c5cfee2721dc79585e7a4002e8b3dc63a391a936c07f4ff84bffcfcd218af8d2db9351b3"},
1670 const char *vigik_get_service(uint16_t service_code
) {
1671 for (int i
= 0; i
< ARRAYLEN(vigik_rsa_pk
); ++i
)
1672 if (service_code
== vigik_rsa_pk
[i
].code
)
1673 return vigik_rsa_pk
[i
].desc
;
1675 //No match, return default
1676 return vigik_rsa_pk
[ARRAYLEN(vigik_rsa_pk
) - 1].desc
;
1680 int vigik_verify(mfc_vigik_t
*d
) {
1681 #define PUBLIC_VIGIK_KEYLEN 128
1685 // n = The public modulus n is the product of the secret prime factors p and q. Its length is 1024 bits.
1687 if (g_debugMode
== DEBUG
) {
1688 PrintAndLogEx(INFO
, "Raw");
1689 print_hex_noascii_break((uint8_t *)d
, sizeof(*d
) - sizeof(d
->rsa_signature
), MFBLOCK_SIZE
* 2);
1691 PrintAndLogEx(INFO
, "Raw signature");
1692 print_hex_noascii_break(d
->rsa_signature
, sizeof(d
->rsa_signature
), MFBLOCK_SIZE
* 2);
1698 param_gethex_to_eol("1C07D46DA3849326D24B3468BD76673F4F3C41827DC413E81E4F3C7804FAC727213059B21D047510D6432448643A92EBFC67FBEDDAB468D13D948B172F5EBC79A0E3FEFDFAF4E81FC7108E070F1E3CD0", 0, signature, PUBLIC_VIGIK_KEYLEN, &dl);
1700 param_gethex_to_eol("1AB86FE0C17FFFFE4379D5E15A4B2FAFFEFCFA0F1F3F7FA03E7DDDF1E3C78FFFB1F0E23F7FFF51584771C5C18307FEA36CA74E60AA6B0409ACA66A9EC155F4E9112345708A2B8457E722608EE1157408", 0, signature, PUBLIC_VIGIK_KEYLEN, &dl);
1704 uint8_t rev_sig
[128];
1705 reverse_array_copy(d
->rsa_signature
, sizeof(d
->rsa_signature
), rev_sig
);
1707 PrintAndLogEx(INFO
, "Raw signature reverse");
1708 print_hex_noascii_break(rev_sig
, sizeof(d
->rsa_signature
), MFBLOCK_SIZE
* 2);
1710 // t = 0xBC = Implicitly known
1711 // t = 0xCC = look at byte before to determine hash function
1712 // uint8_t T[] = {0x33, 0xCC};
1714 // Success decrypt would mean 0x4b BB ... BB BA padding
1715 // padding, message, hash, 8 bits or 16 bits
1717 // signature = h( C || M1 || h(M2) )
1718 // 1024 - 786 - 160 - 16 -1
1720 // message M = 96 bytes, 768 bits
1721 // sha1 hash H = 20 bytes, 160 bits
1722 // padding = 20 bytes, 96 bits
1725 bool is_valid
= false;
1727 for (i
= 0; i
< ARRAYLEN(vigik_rsa_pk
); i
++) {
1728 if (vigik_rsa_pk
[i
].desc
== NULL
) {
1733 mbedtls_mpi_init(&RN
);
1735 // exponent 2 = even
1736 mbedtls_mpi_init(&E
);
1737 mbedtls_mpi_add_int(&E
, &E
, 2);
1740 uint8_t n
[PUBLIC_VIGIK_KEYLEN
];
1741 memset(n
, 0, sizeof(n
));
1742 param_gethex_to_eol(vigik_rsa_pk
[i
].n
, 0, n
, PUBLIC_VIGIK_KEYLEN
, &dl
);
1745 mbedtls_mpi N
, s
, sqr
, res
;
1746 mbedtls_mpi_init(&N
);
1747 mbedtls_mpi_init(&s
);
1748 mbedtls_mpi_init(&sqr
);
1749 mbedtls_mpi_init(&res
);
1751 mbedtls_mpi_read_binary(&N
, (const unsigned char *)n
, PUBLIC_VIGIK_KEYLEN
);
1753 //mbedtls_mpi_read_binary(&s, (const unsigned char*)signature, signature_len);
1754 mbedtls_mpi_read_binary(&s
, (const unsigned char *)rev_sig
, sizeof(d
->rsa_signature
));
1756 // check is sign < (N/2)
1759 mbedtls_mpi_init(&n_2
);
1760 mbedtls_mpi_copy(&n_2
, &N
);
1761 mbedtls_mpi_shift_r(&n_2
, 1);
1762 bool is_less
= (mbedtls_mpi_cmp_mpi(&s
, &n_2
) > 0) ? false : true;
1763 PrintAndLogEx(DEBUG
, "z < (N/2) ..... %s", (is_less
) ? _GREEN_("YES") : _RED_("NO"));
1764 mbedtls_mpi_free(&n_2
);
1768 mbedtls_mpi_exp_mod(&sqr
, &s
, &E
, &N
, &RN
);
1775 ⎯ if J* mod 8 = 1, then f* = n–J*.
1776 ⎯ if J* mod 8 = 4, then f* = J*,
1777 ⎯ if J* mod 8 = 6, then f* = 2J*,
1778 ⎯ if J* mod 8 = 7, then f* = 2(n–J*),
1780 uint8_t b2
= mbedtls_mpi_get_bit(&sqr
, 2);
1781 uint8_t b1
= mbedtls_mpi_get_bit(&sqr
, 1);
1782 uint8_t b0
= mbedtls_mpi_get_bit(&sqr
, 0);
1783 uint8_t lsb
= (b2
<< 2) | (b1
<< 1) | b0
;
1787 mbedtls_mpi_sub_mpi(&res, &N, &sqr);
1788 mbedtls_mpi_write_file( "[=] 1... ", &res, 16, NULL );
1790 mbedtls_mpi_copy(&res, &sqr);
1791 mbedtls_mpi_write_file( "[=] 4... ", &res, 16, NULL );
1793 mbedtls_mpi_mul_int(&res, &sqr, 2);
1794 mbedtls_mpi_write_file( "[=] 6... ", &res, 16, NULL );
1797 mbedtls_mpi_init(&foo);
1798 mbedtls_mpi_sub_mpi(&foo, &N, &sqr);
1799 mbedtls_mpi_mul_int(&res, &foo, 2);
1800 mbedtls_mpi_free(&foo);
1801 mbedtls_mpi_write_file( "[=] 7... ", &res, 16, NULL );
1806 mbedtls_mpi_sub_mpi(&res
, &N
, &sqr
);
1810 mbedtls_mpi_copy(&res
, &sqr
);
1814 mbedtls_mpi_mul_int(&res
, &sqr
, 2);
1819 mbedtls_mpi_init(&foo2
);
1820 mbedtls_mpi_sub_mpi(&foo2
, &N
, &sqr
);
1821 mbedtls_mpi_mul_int(&res
, &foo2
, 2);
1822 mbedtls_mpi_free(&foo2
);
1830 PrintAndLogEx(DEBUG
, "LSB............ " _GREEN_("%u"), lsb
);
1831 if (g_debugMode
== DEBUG
) {
1832 mbedtls_mpi_write_file("[=] N.............. ", &N
, 16, NULL
);
1833 mbedtls_mpi_write_file("[=] signature...... ", &s
, 16, NULL
);
1834 mbedtls_mpi_write_file("[=] square mod n... ", &sqr
, 16, NULL
);
1835 mbedtls_mpi_write_file("[=] n-fs........... ", &res
, 16, NULL
);
1839 uint8_t nfs
[128] = {0};
1840 mbedtls_mpi_write_binary(&res
, nfs
, sizeof(nfs
));
1844 for (int x
= 0; x
< sizeof(nfs
); x
+= 2) {
1850 if (nfs
[x
+ 1] == 0x00)
1854 if (count_zero
> 10) {
1855 PrintAndLogEx(INFO
, "");
1856 PrintAndLogEx(INFO
, "Message XORED");
1857 print_hex_noascii_break(nfs
, sizeof(nfs
), 32);
1858 PrintAndLogEx(INFO
, "\n");
1865 typedef struct vigik_rsa_s {
1871 memcpy(&ts, nfs, sizeof(ts));
1873 if ( ts.hash == 0xCC ) {
1874 PrintAndLogEx(INFO, "Hash byte... 0x%02X", ts.hash);
1875 switch(ts.rsa[126]) {
1877 PrintAndLogEx(INFO, "Hash algo ( 0x%02X ) - SHA1");
1880 PrintAndLogEx(INFO, "Hash algo ( 0x%02X ) - RIPEMD");
1883 PrintAndLogEx(INFO, "Hash algo ( 0x%02X ) - SHA1");
1886 PrintAndLogEx(INFO, "Hash algo ( 0x%02X ) - " _RED_("err"));
1889 } else if ( ts.hash == 0xBC) {
1890 PrintAndLogEx(INFO, "Hash byte... 0x%02X - " _GREEN_("implict"), ts.hash);
1892 PrintAndLogEx(INFO, "Hash byte... 0x%02x - " _RED_("err"), ts.hash);
1895 PrintAndLogEx(INFO, "Message w padding");
1896 print_hex_noascii_break(ts.rsa, sizeof(ts.rsa) - 20, 32);
1900 mbedtls_mpi_free(&N
);
1901 mbedtls_mpi_free(&s
);
1902 mbedtls_mpi_free(&res
);
1903 mbedtls_mpi_free(&RN
);
1904 mbedtls_mpi_free(&E
);
1907 PrintAndLogEx(INFO
, "");
1908 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Signature"));
1909 PrintAndLogEx(INFO
, "RSA: 1024bit");
1911 if (is_valid
== false || i
== ARRAYLEN(vigik_rsa_pk
)) {
1912 PrintAndLogEx(INFO
, "Signature:");
1913 print_hex_noascii_break(d
->rsa_signature
, sizeof(d
->rsa_signature
), MFBLOCK_SIZE
* 2);
1914 PrintAndLogEx(SUCCESS
, "Signature verification: " _RED_("failed"));
1918 PrintAndLogEx(INFO
, "Signature public key name: " _YELLOW_("%s"), vigik_rsa_pk
[i
].desc
);
1919 PrintAndLogEx(INFO
, "Signature public key value:");
1920 PrintAndLogEx(INFO
, "%.64s", vigik_rsa_pk
[i
].n
);
1921 PrintAndLogEx(INFO
, "%.64s", vigik_rsa_pk
[i
].n
+ 64);
1922 PrintAndLogEx(INFO
, "%.64s", vigik_rsa_pk
[i
].n
+ 128);
1923 PrintAndLogEx(INFO
, "%.64s", vigik_rsa_pk
[i
].n
+ 192);
1925 PrintAndLogEx(INFO
, "Signature:");
1926 print_hex_noascii_break(d
->rsa_signature
, sizeof(d
->rsa_signature
), MFBLOCK_SIZE
* 2);
1928 PrintAndLogEx(SUCCESS
, "Signature verification: " _GREEN_("successful"));
1933 int vigik_annotate(mfc_vigik_t
*d
) {
1937 PrintAndLogEx(INFO
, "Manufacture......... %s", sprint_hex(d
->b0
, sizeof(d
->b0
)));
1938 PrintAndLogEx(INFO
, "MAD................. %s", sprint_hex(d
->mad
, sizeof(d
->mad
)));
1939 PrintAndLogEx(INFO
, "Counters............ %u", d
->counters
);
1940 PrintAndLogEx(INFO
, "rtf................. %s", sprint_hex(d
->rtf
, sizeof(d
->rtf
)));
1941 PrintAndLogEx(INFO
, "Service code........ 0x%08x / %u - " _YELLOW_("%s"), d
->service_code
, d
->service_code
, vigik_get_service(d
->service_code
));
1942 PrintAndLogEx(INFO
, "Info flag........... %u -", d
->info_flag
); // , sprint_bin(d->info_flag, 1));
1943 PrintAndLogEx(INFO
, "Key version......... %u", d
->key_version
);
1944 PrintAndLogEx(INFO
, "PTR Counter......... %u", d
->ptr_counter
);
1945 PrintAndLogEx(INFO
, "Counter num......... %u", d
->counter_num
);
1946 PrintAndLogEx(INFO
, "Slot access date.... %s", sprint_hex(d
->slot_access_date
, sizeof(d
->slot_access_date
)));
1947 PrintAndLogEx(INFO
, "Slot dst duration... %u", d
->slot_dst_duration
);
1948 PrintAndLogEx(INFO
, "Other Slots......... %s", sprint_hex(d
->other_slots
, sizeof(d
->other_slots
)));
1949 PrintAndLogEx(INFO
, "Services counter.... %u", d
->services_counter
);
1950 PrintAndLogEx(INFO
, "Loading date........ %s", sprint_hex(d
->loading_date
, sizeof(d
->loading_date
)));
1951 PrintAndLogEx(INFO
, "Reserved null....... %u", d
->reserved_null
);
1952 PrintAndLogEx(INFO
, "----------------------------------------------------------------");
1953 PrintAndLogEx(INFO
, "");
1955 PrintAndLogEx(INFO
, "----------------------------------------------------------------");
1956 PrintAndLogEx(INFO
, "");