Isolate ISO7816 select & exchange from EMVcore

This commit is contained in:
Philippe Teuwen 2021-05-30 18:56:33 +02:00
commit 11334f9440
21 changed files with 247 additions and 174 deletions

View file

@ -193,7 +193,6 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/emv/test/cryptotest.c ${PM3_ROOT}/client/src/emv/test/cryptotest.c
${PM3_ROOT}/client/src/emv/test/dda_test.c ${PM3_ROOT}/client/src/emv/test/dda_test.c
${PM3_ROOT}/client/src/emv/test/sda_test.c ${PM3_ROOT}/client/src/emv/test/sda_test.c
${PM3_ROOT}/client/src/emv/apduinfo.c
${PM3_ROOT}/client/src/emv/cmdemv.c ${PM3_ROOT}/client/src/emv/cmdemv.c
${PM3_ROOT}/client/src/emv/crypto.c ${PM3_ROOT}/client/src/emv/crypto.c
${PM3_ROOT}/client/src/emv/crypto_polarssl.c ${PM3_ROOT}/client/src/emv/crypto_polarssl.c
@ -210,6 +209,8 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/fido/cbortools.c ${PM3_ROOT}/client/src/fido/cbortools.c
${PM3_ROOT}/client/src/fido/cose.c ${PM3_ROOT}/client/src/fido/cose.c
${PM3_ROOT}/client/src/fido/fidocore.c ${PM3_ROOT}/client/src/fido/fidocore.c
${PM3_ROOT}/client/src/iso7816/apduinfo.c
${PM3_ROOT}/client/src/iso7816/iso7816core.c
${PM3_ROOT}/client/src/loclass/cipher.c ${PM3_ROOT}/client/src/loclass/cipher.c
${PM3_ROOT}/client/src/loclass/cipherutils.c ${PM3_ROOT}/client/src/loclass/cipherutils.c
${PM3_ROOT}/client/src/loclass/elite_crack.c ${PM3_ROOT}/client/src/loclass/elite_crack.c

View file

@ -535,7 +535,6 @@ SRCS = aiddesfire.c \
crypto/asn1dump.c \ crypto/asn1dump.c \
crypto/asn1utils.c\ crypto/asn1utils.c\
crypto/libpcrypto.c\ crypto/libpcrypto.c\
emv/apduinfo.c \
emv/cmdemv.c \ emv/cmdemv.c \
emv/crypto.c\ emv/crypto.c\
emv/crypto_polarssl.c\ emv/crypto_polarssl.c\
@ -562,6 +561,8 @@ SRCS = aiddesfire.c \
generator.c \ generator.c \
graph.c \ graph.c \
jansson_path.c \ jansson_path.c \
iso7816/apduinfo.c \
iso7816/iso7816core.c \
loclass/cipher.c \ loclass/cipher.c \
loclass/cipherutils.c \ loclass/cipherutils.c \
loclass/elite_crack.c \ loclass/elite_crack.c \

View file

