diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 8ff5f414c..28edf7c2b 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -193,7 +193,6 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/emv/test/cryptotest.c ${PM3_ROOT}/client/src/emv/test/dda_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/crypto.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/cose.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/cipherutils.c ${PM3_ROOT}/client/src/loclass/elite_crack.c diff --git a/client/Makefile b/client/Makefile index be523d48a..696b48f40 100644 --- a/client/Makefile +++ b/client/Makefile @@ -535,7 +535,6 @@ SRCS = aiddesfire.c \ crypto/asn1dump.c \ crypto/asn1utils.c\ crypto/libpcrypto.c\ - emv/apduinfo.c \ emv/cmdemv.c \ emv/crypto.c\ emv/crypto_polarssl.c\ @@ -562,6 +561,8 @@ SRCS = aiddesfire.c \ generator.c \ graph.c \ jansson_path.c \ + iso7816/apduinfo.c \ + iso7816/iso7816core.c \ loclass/cipher.c \ loclass/cipherutils.c \ loclass/elite_crack.c \ diff --git a/client/android/CMakeLists.txt b/client/android/CMakeLists.txt index f41d11fb5..262403be7 100644 --- a/client/android/CMakeLists.txt +++ b/client/android/CMakeLists.txt @@ -61,7 +61,6 @@ add_library(pm3rrg_rdv4 SHARED ${PM3_ROOT}/client/src/emv/test/cryptotest.c ${PM3_ROOT}/client/src/emv/test/dda_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/crypto.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/cose.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/cipherutils.c ${PM3_ROOT}/client/src/loclass/elite_crack.c diff --git a/client/experimental_lib/CMakeLists.txt b/client/experimental_lib/CMakeLists.txt index 67e424e89..084259d34 100644 --- a/client/experimental_lib/CMakeLists.txt +++ b/client/experimental_lib/CMakeLists.txt @@ -193,7 +193,6 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/emv/test/cryptotest.c ${PM3_ROOT}/client/src/emv/test/dda_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/crypto.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/cose.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/cipherutils.c ${PM3_ROOT}/client/src/loclass/elite_crack.c diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 00dfbde7c..6c1c2d322 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -20,6 +20,7 @@ #include "cliparser.h" #include "cmdhfmf.h" #include "cmdhfmfu.h" +#include "iso7816/iso7816core.h" #include "emv/emvcore.h" #include "ui.h" #include "crc16.h" @@ -28,7 +29,7 @@ #include "cmdhf.h" // handle HF plot #include "cliparser.h" #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 "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; uint8_t result[1024] = {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; if (res) continue; diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index ada329bd7..d85c26e83 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -22,7 +22,7 @@ #include "crc16.h" #include "cmdhf14a.h" #include "protocols.h" // definitions of ISO14B/7816 protocol -#include "emv/apduinfo.h" // GetAPDUCodeDescription +#include "iso7816/apduinfo.h" // GetAPDUCodeDescription #include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint #include "aidsearch.h" diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 7baaaf72d..a512ac041 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -18,7 +18,7 @@ #include "cliparser.h" // CLIParserContext etc #include "cmdhf14a.h" // ExchangeAPDU14a #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 "mifare/desfire_crypto.h" // des_encrypt/des_decrypt #include "des.h" // mbedtls_des_key_set_parity diff --git a/client/src/cmdhffido.c b/client/src/cmdhffido.c index 059a4766f..f68e6a23d 100644 --- a/client/src/cmdhffido.c +++ b/client/src/cmdhffido.c @@ -24,7 +24,7 @@ #include "commonutil.h" #include "comms.h" #include "proxmark3.h" -#include "emv/emvcore.h" +#include "iso7816/iso7816core.h" #include "emv/emvjson.h" #include "cliparser.h" #include "crypto/asn1utils.h" diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 3277214d4..9755c915e 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -24,8 +24,8 @@ #include "protocols.h" #include "cmdtrace.h" #include "cliparser.h" -#include "emv/apduinfo.h" // APDU manipulation / errorcodes -#include "emv/emvcore.h" // APDU logging +#include "iso7816/apduinfo.h" // APDU manipulation / errorcodes +#include "iso7816/iso7816core.h" // APDU logging #include "util_posix.h" // msleep #include "mifare/desfire_crypto.h" #include "crapto1/crapto1.h" diff --git a/client/src/cmdhfseos.c b/client/src/cmdhfseos.c index c5395ba0e..6de8ad89a 100644 --- a/client/src/cmdhfseos.c +++ b/client/src/cmdhfseos.c @@ -19,7 +19,7 @@ #include "ui.h" #include "cmdhf14a.h" // manufacture #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 static int CmdHelp(const char *Cmd); diff --git a/client/src/cmdhfst25ta.c b/client/src/cmdhfst25ta.c index 5d971c443..aa737304c 100644 --- a/client/src/cmdhfst25ta.c +++ b/client/src/cmdhfst25ta.c @@ -19,7 +19,7 @@ #include "crc16.h" #include "cmdhf14a.h" #include "protocols.h" // definitions of ISO14A/7816 protocol -#include "emv/apduinfo.h" // GetAPDUCodeDescription +#include "iso7816/apduinfo.h" // GetAPDUCodeDescription #include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint #include "cmdnfc.h" // print_type4_cc_info diff --git a/client/src/comms.h b/client/src/comms.h index 80ce543da..1579c017f 100644 --- a/client/src/comms.h +++ b/client/src/comms.h @@ -26,7 +26,7 @@ extern "C" { #ifndef DropFieldEx #define DropFieldEx(x) { \ - if ( (x) == ECC_CONTACTLESS) { \ + if ( (x) == CC_CONTACTLESS) { \ DropField(); \ } \ } diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index 8d8128cc5..11111c530 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -56,12 +56,12 @@ static void ParamLoadDefaults(struct tlvdb *tlvRoot) { TLV_ADD(0x9F4E, "proxmrk3rdv\x00"); } -static void PrintChannel(EMVCommandChannel channel) { +static void PrintChannel(Iso7816CommandChannel channel) { switch (channel) { - case ECC_CONTACTLESS: + case CC_CONTACTLESS: PrintAndLogEx(INFO, "Selected channel... " _GREEN_("CONTACTLESS (T=CL)")); break; - case ECC_CONTACT: + case CC_CONTACT: PrintAndLogEx(INFO, "Selected channel... " _GREEN_("CONTACT")); break; } @@ -93,9 +93,9 @@ static int CmdEMVSelect(const char *Cmd) { bool leaveSignalON = arg_get_lit(ctx, 2); bool APDULogging = arg_get_lit(ctx, 3); bool decodeTLV = arg_get_lit(ctx, 4); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 5)) - channel = ECC_CONTACT; + channel = CC_CONTACT; PrintChannel(channel); CLIGetHexWithReturn(ctx, 6, data, &datalen); CLIParserFree(ctx); @@ -143,9 +143,9 @@ static int CmdEMVSearch(const char *Cmd) { bool leaveSignalON = arg_get_lit(ctx, 2); bool APDULogging = arg_get_lit(ctx, 3); bool decodeTLV = arg_get_lit(ctx, 4); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 5)) - channel = ECC_CONTACT; + channel = CC_CONTACT; PrintChannel(channel); CLIParserFree(ctx); @@ -201,9 +201,9 @@ static int CmdEMVPPSE(const char *Cmd) { PSENum = 2; bool APDULogging = arg_get_lit(ctx, 5); bool decodeTLV = arg_get_lit(ctx, 6); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 7)) - channel = ECC_CONTACT; + channel = CC_CONTACT; PrintChannel(channel); CLIParserFree(ctx); @@ -257,9 +257,9 @@ static int CmdEMVGPO(const char *Cmd) { bool dataMakeFromPDOL = arg_get_lit(ctx, 3); bool APDULogging = arg_get_lit(ctx, 4); bool decodeTLV = arg_get_lit(ctx, 5); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 6)) - channel = ECC_CONTACT; + channel = CC_CONTACT; PrintChannel(channel); CLIGetHexWithReturn(ctx, 7, data, &datalen); CLIParserFree(ctx); @@ -362,9 +362,9 @@ static int CmdEMVReadRecord(const char *Cmd) { bool leaveSignalON = arg_get_lit(ctx, 1); bool APDULogging = arg_get_lit(ctx, 2); bool decodeTLV = arg_get_lit(ctx, 3); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 4)) - channel = ECC_CONTACT; + channel = CC_CONTACT; PrintChannel(channel); CLIGetHexWithReturn(ctx, 5, data, &datalen); CLIParserFree(ctx); @@ -449,9 +449,9 @@ static int CmdEMVAC(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 6); bool decodeTLV = arg_get_lit(ctx, 7); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 8)) - channel = ECC_CONTACT; + channel = CC_CONTACT; PrintChannel(channel); CLIGetHexWithReturn(ctx, 9, data, &datalen); @@ -541,9 +541,9 @@ static int CmdEMVGenerateChallenge(const char *Cmd) { bool leaveSignalON = arg_get_lit(ctx, 1); bool APDULogging = arg_get_lit(ctx, 2); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 3)) - channel = ECC_CONTACT; + channel = CC_CONTACT; PrintChannel(channel); CLIParserFree(ctx); @@ -600,9 +600,9 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) { bool dataMakeFromDDOL = arg_get_lit(ctx, 3); bool APDULogging = arg_get_lit(ctx, 4); bool decodeTLV = arg_get_lit(ctx, 5); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 6)) - channel = ECC_CONTACT; + channel = CC_CONTACT; PrintChannel(channel); CLIGetHexWithReturn(ctx, 7, data, &datalen); CLIParserFree(ctx); @@ -841,15 +841,15 @@ static int CmdEMVExec(const char *Cmd) { TrType = TT_VSDC; bool GenACGPO = arg_get_lit(ctx, 10); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 11)) - channel = ECC_CONTACT; + channel = CC_CONTACT; PrintChannel(channel); - uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; + uint8_t psenum = (channel == CC_CONTACT) ? 1 : 2; CLIParserFree(ctx); if (!IfPm3Smartcard()) { - if (channel == ECC_CONTACT) { + if (channel == CC_CONTACT) { PrintAndLogEx(WARNING, "PM3 does not have SMARTCARD support. Exiting."); return PM3_EDEVNOTSUPP; } @@ -1463,13 +1463,13 @@ static int CmdEMVScan(const char *Cmd) { bool GenACGPO = arg_get_lit(ctx, 9); bool MergeJSON = arg_get_lit(ctx, 10); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 11)) - channel = ECC_CONTACT; + channel = CC_CONTACT; 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}; int filenamelen = sizeof(filename); @@ -1478,7 +1478,7 @@ static int CmdEMVScan(const char *Cmd) { CLIParserFree(ctx); if (!IfPm3Smartcard()) { - if (channel == ECC_CONTACT) { + if (channel == CC_CONTACT) { PrintAndLogEx(WARNING, "PM3 does not have SMARTCARD support, exiting"); return PM3_EDEVNOTSUPP; } @@ -1511,7 +1511,7 @@ static int CmdEMVScan(const char *Cmd) { JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`"); - if (channel == ECC_CONTACTLESS) { + if (channel == CC_CONTACTLESS) { // iso 14443 select PrintAndLogEx(INFO, "GET UID, ATS"); @@ -1868,22 +1868,22 @@ static int CmdEMVRoca(const char *Cmd) { bool show_apdu = arg_get_lit(ctx, 2); - EMVCommandChannel channel = ECC_CONTACTLESS; + Iso7816CommandChannel channel = CC_CONTACTLESS; if (arg_get_lit(ctx, 3)) - channel = ECC_CONTACT; + channel = CC_CONTACT; CLIParserFree(ctx); PrintChannel(channel); if (!IfPm3Smartcard()) { - if (channel == ECC_CONTACT) { + if (channel == CC_CONTACT) { PrintAndLogEx(WARNING, "PM3 does not have SMARTCARD support, exiting"); return PM3_EDEVNOTSUPP; } } // select card - uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; + uint8_t psenum = (channel == CC_CONTACT) ? 1 : 2; SetAPDULogging(show_apdu); diff --git a/client/src/emv/emvcore.c b/client/src/emv/emvcore.c index 9073d086a..f4d082628 100644 --- a/client/src/emv/emvcore.c +++ b/client/src/emv/emvcore.c @@ -131,16 +131,6 @@ static const TAIDList AIDlist [] = { { 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) { char buf[100] = {0}; if (AIDlen < 1) @@ -275,90 +265,37 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) { 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) { - 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 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; - } - } - } - +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) { + int res = Iso7816ExchangeEx(channel, ActivateField, LeaveFieldON, apdu, IncludeLe, Result, MaxResultLen, ResultLen, sw); // add to tlv tree - if (tlv) { + if ((res == PM3_SUCCESS) && tlv) { struct tlvdb *t = tlvdb_parse_multi(Result, *ResultLen); tlvdb_add(tlv, t); } - - return 0; + return res; } -int EMVExchange(EMVCommandChannel 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 EMVExchange(Iso7816CommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *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) { - return EMVExchangeEx(channel, ActivateField, LeaveFieldON, (sAPDU) {0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, (channel == ECC_CONTACTLESS), Result, MaxResultLen, ResultLen, sw, 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) { + 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}; *ResultLen = 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); } -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 res = 0; do { @@ -402,7 +339,7 @@ static int EMVSelectWithRetry(EMVCommandChannel channel, bool ActivateField, boo 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}; size_t datalen = 0; int res = 0; @@ -434,7 +371,7 @@ static int EMVCheckAID(EMVCommandChannel channel, bool decodeTLV, struct tlvdb * 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}; size_t datalen = 0; uint8_t sfidata[0x11][APDU_RES_LEN]; @@ -529,7 +466,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO 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}; int aidlen = 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; } -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); } -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); if (*sw == 0x6700 || *sw == 0x6f00) { PrintAndLogEx(INFO, ">>> trying to reissue command without Le..."); @@ -638,11 +575,11 @@ int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uin 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); } -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); if (*sw == 0x6700 || *sw == 0x6f00) { PrintAndLogEx(INFO, ">>> trying to reissue command without Le..."); @@ -651,11 +588,11 @@ int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t * 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); } -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); if (*sw == 0x6700 || *sw == 0x6f00) { 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 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}; size_t len = 0; uint16_t sw = 0; diff --git a/client/src/emv/emvcore.h b/client/src/emv/emvcore.h index 1c422e483..056cab0ba 100644 --- a/client/src/emv/emvcore.h +++ b/client/src/emv/emvcore.h @@ -16,17 +16,10 @@ #include #include -#include "apduinfo.h" +#include "iso7816/apduinfo.h" +#include "iso7816/iso7816core.h" #include "emv_pki.h" -#define APDU_RES_LEN 260 -#define APDU_AID_LEN 50 - -typedef enum { - ECC_CONTACTLESS, - ECC_CONTACT -} EMVCommandChannel; - enum TransactionType { TT_MSD, 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 *GetdCVVRawFromTrack2(const struct tlv *track2); -void SetAPDULogging(bool logging); -bool GetAPDULogging(void); - // 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 -int EMVSearchPSE(EMVCommandChannel 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 EMVSelectPSE(EMVCommandChannel 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 EMVSearchPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv); +int EMVSearch(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); +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(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 int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen); // 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 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 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(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 -int EMVGenerateChallenge(EMVCommandChannel 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 EMVGenerateChallenge(Iso7816CommandChannel channel, bool LeaveFieldON, 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 -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 -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 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 RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root); struct emv_pk *get_ca_pk(struct tlvdb *db); #endif - - - - diff --git a/client/src/fido/fidocore.c b/client/src/fido/fidocore.c index 32aed2f19..1529d9172 100644 --- a/client/src/fido/fidocore.c +++ b/client/src/fido/fidocore.c @@ -14,7 +14,7 @@ #include "commonutil.h" // ARRAYLEN -#include "emv/emvcore.h" +#include "iso7816/iso7816core.h" #include "emv/emvjson.h" #include "cbortools.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) { 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 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 res = 0; // software chaining while (!res && (*sw >> 8) == 0x61) { 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 res = 0; diff --git a/client/src/fido/fidocore.h b/client/src/fido/fidocore.h index 56c563120..9aac31cf6 100644 --- a/client/src/fido/fidocore.h +++ b/client/src/fido/fidocore.h @@ -15,7 +15,7 @@ #include "common.h" #include -#include "emv/apduinfo.h" // sAPDU +#include "iso7816/apduinfo.h" // sAPDU typedef enum { fido2CmdMakeCredential = 0x01, diff --git a/client/src/emv/apduinfo.c b/client/src/iso7816/apduinfo.c similarity index 100% rename from client/src/emv/apduinfo.c rename to client/src/iso7816/apduinfo.c diff --git a/client/src/emv/apduinfo.h b/client/src/iso7816/apduinfo.h similarity index 100% rename from client/src/emv/apduinfo.h rename to client/src/iso7816/apduinfo.h diff --git a/client/src/iso7816/iso7816core.c b/client/src/iso7816/iso7816core.c new file mode 100644 index 000000000..72166ac90 --- /dev/null +++ b/client/src/iso7816/iso7816core.c @@ -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 + +#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); +} diff --git a/client/src/iso7816/iso7816core.h b/client/src/iso7816/iso7816core.h new file mode 100644 index 000000000..dc0ed78f7 --- /dev/null +++ b/client/src/iso7816/iso7816core.h @@ -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 + +#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