TLVPrintFromBuffer(buf, len);
PrintAndLog("* Selected.");
-PrintAndLog("-----BREAK.");
-return 0;
PrintAndLog("\n* Init transaction parameters.");
//9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
- TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // E6
+ TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
+// TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
+// TLV_ADD(0x9F66, "\x8e\x00\x00\x00"); // CDA
//9F02:(Amount, Authorised (Numeric)) len:6
TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
//9F1A:(Terminal Country Code) len:2
TLV_ADD(0x9C, "\x00");
// 9F37 Unpredictable Number len:4
TLV_ADD(0x9F37, "\x01\x02\x03\x04");
+ // 9F6A Unpredictable Number (MSD for UDOL) len:4
+ TLV_ADD(0x9F6A, "\x01\x02\x03\x04");
- TLVPrintFromTLV(tlvRoot);
+ TLVPrintFromTLV(tlvRoot); // TODO delete!!!
PrintAndLog("\n* Calc PDOL.");
struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
}
PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
-//PrintAndLog("-----BREAK.");
-//return 0;
PrintAndLog("\n* GPO.");
res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
// process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV]
if (buf[0] == 0x80) {
-
-
-
if (decodeTLV){
PrintAndLog("GPO response format1:");
TLVPrintFromBuffer(buf, len);
}
- } else {
-
-
+ if (len < 4 || (len - 4) % 4) {
+ PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len);
+ } else {
+ // AIP
+ struct tlvdb * f1AIP = tlvdb_fixed(0x82, 2, buf + 2);
+ tlvdb_add(tlvRoot, f1AIP);
+ if (decodeTLV){
+ PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:");
+ TLVPrintFromTLV(f1AIP);
+ }
+
+ // AFL
+ struct tlvdb * f1AFL = tlvdb_fixed(0x94, len - 4, buf + 2 + 2);
+ tlvdb_add(tlvRoot, f1AFL);
+ if (decodeTLV)
+ TLVPrintFromTLV(f1AFL);
+ }
+ } else {
if (decodeTLV)
TLVPrintFromBuffer(buf, len);
}
+ // extract PAN from track2
+ {
+ const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
+ if (!tlvdb_get(tlvRoot, 0x5a, NULL) && track2 && track2->len >= 8) {
+ struct tlvdb *pan = GetPANFromTrack2(track2);
+ if (pan) {
+ tlvdb_add(tlvRoot, pan);
+
+ const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL);
+ PrintAndLog("\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len));
+ } else {
+ PrintAndLog("\n* * WARNING: Can't extract PAN from track2.");
+ }
+ }
+ }
+
PrintAndLog("\n* Read records from AFL.");
const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
if (!AFL || !AFL->len) {
break;
}
- // additional contacless EMV commands (fDDA, CDA, external authenticate)
+ // transaction check
+ const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
+ uint16_t AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;
+ PrintAndLog("* * AIP=%x", AIP);
+
+ // qVSDC
+ {
+ // 9F26: Application Cryptogram
+ const struct tlv *AC = tlvdb_get(tlvRoot, 0x9F26, NULL);
+ if (AC) {
+ PrintAndLog("\n--> qVSDC transaction.");
+ PrintAndLog("* AC path");
+
+ // 9F36: Application Transaction Counter (ATC)
+ const struct tlv *ATC = tlvdb_get(tlvRoot, 0x9F36, NULL);
+ if (ATC) {
+
+ // 9F10: Issuer Application Data - optional
+ const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9F10, NULL);
+
+ // print AC data
+ PrintAndLog("ATC: %s", sprint_hex(ATC->value, ATC->len));
+ PrintAndLog("AC: %s", sprint_hex(AC->value, AC->len));
+ if (IAD){
+ PrintAndLog("IAD: %s", sprint_hex(IAD->value, IAD->len));
+
+ if (IAD->len >= IAD->value[0] + 1) {
+ PrintAndLog("\tKey index: 0x%02x", IAD->value[1]);
+ PrintAndLog("\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]);
+ PrintAndLog("\tCVR:", sprint_hex(&IAD->value[3], IAD->value[0] - 2));
+ struct tlvdb * cvr = tlvdb_fixed(0x20, IAD->value[0] - 2, &IAD->value[3]);
+ TLVPrintFromTLVLev(cvr, 1);
+ }
+ } else {
+ PrintAndLog("WARNING: IAD not found.");
+ }
+
+ } else {
+ PrintAndLog("ERROR AC: Application Transaction Counter (ATC) not found.");
+ }
+ }
+ }
+
+ // TODO: Mastercard M/CHIP
+ {
+ const struct tlv *CDOL1 = tlvdb_get(tlvRoot, 0x8c, NULL);
+ if (CDOL1 && GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) { // and m/chip transaction flag
+
+ }
+ }
+
+ // MSD
+ if (AIP & 0x8000) {
+ PrintAndLog("\n--> MSD transaction.");
+
+
+ PrintAndLog("* MSD dCVV path. Check dCVV");
+
+ const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL);
+ if (track2) {
+ PrintAndLog("Track2: %s", sprint_hex(track2->value, track2->len));
+
+ struct tlvdb *dCVV = GetdCVVRawFromTrack2(track2);
+ PrintAndLog("dCVV raw data:");
+ TLVPrintFromTLV(dCVV);
+
+ if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) {
+ PrintAndLog("\n* Mastercard calculate UDOL");
+
+ // UDOL (9F69)
+ const struct tlv *UDOL = tlvdb_get(tlvRoot, 0x9F69, NULL);
+ // UDOL(9F69) default: 9F6A (Unpredictable number) 4 bytes
+ const struct tlv defUDOL = {
+ .tag = 0x01,
+ .len = 3,
+ .value = (uint8_t *)"\x9f\x6a\x04",
+ };
+ if (!UDOL)
+ PrintAndLog("Use default UDOL.");
+
+ struct tlv *udol_data_tlv = dol_process(UDOL ? UDOL : &defUDOL, tlvRoot, 0x01); // 0x01 - fake tag!
+ if (!udol_data_tlv){
+ PrintAndLog("ERROR: can't create UDOL TLV.");
+ return 4;
+ }
+
+ PrintAndLog("UDOL data[%d]: %s", udol_data_tlv->len, sprint_hex(udol_data_tlv->value, udol_data_tlv->len));
+
+ PrintAndLog("\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);
+ if (res) {
+ PrintAndLog("ERROR Compute Crypto Checksum. APDU error %4x", sw);
+ return 5;
+ }
+
+ if (decodeTLV) {
+ TLVPrintFromBuffer(buf, len);
+ PrintAndLog("");
+ }
+
+ }
+ } else {
+ PrintAndLog("ERROR MSD: Track2 data not found.");
+ }
+ }
+
+ // additional contacless EMV commands (fDDA, external authenticate)
// DropField