@ -61,7 +61,6 @@ add_library(pm3rrg_rdv4 SHARED
${PM3_ROOT}/client/src/emv/test/cryptotest.c ${PM3_ROOT}/client/src/emv/test/cryptotest.c
${PM3_ROOT}/client/src/emv/test/dda_test.c ${PM3_ROOT}/client/src/emv/test/dda_test.c
${PM3_ROOT}/client/src/emv/test/sda_test.c ${PM3_ROOT}/client/src/emv/test/sda_test.c
${PM3_ROOT}/client/src/emv/apduinfo.c
${PM3_ROOT}/client/src/emv/cmdemv.c ${PM3_ROOT}/client/src/emv/cmdemv.c
${PM3_ROOT}/client/src/emv/crypto.c ${PM3_ROOT}/client/src/emv/crypto.c
${PM3_ROOT}/client/src/emv/crypto_polarssl.c ${PM3_ROOT}/client/src/emv/crypto_polarssl.c
@ -78,6 +77,8 @@ add_library(pm3rrg_rdv4 SHARED
${PM3_ROOT}/client/src/fido/cbortools.c ${PM3_ROOT}/client/src/fido/cbortools.c
${PM3_ROOT}/client/src/fido/cose.c ${PM3_ROOT}/client/src/fido/cose.c
${PM3_ROOT}/client/src/fido/fidocore.c ${PM3_ROOT}/client/src/fido/fidocore.c
${PM3_ROOT}/client/src/iso7816/apduinfo.c
${PM3_ROOT}/client/src/iso7816/iso7816core.c
${PM3_ROOT}/client/src/loclass/cipher.c ${PM3_ROOT}/client/src/loclass/cipher.c
${PM3_ROOT}/client/src/loclass/cipherutils.c ${PM3_ROOT}/client/src/loclass/cipherutils.c
${PM3_ROOT}/client/src/loclass/elite_crack.c ${PM3_ROOT}/client/src/loclass/elite_crack.c

View file

@ -193,7 +193,6 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/emv/test/cryptotest.c ${PM3_ROOT}/client/src/emv/test/cryptotest.c
${PM3_ROOT}/client/src/emv/test/dda_test.c ${PM3_ROOT}/client/src/emv/test/dda_test.c
${PM3_ROOT}/client/src/emv/test/sda_test.c ${PM3_ROOT}/client/src/emv/test/sda_test.c
${PM3_ROOT}/client/src/emv/apduinfo.c
${PM3_ROOT}/client/src/emv/cmdemv.c ${PM3_ROOT}/client/src/emv/cmdemv.c
${PM3_ROOT}/client/src/emv/crypto.c ${PM3_ROOT}/client/src/emv/crypto.c
${PM3_ROOT}/client/src/emv/crypto_polarssl.c ${PM3_ROOT}/client/src/emv/crypto_polarssl.c
@ -210,6 +209,8 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/fido/cbortools.c ${PM3_ROOT}/client/src/fido/cbortools.c
${PM3_ROOT}/client/src/fido/cose.c ${PM3_ROOT}/client/src/fido/cose.c
${PM3_ROOT}/client/src/fido/fidocore.c ${PM3_ROOT}/client/src/fido/fidocore.c
${PM3_ROOT}/client/src/iso7816/apduinfo.c
${PM3_ROOT}/client/src/iso7816/iso7816core.c
${PM3_ROOT}/client/src/loclass/cipher.c ${PM3_ROOT}/client/src/loclass/cipher.c
${PM3_ROOT}/client/src/loclass/cipherutils.c ${PM3_ROOT}/client/src/loclass/cipherutils.c
${PM3_ROOT}/client/src/loclass/elite_crack.c ${PM3_ROOT}/client/src/loclass/elite_crack.c

View file

@ -20,6 +20,7 @@
#include "cliparser.h" #include "cliparser.h"
#include "cmdhfmf.h" #include "cmdhfmf.h"
#include "cmdhfmfu.h" #include "cmdhfmfu.h"
#include "iso7816/iso7816core.h"
#include "emv/emvcore.h" #include "emv/emvcore.h"
#include "ui.h" #include "ui.h"
#include "crc16.h" #include "crc16.h"
@ -28,7 +29,7 @@
#include "cmdhf.h" // handle HF plot #include "cmdhf.h" // handle HF plot
#include "cliparser.h" #include "cliparser.h"
#include "protocols.h" // definitions of ISO14A/7816 protocol, MAGIC_GEN_1A #include "protocols.h" // definitions of ISO14A/7816 protocol, MAGIC_GEN_1A
#include "emv/apduinfo.h" // GetAPDUCodeDescription #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
#include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint #include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint
#include "cmdnfc.h" // print_type4_cc_info #include "cmdnfc.h" // print_type4_cc_info
@ -2008,7 +2009,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
uint16_t sw = 0; uint16_t sw = 0;
uint8_t result[1024] = {0}; uint8_t result[1024] = {0};
size_t resultlen = 0; size_t resultlen = 0;
int res = EMVSelect(ECC_CONTACTLESS, ActivateField, true, vaid, vaidlen, result, sizeof(result), &resultlen, &sw, NULL); int res = Iso7816Select(CC_CONTACTLESS, ActivateField, true, vaid, vaidlen, result, sizeof(result), &resultlen, &sw);
ActivateField = false; ActivateField = false;
if (res) if (res)
continue; continue;

View file

@ -22,7 +22,7 @@
#include "crc16.h" #include "crc16.h"
#include "cmdhf14a.h" #include "cmdhf14a.h"
#include "protocols.h" // definitions of ISO14B/7816 protocol #include "protocols.h" // definitions of ISO14B/7816 protocol
#include "emv/apduinfo.h" // GetAPDUCodeDescription #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
#include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint #include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint
#include "aidsearch.h" #include "aidsearch.h"

View file

@ -18,7 +18,7 @@
#include "cliparser.h" // CLIParserContext etc #include "cliparser.h" // CLIParserContext etc
#include "cmdhf14a.h" // ExchangeAPDU14a #include "cmdhf14a.h" // ExchangeAPDU14a
#include "protocols.h" // definitions of ISO14A/7816 protocol #include "protocols.h" // definitions of ISO14A/7816 protocol
#include "emv/apduinfo.h" // GetAPDUCodeDescription #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
#include "crypto/libpcrypto.h" // Hash calculation (sha1, sha256, sha512) #include "crypto/libpcrypto.h" // Hash calculation (sha1, sha256, sha512)
#include "mifare/desfire_crypto.h" // des_encrypt/des_decrypt #include "mifare/desfire_crypto.h" // des_encrypt/des_decrypt
#include "des.h" // mbedtls_des_key_set_parity #include "des.h" // mbedtls_des_key_set_parity

View file

@ -24,7 +24,7 @@
#include "commonutil.h" #include "commonutil.h"
#include "comms.h" #include "comms.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "emv/emvcore.h" #include "iso7816/iso7816core.h"
#include "emv/emvjson.h" #include "emv/emvjson.h"
#include "cliparser.h" #include "cliparser.h"
#include "crypto/asn1utils.h" #include "crypto/asn1utils.h"

View file

@ -24,8 +24,8 @@
#include "protocols.h" #include "protocols.h"
#include "cmdtrace.h" #include "cmdtrace.h"
#include "cliparser.h" #include "cliparser.h"
#include "emv/apduinfo.h" // APDU manipulation / errorcodes #include "iso7816/apduinfo.h" // APDU manipulation / errorcodes
#include "emv/emvcore.h" // APDU logging #include "iso7816/iso7816core.h" // APDU logging
#include "util_posix.h" // msleep #include "util_posix.h" // msleep
#include "mifare/desfire_crypto.h" #include "mifare/desfire_crypto.h"
#include "crapto1/crapto1.h" #include "crapto1/crapto1.h"

View file

@ -19,7 +19,7 @@
#include "ui.h" #include "ui.h"
#include "cmdhf14a.h" // manufacture #include "cmdhf14a.h" // manufacture
#include "protocols.h" // definitions of ISO14A/7816 protocol #include "protocols.h" // definitions of ISO14A/7816 protocol
#include "emv/apduinfo.h" // GetAPDUCodeDescription #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
#include "crypto/asn1utils.h" // ASN1 decode / print #include "crypto/asn1utils.h" // ASN1 decode / print
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);

View file

@ -19,7 +19,7 @@
#include "crc16.h" #include "crc16.h"
#include "cmdhf14a.h" #include "cmdhf14a.h"
#include "protocols.h" // definitions of ISO14A/7816 protocol #include "protocols.h" // definitions of ISO14A/7816 protocol
#include "emv/apduinfo.h" // GetAPDUCodeDescription #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
#include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint #include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint
#include "cmdnfc.h" // print_type4_cc_info #include "cmdnfc.h" // print_type4_cc_info

View file

@ -26,7 +26,7 @@ extern "C" {
#ifndef DropFieldEx #ifndef DropFieldEx
#define DropFieldEx(x) { \ #define DropFieldEx(x) { \
if ( (x) == ECC_CONTACTLESS) { \ if ( (x) == CC_CONTACTLESS) { \
DropField(); \ DropField(); \
} \ } \
} }

