mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-02-13 02:34:48 +08:00
added channel parameter
This commit is contained in:
parent
01a10bade7
commit
4c7e5757f3
4 changed files with 128 additions and 77 deletions
|
@ -54,6 +54,7 @@ int CmdEMVSelect(const char *cmd) {
|
|||
arg_lit0("kK", "keep", "keep field for next command"),
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx0(NULL, NULL, "<HEX applet AID>", NULL),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -63,7 +64,10 @@ int CmdEMVSelect(const char *cmd) {
|
|||
bool leaveSignalON = arg_get_lit(2);
|
||||
bool APDULogging = arg_get_lit(3);
|
||||
bool decodeTLV = arg_get_lit(4);
|
||||
CLIGetHexWithReturn(5, data, &datalen);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(5))
|
||||
channel = ECC_CONTACT;
|
||||
CLIGetHexWithReturn(6, data, &datalen);
|
||||
CLIParserFree();
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
|
@ -72,7 +76,7 @@ int CmdEMVSelect(const char *cmd) {
|
|||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = EMVSelect(activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
|
||||
int res = EMVSelect(channel, activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
|
||||
|
||||
if (sw)
|
||||
PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
|
@ -98,6 +102,7 @@ int CmdEMVSearch(const char *cmd) {
|
|||
arg_lit0("kK", "keep", "keep field ON for next command"),
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(cmd, argtable, true);
|
||||
|
@ -106,6 +111,9 @@ int CmdEMVSearch(const char *cmd) {
|
|||
bool leaveSignalON = arg_get_lit(2);
|
||||
bool APDULogging = arg_get_lit(3);
|
||||
bool decodeTLV = arg_get_lit(4);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(5))
|
||||
channel = ECC_CONTACT;
|
||||
CLIParserFree();
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
|
@ -114,7 +122,7 @@ int CmdEMVSearch(const char *cmd) {
|
|||
const char *al = "Applets list";
|
||||
t = tlvdb_fixed(1, strlen(al), (const unsigned char *)al);
|
||||
|
||||
if (EMVSearch(activateField, leaveSignalON, decodeTLV, t)) {
|
||||
if (EMVSearch(channel, activateField, leaveSignalON, decodeTLV, t)) {
|
||||
tlvdb_free(t);
|
||||
return 2;
|
||||
}
|
||||
|
@ -145,6 +153,7 @@ int CmdEMVPPSE(const char *cmd) {
|
|||
arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"),
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(cmd, argtable, true);
|
||||
|
@ -158,6 +167,9 @@ int CmdEMVPPSE(const char *cmd) {
|
|||
PSENum = 2;
|
||||
bool APDULogging = arg_get_lit(5);
|
||||
bool decodeTLV = arg_get_lit(6);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(7))
|
||||
channel = ECC_CONTACT;
|
||||
CLIParserFree();
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
|
@ -166,7 +178,7 @@ int CmdEMVPPSE(const char *cmd) {
|
|||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = EMVSelectPSE(activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw);
|
||||
int res = EMVSelectPSE(channel, activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw);
|
||||
|
||||
if (sw)
|
||||
PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
|
@ -198,6 +210,7 @@ int CmdEMVGPO(const char *cmd) {
|
|||
arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"),
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx0(NULL, NULL, "<HEX PDOLdata/PDOL>", NULL),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -208,7 +221,10 @@ int CmdEMVGPO(const char *cmd) {
|
|||
bool dataMakeFromPDOL = arg_get_lit(3);
|
||||
bool APDULogging = arg_get_lit(4);
|
||||
bool decodeTLV = arg_get_lit(5);
|
||||
CLIGetHexWithReturn(6, data, &datalen);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(6))
|
||||
channel = ECC_CONTACT;
|
||||
CLIGetHexWithReturn(7, data, &datalen);
|
||||
CLIParserFree();
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
|
@ -258,7 +274,7 @@ int CmdEMVGPO(const char *cmd) {
|
|||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = EMVGPO(leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
int res = EMVGPO(channel, leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
|
||||
if (pdol_data_tlv != &data_tlv)
|
||||
free(pdol_data_tlv);
|
||||
|
@ -289,6 +305,7 @@ int CmdEMVReadRecord(const char *cmd) {
|
|||
arg_lit0("kK", "keep", "keep field ON for next command"),
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx1(NULL, NULL, "<SFI 1byte HEX><SFIrec 1byte HEX>", NULL),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -297,7 +314,10 @@ int CmdEMVReadRecord(const char *cmd) {
|
|||
bool leaveSignalON = arg_get_lit(1);
|
||||
bool APDULogging = arg_get_lit(2);
|
||||
bool decodeTLV = arg_get_lit(3);
|
||||
CLIGetHexWithReturn(4, data, &datalen);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(4))
|
||||
channel = ECC_CONTACT;
|
||||
CLIGetHexWithReturn(5, data, &datalen);
|
||||
CLIParserFree();
|
||||
|
||||
if (datalen != 2) {
|
||||
|
@ -311,7 +331,7 @@ int CmdEMVReadRecord(const char *cmd) {
|
|||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = EMVReadRecord(leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL);
|
||||
int res = EMVReadRecord(channel, leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL);
|
||||
|
||||
if (sw)
|
||||
PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
|
@ -346,6 +366,7 @@ int CmdEMVAC(const char *cmd) {
|
|||
arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"),
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx1(NULL, NULL, "<HEX CDOLdata/CDOL>", NULL),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -375,7 +396,10 @@ int CmdEMVAC(const char *cmd) {
|
|||
bool dataMakeFromCDOL = arg_get_lit(5);
|
||||
bool APDULogging = arg_get_lit(6);
|
||||
bool decodeTLV = arg_get_lit(7);
|
||||
CLIGetHexWithReturn(8, data, &datalen);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(8))
|
||||
channel = ECC_CONTACT;
|
||||
CLIGetHexWithReturn(9, data, &datalen);
|
||||
CLIParserFree();
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
|
@ -419,7 +443,7 @@ int CmdEMVAC(const char *cmd) {
|
|||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = EMVAC(leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
int res = EMVAC(channel, leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
|
||||
if (cdol_data_tlv != &data_tlv)
|
||||
free(cdol_data_tlv);
|
||||
|
@ -447,12 +471,16 @@ int CmdEMVGenerateChallenge(const char *cmd) {
|
|||
arg_param_begin,
|
||||
arg_lit0("kK", "keep", "keep field ON for next command"),
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(cmd, argtable, true);
|
||||
|
||||
bool leaveSignalON = arg_get_lit(1);
|
||||
bool APDULogging = arg_get_lit(2);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(3))
|
||||
channel = ECC_CONTACT;
|
||||
CLIParserFree();
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
|
@ -461,7 +489,7 @@ int CmdEMVGenerateChallenge(const char *cmd) {
|
|||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = EMVGenerateChallenge(leaveSignalON, buf, sizeof(buf), &len, &sw, NULL);
|
||||
int res = EMVGenerateChallenge(channel, leaveSignalON, buf, sizeof(buf), &len, &sw, NULL);
|
||||
|
||||
if (sw)
|
||||
PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
|
||||
|
@ -494,6 +522,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) {
|
|||
arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"),
|
||||
arg_lit0("aA", "apdu", "show APDU reqests and responses"),
|
||||
arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_strx1(NULL, NULL, "<HEX DDOLdata/DDOL>", NULL),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -504,7 +533,10 @@ int CmdEMVInternalAuthenticate(const char *cmd) {
|
|||
bool dataMakeFromDDOL = arg_get_lit(3);
|
||||
bool APDULogging = arg_get_lit(4);
|
||||
bool decodeTLV = arg_get_lit(5);
|
||||
CLIGetHexWithReturn(6, data, &datalen);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(6))
|
||||
channel = ECC_CONTACT;
|
||||
CLIGetHexWithReturn(7, data, &datalen);
|
||||
CLIParserFree();
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
|
@ -548,7 +580,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) {
|
|||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = EMVInternalAuthenticate(leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
|
||||
int res = EMVInternalAuthenticate(channel, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL);
|
||||
|
||||
if (ddol_data_tlv != &data_tlv)
|
||||
free(ddol_data_tlv);
|
||||
|
@ -663,6 +695,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."),
|
||||
arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
|
||||
arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(cmd, argtable, true);
|
||||
|
@ -682,6 +715,9 @@ int CmdEMVExec(const char *cmd) {
|
|||
TrType = TT_VSDC;
|
||||
|
||||
bool GenACGPO = arg_get_lit(9);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(10))
|
||||
channel = ECC_CONTACT;
|
||||
CLIParserFree();
|
||||
|
||||
SetAPDULogging(showAPDU);
|
||||
|
@ -696,7 +732,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
// PPSE
|
||||
PrintAndLogEx(NORMAL, "\n* PPSE.");
|
||||
SetAPDULogging(showAPDU);
|
||||
res = EMVSearchPSE(activateField, true, decodeTLV, tlvSelect);
|
||||
res = EMVSearchPSE(channel, activateField, true, decodeTLV, tlvSelect);
|
||||
|
||||
// check PPSE and select application id
|
||||
if (!res) {
|
||||
|
@ -709,7 +745,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
if (!AIDlen) {
|
||||
PrintAndLogEx(NORMAL, "\n* Search AID in list.");
|
||||
SetAPDULogging(false);
|
||||
if (EMVSearch(activateField, true, decodeTLV, tlvSelect)) {
|
||||
if (EMVSearch(channel, activateField, true, decodeTLV, tlvSelect)) {
|
||||
dreturn(2);
|
||||
}
|
||||
|
||||
|
@ -731,7 +767,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
// Select
|
||||
PrintAndLogEx(NORMAL, "\n* Selecting AID:%s", sprint_hex_inrow(AID, AIDlen));
|
||||
SetAPDULogging(showAPDU);
|
||||
res = EMVSelect(false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
|
||||
if (res) {
|
||||
PrintAndLogEx(WARNING, "Can't select AID (%d). Exit...", res);
|
||||
|
@ -762,7 +798,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
PrintAndLogEx(NORMAL, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n* GPO.");
|
||||
res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
|
||||
free(pdol_data_tlv_data);
|
||||
//free(pdol_data_tlv); --- free on exit.
|
||||
|
@ -818,7 +854,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
for (int n = SFIstart; n <= SFIend; n++) {
|
||||
PrintAndLogEx(NORMAL, "* * * SFI[%02x] %d", SFI, n);
|
||||
|
||||
res = EMVReadRecord(true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
if (res) {
|
||||
PrintAndLogEx(WARNING, "Error SFI[%02x]. APDU error %4x", SFI, sw);
|
||||
continue;
|
||||
|
@ -874,7 +910,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
// DDA
|
||||
if (AIP & 0x0020) {
|
||||
PrintAndLogEx(NORMAL, "\n* DDA");
|
||||
trDDA(decodeTLV, tlvRoot);
|
||||
trDDA(channel, decodeTLV, tlvRoot);
|
||||
}
|
||||
|
||||
// transaction check
|
||||
|
@ -924,7 +960,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
PrintAndLogEx(NORMAL, "\n--> Mastercard M/Chip transaction.");
|
||||
|
||||
PrintAndLogEx(NORMAL, "* * Generate challenge");
|
||||
res = EMVGenerateChallenge(true, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
res = EMVGenerateChallenge(channel, true, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
if (res) {
|
||||
PrintAndLogEx(WARNING, "Error GetChallenge. APDU error %4x", sw);
|
||||
dreturn(6);
|
||||
|
@ -952,7 +988,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
|
||||
PrintAndLogEx(NORMAL, "* * AC1");
|
||||
// EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
|
||||
res = EMVAC(true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
|
||||
if (res) {
|
||||
PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw);
|
||||
|
@ -1041,7 +1077,7 @@ int CmdEMVExec(const char *cmd) {
|
|||
|
||||
PrintAndLogEx(NORMAL, "\n* Mastercard compute cryptographic checksum(UDOL)");
|
||||
|
||||
res = MSCComputeCryptoChecksum(true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
res = MSCComputeCryptoChecksum(channel, true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
if (res) {
|
||||
PrintAndLogEx(WARNING, "Error Compute Crypto Checksum. APDU error %4x", sw);
|
||||
free(udol_data_tlv);
|
||||
|
@ -1099,6 +1135,7 @@ int CmdEMVScan(const char *cmd) {
|
|||
arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."),
|
||||
arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."),
|
||||
arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"),
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_str1(NULL, NULL, "output.json", "JSON output file name"),
|
||||
arg_param_end
|
||||
};
|
||||
|
@ -1119,10 +1156,13 @@ int CmdEMVScan(const char *cmd) {
|
|||
|
||||
bool GenACGPO = arg_get_lit(9);
|
||||
bool MergeJSON = arg_get_lit(10);
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(11))
|
||||
channel = ECC_CONTACT;
|
||||
uint8_t relfname[250] ={0};
|
||||
char *crelfname = (char *)relfname;
|
||||
int relfnamelen = 0;
|
||||
CLIGetStrWithReturn(11, relfname, &relfnamelen);
|
||||
CLIGetStrWithReturn(12, relfname, &relfnamelen);
|
||||
CLIParserFree();
|
||||
|
||||
SetAPDULogging(showAPDU);
|
||||
|
@ -1174,7 +1214,7 @@ int CmdEMVScan(const char *cmd) {
|
|||
|
||||
// EMV PPSE
|
||||
PrintAndLogEx(NORMAL, "--> PPSE.");
|
||||
res = EMVSelectPSE(true, true, 2, buf, sizeof(buf), &len, &sw);
|
||||
res = EMVSelectPSE(channel, true, true, 2, buf, sizeof(buf), &len, &sw);
|
||||
|
||||
if (!res && sw == 0x9000){
|
||||
if (decodeTLV)
|
||||
|
@ -1191,7 +1231,7 @@ int CmdEMVScan(const char *cmd) {
|
|||
tlvdb_free(fci);
|
||||
}
|
||||
|
||||
res = EMVSearchPSE(false, true, decodeTLV, tlvSelect);
|
||||
res = EMVSearchPSE(channel, false, true, decodeTLV, tlvSelect);
|
||||
|
||||
// check PPSE and select application id
|
||||
if (!res) {
|
||||
|
@ -1200,7 +1240,7 @@ int CmdEMVScan(const char *cmd) {
|
|||
// EMV SEARCH with AID list
|
||||
SetAPDULogging(false);
|
||||
PrintAndLogEx(NORMAL, "--> AID search.");
|
||||
if (EMVSearch(false, true, decodeTLV, tlvSelect)) {
|
||||
if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) {
|
||||
PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit...");
|
||||
tlvdb_free(tlvSelect);
|
||||
DropField();
|
||||
|
@ -1233,7 +1273,7 @@ int CmdEMVScan(const char *cmd) {
|
|||
|
||||
PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen));
|
||||
SetAPDULogging(showAPDU);
|
||||
res = EMVSelect(false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
|
||||
if (res) {
|
||||
PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res);
|
||||
|
@ -1281,7 +1321,7 @@ int CmdEMVScan(const char *cmd) {
|
|||
PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
|
||||
|
||||
PrintAndLogEx(INFO, "-->GPO.");
|
||||
res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
|
||||
free(pdol_data_tlv_data);
|
||||
free(pdol_data_tlv);
|
||||
|
@ -1340,7 +1380,7 @@ int CmdEMVScan(const char *cmd) {
|
|||
for(int n = SFIstart; n <= SFIend; n++) {
|
||||
PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n);
|
||||
|
||||
res = EMVReadRecord(true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
if (res) {
|
||||
PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw);
|
||||
continue;
|
||||
|
|
|
@ -230,12 +230,13 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) {
|
|||
return tlvdb_fixed(0x02, dCVVlen, dCVV);
|
||||
}
|
||||
|
||||
int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
|
||||
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) {
|
||||
DropField();
|
||||
|
@ -250,11 +251,16 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool Includ
|
|||
if (APDULogging)
|
||||
PrintAndLogEx(NORMAL, ">>>> %s", sprint_hex(data, (IncludeLe?6:5) + apdu.Lc));
|
||||
|
||||
// 6 byes + data = INS + CLA + P1 + P2 + Lc + <data = Nc> + Le(?IncludeLe)
|
||||
int res = ExchangeAPDU14a(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
switch(channel) {
|
||||
case ECC_CONTACTLESS:
|
||||
// 6 byes + data = INS + CLA + P1 + P2 + Lc + <data = Nc> + Le(?IncludeLe)
|
||||
res = ExchangeAPDU14a(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
case ECC_CONTACT:
|
||||
break;
|
||||
}
|
||||
|
||||
if (APDULogging)
|
||||
|
@ -289,15 +295,15 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool Includ
|
|||
return 0;
|
||||
}
|
||||
|
||||
int EMVExchange(bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
|
||||
return EMVExchangeEx(false, LeaveFieldON, apdu, true, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
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, true, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
}
|
||||
|
||||
int EMVSelect(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(ActivateField, LeaveFieldON, (sAPDU){0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, true, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
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}, true, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
}
|
||||
|
||||
int EMVSelectPSE(bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
|
||||
int EMVSelectPSE(EMVCommandChannel 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;
|
||||
|
@ -314,19 +320,19 @@ int EMVSelectPSE(bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t
|
|||
}
|
||||
|
||||
// select
|
||||
res = EMVSelect(ActivateField, LeaveFieldON, buf, len, Result, MaxResultLen, ResultLen, sw, NULL);
|
||||
res = EMVSelect(channel, ActivateField, LeaveFieldON, buf, len, Result, MaxResultLen, ResultLen, sw, NULL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) {
|
||||
int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) {
|
||||
uint8_t data[APDU_RES_LEN] = {0};
|
||||
size_t datalen = 0;
|
||||
uint16_t sw = 0;
|
||||
int res;
|
||||
|
||||
// select PPSE
|
||||
res = EMVSelectPSE(ActivateField, true, 2, data, sizeof(data), &datalen, &sw);
|
||||
res = EMVSelectPSE(channel, ActivateField, true, 2, data, sizeof(data), &datalen, &sw);
|
||||
|
||||
if (!res){
|
||||
struct tlvdb *t = NULL;
|
||||
|
@ -340,7 +346,7 @@ int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct t
|
|||
while (ttmp) {
|
||||
const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x4f, NULL);
|
||||
if (tgAID) {
|
||||
res = EMVSelect(false, true, (uint8_t *)tgAID->value, tgAID->len, data, sizeof(data), &datalen, &sw, tlv);
|
||||
res = EMVSelect(channel, false, true, (uint8_t *)tgAID->value, tgAID->len, data, sizeof(data), &datalen, &sw, tlv);
|
||||
|
||||
// retry if error and not returned sw error
|
||||
if (res && res != 5) {
|
||||
|
@ -387,7 +393,7 @@ int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct t
|
|||
return res;
|
||||
}
|
||||
|
||||
int EMVSearch(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) {
|
||||
int EMVSearch(EMVCommandChannel 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};
|
||||
|
@ -398,7 +404,7 @@ int EMVSearch(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvd
|
|||
int retrycnt = 0;
|
||||
for(int i = 0; i < AIDlistLen; i ++) {
|
||||
param_gethex_to_eol(AIDlist[i].aid, 0, aidbuf, sizeof(aidbuf), &aidlen);
|
||||
res = EMVSelect((i == 0) ? ActivateField : false, (i == AIDlistLen - 1) ? LeaveFieldON : true, aidbuf, aidlen, data, sizeof(data), &datalen, &sw, tlv);
|
||||
res = EMVSelect(channel, (i == 0) ? ActivateField : false, (i == AIDlistLen - 1) ? LeaveFieldON : true, aidbuf, aidlen, data, sizeof(data), &datalen, &sw, tlv);
|
||||
// retry if error and not returned sw error
|
||||
if (res && res != 5) {
|
||||
if (++retrycnt < 3){
|
||||
|
@ -468,38 +474,38 @@ int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int EMVGPO(bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
|
||||
return EMVExchange(LeaveFieldON, (sAPDU){0x80, 0xa8, 0x00, 0x00, PDOLLen, PDOL}, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
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) {
|
||||
return EMVExchange(channel, LeaveFieldON, (sAPDU){0x80, 0xa8, 0x00, 0x00, PDOLLen, PDOL}, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
}
|
||||
|
||||
int EMVReadRecord(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 = EMVExchange(LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, 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 res = EMVExchange(channel, LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
if (*sw == 0x6700) {
|
||||
PrintAndLogEx(INFO, ">>> trying to reissue command withouth Le...");
|
||||
res = EMVExchangeEx(false, LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int EMVAC(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(LeaveFieldON, (sAPDU){0x80, 0xae, RefControl, 0x00, CDOLLen, CDOL}, Result, MaxResultLen, ResultLen, sw, 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) {
|
||||
return EMVExchange(channel, LeaveFieldON, (sAPDU){0x80, 0xae, RefControl, 0x00, CDOLLen, CDOL}, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
}
|
||||
|
||||
int EMVGenerateChallenge(bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
|
||||
int res = EMVExchange(LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, 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 res = EMVExchange(channel, LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
if (*sw == 0x6700) {
|
||||
PrintAndLogEx(INFO, ">>> trying to reissue command withouth Le...");
|
||||
res = EMVExchangeEx(false, LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int EMVInternalAuthenticate(bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
|
||||
return EMVExchange(LeaveFieldON, (sAPDU){0x00, 0x88, 0x00, 0x00, DDOLLen, DDOL}, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
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) {
|
||||
return EMVExchange(channel, LeaveFieldON, (sAPDU){0x00, 0x88, 0x00, 0x00, DDOLLen, DDOL}, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
}
|
||||
|
||||
int MSCComputeCryptoChecksum(bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
|
||||
return EMVExchange(LeaveFieldON, (sAPDU){0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, 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) {
|
||||
return EMVExchange(channel, LeaveFieldON, (sAPDU){0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, Result, MaxResultLen, ResultLen, sw, tlv);
|
||||
}
|
||||
|
||||
// Authentication
|
||||
|
@ -569,7 +575,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(bool decodeTLV, struct tlvdb *tlv) {
|
||||
int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) {
|
||||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
|
@ -709,7 +715,7 @@ int trDDA(bool decodeTLV, struct tlvdb *tlv) {
|
|||
PrintAndLogEx(NORMAL, "DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len));
|
||||
|
||||
PrintAndLogEx(NORMAL, "\n* Internal Authenticate");
|
||||
int res = EMVInternalAuthenticate(true, (uint8_t *)ddol_data_tlv->value, ddol_data_tlv->len, buf, sizeof(buf), &len, &sw, NULL);
|
||||
int res = EMVInternalAuthenticate(channel, true, (uint8_t *)ddol_data_tlv->value, ddol_data_tlv->len, buf, sizeof(buf), &len, &sw, NULL);
|
||||
if (res) {
|
||||
PrintAndLogEx(WARNING, "Internal Authenticate error(%d): %4x. Exit...", res, sw);
|
||||
free(ddol_data_tlv);
|
||||
|
|
|
@ -32,6 +32,11 @@
|
|||
#define APDU_RES_LEN 260
|
||||
#define APDU_AID_LEN 50
|
||||
|
||||
typedef enum {
|
||||
ECC_CONTACTLESS,
|
||||
ECC_CONTACT
|
||||
} EMVCommandChannel;
|
||||
|
||||
enum TransactionType {
|
||||
TT_MSD,
|
||||
TT_VSDC, // not standart for contactless!!!!
|
||||
|
@ -71,28 +76,28 @@ extern struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2);
|
|||
extern void SetAPDULogging(bool logging);
|
||||
|
||||
// exchange
|
||||
extern int EMVExchange(bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
|
||||
extern int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
|
||||
|
||||
// search application
|
||||
extern int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv);
|
||||
extern int EMVSearch(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv);
|
||||
extern int EMVSelectPSE(bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw);
|
||||
extern int EMVSelect(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);
|
||||
extern int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv);
|
||||
extern int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv);
|
||||
extern int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw);
|
||||
extern 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);
|
||||
// select application
|
||||
extern int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen);
|
||||
// Get Processing Options
|
||||
extern int EMVGPO(bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
|
||||
extern int EMVReadRecord(bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
|
||||
extern 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);
|
||||
extern 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);
|
||||
// AC
|
||||
extern int EMVGenerateChallenge(bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
|
||||
extern int EMVAC(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);
|
||||
extern int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
|
||||
extern 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);
|
||||
// DDA
|
||||
extern int EMVInternalAuthenticate(bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
|
||||
extern 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);
|
||||
// Mastercard
|
||||
int MSCComputeCryptoChecksum(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(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);
|
||||
// Auth
|
||||
extern int trSDA(struct tlvdb *tlv);
|
||||
extern int trDDA(bool decodeTLV, struct tlvdb *tlv);
|
||||
extern int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv);
|
||||
extern int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, struct tlv *ac_data_tlv);
|
||||
|
||||
extern int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root);
|
||||
|
|
|
@ -170,17 +170,17 @@ char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int memberN
|
|||
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(ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL);
|
||||
return EMVSelect(ECC_CONTACTLESS, ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL);
|
||||
}
|
||||
|
||||
int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
|
||||
int res = EMVExchange(true, apdu, Result, MaxResultLen, ResultLen, sw, NULL);
|
||||
int res = EMVExchange(ECC_CONTACTLESS, true, apdu, Result, MaxResultLen, ResultLen, sw, NULL);
|
||||
if (res == 5) // apdu result (sw) not a 0x9000
|
||||
res = 0;
|
||||
// software chaining
|
||||
while (!res && (*sw >> 8) == 0x61) {
|
||||
size_t oldlen = *ResultLen;
|
||||
res = EMVExchange(true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL);
|
||||
res = EMVExchange(ECC_CONTACTLESS, true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL);
|
||||
if (res == 5) // apdu result (sw) not a 0x9000
|
||||
res = 0;
|
||||
|
||||
|
|
Loading…
Reference in a new issue