1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2017 Merlok
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
9 //-----------------------------------------------------------------------------
15 #include "commonutil.h" // ARRAYLEN
16 #include "comms.h" // DropField
17 #include "cmdparser.h"
18 #include "cmdsmartcard.h" // ExchangeAPDUSC
25 #include "util_posix.h"
27 // Got from here. Thanks!
28 // https://eftlab.co.uk/index.php/site-map/knowledge-base/211-emv-aid-rid-pix
29 static const char *PSElist
[] = {
30 "325041592E5359532E4444463031", // 2PAY.SYS.DDF01 - Visa Proximity Payment System Environment - PPSE
31 "315041592E5359532E4444463031" // 1PAY.SYS.DDF01 - Visa Payment System Environment - PSE
34 const char *TransactionTypeStr
[] = {
42 enum CardPSVendor vendor
;
46 static const TAIDList AIDlist
[] = {
48 { CV_VISA
, "A00000000305076010" }, // VISA ELO Credit
49 { CV_VISA
, "A0000000031010" }, // VISA Debit/Credit (Classic)
50 { CV_VISA
, "A000000003101001" }, // VISA Credit
51 { CV_VISA
, "A000000003101002" }, // VISA Debit
52 { CV_VISA
, "A0000000032010" }, // VISA Electron
53 { CV_VISA
, "A0000000032020" }, // VISA
54 { CV_VISA
, "A0000000033010" }, // VISA Interlink
55 { CV_VISA
, "A0000000034010" }, // VISA Specific
56 { CV_VISA
, "A0000000035010" }, // VISA Specific
57 { CV_VISA
, "A0000000036010" }, // Domestic Visa Cash Stored Value
58 { CV_VISA
, "A0000000036020" }, // International Visa Cash Stored Value
59 { CV_VISA
, "A0000000038002" }, // VISA Auth, VisaRemAuthen EMV-CAP (DPA)
60 { CV_VISA
, "A0000000038010" }, // VISA Plus
61 { CV_VISA
, "A0000000039010" }, // VISA Loyalty
62 { CV_VISA
, "A000000003999910" }, // VISA Proprietary ATM
64 { CV_VISA
, "A000000098" }, // Debit Card
65 { CV_VISA
, "A0000000980848" }, // Debit Card
66 // Mastercard International
67 { CV_MASTERCARD
, "A00000000401" }, // MasterCard PayPass
68 { CV_MASTERCARD
, "A0000000041010" }, // MasterCard Credit
69 { CV_MASTERCARD
, "A00000000410101213" }, // MasterCard Credit
70 { CV_MASTERCARD
, "A00000000410101215" }, // MasterCard Credit
71 { CV_MASTERCARD
, "A0000000042010" }, // MasterCard Specific
72 { CV_MASTERCARD
, "A0000000043010" }, // MasterCard Specific
73 { CV_MASTERCARD
, "A0000000043060" }, // Maestro (Debit)
74 { CV_MASTERCARD
, "A000000004306001" }, // Maestro (Debit)
75 { CV_MASTERCARD
, "A0000000044010" }, // MasterCard Specific
76 { CV_MASTERCARD
, "A0000000045010" }, // MasterCard Specific
77 { CV_MASTERCARD
, "A0000000046000" }, // Cirrus
78 { CV_MASTERCARD
, "A0000000048002" }, // SecureCode Auth EMV-CAP
79 { CV_MASTERCARD
, "A0000000049999" }, // MasterCard PayPass
80 { CV_MASTERCARD
, "B012345678" }, // Maestro TEST Used for development
82 { CV_AMERICANEXPRESS
, "A000000025" },
83 { CV_AMERICANEXPRESS
, "A0000000250000" },
84 { CV_AMERICANEXPRESS
, "A00000002501" },
85 { CV_AMERICANEXPRESS
, "A000000025010402" },
86 { CV_AMERICANEXPRESS
, "A000000025010701" },
87 { CV_AMERICANEXPRESS
, "A000000025010801" },
88 // Groupement des Cartes Bancaires "CB"
89 { CV_CB
, "A0000000421010" }, // Cartes Bancaire EMV Card
90 { CV_CB
, "A0000000422010" },
91 { CV_CB
, "A0000000423010" },
92 { CV_CB
, "A0000000424010" },
93 { CV_CB
, "A0000000425010" },
95 { CV_JCB
, "A00000006510" }, // JCB
96 { CV_JCB
, "A0000000651010" }, // JCB J Smart Credit
97 // Switch Card Services Ltd.
98 { CV_SWITCH
, "A0000000050001" }, // Maestro UK
99 { CV_SWITCH
, "A0000000050002" }, // Solo
100 // Diners Club International Ltd.
101 { CV_DINERS
, "A0000001523010" }, // Discover, Pulse D Pas Discover Card
102 { CV_DINERS
, "A0000001524010" }, // Discover, Discover Debit Common Card
104 { CV_OTHER
, "A00000002401" }, // Midland Bank Plc - Self Service
105 { CV_OTHER
, "A0000000291010" }, // LINK Interchange Network Ltd - Link / American Express
106 { CV_OTHER
, "A00000006900" }, // Société Européenne de Monnaie Electronique SEME - Moneo
107 { CV_OTHER
, "A000000077010000021000000000003B" }, // Oberthur Technologies France - Visa AEPN
108 { CV_OTHER
, "A0000001211010" }, // PBS Danmark A/S - Denmark - Dankort (VISA GEM Vision) - Danish domestic debit card
109 { CV_OTHER
, "A0000001410001" }, // Associazione Bancaria Italiana - Italy - PagoBANCOMAT - CoGeBan Consorzio BANCOMAT (Italian domestic debit card)
110 { CV_OTHER
, "A0000001544442" }, // Banricompras Debito - Banrisul - Banco do Estado do Rio Grande do SUL - S.A.
111 { CV_OTHER
, "A000000172950001" }, // Financial Information Service Co. Ltd. - Taiwan - BAROC Financial Application Taiwan- The Bankers Association of the Republic of China
112 { CV_OTHER
, "A0000001850002" }, // Post Office Limited - United Kingdom - UK Post Office Account card
113 { CV_OTHER
, "A0000002281010" }, // Saudi Arabian Monetary Agency (SAMA) - Kingdom of Saudi Arabia - SPAN (M/Chip) - SPAN2 (Saudi Payments Network) - Saudi Arabia domestic credit/debit card (Saudi Arabia Monetary Agency)
114 { CV_OTHER
, "A0000002282010" }, // Saudi Arabian Monetary Agency (SAMA) - Kingdom of Saudi Arabia - SPAN (VIS) - SPAN2 (Saudi Payments Network) - Saudi Arabia domestic credit/debit card (Saudi Arabia Monetary Agency)
115 { CV_OTHER
, "A0000002771010" }, // Interac Association - Canada - INTERAC - Canadian domestic credit/debit card
116 { CV_OTHER
, "A00000031510100528" }, // Currence Holding/PIN BV - The Netherlands- Currence PuC
117 { CV_OTHER
, "A0000003156020" }, // Currence Holding/PIN BV - The Netherlands - Chipknip
118 { CV_OTHER
, "A0000003591010028001" }, // Euro Alliance of Payment Schemes s.c.r.l. (EAPS) - Belgium - Girocard EAPS - ZKA (Germany)
119 { CV_OTHER
, "A0000003710001" }, // Verve - Nigeria - InterSwitch Verve Card - Nigerian local switch company
120 { CV_OTHER
, "A0000004540010" }, // eTranzact - Nigeria - Etranzact Genesis Card - Nigerian local switch company
121 { CV_OTHER
, "A0000004540011" }, // eTranzact - Nigeria - Etranzact Genesis Card 2 - Nigerian local switch company
122 { CV_OTHER
, "A0000004766C" }, // Google - United States - GOOGLE_PAYMENT_AID
123 { CV_OTHER
, "A0000005241010" }, // RuPay - India - RuPay - RuPay (India)
124 { CV_OTHER
, "A0000006723010" }, // TROY - Turkey - TROY chip credit card - Turkey's Payment Method
125 { CV_OTHER
, "A0000006723020" }, // TROY - Turkey - TROY chip debit card - Turkey's Payment Method
126 { CV_OTHER
, "A0000007705850" }, // Indian Oil Corporation Limited - India - XTRAPOWER Fleet Card Program - Indian Oil’s Pre Paid Program
127 { CV_OTHER
, "D27600002545500100" }, // ZKA - Germany - Girocard - ZKA Girocard (Geldkarte) (Germany)
128 { CV_OTHER
, "D4100000030001" }, // KS X 6923/6924 (T-Money, South Korea and Snapper+, Wellington, New Zealand)
129 { CV_OTHER
, "D5280050218002" }, // The Netherlands - ? - (Netherlands)
130 { CV_OTHER
, "D5780000021010" }, // Bankaxept Norway Bankaxept Norwegian domestic debit card
131 { CV_OTHER
, "F0000000030001" }, // BRADESCO - Brazilian Bank Banco Bradesco
134 enum CardPSVendor
GetCardPSVendor(uint8_t *AID
, size_t AIDlen
) {
139 hex_to_buffer((uint8_t *)buf
, AID
, AIDlen
, sizeof(buf
) - 1, 0, 0, true);
141 for (int i
= 0; i
< ARRAYLEN(AIDlist
); i
++) {
142 if (strncmp(AIDlist
[i
].aid
, buf
, strlen(AIDlist
[i
].aid
)) == 0) {
143 return AIDlist
[i
].vendor
;
150 static void emv_print_cb(void *data
, const struct tlv
*tlv
, int level
, bool is_leaf
) {
151 emv_tag_dump(tlv
, level
);
153 print_buffer(tlv
->value
, tlv
->len
, level
);
157 bool TLVPrintFromBuffer(uint8_t *data
, int datalen
) {
158 struct tlvdb
*t
= tlvdb_parse_multi(data
, datalen
);
160 PrintAndLogEx(INFO
, "-------------------- " _CYAN_("TLV decoded") " --------------------");
162 tlvdb_visit(t
, emv_print_cb
, NULL
, 0);
166 PrintAndLogEx(WARNING
, "TLV ERROR: Can't parse response as TLV tree.");
171 void TLVPrintFromTLVLev(struct tlvdb
*tlv
, int level
) {
175 tlvdb_visit(tlv
, emv_print_cb
, NULL
, level
);
178 void TLVPrintFromTLV(struct tlvdb
*tlv
) {
179 TLVPrintFromTLVLev(tlv
, 0);
182 void TLVPrintAIDlistFromSelectTLV(struct tlvdb
*tlv
) {
183 PrintAndLogEx(INFO
, "|------------------+--------+-------------------------|");
184 PrintAndLogEx(INFO
, "| AID |Priority| Name |");
185 PrintAndLogEx(INFO
, "|------------------+--------+-------------------------|");
187 struct tlvdb
*ttmp
= tlvdb_find(tlv
, 0x6f);
189 PrintAndLogEx(INFO
, "| none |");
192 const struct tlv
*tgAID
= tlvdb_get_inchild(ttmp
, 0x84, NULL
);
193 const struct tlv
*tgName
= tlvdb_get_inchild(ttmp
, 0x50, NULL
);
194 const struct tlv
*tgPrio
= tlvdb_get_inchild(ttmp
, 0x87, NULL
);
197 PrintAndLogEx(INFO
, "| %s| %s | %s|",
198 sprint_hex_inrow_ex(tgAID
->value
, tgAID
->len
, 17),
199 (tgPrio
) ? sprint_hex(tgPrio
->value
, 1) : " ",
200 (tgName
) ? sprint_ascii_ex(tgName
->value
, tgName
->len
, 24) : " ");
202 ttmp
= tlvdb_find_next(ttmp
, 0x6f);
205 PrintAndLogEx(INFO
, "|------------------+--------+-------------------------|");
208 struct tlvdb
*GetPANFromTrack2(const struct tlv
*track2
) {
209 char track2Hex
[200] = {0};
210 uint8_t PAN
[100] = {0};
212 char *tmp
= track2Hex
;
217 for (int i
= 0; i
< track2
->len
; ++i
, tmp
+= 2)
218 sprintf(tmp
, "%02x", (unsigned int)track2
->value
[i
]);
220 int posD
= strchr(track2Hex
, 'd') - track2Hex
;
225 if (strlen(track2Hex
) % 2) {
226 track2Hex
[posD
] = 'F';
227 track2Hex
[posD
+ 1] = '\0';
230 param_gethex_to_eol(track2Hex
, 0, PAN
, sizeof(PAN
), &PANlen
);
232 return tlvdb_fixed(0x5a, PANlen
, PAN
);
235 struct tlvdb
*GetdCVVRawFromTrack2(const struct tlv
*track2
) {
236 char track2Hex
[200] = {0};
237 char dCVVHex
[100] = {0};
238 uint8_t dCVV
[100] = {0};
240 const int PINlen
= 5; // must calculated from 9F67 MSD Offset but i have not seen this tag)
241 char *tmp
= track2Hex
;
246 for (int i
= 0; i
< track2
->len
; ++i
, tmp
+= 2)
247 sprintf(tmp
, "%02x", (unsigned int)track2
->value
[i
]);
249 int posD
= strchr(track2Hex
, 'd') - track2Hex
;
253 memset(dCVVHex
, '0', 32);
255 memcpy(dCVVHex
+ 0, track2Hex
+ posD
+ PINlen
+ 11, 4);
257 memcpy(dCVVHex
+ 4, track2Hex
, 5);
259 memcpy(dCVVHex
+ 9, track2Hex
+ posD
+ 1, 4);
261 memcpy(dCVVHex
+ 13, track2Hex
+ posD
+ 5, 3);
263 param_gethex_to_eol(dCVVHex
, 0, dCVV
, sizeof(dCVV
), &dCVVlen
);
265 return tlvdb_fixed(0x02, dCVVlen
, dCVV
);
268 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
) {
269 int res
= Iso7816ExchangeEx(channel
, ActivateField
, LeaveFieldON
, apdu
, IncludeLe
, 0, Result
, MaxResultLen
, ResultLen
, sw
);
271 if ((res
== PM3_SUCCESS
) && tlv
) {
272 struct tlvdb
*t
= tlvdb_parse_multi(Result
, *ResultLen
);
278 int EMVExchange(Iso7816CommandChannel channel
, bool LeaveFieldON
, sAPDU apdu
, uint8_t *Result
, size_t MaxResultLen
, size_t *ResultLen
, uint16_t *sw
, struct tlvdb
*tlv
) {
279 int res
= Iso7816Exchange(channel
, LeaveFieldON
, apdu
, Result
, MaxResultLen
, ResultLen
, sw
);
281 if ((res
== PM3_SUCCESS
) && tlv
) {
282 struct tlvdb
*t
= tlvdb_parse_multi(Result
, *ResultLen
);
288 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
) {
289 int res
= Iso7816Select(channel
, ActivateField
, LeaveFieldON
, AID
, AIDLen
, Result
, MaxResultLen
, ResultLen
, sw
);
291 if ((res
== PM3_SUCCESS
) && tlv
) {
292 struct tlvdb
*t
= tlvdb_parse_multi(Result
, *ResultLen
);
298 int EMVSelectPSE(Iso7816CommandChannel channel
, bool ActivateField
, bool LeaveFieldON
, uint8_t PSENum
, uint8_t *Result
, size_t MaxResultLen
, size_t *ResultLen
, uint16_t *sw
) {
299 uint8_t buf
[APDU_AID_LEN
] = {0};
304 param_gethex_to_eol(PSElist
[1], 0, buf
, sizeof(buf
), &len
);
307 param_gethex_to_eol(PSElist
[0], 0, buf
, sizeof(buf
), &len
);
312 return EMVSelect(channel
, ActivateField
, LeaveFieldON
, buf
, len
, Result
, MaxResultLen
, ResultLen
, sw
, NULL
);
315 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
) {
319 res
= EMVSelect(channel
, false, true, AID
, AIDLen
, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
321 // retry if error and not returned sw error
322 if (res
&& res
!= 5) {
323 if (++retrycnt
< 3) {
326 // card select error, proxmark error
328 PrintAndLogEx(WARNING
, "exiting...");
333 PrintAndLogEx(FAILED
, "Retry failed [%s]. Skipped...", sprint_hex_inrow(AID
, AIDLen
));
337 } while (res
&& res
!= 5);
342 static int EMVCheckAID(Iso7816CommandChannel channel
, bool decodeTLV
, struct tlvdb
*tlvdbelm
, struct tlvdb
*tlv
) {
343 uint8_t data
[APDU_RES_LEN
] = {0};
349 const struct tlv
*tgAID
= tlvdb_get_inchild(tlvdbelm
, 0x4f, NULL
);
351 res
= EMVSelectWithRetry(channel
, false, true, (uint8_t *)tgAID
->value
, tgAID
->len
, data
, sizeof(data
), &datalen
, &sw
, tlv
);
353 // if returned sw error
356 tlvdbelm
= tlvdb_find_next(tlvdbelm
, 0x61);
365 PrintAndLogEx(SUCCESS
, "%s:", sprint_hex_inrow(tgAID
->value
, tgAID
->len
));
366 TLVPrintFromBuffer(data
, datalen
);
369 tlvdbelm
= tlvdb_find_next(tlvdbelm
, 0x61);
374 int EMVSearchPSE(Iso7816CommandChannel channel
, bool ActivateField
, bool LeaveFieldON
, uint8_t PSENum
, bool decodeTLV
, struct tlvdb
*tlv
) {
375 uint8_t data
[APDU_RES_LEN
] = {0};
377 uint8_t sfidata
[0x11][APDU_RES_LEN
];
378 size_t sfidatalen
[0x11] = {0};
381 const char *PSE_or_PPSE
= PSENum
== 1 ? "PSE" : "PPSE";
384 res
= EMVSelectPSE(channel
, ActivateField
, true, PSENum
, data
, sizeof(data
), &datalen
, &sw
);
388 PrintAndLogEx(FAILED
, "Select PSE error. APDU error: %04x.", sw
);
392 bool fileFound
= false;
394 struct tlvdb
*t
= tlvdb_parse_multi(data
, datalen
);
397 struct tlvdb
*tsfi
= tlvdb_find_path(t
, (tlv_tag_t
[]) {0x6f, 0xa5, 0x88, 0x00});
400 tlv_get_uint8(tlvdb_get_tlv(tsfi
), &sfin
);
401 PrintAndLogEx(INFO
, "* PPSE get SFI: 0x%02x.", sfin
);
403 for (uint8_t ui
= 0x01; ui
<= 0x10; ui
++) {
404 PrintAndLogEx(INFO
, "* * Get SFI: 0x%02x. num: 0x%02x", sfin
, ui
);
405 res
= EMVReadRecord(channel
, true, sfin
, ui
, sfidata
[ui
], APDU_RES_LEN
, &sfidatalen
[ui
], &sw
, NULL
);
410 PrintAndLogEx(INFO
, "* * PPSE get SFI. End of records.");
417 PrintAndLogEx(FAILED
, "PPSE get Error. APDU error: %04x.", sw
);
422 TLVPrintFromBuffer(sfidata
[ui
], sfidatalen
[ui
]);
426 for (uint8_t ui
= 0x01; ui
<= 0x10; ui
++) {
427 if (sfidatalen
[ui
]) {
429 struct tlvdb
*tsfi_a
= tlvdb_parse_multi(sfidata
[ui
], sfidatalen
[ui
]);
431 struct tlvdb
*tsfitmp
= tlvdb_find_path(tsfi_a
, (tlv_tag_t
[]) {0x70, 0x61, 0x00});
433 PrintAndLogEx(FAILED
, "SFI 0x%02zu doesn't have any records.", sfidatalen
[ui
]);
436 res
= EMVCheckAID(channel
, decodeTLV
, tsfitmp
, tlv
);
445 // PSE/PPSE plain (wo SFI)
446 struct tlvdb
*ttmp
= tlvdb_find_path(t
, (tlv_tag_t
[]) {0x6f, 0xa5, 0xbf0c, 0x61, 0x00});
448 res
= EMVCheckAID(channel
, decodeTLV
, ttmp
, tlv
);
453 PrintAndLogEx(FAILED
, "PPSE doesn't have any records.");
457 PrintAndLogEx(WARNING
, "%s ERROR: Can't get TLV from response.", PSE_or_PPSE
);
460 PrintAndLogEx(ERR
, "%s ERROR: Can't select PPSE AID. Error: %d", PSE_or_PPSE
, res
);
464 DropFieldEx(channel
);
469 int EMVSearch(Iso7816CommandChannel channel
, bool ActivateField
, bool LeaveFieldON
, bool decodeTLV
, struct tlvdb
*tlv
) {
470 uint8_t aidbuf
[APDU_AID_LEN
] = {0};
472 uint8_t data
[APDU_RES_LEN
] = {0};
478 for (int i
= 0; i
< ARRAYLEN(AIDlist
); i
++) {
480 if (kbd_enter_pressed()) {
481 PrintAndLogEx(INFO
, "user aborted...");
485 param_gethex_to_eol(AIDlist
[i
].aid
, 0, aidbuf
, sizeof(aidbuf
), &aidlen
);
486 res
= EMVSelect(channel
, (i
== 0) ? ActivateField
: false, true, aidbuf
, aidlen
, data
, sizeof(data
), &datalen
, &sw
, tlv
);
487 // retry if error and not returned sw error
488 if (res
&& res
!= 5) {
489 if (++retrycnt
< 3) {
492 // (1) - card select error, (4) reply timeout, (200) - result length = 0
493 if (res
== 1 || res
== 4 || res
== 200) {
495 DropFieldEx(channel
);
497 PrintAndLogEx(WARNING
, "exiting...");
502 PrintAndLogEx(FAILED
, "Retry failed [%s]. Skipped...", AIDlist
[i
].aid
);
515 PrintAndLogEx(SUCCESS
, "%s", AIDlist
[i
].aid
);
516 TLVPrintFromBuffer(data
, datalen
);
521 DropFieldEx(channel
);
526 int EMVSelectApplication(struct tlvdb
*tlv
, uint8_t *AID
, size_t *AIDlen
) {
527 // check priority. 0x00 - highest
532 struct tlvdb
*ttmp
= tlvdb_find(tlv
, 0x6f);
537 const struct tlv
*tgAID
= tlvdb_get_inchild(ttmp
, 0x84, NULL
);
538 const struct tlv
*tgPrio
= tlvdb_get_inchild(ttmp
, 0x87, NULL
);
544 int pt
= bytes_to_num((uint8_t *)tgPrio
->value
, (tgPrio
->len
< 2) ? tgPrio
->len
: 2);
548 memcpy(AID
, tgAID
->value
, tgAID
->len
);
549 *AIDlen
= tgAID
->len
;
552 // takes the first application from list wo priority
554 memcpy(AID
, tgAID
->value
, tgAID
->len
);
555 *AIDlen
= tgAID
->len
;
559 ttmp
= tlvdb_find_next(ttmp
, 0x6f);
565 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
) {
566 return EMVExchangeEx(channel
, false, LeaveFieldON
, (sAPDU
) {0x80, 0xa8, 0x00, 0x00, PDOLLen
, PDOL
}, true, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
569 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
) {
570 int res
= EMVExchangeEx(channel
, false, LeaveFieldON
, (sAPDU
) {0x00, 0xb2, SFIrec
, (SFI
<< 3) | 0x04, 0, NULL
}, true, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
571 if (*sw
== 0x6700 || *sw
== 0x6f00) {
572 PrintAndLogEx(INFO
, ">>> trying to reissue command without Le...");
573 res
= EMVExchangeEx(channel
, false, LeaveFieldON
, (sAPDU
) {0x00, 0xb2, SFIrec
, (SFI
<< 3) | 0x04, 0, NULL
}, false, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
578 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
) {
579 return EMVExchange(channel
, LeaveFieldON
, (sAPDU
) {0x80, 0xae, RefControl
, 0x00, CDOLLen
, CDOL
}, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
582 int EMVGenerateChallenge(Iso7816CommandChannel channel
, bool LeaveFieldON
, uint8_t *Result
, size_t MaxResultLen
, size_t *ResultLen
, uint16_t *sw
, struct tlvdb
*tlv
) {
583 int res
= EMVExchangeEx(channel
, false, LeaveFieldON
, (sAPDU
) {0x00, 0x84, 0x00, 0x00, 0x00, NULL
}, true, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
584 if (*sw
== 0x6700 || *sw
== 0x6f00) {
585 PrintAndLogEx(INFO
, ">>> trying to reissue command without Le...");
586 res
= EMVExchangeEx(channel
, false, LeaveFieldON
, (sAPDU
) {0x00, 0x84, 0x00, 0x00, 0x00, NULL
}, false, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
591 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
) {
592 return EMVExchangeEx(channel
, false, LeaveFieldON
, (sAPDU
) {0x00, 0x88, 0x00, 0x00, DDOLLen
, DDOL
}, true, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
595 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
) {
596 int res
= EMVExchangeEx(channel
, false, LeaveFieldON
, (sAPDU
) {0x80, 0x2a, 0x8e, 0x80, UDOLlen
, UDOL
}, true, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
597 if (*sw
== 0x6700 || *sw
== 0x6f00) {
598 PrintAndLogEx(INFO
, ">>> trying to reissue command without Le...");
599 res
= EMVExchangeEx(channel
, false, LeaveFieldON
, (sAPDU
) {0x80, 0x2a, 0x8e, 0x80, UDOLlen
, UDOL
}, false, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
605 struct emv_pk
*get_ca_pk(struct tlvdb
*db
) {
606 const struct tlv
*df_tlv
= tlvdb_get(db
, 0x84, NULL
);
607 const struct tlv
*caidx_tlv
= tlvdb_get(db
, 0x8f, NULL
);
609 if (!df_tlv
|| !caidx_tlv
|| df_tlv
->len
< 6 || caidx_tlv
->len
!= 1)
612 PrintAndLogEx(INFO
, "CA public key index 0x%0x", caidx_tlv
->value
[0]);
613 return emv_pk_get_ca_pk(df_tlv
->value
, caidx_tlv
->value
[0]);
616 int trSDA(struct tlvdb
*tlv
) {
618 struct emv_pk
*pk
= get_ca_pk(tlv
);
620 PrintAndLogEx(ERR
, "Error: Key not found, exiting");
624 struct emv_pk
*issuer_pk
= emv_pki_recover_issuer_cert(pk
, tlv
);
627 PrintAndLogEx(ERR
, "Error: Issuer certificate not found, exiting");
631 PrintAndLogEx(SUCCESS
, "Issuer Public key recovered RID " _YELLOW_("%s") " IDX " _YELLOW_("%02hhx") " CSN " _YELLOW_("%s"),
632 sprint_hex(issuer_pk
->rid
, 5),
634 sprint_hex(issuer_pk
->serial
, 3)
637 const struct tlv
*sda_tlv
= tlvdb_get(tlv
, 0x21, NULL
);
638 if (!sda_tlv
|| sda_tlv
->len
< 1) {
639 emv_pk_free(issuer_pk
);
641 PrintAndLogEx(WARNING
, "Can't find input list for Offline Data Authentication, exiting");
645 struct tlvdb
*dac_db
= emv_pki_recover_dac(issuer_pk
, tlv
, sda_tlv
);
647 const struct tlv
*dac_tlv
= tlvdb_get(dac_db
, 0x9f45, NULL
);
648 PrintAndLogEx(INFO
, "SDA verified (%s) (Data Authentication Code: %02hhx:%02hhx)", _GREEN_("ok"), dac_tlv
->value
[0], dac_tlv
->value
[1]);
649 tlvdb_add(tlv
, dac_db
);
651 emv_pk_free(issuer_pk
);
653 PrintAndLogEx(ERR
, "SSAD verify error");
657 emv_pk_free(issuer_pk
);
662 static const unsigned char default_ddol_value
[] = {0x9f, 0x37, 0x04};
663 static struct tlv default_ddol_tlv
= {.tag
= 0x9f49, .len
= 3, .value
= default_ddol_value
};
665 int trDDA(Iso7816CommandChannel channel
, bool decodeTLV
, struct tlvdb
*tlv
) {
666 uint8_t buf
[APDU_RES_LEN
] = {0};
670 struct emv_pk
*pk
= get_ca_pk(tlv
);
672 PrintAndLogEx(ERR
, "Error: Key not found, exiting");
676 const struct tlv
*sda_tlv
= tlvdb_get(tlv
, 0x21, NULL
);
677 /* if (!sda_tlv || sda_tlv->len < 1) { it may be 0!!!!
679 PrintAndLogEx(ERR, "Error: Can't find input list for Offline Data Authentication, exiting");
683 struct emv_pk
*issuer_pk
= emv_pki_recover_issuer_cert(pk
, tlv
);
686 PrintAndLogEx(ERR
, "Error: Issuer certificate not found, exiting");
690 PrintAndLogEx(SUCCESS
, "Issuer Public key recovered RID " _YELLOW_("%s") " IDX " _YELLOW_("%02hhx") " CSN " _YELLOW_("%s"),
691 sprint_hex(issuer_pk
->rid
, 5),
693 sprint_hex(issuer_pk
->serial
, 3)
696 struct emv_pk
*icc_pk
= emv_pki_recover_icc_cert(issuer_pk
, tlv
, sda_tlv
);
699 emv_pk_free(issuer_pk
);
700 PrintAndLogEx(ERR
, "Error: ICC certificate not found, exiting");
704 PrintAndLogEx(SUCCESS
, "ICC Public key recovered. RID " _YELLOW_("%s") " IDX " _YELLOW_("%02hhx") " CSN " _YELLOW_("%s"),
705 sprint_hex(icc_pk
->rid
, 5),
707 sprint_hex(icc_pk
->serial
, 3)
710 if (tlvdb_get(tlv
, 0x9f2d, NULL
)) {
711 struct emv_pk
*icc_pe_pk
= emv_pki_recover_icc_pe_cert(issuer_pk
, tlv
);
713 PrintAndLogEx(WARNING
, "WARNING: ICC PE Public key recover error");
715 PrintAndLogEx(SUCCESS
, "ICC PE Public key recovered. RID " _YELLOW_("%s") " IDX " _YELLOW_("%02hhx") " CSN " _YELLOW_("%s"),
716 sprint_hex(icc_pe_pk
->rid
, 5),
718 sprint_hex(icc_pe_pk
->serial
, 3)
722 PrintAndLogEx(INFO
, "ICC PE Public Key (PIN Encipherment Public Key Certificate) not found.\n");
725 // 9F4B: Signed Dynamic Application Data
726 const struct tlv
*sdad_tlv
= tlvdb_get(tlv
, 0x9f4b, NULL
);
727 // DDA with internal authenticate OR fDDA with filled 0x9F4B tag (GPO result)
728 // EMV kernel3 v2.4, contactless book C-3, C.1., page 147
730 PrintAndLogEx(INFO
, "* * Got Signed Dynamic Application Data (9F4B) form GPO. Maybe fDDA...");
732 struct tlvdb
*atc_db
= emv_pki_recover_atc_ex(icc_pk
, tlv
, true);
734 PrintAndLogEx(ERR
, "Error: Can't recover IDN (ICC Dynamic Number)");
736 emv_pk_free(issuer_pk
);
741 // 9f36 Application Transaction Counter (ATC)
742 const struct tlv
*atc_tlv
= tlvdb_get(atc_db
, 0x9f36, NULL
);
744 PrintAndLogEx(INFO
, "ATC (Application Transaction Counter) [%zu] %s", atc_tlv
->len
, sprint_hex_inrow(atc_tlv
->value
, atc_tlv
->len
));
746 const struct tlv
*core_atc_tlv
= tlvdb_get(tlv
, 0x9f36, NULL
);
747 if (tlv_equal(core_atc_tlv
, atc_tlv
)) {
748 PrintAndLogEx(SUCCESS
, "ATC check OK.");
749 PrintAndLogEx(SUCCESS
, "fDDA (fast DDA) verified OK.");
751 PrintAndLogEx(WARNING
, "Error: fDDA verified, but ATC in the certificate and ATC in the record not the same.");
754 PrintAndLogEx(WARNING
, "ERROR: fDDA (fast DDA) verify error");
756 emv_pk_free(issuer_pk
);
763 struct tlvdb
*dac_db
= emv_pki_recover_dac(issuer_pk
, tlv
, sda_tlv
);
765 const struct tlv
*dac_tlv
= tlvdb_get(dac_db
, 0x9f45, NULL
);
766 PrintAndLogEx(INFO
, "SDAD verified (%s) (Data Authentication Code: %02hhx:%02hhx)\n", _GREEN_("ok"), dac_tlv
->value
[0], dac_tlv
->value
[1]);
767 tlvdb_add(tlv
, dac_db
);
769 PrintAndLogEx(ERR
, "Error: SSAD verify error");
771 emv_pk_free(issuer_pk
);
776 PrintAndLogEx(INFO
, "* Calc DDOL");
777 const struct tlv
*ddol_tlv
= tlvdb_get(tlv
, 0x9f49, NULL
);
779 ddol_tlv
= &default_ddol_tlv
;
780 PrintAndLogEx(INFO
, "DDOL [9f49] not found. Using default DDOL");
783 struct tlv
*ddol_data_tlv
= dol_process(ddol_tlv
, tlv
, 0);
784 if (!ddol_data_tlv
) {
785 PrintAndLogEx(ERR
, "Error: Can't create DDOL TLV");
787 emv_pk_free(issuer_pk
);
792 PrintAndLogEx(INFO
, "DDOL data[%zu]: %s", ddol_data_tlv
->len
, sprint_hex(ddol_data_tlv
->value
, ddol_data_tlv
->len
));
794 PrintAndLogEx(INFO
, "* Internal Authenticate");
795 int res
= EMVInternalAuthenticate(channel
, true, (uint8_t *)ddol_data_tlv
->value
, ddol_data_tlv
->len
, buf
, sizeof(buf
), &len
, &sw
, NULL
);
797 PrintAndLogEx(ERR
, "Internal Authenticate error(%d): %4x, exiting..", res
, sw
);
800 emv_pk_free(issuer_pk
);
805 struct tlvdb
*dda_db
= NULL
;
806 if (buf
[0] == 0x80) {
808 PrintAndLogEx(WARNING
, "Warning: Internal Authenticate format1 parsing error. length=%zu", len
);
810 // parse response 0x80
811 struct tlvdb
*t80
= tlvdb_parse_multi(buf
, len
);
812 const struct tlv
*t80tlv
= tlvdb_get_tlv(t80
);
814 // 9f4b Signed Dynamic Application Data
815 dda_db
= tlvdb_fixed(0x9f4b, t80tlv
->len
, t80tlv
->value
);
816 tlvdb_add(tlv
, dda_db
);
821 PrintAndLogEx(INFO
, "* * Decode response format 1:");
822 TLVPrintFromTLV(dda_db
);
826 dda_db
= tlvdb_parse_multi(buf
, len
);
828 PrintAndLogEx(ERR
, "Error: Can't parse Internal Authenticate result as TLV");
831 emv_pk_free(issuer_pk
);
835 tlvdb_add(tlv
, dda_db
);
838 TLVPrintFromTLV(dda_db
);
841 struct tlvdb
*idn_db
= emv_pki_recover_idn_ex(icc_pk
, dda_db
, ddol_data_tlv
, true);
844 PrintAndLogEx(ERR
, "Error: Can't recover IDN (ICC Dynamic Number)");
847 emv_pk_free(issuer_pk
);
853 // 9f4c ICC Dynamic Number
854 const struct tlv
*idn_tlv
= tlvdb_get(idn_db
, 0x9f4c, NULL
);
856 PrintAndLogEx(INFO
, "IDN (ICC Dynamic Number) [%zu] %s", idn_tlv
->len
, sprint_hex_inrow(idn_tlv
->value
, idn_tlv
->len
));
857 PrintAndLogEx(INFO
, "DDA verified OK.");
858 tlvdb_add(tlv
, idn_db
);
861 PrintAndLogEx(ERR
, "DDA verify error");
865 emv_pk_free(issuer_pk
);
872 emv_pk_free(issuer_pk
);
877 int trCDA(struct tlvdb
*tlv
, struct tlvdb
*ac_tlv
, struct tlv
*pdol_data_tlv
, struct tlv
*ac_data_tlv
) {
879 struct emv_pk
*pk
= get_ca_pk(tlv
);
881 PrintAndLogEx(ERR
, "Error: Key not found, exiting");
885 const struct tlv
*sda_tlv
= tlvdb_get(tlv
, 0x21, NULL
);
886 if (!sda_tlv
|| sda_tlv
->len
< 1) {
887 PrintAndLogEx(ERR
, "Error: Can't find input list for Offline Data Authentication, exiting");
892 struct emv_pk
*issuer_pk
= emv_pki_recover_issuer_cert(pk
, tlv
);
894 PrintAndLogEx(ERR
, "Error: Issuer certificate not found, exiting");
899 PrintAndLogEx(SUCCESS
, "Issuer Public key recovered RID " _YELLOW_("%s") " IDX " _YELLOW_("%02hhx") " CSN " _YELLOW_("%s"),
900 sprint_hex(issuer_pk
->rid
, 5),
902 sprint_hex(issuer_pk
->serial
, 3)
905 struct emv_pk
*icc_pk
= emv_pki_recover_icc_cert(issuer_pk
, tlv
, sda_tlv
);
907 PrintAndLogEx(ERR
, "Error: ICC certificate not found, exiting");
909 emv_pk_free(issuer_pk
);
913 PrintAndLogEx(SUCCESS
, "ICC Public key recovered. RID " _YELLOW_("%s") " IDX " _YELLOW_("%02hhx") " CSN " _YELLOW_("%s"),
914 sprint_hex(icc_pk
->rid
, 5),
916 sprint_hex(icc_pk
->serial
, 3)
919 // Signed Static Application Data (SSAD) check
920 const struct tlv
*ssad_tlv
= tlvdb_get(tlv
, 0x93, NULL
);
921 if (ssad_tlv
&& ssad_tlv
->len
> 1) {
922 struct tlvdb
*dac_db
= emv_pki_recover_dac(issuer_pk
, tlv
, sda_tlv
);
924 const struct tlv
*dac_tlv
= tlvdb_get(dac_db
, 0x9f45, NULL
);
925 PrintAndLogEx(SUCCESS
, "Signed Static Application Data (SSAD) verified (%s) (%02hhx:%02hhx)", _GREEN_("ok"), dac_tlv
->value
[0], dac_tlv
->value
[1]);
926 tlvdb_add(tlv
, dac_db
);
928 PrintAndLogEx(ERR
, "Error: Signed Static Application Data (SSAD) verify error");
930 emv_pk_free(issuer_pk
);
936 PrintAndLogEx(INFO
, "* * Check Signed Dynamic Application Data (SDAD)");
937 struct tlvdb
*idn_db
= emv_pki_perform_cda_ex(icc_pk
, tlv
, ac_tlv
,
938 pdol_data_tlv
, // pdol
939 ac_data_tlv
, // cdol1
943 const struct tlv
*idn_tlv
= tlvdb_get(idn_db
, 0x9f4c, NULL
);
944 PrintAndLogEx(INFO
, "IDN (ICC Dynamic Number) [%zu] %s", idn_tlv
->len
, sprint_hex_inrow(idn_tlv
->value
, idn_tlv
->len
));
945 PrintAndLogEx(SUCCESS
, "CDA verified (%s)", _GREEN_("ok"));
946 tlvdb_add(tlv
, idn_db
);
948 PrintAndLogEx(ERR
, "ERROR: CDA verify error");
952 emv_pk_free(issuer_pk
);
957 int RecoveryCertificates(struct tlvdb
*tlvRoot
, json_t
*root
) {
958 struct emv_pk
*pk
= get_ca_pk(tlvRoot
);
960 PrintAndLogEx(ERR
, "ERROR: Key not found, exiting");
964 struct emv_pk
*issuer_pk
= emv_pki_recover_issuer_cert(pk
, tlvRoot
);
967 PrintAndLogEx(WARNING
, "WARNING: Issuer certificate not found, exiting");
971 PrintAndLogEx(SUCCESS
, "Issuer Public key recovered RID " _YELLOW_("%s") " IDX " _YELLOW_("%02hhx") " CSN " _YELLOW_("%s"),
972 sprint_hex(issuer_pk
->rid
, 5),
974 sprint_hex(issuer_pk
->serial
, 3)
977 JsonSaveBufAsHex(root
, "$.ApplicationData.RID", issuer_pk
->rid
, 5);
979 char *issuer_pk_c
= emv_pk_dump_pk(issuer_pk
);
980 JsonSaveStr(root
, "$.ApplicationData.IssuerPublicKeyDec", issuer_pk_c
);
981 JsonSaveBufAsHex(root
, "$.ApplicationData.IssuerPublicKeyModulus", issuer_pk
->modulus
, issuer_pk
->mlen
);
984 const struct tlv
*sda_tlv
= tlvdb_get(tlvRoot
, 0x21, NULL
);
985 struct emv_pk
*icc_pk
= emv_pki_recover_icc_cert(issuer_pk
, tlvRoot
, sda_tlv
);
988 emv_pk_free(issuer_pk
);
989 PrintAndLogEx(WARNING
, "WARNING: ICC certificate not found, exiting");
993 PrintAndLogEx(SUCCESS
, "ICC Public key recovered RID " _YELLOW_("%s") " IDX " _YELLOW_("%02hhx") " CSN " _YELLOW_("%s"),
994 sprint_hex(icc_pk
->rid
, 5),
996 sprint_hex(icc_pk
->serial
, 3)
999 char *icc_pk_c
= emv_pk_dump_pk(icc_pk
);
1000 JsonSaveStr(root
, "$.ApplicationData.ICCPublicKeyDec", icc_pk_c
);
1001 JsonSaveBufAsHex(root
, "$.ApplicationData.ICCPublicKeyModulus", icc_pk
->modulus
, icc_pk
->mlen
);