View file

@ -56,12 +56,12 @@ static void ParamLoadDefaults(struct tlvdb *tlvRoot) {
TLV_ADD(0x9F4E, "proxmrk3rdv\x00"); TLV_ADD(0x9F4E, "proxmrk3rdv\x00");
} }
static void PrintChannel(EMVCommandChannel channel) { static void PrintChannel(Iso7816CommandChannel channel) {
switch (channel) { switch (channel) {
case ECC_CONTACTLESS: case CC_CONTACTLESS:
PrintAndLogEx(INFO, "Selected channel... " _GREEN_("CONTACTLESS (T=CL)")); PrintAndLogEx(INFO, "Selected channel... " _GREEN_("CONTACTLESS (T=CL)"));
break; break;
case ECC_CONTACT: case CC_CONTACT:
PrintAndLogEx(INFO, "Selected channel... " _GREEN_("CONTACT")); PrintAndLogEx(INFO, "Selected channel... " _GREEN_("CONTACT"));
break; break;
} }
@ -93,9 +93,9 @@ static int CmdEMVSelect(const char *Cmd) {
bool leaveSignalON = arg_get_lit(ctx, 2); bool leaveSignalON = arg_get_lit(ctx, 2);
bool APDULogging = arg_get_lit(ctx, 3); bool APDULogging = arg_get_lit(ctx, 3);
bool decodeTLV = arg_get_lit(ctx, 4); bool decodeTLV = arg_get_lit(ctx, 4);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 5)) if (arg_get_lit(ctx, 5))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(ctx, 6, data, &datalen); CLIGetHexWithReturn(ctx, 6, data, &datalen);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -143,9 +143,9 @@ static int CmdEMVSearch(const char *Cmd) {
bool leaveSignalON = arg_get_lit(ctx, 2); bool leaveSignalON = arg_get_lit(ctx, 2);
bool APDULogging = arg_get_lit(ctx, 3); bool APDULogging = arg_get_lit(ctx, 3);
bool decodeTLV = arg_get_lit(ctx, 4); bool decodeTLV = arg_get_lit(ctx, 4);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 5)) if (arg_get_lit(ctx, 5))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -201,9 +201,9 @@ static int CmdEMVPPSE(const char *Cmd) {
PSENum = 2; PSENum = 2;
bool APDULogging = arg_get_lit(ctx, 5); bool APDULogging = arg_get_lit(ctx, 5);
bool decodeTLV = arg_get_lit(ctx, 6); bool decodeTLV = arg_get_lit(ctx, 6);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 7)) if (arg_get_lit(ctx, 7))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -257,9 +257,9 @@ static int CmdEMVGPO(const char *Cmd) {
bool dataMakeFromPDOL = arg_get_lit(ctx, 3); bool dataMakeFromPDOL = arg_get_lit(ctx, 3);
bool APDULogging = arg_get_lit(ctx, 4); bool APDULogging = arg_get_lit(ctx, 4);
bool decodeTLV = arg_get_lit(ctx, 5); bool decodeTLV = arg_get_lit(ctx, 5);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 6)) if (arg_get_lit(ctx, 6))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(ctx, 7, data, &datalen); CLIGetHexWithReturn(ctx, 7, data, &datalen);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -362,9 +362,9 @@ static int CmdEMVReadRecord(const char *Cmd) {
bool leaveSignalON = arg_get_lit(ctx, 1); bool leaveSignalON = arg_get_lit(ctx, 1);
bool APDULogging = arg_get_lit(ctx, 2); bool APDULogging = arg_get_lit(ctx, 2);
bool decodeTLV = arg_get_lit(ctx, 3); bool decodeTLV = arg_get_lit(ctx, 3);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 4)) if (arg_get_lit(ctx, 4))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(ctx, 5, data, &datalen); CLIGetHexWithReturn(ctx, 5, data, &datalen);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -449,9 +449,9 @@ static int CmdEMVAC(const char *Cmd) {
bool APDULogging = arg_get_lit(ctx, 6); bool APDULogging = arg_get_lit(ctx, 6);
bool decodeTLV = arg_get_lit(ctx, 7); bool decodeTLV = arg_get_lit(ctx, 7);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 8)) if (arg_get_lit(ctx, 8))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(ctx, 9, data, &datalen); CLIGetHexWithReturn(ctx, 9, data, &datalen);
@ -541,9 +541,9 @@ static int CmdEMVGenerateChallenge(const char *Cmd) {
bool leaveSignalON = arg_get_lit(ctx, 1); bool leaveSignalON = arg_get_lit(ctx, 1);
bool APDULogging = arg_get_lit(ctx, 2); bool APDULogging = arg_get_lit(ctx, 2);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 3)) if (arg_get_lit(ctx, 3))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -600,9 +600,9 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) {
bool dataMakeFromDDOL = arg_get_lit(ctx, 3); bool dataMakeFromDDOL = arg_get_lit(ctx, 3);
bool APDULogging = arg_get_lit(ctx, 4); bool APDULogging = arg_get_lit(ctx, 4);
bool decodeTLV = arg_get_lit(ctx, 5); bool decodeTLV = arg_get_lit(ctx, 5);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 6)) if (arg_get_lit(ctx, 6))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(ctx, 7, data, &datalen); CLIGetHexWithReturn(ctx, 7, data, &datalen);
CLIParserFree(ctx); CLIParserFree(ctx);
@ -841,15 +841,15 @@ static int CmdEMVExec(const char *Cmd) {
TrType = TT_VSDC; TrType = TT_VSDC;
bool GenACGPO = arg_get_lit(ctx, 10); bool GenACGPO = arg_get_lit(ctx, 10);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 11)) if (arg_get_lit(ctx, 11))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; uint8_t psenum = (channel == CC_CONTACT) ? 1 : 2;
CLIParserFree(ctx); CLIParserFree(ctx);
if (!IfPm3Smartcard()) { if (!IfPm3Smartcard()) {
if (channel == ECC_CONTACT) { if (channel == CC_CONTACT) {
PrintAndLogEx(WARNING, "PM3 does not have SMARTCARD support. Exiting."); PrintAndLogEx(WARNING, "PM3 does not have SMARTCARD support. Exiting.");
return PM3_EDEVNOTSUPP; return PM3_EDEVNOTSUPP;
} }
@ -1463,13 +1463,13 @@ static int CmdEMVScan(const char *Cmd) {
bool GenACGPO = arg_get_lit(ctx, 9); bool GenACGPO = arg_get_lit(ctx, 9);
bool MergeJSON = arg_get_lit(ctx, 10); bool MergeJSON = arg_get_lit(ctx, 10);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 11)) if (arg_get_lit(ctx, 11))
channel = ECC_CONTACT; channel = CC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; uint8_t psenum = (channel == CC_CONTACT) ? 1 : 2;
uint8_t filename[FILE_PATH_SIZE] = {0}; uint8_t filename[FILE_PATH_SIZE] = {0};
int filenamelen = sizeof(filename); int filenamelen = sizeof(filename);
@ -1478,7 +1478,7 @@ static int CmdEMVScan(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
if (!IfPm3Smartcard()) { if (!IfPm3Smartcard()) {
if (channel == ECC_CONTACT) { if (channel == CC_CONTACT) {
PrintAndLogEx(WARNING, "PM3 does not have SMARTCARD support, exiting"); PrintAndLogEx(WARNING, "PM3 does not have SMARTCARD support, exiting");
return PM3_EDEVNOTSUPP; return PM3_EDEVNOTSUPP;
} }
@ -1511,7 +1511,7 @@ static int CmdEMVScan(const char *Cmd) {
JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`"); JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`");
if (channel == ECC_CONTACTLESS) { if (channel == CC_CONTACTLESS) {
// iso 14443 select // iso 14443 select
PrintAndLogEx(INFO, "GET UID, ATS"); PrintAndLogEx(INFO, "GET UID, ATS");
@ -1868,22 +1868,22 @@ static int CmdEMVRoca(const char *Cmd) {
bool show_apdu = arg_get_lit(ctx, 2); bool show_apdu = arg_get_lit(ctx, 2);
EMVCommandChannel channel = ECC_CONTACTLESS; Iso7816CommandChannel channel = CC_CONTACTLESS;
if (arg_get_lit(ctx, 3)) if (arg_get_lit(ctx, 3))
channel = ECC_CONTACT; channel = CC_CONTACT;
CLIParserFree(ctx); CLIParserFree(ctx);
PrintChannel(channel); PrintChannel(channel);
if (!IfPm3Smartcard()) { if (!IfPm3Smartcard()) {
if (channel == ECC_CONTACT) { if (channel == CC_CONTACT) {
PrintAndLogEx(WARNING, "PM3 does not have SMARTCARD support, exiting"); PrintAndLogEx(WARNING, "PM3 does not have SMARTCARD support, exiting");
return PM3_EDEVNOTSUPP; return PM3_EDEVNOTSUPP;
} }
} }
// select card // select card
uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; uint8_t psenum = (channel == CC_CONTACT) ? 1 : 2;
SetAPDULogging(show_apdu); SetAPDULogging(show_apdu);

View file

@ -131,16 +131,6 @@ static const TAIDList AIDlist [] = {
{ CV_OTHER, "F0000000030001" }, // BRADESCO - Brazilian Bank Banco Bradesco { CV_OTHER, "F0000000030001" }, // BRADESCO - Brazilian Bank Banco Bradesco
}; };
//iceman: this logging setting, should be unified with client debug etc.
static bool APDULogging = false;
void SetAPDULogging(bool logging) {
APDULogging = logging;
}
bool GetAPDULogging(void) {
return APDULogging;
}
enum CardPSVendor GetCardPSVendor(uint8_t *AID, size_t AIDlen) { enum CardPSVendor GetCardPSVendor(uint8_t *AID, size_t AIDlen) {
char buf[100] = {0}; char buf[100] = {0};
if (AIDlen < 1) if (AIDlen < 1)
@ -275,90 +265,37 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) {
return tlvdb_fixed(0x02, dCVVlen, dCVV); return tlvdb_fixed(0x02, dCVVlen, dCVV);
} }
static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { static int EMVExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
uint8_t data[APDU_RES_LEN] = {0}; int res = Iso7816ExchangeEx(channel, ActivateField, LeaveFieldON, apdu, IncludeLe, Result, MaxResultLen, ResultLen, sw);
*ResultLen = 0;
if (sw) *sw = 0;
uint16_t isw = 0;
int res = 0;
if (ActivateField) {
DropFieldEx(channel);
msleep(50);
}
// COMPUTE APDU
int datalen = 0;
if (APDUEncodeS(&apdu, false, IncludeLe ? 0x100 : 0x00, data, &datalen)) {
PrintAndLogEx(ERR, "APDU encoding error.");
return 201;
}
if (APDULogging)
PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen));
switch (channel) {
case ECC_CONTACTLESS:
res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
if (res != PM3_SUCCESS) {
res = exchange_14b_apdu(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen, 4000);
if (res != PM3_SUCCESS)
return res;
}
break;
case ECC_CONTACT:
res = 1;
if (IfPm3Smartcard())
res = ExchangeAPDUSC(false, data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
if (res) {
return res;
}
break;
}
if (APDULogging)
PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(Result, *ResultLen));
if (*ResultLen < 2) {
return 200;
}
*ResultLen -= 2;
isw = Result[*ResultLen] * 0x0100 + Result[*ResultLen + 1];
if (sw)
*sw = isw;
if (isw != 0x9000) {
if (APDULogging) {
if (*sw >> 8 == 0x61) {
PrintAndLogEx(ERR, "APDU chaining len:%02x -->", *sw & 0xff);
} else {
PrintAndLogEx(ERR, "APDU(%02x%02x) ERROR: [%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xff));
return 5;
}
}
}
// add to tlv tree // add to tlv tree
if (tlv) { if ((res == PM3_SUCCESS) && tlv) {
struct tlvdb *t = tlvdb_parse_multi(Result, *ResultLen); struct tlvdb *t = tlvdb_parse_multi(Result, *ResultLen);
tlvdb_add(tlv, t); tlvdb_add(tlv, t);
} }
return res;
return 0;
} }
int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVExchange(Iso7816CommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchangeEx(channel, false, LeaveFieldON, apdu, false, Result, MaxResultLen, ResultLen, sw, tlv); int res = Iso7816Exchange(channel, LeaveFieldON, apdu, Result, MaxResultLen, ResultLen, sw);
// add to tlv tree
if ((res == PM3_SUCCESS) && tlv) {
struct tlvdb *t = tlvdb_parse_multi(Result, *ResultLen);
tlvdb_add(tlv, t);
}
return res;
} }
int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVSelect(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchangeEx(channel, ActivateField, LeaveFieldON, (sAPDU) {0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, (channel == ECC_CONTACTLESS), Result, MaxResultLen, ResultLen, sw, tlv); int res = Iso7816Select(channel, ActivateField, LeaveFieldON, AID, AIDLen, Result, MaxResultLen, ResultLen, sw);
// add to tlv tree
if ((res == PM3_SUCCESS) && tlv) {
struct tlvdb *t = tlvdb_parse_multi(Result, *ResultLen);
tlvdb_add(tlv, t);
}
return res;
} }
int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { int EMVSelectPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
uint8_t buf[APDU_AID_LEN] = {0}; uint8_t buf[APDU_AID_LEN] = {0};
*ResultLen = 0; *ResultLen = 0;
int len = 0; int len = 0;
@ -375,7 +312,7 @@ int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO
return EMVSelect(channel, ActivateField, LeaveFieldON, buf, len, Result, MaxResultLen, ResultLen, sw, NULL); return EMVSelect(channel, ActivateField, LeaveFieldON, buf, len, Result, MaxResultLen, ResultLen, sw, NULL);
} }
static int EMVSelectWithRetry(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { static int EMVSelectWithRetry(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
int retrycnt = 0; int retrycnt = 0;
int res = 0; int res = 0;
do { do {
@ -402,7 +339,7 @@ static int EMVSelectWithRetry(EMVCommandChannel channel, bool ActivateField, boo
return res; return res;
} }
static int EMVCheckAID(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlvdbelm, struct tlvdb *tlv) { static int EMVCheckAID(Iso7816CommandChannel channel, bool decodeTLV, struct tlvdb *tlvdbelm, struct tlvdb *tlv) {
uint8_t data[APDU_RES_LEN] = {0}; uint8_t data[APDU_RES_LEN] = {0};
size_t datalen = 0; size_t datalen = 0;
int res = 0; int res = 0;
@ -434,7 +371,7 @@ static int EMVCheckAID(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *
return res; return res;
} }
int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv) { int EMVSearchPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv) {
uint8_t data[APDU_RES_LEN] = {0}; uint8_t data[APDU_RES_LEN] = {0};
size_t datalen = 0; size_t datalen = 0;
uint8_t sfidata[0x11][APDU_RES_LEN]; uint8_t sfidata[0x11][APDU_RES_LEN];
@ -529,7 +466,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO
return res; return res;
} }
int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) { int EMVSearch(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) {
uint8_t aidbuf[APDU_AID_LEN] = {0}; uint8_t aidbuf[APDU_AID_LEN] = {0};
int aidlen = 0; int aidlen = 0;
uint8_t data[APDU_RES_LEN] = {0}; uint8_t data[APDU_RES_LEN] = {0};
@ -625,11 +562,11 @@ int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen) {
return 0; return 0;
} }
int EMVGPO(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVGPO(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x80, 0xa8, 0x00, 0x00, PDOLLen, PDOL}, true, Result, MaxResultLen, ResultLen, sw, tlv); return EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x80, 0xa8, 0x00, 0x00, PDOLLen, PDOL}, true, Result, MaxResultLen, ResultLen, sw, tlv);
} }
int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVReadRecord(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, true, Result, MaxResultLen, ResultLen, sw, tlv); int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, true, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700 || *sw == 0x6f00) { if (*sw == 0x6700 || *sw == 0x6f00) {
PrintAndLogEx(INFO, ">>> trying to reissue command without Le..."); PrintAndLogEx(INFO, ">>> trying to reissue command without Le...");
@ -638,11 +575,11 @@ int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uin
return res; return res;
} }
int EMVAC(EMVCommandChannel channel, bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVAC(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchange(channel, LeaveFieldON, (sAPDU) {0x80, 0xae, RefControl, 0x00, CDOLLen, CDOL}, Result, MaxResultLen, ResultLen, sw, tlv); return EMVExchange(channel, LeaveFieldON, (sAPDU) {0x80, 0xae, RefControl, 0x00, CDOLLen, CDOL}, Result, MaxResultLen, ResultLen, sw, tlv);
} }
int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVGenerateChallenge(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, true, Result, MaxResultLen, ResultLen, sw, tlv); int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, true, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700 || *sw == 0x6f00) { if (*sw == 0x6700 || *sw == 0x6f00) {
PrintAndLogEx(INFO, ">>> trying to reissue command without Le..."); PrintAndLogEx(INFO, ">>> trying to reissue command without Le...");
@ -651,11 +588,11 @@ int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *
return res; return res;
} }
int EMVInternalAuthenticate(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVInternalAuthenticate(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0x88, 0x00, 0x00, DDOLLen, DDOL}, true, Result, MaxResultLen, ResultLen, sw, tlv); return EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0x88, 0x00, 0x00, DDOLLen, DDOL}, true, Result, MaxResultLen, ResultLen, sw, tlv);
} }
int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int MSCComputeCryptoChecksum(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, true, Result, MaxResultLen, ResultLen, sw, tlv); int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, true, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700 || *sw == 0x6f00) { if (*sw == 0x6700 || *sw == 0x6f00) {
PrintAndLogEx(INFO, ">>> trying to reissue command without Le..."); PrintAndLogEx(INFO, ">>> trying to reissue command without Le...");
@ -725,7 +662,7 @@ int trSDA(struct tlvdb *tlv) {
static const unsigned char default_ddol_value[] = {0x9f, 0x37, 0x04}; static const unsigned char default_ddol_value[] = {0x9f, 0x37, 0x04};
static struct tlv default_ddol_tlv = {.tag = 0x9f49, .len = 3, .value = default_ddol_value }; static struct tlv default_ddol_tlv = {.tag = 0x9f49, .len = 3, .value = default_ddol_value };
int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { int trDDA(Iso7816CommandChannel channel, bool decodeTLV, struct tlvdb *tlv) {
uint8_t buf[APDU_RES_LEN] = {0}; uint8_t buf[APDU_RES_LEN] = {0};
size_t len = 0; size_t len = 0;
uint16_t sw = 0; uint16_t sw = 0;

View file

@ -16,17 +16,10 @@
#include <inttypes.h> #include <inttypes.h>
#include <jansson.h> #include <jansson.h>
#include "apduinfo.h" #include "iso7816/apduinfo.h"
#include "iso7816/iso7816core.h"
#include "emv_pki.h" #include "emv_pki.h"
#define APDU_RES_LEN 260
#define APDU_AID_LEN 50
typedef enum {
ECC_CONTACTLESS,
ECC_CONTACT
} EMVCommandChannel;
enum TransactionType { enum TransactionType {
TT_MSD, TT_MSD,
TT_VSDC, // contact only. not standard for contactless TT_VSDC, // contact only. not standard for contactless
@ -56,39 +49,32 @@ void TLVPrintAIDlistFromSelectTLV(struct tlvdb *tlv);
struct tlvdb *GetPANFromTrack2(const struct tlv *track2); struct tlvdb *GetPANFromTrack2(const struct tlv *track2);
struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2); struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2);
void SetAPDULogging(bool logging);
bool GetAPDULogging(void);
// exchange // exchange
int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); int EMVExchange(Iso7816CommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
// search application // search application
int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv); int EMVSearchPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv);
int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); int EMVSearch(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv);
int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); int EMVSelectPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw);
int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); int EMVSelect(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
// select application // select application
int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen); int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen);
// Get Processing Options // Get Processing Options
int EMVGPO(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); int EMVGPO(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); int EMVReadRecord(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
// AC // AC
int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); int EMVGenerateChallenge(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
int EMVAC(EMVCommandChannel channel, bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); int EMVAC(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
// DDA // DDA
int EMVInternalAuthenticate(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); int EMVInternalAuthenticate(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
// Mastercard // Mastercard
int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); int MSCComputeCryptoChecksum(Iso7816CommandChannel channel, bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
// Auth // Auth
int trSDA(struct tlvdb *tlv); int trSDA(struct tlvdb *tlv);
int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv); int trDDA(Iso7816CommandChannel channel, bool decodeTLV, struct tlvdb *tlv);
int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, struct tlv *ac_data_tlv); int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, struct tlv *ac_data_tlv);
int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root); int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root);
struct emv_pk *get_ca_pk(struct tlvdb *db); struct emv_pk *get_ca_pk(struct tlvdb *db);
#endif #endif

