added IAD decoding and some improvements

This commit is contained in:
merlokk 2019-02-19 21:15:54 +02:00
parent 26bca36929
commit 56c9bcc03a

View file

@ -1212,16 +1212,79 @@ int CmdEMVExec(const char *cmd) {
if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) PrintAndLogEx(INFO, "AC1 result: ARQC (Online authorisation requested)");
if ((CID & EMVAC_AC_MASK) == EMVAC_AC_MASK) PrintAndLogEx(INFO, "AC1 result: RFU");
PrintAndLogEx(NORMAL, "\n* * Processing online request\n");
// decode Issuer Application Data (IAD)
uint8_t CryptoVersion = 0;
const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9f10, NULL);
if (IAD && (IAD->len > 1)) {
PrintAndLogEx(NORMAL, "\n* * Issuer Application Data (IAD):");
uint8_t VDDlen = IAD->value[0]; // Visa discretionary data length
uint8_t IDDlen = 0; // Issuer discretionary data length
PrintAndLogEx(NORMAL, "IAD length: %d", IAD->len);
PrintAndLogEx(NORMAL, "VDDlen: %d", VDDlen);
if (VDDlen < IAD->len - 1)
IDDlen = IAD->value[VDDlen + 1];
PrintAndLogEx(NORMAL, "IDDlen: %d", IDDlen);
uint8_t DerivKeyIndex = IAD->value[1];
CryptoVersion = IAD->value[2];
PrintAndLogEx(NORMAL, "CryptoVersion: %d", CryptoVersion);
PrintAndLogEx(NORMAL, "DerivKeyIndex: %d", DerivKeyIndex);
// Card Verification Results (CVR) decode
if ((VDDlen - 2) > 0) {
uint8_t CVRlen = IAD->value[3];
if (CVRlen == (VDDlen - 2 - 1)) {
PrintAndLogEx(NORMAL, "CVR length: %d", CVRlen);
PrintAndLogEx(NORMAL, "CVR: %s", sprint_hex(&IAD->value[4], CVRlen));
} else {
PrintAndLogEx(NORMAL, "Wrong CVR length! CVR: %s", sprint_hex(&IAD->value[3], VDDlen - 2));
}
}
if (IDDlen)
PrintAndLogEx(NORMAL, "IDD: %s", sprint_hex(&IAD->value[VDDlen + 1], IDDlen));
} else {
PrintAndLogEx(NORMAL, "Issuer Application Data (IAD) not found.");
}
PrintAndLogEx(NORMAL, "\n* * Processing online request");
// authorization response code from acquirer
const char HostResponse[] = "00"; // 0x3030
PrintAndLogEx(NORMAL, "* * Host Response: `%s`", HostResponse);
tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse);
size_t HostResponseLen = sizeof(HostResponse) - 1;
PrintAndLogEx(NORMAL, "Host Response: `%s`", HostResponse);
tlvdb_change_or_add_node(tlvRoot, 0x8a, HostResponseLen, (const unsigned char *)HostResponse);
if (CryptoVersion == 10) {
PrintAndLogEx(NORMAL, "\n* * Generate ARPC");
// Application Cryptogram (AC)
const struct tlv *AC = tlvdb_get(tlvRoot, 0x9f26, NULL);
if (AC && (AC->len > 0)) {
PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len));
size_t rawARPClen = AC->len;
uint8_t rawARPC[rawARPClen];
memcpy(rawARPC, AC->value, AC->len);
for (int i = 0; (i < HostResponseLen) && (i < rawARPClen); i++)
rawARPC[i] ^= HostResponse[i];
PrintAndLogEx(NORMAL, "raw ARPC: %s", sprint_hex(rawARPC, rawARPClen));
// here must be calculation of ARPC, but we dont know a bank keys.
PrintAndLogEx(NORMAL, "ARPC: n/a");
} else {
PrintAndLogEx(NORMAL, "Application Cryptogram (AC) not found.");
}
// here must be external authenticate, but we dont know ARPC
}
// needs to send AC2 command (res == ARQC)
if ((CID & 0xc0) == 0x80) {
PrintAndLogEx(NORMAL, "* * Calc CDOL2");
PrintAndLogEx(NORMAL, "\n* * Calc CDOL2");
struct tlv *cdol2_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
if (!cdol2_data_tlv) {
PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV.");
@ -1230,9 +1293,11 @@ int CmdEMVExec(const char *cmd) {
PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol2_data_tlv->len, sprint_hex(cdol2_data_tlv->value, cdol2_data_tlv->len));
PrintAndLogEx(NORMAL, "* * AC2");
//PrintAndLogEx(NORMAL, "* * AC2");
// here must be AC2, but we dont make external authenticate (
/* // AC2
PRINT_INDENT(level);
if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n");