1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Proxmark3 RDV40 Smartcard module commands
17 //-----------------------------------------------------------------------------
18 #include "cmdsmartcard.h"
21 #include "cmdparser.h" // command_t
22 #include "commonutil.h" // ARRAYLEN
23 #include "iso7816/iso7816core.h"
24 #include "protocols.h"
26 #include "proxmark3.h"
27 #include "comms.h" // getfromdevice
28 #include "emv/emvcore.h" // decodeTVL
29 #include "crypto/libpcrypto.h" // sha512hash
32 #include "fileutils.h"
33 #include "crc16.h" // crc
34 #include "cliparser.h" // cliparsing
35 #include "atrs.h" // ATR lookup
37 #pragma GCC diagnostic push
38 #pragma GCC diagnostic ignored "-Wswitch-enum"
39 #include "mbedtls/net_sockets.h"
40 #pragma GCC diagnostic pop
43 #include "util_posix.h"
47 static int CmdHelp(const char *Cmd
);
49 static int smart_loadjson(const char *preferredName
, json_t
**root
) {
53 if (preferredName
== NULL
) return 1;
56 int res
= searchFile(&path
, RESOURCES_SUBDIR
, preferredName
, ".json", false);
57 if (res
!= PM3_SUCCESS
) {
61 int retval
= PM3_SUCCESS
;
62 *root
= json_load_file(path
, 0, &error
);
64 PrintAndLogEx(ERR
, "json (%s) error on line %d: %s", path
, error
.line
, error
.text
);
69 if (!json_is_array(*root
)) {
70 PrintAndLogEx(ERR
, "Invalid json (%s) format. root must be an array.", path
);
75 PrintAndLogEx(SUCCESS
, "Loaded file (%s) OK.", path
);
81 static uint8_t GetATRTA1(const uint8_t *atr
, size_t atrlen
) {
88 return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1.
91 static int DiArray
[] = {
99 64, // b0111. This was RFU in ISO/IEC 7816-3:1997 and former. Some card readers or drivers may erroneously reject cards using this value
110 static int FiArray
[] = {
111 372, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
129 static float FArray
[] = {
130 4, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock
148 static int GetATRDi(uint8_t *atr
, size_t atrlen
) {
149 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
150 return DiArray
[TA1
& 0x0F]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di
153 static int GetATRFi(uint8_t *atr
, size_t atrlen
) {
154 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
155 return FiArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
158 static float GetATRF(uint8_t *atr
, size_t atrlen
) {
159 uint8_t TA1
= GetATRTA1(atr
, atrlen
);
160 return FArray
[TA1
>> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi
163 static void PrintATR(uint8_t *atr
, size_t atrlen
) {
166 uint8_t K
= T0
& 0x0F;
167 uint8_t T1len
= 0, TD1len
= 0, TDilen
= 0;
168 bool protocol_T0_present
= true;
169 bool protocol_T15_present
= false;
172 PrintAndLogEx(INFO
, " - TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr
[2 + T1len
]);
177 PrintAndLogEx(INFO
, " - TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr
[2 + T1len
]);
182 PrintAndLogEx(INFO
, " - TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr
[2 + T1len
]);
187 uint8_t TD1
= atr
[2 + T1len
];
188 PrintAndLogEx(INFO
, " - TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol " _GREEN_("T%d"), TD1
, TD1
& 0x0f);
189 protocol_T0_present
= false;
190 if ((TD1
& 0x0f) == 0) {
191 protocol_T0_present
= true;
193 if ((TD1
& 0x0f) == 15) {
194 protocol_T15_present
= true;
200 PrintAndLogEx(INFO
, " - TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
204 PrintAndLogEx(INFO
, " - TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
208 PrintAndLogEx(INFO
, " - TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr
[2 + T1len
+ TD1len
]);
212 uint8_t TDi
= atr
[2 + T1len
+ TD1len
];
213 PrintAndLogEx(INFO
, " - TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol " _GREEN_("T%d"), TDi
, TDi
& 0x0f);
214 if ((TDi
& 0x0f) == 0) {
215 protocol_T0_present
= true;
217 if ((TDi
& 0x0f) == 15) {
218 protocol_T15_present
= true;
222 bool nextCycle
= true;
227 PrintAndLogEx(INFO
, " - TA%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
231 PrintAndLogEx(INFO
, " - TB%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
235 PrintAndLogEx(INFO
, " - TC%d: 0x%02x", vi
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
239 TDi
= atr
[2 + T1len
+ TD1len
+ TDilen
];
240 PrintAndLogEx(INFO
, " - TD%d [ 0x%02x ] Protocol T=%d", vi
, TDi
, TDi
& 0x0f);
250 if (!protocol_T0_present
|| protocol_T15_present
) { // there is CRC Check Byte TCK
252 for (int i
= 1; i
< atrlen
; i
++)
256 PrintAndLogEx(WARNING
, "Invalid check sum. Must be 0 got 0x%02X", vxor
);
258 PrintAndLogEx(INFO
, "Check sum OK.");
262 PrintAndLogEx(WARNING
, "Not a direct convention [ 0x%02x ]", atr
[0]);
264 uint8_t calen
= 2 + T1len
+ TD1len
+ TDilen
+ K
;
266 if (atrlen
!= calen
&& atrlen
!= calen
+ 1) // may be CRC
267 PrintAndLogEx(WARNING
, "Invalid ATR length. len: %zu, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen
, T1len
, TD1len
, TDilen
, K
);
270 PrintAndLogEx(DEBUG
, "Historical bytes | len %02d | format %02x", K
, atr
[2 + T1len
+ TD1len
+ TDilen
]);
273 PrintAndLogEx(INFO
, " Historical bytes ( %u )", K
);
274 print_buffer(&atr
[2 + T1len
+ TD1len
+ TDilen
], K
, 1);
278 static int smart_wait(uint8_t *out
, int maxoutlen
, bool verbose
) {
282 clearCommandBuffer();
283 PacketResponseNG resp
;
284 if (WaitForResponseTimeout(CMD_SMART_RAW
, &resp
, 1000)) {
286 if (resp
.status
!= PM3_SUCCESS
) {
287 if (verbose
) PrintAndLogEx(WARNING
, "smart card response status failed");
293 if (verbose
) PrintAndLogEx(WARNING
, "smart card response failed");
297 if (len
> maxoutlen
) {
298 if (verbose
) PrintAndLogEx(ERR
, "Response too large. Got %u, expected %d", len
, maxoutlen
);
302 memcpy(out
, resp
.data
.asBytes
, len
);
307 if (out
[len
- 2] == 0x90 && out
[len
- 1] == 0x00) {
308 PrintAndLogEx(SUCCESS
, _GREEN_("%02X%02X") " | %s", out
[len
- 2], out
[len
- 1], GetAPDUCodeDescription(out
[len
- 2], out
[len
- 1]));
310 PrintAndLogEx(SUCCESS
, "%02X%02X | %s", out
[len
- 2], out
[len
- 1], GetAPDUCodeDescription(out
[len
- 2], out
[len
- 1]));
315 PrintAndLogEx(SUCCESS
, " %d | %s", len
, sprint_hex_inrow_ex(out
, len
, 8));
323 PrintAndLogEx(WARNING
, "smart card response timeout");
328 static int smart_responseEx(uint8_t *out
, int maxoutlen
, bool verbose
) {
330 int datalen
= smart_wait(out
, maxoutlen
, verbose
);
331 int totallen
= datalen
;
332 bool needGetData
= false;
338 if (out
[datalen
- 2] == 0x61 || out
[datalen
- 2] == 0x9F) {
343 // Don't discard data we already received except the SW code.
344 // If we only received 1 byte, this is the echo of INS, we discard it.
350 maxoutlen
-= totallen
;
351 PrintAndLogEx(DEBUG
, "Keeping data (%d bytes): %s", ofs
, sprint_hex(out
, ofs
));
353 int len
= out
[datalen
- 1];
354 if (len
== 0 || len
> MAX_APDU_SIZE
) {
355 // Cap the data length or the smartcard may send us a buffer we can't handle
358 if (maxoutlen
< len
) {
359 // We don't have enough buffer to hold the next part
363 if (verbose
) PrintAndLogEx(INFO
, "Requesting " _YELLOW_("0x%02X") " bytes response", len
);
365 uint8_t cmd_getresp
[] = {0x00, ISO7816_GET_RESPONSE
, 0x00, 0x00, len
};
366 smart_card_raw_t
*payload
= calloc(1, sizeof(smart_card_raw_t
) + sizeof(cmd_getresp
));
367 payload
->flags
= SC_RAW
| SC_LOG
;
368 payload
->len
= sizeof(cmd_getresp
);
369 payload
->wait_delay
= 0;
370 memcpy(payload
->data
, cmd_getresp
, sizeof(cmd_getresp
));
372 clearCommandBuffer();
373 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + sizeof(cmd_getresp
));
376 datalen
= smart_wait(&out
[ofs
], maxoutlen
, verbose
);
383 if (datalen
!= len
+ 2) {
385 if (datalen
== len
+ 2 + 1) { // 2 - response, 1 - ACK
386 if (out
[ofs
] != ISO7816_GET_RESPONSE
) {
388 PrintAndLogEx(ERR
, "GetResponse ACK error. len 0x%x | data[0] %02X", len
, out
[0]);
395 memmove(&out
[ofs
], &out
[ofs
+ 1], datalen
);
400 PrintAndLogEx(WARNING
, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len
, datalen
- 3);
410 static int smart_response(uint8_t *out
, int maxoutlen
) {
411 return smart_responseEx(out
, maxoutlen
, true);
414 static int CmdSmartRaw(const char *Cmd
) {
415 CLIParserContext
*ctx
;
416 CLIParserInit(&ctx
, "smart raw",
417 "Sends raw bytes to card",
418 "smart raw -s -0 -d 00a404000e315041592e5359532e4444463031 -> `1PAY.SYS.DDF01` PPSE directory with get ATR\n"
419 "smart raw -0 -d 00a404000e325041592e5359532e4444463031 -> `2PAY.SYS.DDF01` PPSE directory\n"
420 "smart raw -0 -t -d 00a4040007a0000000041010 -> Mastercard\n"
421 "smart raw -0 -t -d 00a4040007a0000000031010 -> Visa"
426 arg_lit0("r", NULL
, "do not read response"),
427 arg_lit0("a", NULL
, "active smartcard without select (reset sc module)"),
428 arg_lit0("s", NULL
, "active smartcard with select (get ATR)"),
429 arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
430 arg_lit0("0", NULL
, "use protocol T=0"),
431 arg_int0(NULL
, "timeout", "<ms>", "Timeout in MS waiting for SIM to respond. (def 337ms)"),
432 arg_str1("d", "data", "<hex>", "bytes to send"),
435 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
437 bool reply
= (arg_get_lit(ctx
, 1) == false);
438 bool active
= arg_get_lit(ctx
, 2);
439 bool active_select
= arg_get_lit(ctx
, 3);
440 bool decode_tlv
= arg_get_lit(ctx
, 4);
441 bool use_t0
= arg_get_lit(ctx
, 5);
442 int timeout
= arg_get_int_def(ctx
, 6, -1);
445 uint8_t data
[PM3_CMD_DATA_SIZE
] = {0x00};
446 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 7), data
, sizeof(data
), &dlen
);
450 PrintAndLogEx(FAILED
, "Error parsing bytes");
454 smart_card_raw_t
*payload
= calloc(1, sizeof(smart_card_raw_t
) + dlen
);
455 if (payload
== NULL
) {
456 PrintAndLogEx(FAILED
, "failed to allocate memory");
460 memcpy(payload
->data
, data
, dlen
);
462 payload
->flags
= SC_LOG
;
463 if (active
|| active_select
) {
465 payload
->flags
|= (SC_CONNECT
| SC_CLEARLOG
);
467 payload
->flags
|= SC_SELECT
;
470 payload
->wait_delay
= 0;
472 payload
->flags
|= SC_WAIT
;
473 payload
->wait_delay
= timeout
;
475 PrintAndLogEx(DEBUG
, "SIM Card timeout... %u ms", payload
->wait_delay
);
479 payload
->flags
|= SC_RAW_T0
;
481 payload
->flags
|= SC_RAW
;
484 uint8_t *buf
= calloc(PM3_CMD_DATA_SIZE
, sizeof(uint8_t));
486 PrintAndLogEx(DEBUG
, "failed to allocate memory");
491 clearCommandBuffer();
492 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + dlen
);
494 if (reply
== false) {
498 // reading response from smart card
499 int len
= smart_response(buf
, PM3_CMD_DATA_SIZE
);
506 if (buf
[0] == 0x6C) {
508 // request more bytes to download
510 memcpy(payload
->data
, data
, dlen
);
511 clearCommandBuffer();
512 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + dlen
);
514 len
= smart_response(buf
, PM3_CMD_DATA_SIZE
);
519 if (decode_tlv
&& len
> 4) {
520 TLVPrintFromBuffer(buf
, len
- 2);
523 PrintAndLogEx(INFO
, "Response data:");
524 PrintAndLogEx(INFO
, " # | bytes | ascii");
525 PrintAndLogEx(INFO
, "---+-------------------------------------------------+-----------------");
526 print_hex_break(buf
, len
, 16);
529 PrintAndLogEx(NORMAL
, "");
536 static int CmdSmartUpgrade(const char *Cmd
) {
537 PrintAndLogEx(INFO
, "--------------------------------------------------------------------");
538 PrintAndLogEx(WARNING
, _RED_("WARNING") " - sim module firmware upgrade");
539 PrintAndLogEx(WARNING
, _RED_("A dangerous command, do wrong and you could brick the sim module"));
540 PrintAndLogEx(INFO
, "--------------------------------------------------------------------");
541 PrintAndLogEx(NORMAL
, "");
543 CLIParserContext
*ctx
;
544 CLIParserInit(&ctx
, "smart upgrade",
545 "Upgrade RDV4 sim module firmware",
546 "smart upgrade -f sim014.bin"
551 arg_str1("f", "file", "<fn>", "Specify firmware file name"),
554 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
556 char filename
[FILE_PATH_SIZE
] = {0};
557 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
560 char *bin_extension
= filename
;
561 char *dot_position
= NULL
;
562 while ((dot_position
= strchr(bin_extension
, '.')) != NULL
) {
563 bin_extension
= dot_position
+ 1;
566 // generate filename for the related SHA512 hash file
567 char sha512filename
[FILE_PATH_SIZE
] = {'\0'};
568 if (!strcmp(bin_extension
, "BIN") || !strcmp(bin_extension
, "bin")) {
569 memcpy(sha512filename
, filename
, strlen(filename
) - strlen("bin"));
570 strcat(sha512filename
, "sha512.txt");
572 PrintAndLogEx(FAILED
, "Filename extension of firmware upgrade file must be .BIN");
576 PrintAndLogEx(INFO
, "firmware file " _YELLOW_("%s"), filename
);
577 PrintAndLogEx(INFO
, "Checking integrity " _YELLOW_("%s"), sha512filename
);
579 // load firmware file
580 size_t firmware_size
= 0;
581 uint8_t *firmware
= NULL
;
582 if (loadFile_safe(filename
, "", (void **)&firmware
, &firmware_size
) != PM3_SUCCESS
) {
583 PrintAndLogEx(FAILED
, "Firmware file " _YELLOW_("%s") " not found or locked.", filename
);
588 size_t sha512_size
= 0;
589 char *hashstring
= NULL
;
590 if (loadFile_safe(sha512filename
, "", (void **)&hashstring
, &sha512_size
) != PM3_SUCCESS
) {
591 PrintAndLogEx(FAILED
, "SHA-512 file not found or locked.");
596 if (sha512_size
< 128) {
597 PrintAndLogEx(FAILED
, "SHA-512 file wrong size");
602 hashstring
[128] = '\0';
606 if (param_gethex_ex(hashstring
, 0, hash_1
, &hash1n
) && hash1n
!= 128) {
607 PrintAndLogEx(FAILED
, "Couldn't read SHA-512 file. expect 128 hex bytes, got ( "_RED_("%d") " )", hash1n
);
614 if (sha512hash(firmware
, firmware_size
, hash_2
)) {
615 PrintAndLogEx(FAILED
, "Couldn't calculate SHA-512 of firmware");
621 if (memcmp(hash_1
, hash_2
, 64)) {
622 PrintAndLogEx(FAILED
, "Couldn't verify integrity of firmware file " _RED_("(wrong SHA-512 hash)"));
629 PrintAndLogEx(INFO
, _GREEN_("Don\'t turn off your PM3!"));
630 PrintAndLogEx(SUCCESS
, "Sim module firmware uploading to PM3...");
632 PacketResponseNG resp
;
636 uint32_t bytes_sent
= 0;
637 uint32_t bytes_remaining
= firmware_size
;
639 while (bytes_remaining
> 0) {
643 uint32_t bytes_in_packet
;
648 uint32_t bytes_in_packet
= MIN(sizeof(upload
.data
), bytes_remaining
);
650 upload
.idx
= index
+ bytes_sent
;
651 upload
.bytes_in_packet
= bytes_in_packet
;
652 memcpy(upload
.data
, firmware
+ bytes_sent
, bytes_in_packet
);
654 uint8_t a
= 0, b
= 0;
655 compute_crc(CRC_14443_A
, upload
.data
, bytes_in_packet
, &a
, &b
);
656 upload
.crc
= (a
<< 8 | b
);
658 clearCommandBuffer();
659 SendCommandNG(CMD_SMART_UPLOAD
, (uint8_t *)&upload
, sizeof(upload
));
660 if (!WaitForResponseTimeout(CMD_SMART_UPLOAD
, &resp
, 2000)) {
661 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
666 if (resp
.status
!= PM3_SUCCESS
) {
667 PrintAndLogEx(WARNING
, "uploading to device failed");
671 bytes_remaining
-= bytes_in_packet
;
672 bytes_sent
+= bytes_in_packet
;
673 PrintAndLogEx(INPLACE
, "%d bytes sent", bytes_sent
);
675 PrintAndLogEx(NORMAL
, "");
676 PrintAndLogEx(SUCCESS
, "Sim module firmware updating...");
678 // trigger the firmware upgrade
679 clearCommandBuffer();
684 payload
.fw_size
= firmware_size
;
686 uint8_t a
= 0, b
= 0;
687 compute_crc(CRC_14443_A
, firmware
, firmware_size
, &a
, &b
);
688 payload
.crc
= (a
<< 8 | b
);
691 SendCommandNG(CMD_SMART_UPGRADE
, (uint8_t *)&payload
, sizeof(payload
));
692 if (!WaitForResponseTimeout(CMD_SMART_UPGRADE
, &resp
, 2500)) {
693 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
697 if (resp
.status
== PM3_SUCCESS
) {
698 PrintAndLogEx(SUCCESS
, "Sim module firmware upgrade " _GREEN_("successful"));
699 PrintAndLogEx(HINT
, "run " _YELLOW_("`hw status`") " to validate the fw version ");
701 PrintAndLogEx(FAILED
, "Sim module firmware upgrade " _RED_("failed"));
706 static int CmdSmartInfo(const char *Cmd
) {
707 CLIParserContext
*ctx
;
708 CLIParserInit(&ctx
, "smart info",
709 "Extract more detailed information from smart card.",
715 arg_lit0("v", "verbose", "verbose output"),
718 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
719 bool verbose
= arg_get_lit(ctx
, 1);
722 clearCommandBuffer();
723 SendCommandNG(CMD_SMART_ATR
, NULL
, 0);
724 PacketResponseNG resp
;
725 if (WaitForResponseTimeout(CMD_SMART_ATR
, &resp
, 2500) == false) {
727 PrintAndLogEx(WARNING
, "smart card timeout");
732 if (resp
.status
!= PM3_SUCCESS
) {
734 PrintAndLogEx(WARNING
, "smart card select failed");
739 smart_card_atr_t card
;
740 memcpy(&card
, (smart_card_atr_t
*)resp
.data
.asBytes
, sizeof(smart_card_atr_t
));
743 PrintAndLogEx(INFO
, "--- " _CYAN_("Smartcard Information") " ---------");
744 PrintAndLogEx(INFO
, "ISO7816-3 ATR... %s", sprint_hex(card
.atr
, card
.atr_len
));
745 // convert bytes to str.
746 char *hexstr
= calloc((card
.atr_len
<< 1) + 1, sizeof(uint8_t));
747 if (hexstr
== NULL
) {
748 PrintAndLogEx(WARNING
, "failed to allocate memory");
752 hex_to_buffer((uint8_t *)hexstr
, card
.atr
, card
.atr_len
, (card
.atr_len
<< 1), 0, 0, true);
753 PrintAndLogEx(INFO
, "Fingerprint..... %s", getAtrInfo(hexstr
));
757 PrintAndLogEx(INFO
, "ATR");
758 PrintATR(card
.atr
, card
.atr_len
);
760 // print D/F (brom byte TA1 or defaults)
761 PrintAndLogEx(NORMAL
, "");
762 PrintAndLogEx(INFO
, "D/F (TA1)");
763 int Di
= GetATRDi(card
.atr
, card
.atr_len
);
764 int Fi
= GetATRFi(card
.atr
, card
.atr_len
);
765 float F
= GetATRF(card
.atr
, card
.atr_len
);
766 if (GetATRTA1(card
.atr
, card
.atr_len
) == 0x11)
767 PrintAndLogEx(INFO
, "Using default values...");
769 PrintAndLogEx(INFO
, "\t- Di %d", Di
);
770 PrintAndLogEx(INFO
, "\t- Fi %d", Fi
);
771 PrintAndLogEx(INFO
, "\t- F %.1f MHz", F
);
774 PrintAndLogEx(INFO
, "\t- Cycles/ETU %d", Fi
/ Di
);
775 PrintAndLogEx(INFO
, "\t- %.1f bits/sec at 4 MHz", (float)4000000 / (Fi
/ Di
));
776 PrintAndLogEx(INFO
, "\t- %.1f bits/sec at Fmax (%.1fMHz)", (F
* 1000000) / (Fi
/ Di
), F
);
778 PrintAndLogEx(WARNING
, "\t- Di or Fi is RFU.");
784 static int CmdSmartReader(const char *Cmd
) {
785 CLIParserContext
*ctx
;
786 CLIParserInit(&ctx
, "smart reader",
787 "Act as a smart card reader.",
793 arg_lit0("v", "verbose", "verbose output"),
796 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
797 bool verbose
= arg_get_lit(ctx
, 1);
800 clearCommandBuffer();
801 SendCommandNG(CMD_SMART_ATR
, NULL
, 0);
802 PacketResponseNG resp
;
803 if (WaitForResponseTimeout(CMD_SMART_ATR
, &resp
, 2500) == false) {
805 PrintAndLogEx(WARNING
, "smart card select failed");
810 if (resp
.status
!= PM3_SUCCESS
) {
812 PrintAndLogEx(WARNING
, "smart card select failed");
816 smart_card_atr_t
*card
= (smart_card_atr_t
*)resp
.data
.asBytes
;
817 PrintAndLogEx(INFO
, "ISO7816-3 ATR... %s", sprint_hex(card
->atr
, card
->atr_len
));
819 // convert bytes to str.
820 char *hexstr
= calloc((card
->atr_len
<< 1) + 1, sizeof(uint8_t));
821 if (hexstr
== NULL
) {
822 PrintAndLogEx(WARNING
, "failed to allocate memory");
826 hex_to_buffer((uint8_t *)hexstr
, card
->atr
, card
->atr_len
, (card
->atr_len
<< 1), 0, 0, true);
827 PrintAndLogEx(INFO
, "Fingerprint..... %s", getAtrInfo(hexstr
));
832 static int CmdSmartSetClock(const char *Cmd
) {
834 CLIParserContext
*ctx
;
835 CLIParserInit(&ctx
, "smart setclock",
836 "Set clock speed for smart card interface.",
837 "smart setclock --4mhz\n"
838 "smart setclock --16mhz"
843 arg_lit0(NULL
, "16mhz", "16 MHz clock speed"),
844 arg_lit0(NULL
, "8mhz", "8 MHz clock speed"),
845 arg_lit0(NULL
, "4mhz", "4 MHz clock speed"),
848 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
849 bool c16
= arg_get_lit(ctx
, 1);
850 bool c8
= arg_get_lit(ctx
, 2);
851 bool c4
= arg_get_lit(ctx
, 3);
854 if ((c16
+ c8
+ c4
) > 1) {
855 PrintAndLogEx(WARNING
, "Only one clock speed can be used at a time");
870 clearCommandBuffer();
871 SendCommandNG(CMD_SMART_SETCLOCK
, (uint8_t *)&payload
, sizeof(payload
));
872 PacketResponseNG resp
;
873 if (!WaitForResponseTimeout(CMD_SMART_SETCLOCK
, &resp
, 2500)) {
874 PrintAndLogEx(WARNING
, "smart card select failed");
878 if (resp
.status
!= PM3_SUCCESS
) {
879 PrintAndLogEx(WARNING
, "smart card set clock failed");
883 switch (payload
.new_clk
) {
885 PrintAndLogEx(SUCCESS
, "Clock changed to " _GREEN_("16") " MHz giving " _GREEN_("10800") " baudrate");
888 PrintAndLogEx(SUCCESS
, "Clock changed to " _GREEN_("8") " MHz giving " _GREEN_("21600") " baudrate");
891 PrintAndLogEx(SUCCESS
, "Clock changed to " _GREEN_("4") " MHz giving " _GREEN_("86400") " baudrate");
899 static int CmdSmartList(const char *Cmd
) {
900 return CmdTraceListAlias(Cmd
, "smart", "7816");
903 static void smart_brute_prim(void) {
905 uint8_t *buf
= calloc(PM3_CMD_DATA_SIZE
, sizeof(uint8_t));
909 uint8_t get_card_data
[] = {
910 0x80, 0xCA, 0x9F, 0x13, 0x00,
911 0x80, 0xCA, 0x9F, 0x17, 0x00,
912 0x80, 0xCA, 0x9F, 0x36, 0x00,
913 0x80, 0xCA, 0x9F, 0x4f, 0x00
916 PrintAndLogEx(INFO
, "Reading primitives");
918 for (int i
= 0; i
< ARRAYLEN(get_card_data
); i
+= 5) {
920 smart_card_raw_t
*payload
= calloc(1, sizeof(smart_card_raw_t
) + 5);
921 payload
->flags
= SC_RAW_T0
;
923 payload
->wait_delay
= 0;
924 memcpy(payload
->data
, get_card_data
+ i
, 5);
926 clearCommandBuffer();
927 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + 5);
930 int len
= smart_responseEx(buf
, PM3_CMD_DATA_SIZE
, false);
932 PrintAndLogEx(SUCCESS
, "\tHEX %d |: %s", len
, sprint_hex(buf
, len
));
938 static int smart_brute_sfi(bool decodeTLV
) {
940 uint8_t *buf
= calloc(PM3_CMD_DATA_SIZE
, sizeof(uint8_t));
946 uint8_t READ_RECORD
[] = {0x00, 0xB2, 0x00, 0x00, 0x00};
947 PrintAndLogEx(INFO
, "Start SFI brute forcing");
949 for (uint8_t sfi
= 1; sfi
<= 31; sfi
++) {
951 PrintAndLogEx(NORMAL
, "." NOLF
);
953 for (uint16_t rec
= 1; rec
<= 255; rec
++) {
955 if (kbd_enter_pressed()) {
956 PrintAndLogEx(WARNING
, "\naborted via keyboard!\n");
961 READ_RECORD
[2] = rec
;
962 READ_RECORD
[3] = (sfi
<< 3) | 4;
964 smart_card_raw_t
*payload
= calloc(1, sizeof(smart_card_raw_t
) + sizeof(READ_RECORD
));
965 payload
->flags
= SC_RAW_T0
;
966 payload
->len
= sizeof(READ_RECORD
);
967 payload
->wait_delay
= 0;
968 memcpy(payload
->data
, READ_RECORD
, sizeof(READ_RECORD
));
970 clearCommandBuffer();
971 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + sizeof(READ_RECORD
));
973 len
= smart_responseEx(buf
, PM3_CMD_DATA_SIZE
, false);
975 if (buf
[0] == 0x6C) {
976 READ_RECORD
[4] = buf
[1];
978 memcpy(payload
->data
, READ_RECORD
, sizeof(READ_RECORD
));
979 clearCommandBuffer();
980 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + sizeof(READ_RECORD
));
981 len
= smart_responseEx(buf
, PM3_CMD_DATA_SIZE
, false);
990 PrintAndLogEx(SUCCESS
, "\n\t file %02d, record %02d found", sfi
, rec
);
992 uint8_t modifier
= (buf
[0] == 0xC0) ? 1 : 0;
995 if (!TLVPrintFromBuffer(buf
+ modifier
, len
- 2 - modifier
)) {
996 PrintAndLogEx(SUCCESS
, "\tHEX: %s", sprint_hex(buf
, len
));
1000 memset(buf
, 0x00, PM3_CMD_DATA_SIZE
);
1007 static void smart_brute_options(bool decodeTLV
) {
1009 uint8_t *buf
= calloc(PM3_CMD_DATA_SIZE
, sizeof(uint8_t));
1013 // Get processing options command
1014 uint8_t GET_PROCESSING_OPTIONS
[] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00};
1016 smart_card_raw_t
*payload
= calloc(1, sizeof(smart_card_raw_t
) + sizeof(GET_PROCESSING_OPTIONS
));
1017 payload
->flags
= SC_RAW_T0
;
1018 payload
->len
= sizeof(GET_PROCESSING_OPTIONS
);
1019 memcpy(payload
->data
, GET_PROCESSING_OPTIONS
, sizeof(GET_PROCESSING_OPTIONS
));
1021 clearCommandBuffer();
1022 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + sizeof(GET_PROCESSING_OPTIONS
));
1025 int len
= smart_responseEx(buf
, PM3_CMD_DATA_SIZE
, false);
1027 PrintAndLogEx(SUCCESS
, "Got processing options");
1029 TLVPrintFromBuffer(buf
, len
- 2);
1032 PrintAndLogEx(FAILED
, "Getting processing options failed");
1038 static int CmdSmartBruteforceSFI(const char *Cmd
) {
1039 CLIParserContext
*ctx
;
1040 CLIParserInit(&ctx
, "smart brute",
1041 "Tries to bruteforce SFI, using a known list of AID's",
1045 void *argtable
[] = {
1047 arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
1048 // arg_lit0("0", NULL, "use protocol T=0"),
1051 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1052 bool decode_tlv
= arg_get_lit(ctx
, 1);
1053 // bool use_t0 = arg_get_lit(ctx, 2);
1056 const char *SELECT
= "00a40400%02zu%s";
1058 // uint8_t GENERATE_AC[] = {0x80, 0xAE};
1059 // uint8_t GET_CHALLENGE[] = {0x00, 0x84, 0x00};
1060 // uint8_t GET_DATA[] = {0x80, 0xCA, 0x00, 0x00, 0x00};
1061 // uint8_t SELECT[] = {0x00, 0xA4, 0x04, 0x00};
1062 // uint8_t UNBLOCK_PIN[] = {0x84, 0x24, 0x00, 0x00, 0x00};
1063 // uint8_t VERIFY[] = {0x00, 0x20, 0x00, 0x80};
1065 PrintAndLogEx(INFO
, "Importing AID list");
1066 json_t
*root
= NULL
;
1067 smart_loadjson("aidlist", &root
);
1069 uint8_t *buf
= calloc(PM3_CMD_DATA_SIZE
, sizeof(uint8_t));
1073 PrintAndLogEx(INFO
, "Selecting card");
1074 if (!smart_select(false, NULL
)) {
1081 for (int i
= 0; i
< json_array_size(root
); i
++) {
1083 PrintAndLogEx(NORMAL
, "+" NOLF
);
1088 json_t
*data
, *jaid
;
1090 data
= json_array_get(root
, i
);
1091 if (json_is_object(data
) == false) {
1092 PrintAndLogEx(ERR
, "\ndata %d is not an object\n", i
+ 1);
1098 jaid
= json_object_get(data
, "AID");
1099 if (json_is_string(jaid
) == false) {
1100 PrintAndLogEx(ERR
, "\nAID data [%d] is not a string", i
+ 1);
1106 const char *aid
= json_string_value(jaid
);
1110 size_t aidlen
= strlen(aid
);
1111 caid
= calloc(8 + 2 + aidlen
+ 1, sizeof(uint8_t));
1112 snprintf(caid
, 8 + 2 + aidlen
+ 1, SELECT
, aidlen
>> 1, aid
);
1115 uint8_t cmddata
[PM3_CMD_DATA_SIZE
];
1116 int res
= param_gethex_to_eol(caid
, 0, cmddata
, sizeof(cmddata
), &hexlen
);
1120 smart_card_raw_t
*payload
= calloc(1, sizeof(smart_card_raw_t
) + hexlen
);
1121 payload
->flags
= SC_RAW_T0
;
1122 payload
->len
= hexlen
;
1123 payload
->wait_delay
= 0;
1124 memcpy(payload
->data
, cmddata
, hexlen
);
1125 clearCommandBuffer();
1126 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + hexlen
);
1129 int len
= smart_responseEx(buf
, PM3_CMD_DATA_SIZE
, false);
1133 json_t
*jvendor
, *jname
;
1134 jvendor
= json_object_get(data
, "Vendor");
1135 if (json_is_string(jvendor
) == false) {
1136 PrintAndLogEx(ERR
, "Vendor data [%d] is not a string", i
+ 1);
1140 const char *vendor
= json_string_value(jvendor
);
1144 jname
= json_object_get(data
, "Name");
1145 if (json_is_string(jname
) == false) {
1146 PrintAndLogEx(ERR
, "Name data [%d] is not a string", i
+ 1);
1149 const char *name
= json_string_value(jname
);
1153 PrintAndLogEx(SUCCESS
, "\nAID %s | %s | %s", aid
, vendor
, name
);
1155 smart_brute_options(decode_tlv
);
1159 smart_brute_sfi(decode_tlv
);
1161 PrintAndLogEx(SUCCESS
, "\nSFI brute force done\n");
1170 PrintAndLogEx(SUCCESS
, "\nSearch completed.");
1174 static void atsToEmulatedAtr(uint8_t *ats
, uint8_t *atr
, int *atrLen
) {
1175 uint8_t historicalLen
= 0;
1182 if ((ats
[1] & 64) != 0) {
1185 if ((ats
[1] & 32) != 0) {
1188 if ((ats
[1] & 16) != 0) {
1192 if (offset
>= ats
[0]) {
1195 historicalLen
= ats
[0] - offset
;
1200 atr
[1] = 0x80 | historicalLen
;
1204 uint8_t tck
= atr
[1] ^ atr
[2] ^ atr
[3];
1205 for (uint8_t i
= 0; i
< historicalLen
; ++i
) {
1206 atr
[4 + i
] = ats
[offset
+ i
];
1207 tck
= tck
^ ats
[offset
+ i
];
1209 atr
[4 + historicalLen
] = tck
;
1211 *atrLen
= 5 + historicalLen
;
1214 static void atqbToEmulatedAtr(uint8_t *atqb
, uint8_t cid
, uint8_t *atr
, int *atrLen
) {
1220 memcpy(atr
+ 4, atqb
, 7);
1224 for (int i
= 1; i
< 12; ++i
) {
1232 static int CmdPCSC(const char *Cmd
) {
1233 CLIParserContext
*ctx
;
1234 CLIParserInit(&ctx
, "smart pcsc",
1235 "Make pm3 available to host OS smartcard driver via vpcd to enable use with other software such as GlobalPlatform Pro",
1236 "Requires the virtual smartcard daemon to be installed and running\n"
1237 " see https://frankmorgner.github.io/vsmartcard/virtualsmartcard/README.html\n"
1239 " `-v` shows APDU transactions between OS and card\n"
1242 void *argtable
[] = {
1244 arg_str0(NULL
, "host", "<str>", "vpcd socket host (default: localhost)"),
1245 arg_str0("p", "port", "<int>", "vpcd socket port (default: 35963)"),
1246 arg_lit0("v", "verbose", "display APDU transactions between OS and card"),
1247 arg_lit0("a", NULL
, "use ISO 14443A contactless interface"),
1248 arg_lit0("b", NULL
, "use ISO 14443B contactless interface"),
1249 // arg_lit0("v", NULL, "use ISO 15693 contactless interface"),
1250 arg_lit0("c", NULL
, "use ISO 7816 contact interface"),
1253 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1255 uint8_t host
[100] = {0};
1256 int hostLen
= sizeof(host
) - 1; // CLIGetStrWithReturn does not guarantee string to be null-terminated
1257 CLIGetStrWithReturn(ctx
, 1, host
, &hostLen
);
1259 strcpy((char *) host
, "localhost");
1262 uint8_t port
[6] = {0};
1263 int portLen
= sizeof(port
) - 1; // CLIGetStrWithReturn does not guarantee string to be null-terminated
1264 CLIGetStrWithReturn(ctx
, 2, port
, &portLen
);
1266 strcpy((char *) port
, "35963");
1269 bool verbose
= arg_get_lit(ctx
, 3);
1270 bool use14a
= arg_get_lit(ctx
, 4);
1271 bool use14b
= arg_get_lit(ctx
, 5);
1272 // bool use15 = arg_get_lit(ctx, 6);
1273 bool use_contact
= arg_get_lit(ctx
, 6);
1276 mbedtls_net_context netCtx
;
1277 mbedtls_net_init(&netCtx
);
1279 PrintAndLogEx(INFO
, "Relaying PM3 to host OS pcsc daemon");
1280 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
1282 uint8_t cmdbuf
[512] = {0};
1283 iso14a_card_select_t card14a
;
1284 iso14b_card_select_t card14b
;
1285 smart_card_atr_t card
;
1287 bool have_card
= false;
1288 Iso7816CommandChannel card_type
= CC_CONTACT
;
1289 isodep_state_t cl_proto
= ISODEP_INACTIVE
;
1290 bool field_activated
= false;
1296 int bytes_read
= mbedtls_net_recv_timeout(&netCtx
, cmdbuf
, sizeof(cmdbuf
), 100);
1298 if (bytes_read
== MBEDTLS_ERR_SSL_TIMEOUT
|| bytes_read
== MBEDTLS_ERR_SSL_WANT_READ
) {
1302 if (bytes_read
> 0) {
1304 if (cmdbuf
[1] == 0x01 && cmdbuf
[2] == 0x04) { // vpcd GET ATR
1305 uint8_t atr
[256] = {0};
1308 switch (card_type
) {
1310 memcpy(atr
, card
.atr
, card
.atr_len
);
1311 atrLen
= card
.atr_len
;
1314 case CC_CONTACTLESS
: {
1316 if (cl_proto
== ISODEP_NFCA
) {
1317 atsToEmulatedAtr(card14a
.ats
, atr
, &atrLen
);
1319 if (cl_proto
== ISODEP_NFCB
) {
1320 atqbToEmulatedAtr(card14b
.atqb
, card14b
.cid
, atr
, &atrLen
);
1322 if (cl_proto
== ISODEP_NFCV
) {
1332 uint8_t res
[22] = {0};
1334 memcpy(res
+ 2, atr
, atrLen
);
1335 mbedtls_net_send(&netCtx
, res
, 2 + atrLen
);
1337 } else if (cmdbuf
[1] != 0x01) { // vpcd APDU
1338 int apduLen
= (cmdbuf
[0] << 8) + cmdbuf
[1];
1340 uint8_t apduRes
[APDU_RES_LEN
] = {0};
1344 PrintAndLogEx(INFO
, ">> %s", sprint_hex(cmdbuf
+ 2, apduLen
));
1347 switch (card_type
) {
1349 if (ExchangeAPDUSC(false, cmdbuf
+ 2, apduLen
, !field_activated
, true, apduRes
, sizeof(apduRes
), &apduResLen
) != PM3_SUCCESS
) {
1351 mbedtls_net_close(&netCtx
);
1356 case CC_CONTACTLESS
: {
1358 if (cl_proto
== ISODEP_NFCA
) {
1359 if (ExchangeAPDU14a(cmdbuf
+ 2, apduLen
, !field_activated
, true, apduRes
, sizeof(apduRes
), &apduResLen
) != PM3_SUCCESS
) {
1361 mbedtls_net_close(&netCtx
);
1365 if (cl_proto
== ISODEP_NFCB
) {
1367 if (exchange_14b_apdu(cmdbuf
+ 2, apduLen
, !field_activated
, true, apduRes
, sizeof(apduRes
), &apduResLen
, 0)) {
1369 mbedtls_net_close(&netCtx
);
1373 if (cl_proto
== ISODEP_NFCV
) {
1384 field_activated
= true;
1387 PrintAndLogEx(INFO
, "<< %s", sprint_hex(apduRes
, apduResLen
));
1390 uint8_t res
[APDU_RES_LEN
+ 2] = {0};
1391 res
[0] = (apduResLen
>> 8) & 0xFF;
1392 res
[1] = apduResLen
& 0xFF;
1393 memcpy(res
+ 2, apduRes
, apduResLen
);
1394 mbedtls_net_send(&netCtx
, res
, 2 + apduResLen
);
1399 if (use14a
&& IfPm3Iso14443a() && SelectCard14443A_4(false, false, &card14a
) == PM3_SUCCESS
) {
1401 card_type
= CC_CONTACTLESS
;
1402 cl_proto
= ISODEP_NFCA
;
1405 if (use14b
&& IfPm3Iso14443b() && select_card_14443b_4(false, &card14b
) == PM3_SUCCESS
) {
1407 card_type
= CC_CONTACTLESS
;
1408 cl_proto
= ISODEP_NFCB
;
1413 if (use_contact
&& IfPm3Iso14443() && smart_select(false, &card
) == PM3_SUCCESS
) {
1415 card_type
= CC_CONTACT
;
1419 field_activated
= false;
1420 if (mbedtls_net_connect(&netCtx
, (char *) host
, (char *) port
, MBEDTLS_NET_PROTO_TCP
)) {
1421 PrintAndLogEx(FAILED
, "Failed to connect to vpcd socket. Ensure you have vpcd installed and running");
1422 mbedtls_net_close(&netCtx
);
1423 mbedtls_net_free(&netCtx
);
1431 } while (!kbd_enter_pressed());
1433 mbedtls_net_close(&netCtx
);
1434 mbedtls_net_free(&netCtx
);
1440 static command_t CommandTable
[] = {
1441 {"----------", CmdHelp
, IfPm3Iso14443a
, "------------------- " _CYAN_("General") " -------------------"},
1442 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
1443 {"list", CmdSmartList
, AlwaysAvailable
, "List ISO 7816 history"},
1444 {"----------", CmdHelp
, IfPm3Iso14443a
, "------------------- " _CYAN_("Operations") " -------------------"},
1445 {"brute", CmdSmartBruteforceSFI
, IfPm3Smartcard
, "Bruteforce SFI"},
1446 {"info", CmdSmartInfo
, IfPm3Smartcard
, "Tag information"},
1447 {"pcsc", CmdPCSC
, AlwaysAvailable
, "Turn pm3 into pcsc reader and relay to host OS via vpcd"},
1448 {"reader", CmdSmartReader
, IfPm3Smartcard
, "Act like an IS07816 reader"},
1449 {"raw", CmdSmartRaw
, IfPm3Smartcard
, "Send raw hex data to tag"},
1450 {"upgrade", CmdSmartUpgrade
, AlwaysAvailable
, "Upgrade sim module firmware"},
1451 {"setclock", CmdSmartSetClock
, IfPm3Smartcard
, "Set clock speed"},
1452 {NULL
, NULL
, NULL
, NULL
}
1455 static int CmdHelp(const char *Cmd
) {
1456 (void)Cmd
; // Cmd is not used so far
1457 CmdsHelp(CommandTable
);
1461 int CmdSmartcard(const char *Cmd
) {
1462 clearCommandBuffer();
1463 return CmdsParse(CommandTable
, Cmd
);
1466 int ExchangeAPDUSC(bool verbose
, uint8_t *datain
, int datainlen
, bool activateCard
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
) {
1470 smart_card_raw_t
*payload
= calloc(1, sizeof(smart_card_raw_t
) + datainlen
);
1471 payload
->flags
= (SC_RAW_T0
| SC_LOG
);
1473 payload
->flags
|= (SC_SELECT
| SC_CONNECT
);
1475 payload
->len
= datainlen
;
1476 payload
->wait_delay
= 0;
1477 memcpy(payload
->data
, datain
, datainlen
);
1479 clearCommandBuffer();
1480 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + datainlen
);
1482 int len
= smart_responseEx(dataout
, maxdataoutlen
, verbose
);
1489 if (len
> 1 && dataout
[len
- 2] == 0x6c && datainlen
> 4) {
1491 payload
->flags
= SC_RAW_T0
;
1493 // transfer length via T=0
1494 datain
[4] = dataout
[len
- 1];
1495 memcpy(payload
->data
, datain
, 5);
1496 clearCommandBuffer();
1497 SendCommandNG(CMD_SMART_RAW
, (uint8_t *)payload
, sizeof(smart_card_raw_t
) + 5);
1499 len
= smart_responseEx(dataout
, maxdataoutlen
, verbose
);
1511 bool smart_select(bool verbose
, smart_card_atr_t
*atr
) {
1513 memset(atr
, 0, sizeof(smart_card_atr_t
));
1516 clearCommandBuffer();
1517 SendCommandNG(CMD_SMART_ATR
, NULL
, 0);
1518 PacketResponseNG resp
;
1519 if (WaitForResponseTimeout(CMD_SMART_ATR
, &resp
, 2500) == false) {
1520 if (verbose
) PrintAndLogEx(WARNING
, "smart card select timeout");
1524 if (resp
.status
!= PM3_SUCCESS
) {
1525 if (verbose
) PrintAndLogEx(WARNING
, "smart card select failed");
1529 smart_card_atr_t card
;
1530 memcpy(&card
, (smart_card_atr_t
*)resp
.data
.asBytes
, sizeof(smart_card_atr_t
));
1533 memcpy(atr
, &card
, sizeof(smart_card_atr_t
));
1537 PrintAndLogEx(INFO
, "ISO7816-3 ATR : %s", sprint_hex(card
.atr
, card
.atr_len
));