View file

@ -14,7 +14,7 @@
#include "commonutil.h" // ARRAYLEN #include "commonutil.h" // ARRAYLEN
#include "emv/emvcore.h" #include "iso7816/iso7816core.h"
#include "emv/emvjson.h" #include "emv/emvjson.h"
#include "cbortools.h" #include "cbortools.h"
#include "x509_crt.h" #include "x509_crt.h"
@ -172,17 +172,17 @@ const char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int m
int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01};
return EMVSelect(ECC_CONTACTLESS, ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); return Iso7816Select(CC_CONTACTLESS, ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw);
} }
int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
int res = EMVExchange(ECC_CONTACTLESS, true, apdu, Result, MaxResultLen, ResultLen, sw, NULL); int res = Iso7816Exchange(CC_CONTACTLESS, true, apdu, Result, MaxResultLen, ResultLen, sw);
if (res == 5) // apdu result (sw) not a 0x9000 if (res == 5) // apdu result (sw) not a 0x9000
res = 0; res = 0;
// software chaining // software chaining
while (!res && (*sw >> 8) == 0x61) { while (!res && (*sw >> 8) == 0x61) {
size_t oldlen = *ResultLen; size_t oldlen = *ResultLen;
res = EMVExchange(ECC_CONTACTLESS, true, (sAPDU) {0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); res = Iso7816Exchange(CC_CONTACTLESS, true, (sAPDU) {0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw);
if (res == 5) // apdu result (sw) not a 0x9000 if (res == 5) // apdu result (sw) not a 0x9000
res = 0; res = 0;

View file

@ -15,7 +15,7 @@
#include "common.h" #include "common.h"
#include <jansson.h> #include <jansson.h>
#include "emv/apduinfo.h" // sAPDU #include "iso7816/apduinfo.h" // sAPDU
typedef enum { typedef enum {
fido2CmdMakeCredential = 0x01, fido2CmdMakeCredential = 0x01,

View file

@ -0,0 +1,108 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2017 Merlok
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// ISO7816 core functions
//-----------------------------------------------------------------------------
#include "iso7816core.h"
#include <string.h>
#include "commonutil.h" // ARRAYLEN
#include "comms.h" // DropField
#include "cmdparser.h"
#include "cmdsmartcard.h" // ExchangeAPDUSC
#include "ui.h"
#include "cmdhf14a.h"
#include "cmdhf14b.h"
#include "util_posix.h"
//iceman: this logging setting, should be unified with client debug etc.
static bool APDULogging = false;
void SetAPDULogging(bool logging) {
APDULogging = logging;
}
bool GetAPDULogging(void) {
return APDULogging;
}
int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
uint8_t data[APDU_RES_LEN] = {0};
*ResultLen = 0;
if (sw) *sw = 0;
uint16_t isw = 0;
int res = 0;
if (ActivateField) {
DropFieldEx(channel);
msleep(50);
}
// COMPUTE APDU
int datalen = 0;
if (APDUEncodeS(&apdu, false, IncludeLe ? 0x100 : 0x00, data, &datalen)) {
PrintAndLogEx(ERR, "APDU encoding error.");
return 201;
}
if (APDULogging)
PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen));
switch (channel) {
case CC_CONTACTLESS:
res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
if (res != PM3_SUCCESS) {
res = exchange_14b_apdu(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen, 4000);
if (res != PM3_SUCCESS)
return res;
}
break;
case CC_CONTACT:
res = 1;
if (IfPm3Smartcard())
res = ExchangeAPDUSC(false, data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
if (res) {
return res;
}
break;
}
if (APDULogging)
PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(Result, *ResultLen));
if (*ResultLen < 2) {
return 200;
}
*ResultLen -= 2;
isw = Result[*ResultLen] * 0x0100 + Result[*ResultLen + 1];
if (sw)
*sw = isw;
if (isw != 0x9000) {
if (APDULogging) {
if (*sw >> 8 == 0x61) {
PrintAndLogEx(ERR, "APDU chaining len:%02x -->", *sw & 0xff);
} else {
PrintAndLogEx(ERR, "APDU(%02x%02x) ERROR: [%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xff));
return 5;
}
}
}
return PM3_SUCCESS;
}
int Iso7816Exchange(Iso7816CommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
return Iso7816ExchangeEx(channel, false, LeaveFieldON, apdu, false, Result, MaxResultLen, ResultLen, sw);
}
int Iso7816Select(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
return Iso7816ExchangeEx(channel, ActivateField, LeaveFieldON, (sAPDU) {0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, (channel == CC_CONTACTLESS), Result, MaxResultLen, ResultLen, sw);
}

View file

@ -0,0 +1,37 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2017 Merlok
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// ISO7816 core functionality
//-----------------------------------------------------------------------------
#ifndef ISO7816CORE_H__
#define ISO7816CORE_H__
#include "common.h"
#include <inttypes.h>
#include "apduinfo.h"
#define APDU_RES_LEN 260
#define APDU_AID_LEN 50
typedef enum {
CC_CONTACTLESS,
CC_CONTACT
} Iso7816CommandChannel;
void SetAPDULogging(bool logging);
bool GetAPDULogging(void);
// exchange
int Iso7816Exchange(Iso7816CommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw);
int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw);
// search application
int Iso7816Select(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw);
#endif