+ // VSDC
+ if (GetCardPSVendor(AID, AIDlen) == CV_VISA && (TrType == TT_VSDC || TrType == TT_CDA)){
+ PrintAndLogEx(NORMAL, "\n--> VSDC transaction.");
+
+ PrintAndLogEx(NORMAL, "* * Calc CDOL1");
+ struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
+ if (!cdol_data_tlv) {
+ PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV.");
+ dreturn(6);
+ }
+
+ PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len));
+
+ PrintAndLogEx(NORMAL, "* * AC1");
+ // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
+ 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);
+ dreturn(7);
+ }
+
+ // process Format1 (0x80) and print Format2 (0x77)
+ ProcessACResponseFormat1(tlvRoot, buf, len, decodeTLV);
+
+ uint8_t CID = 0;
+ tlvdb_get_uint8(tlvRoot, 0x9f27, &CID);
+
+ // AC1 print result
+ PrintAndLog("");
+ if ((CID & EMVAC_AC_MASK) == EMVAC_AAC) PrintAndLogEx(INFO, "AC1 result: AAC (Transaction declined)");
+ if ((CID & EMVAC_AC_MASK) == EMVAC_TC) PrintAndLogEx(INFO, "AC1 result: TC (Transaction approved)");
+ 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");
+
+ // 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
+ 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 & EMVAC_AC_MASK) == EMVAC_ARQC) {
+ 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.");
+ dreturn(6);
+ }
+
+ PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol2_data_tlv->len, sprint_hex(cdol2_data_tlv->value, cdol2_data_tlv->len));
+
+ //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");
+ if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) fprintf(f, "\tAC2: TC (Transaction approved)\n");
+ if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) fprintf(f, "\tAC2: not requested (ARQC)\n");
+ if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n");
+*/
+ }
+