]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/emv/emvcore.c
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 //-----------------------------------------------------------------------------
13 // Got from here. Thanks)
14 // https://eftlab.co.uk/index.php/site-map/knowledge-base/211-emv-aid-rid-pix
15 static const char *PSElist
[] = {
16 "325041592E5359532E4444463031", // 2PAY.SYS.DDF01 - Visa Proximity Payment System Environment - PPSE
17 "315041592E5359532E4444463031" // 1PAY.SYS.DDF01 - Visa Payment System Environment - PSE
19 static const size_t PSElistLen
= sizeof(PSElist
)/sizeof(char*);
22 enum CardPSVendor vendor
;
26 static const TAIDList AIDlist
[] = {
28 { CV_VISA
, "A00000000305076010"}, // VISA ELO Credit
29 { CV_VISA
, "A0000000031010" }, // VISA Debit/Credit (Classic)
30 { CV_VISA
, "A000000003101001" }, // VISA Credit
31 { CV_VISA
, "A000000003101002" }, // VISA Debit
32 { CV_VISA
, "A0000000032010" }, // VISA Electron
33 { CV_VISA
, "A0000000032020" }, // VISA
34 { CV_VISA
, "A0000000033010" }, // VISA Interlink
35 { CV_VISA
, "A0000000034010" }, // VISA Specific
36 { CV_VISA
, "A0000000035010" }, // VISA Specific
37 { CV_VISA
, "A0000000036010" }, // Domestic Visa Cash Stored Value
38 { CV_VISA
, "A0000000036020" }, // International Visa Cash Stored Value
39 { CV_VISA
, "A0000000038002" }, // VISA Auth, VisaRemAuthen EMV-CAP (DPA)
40 { CV_VISA
, "A0000000038010" }, // VISA Plus
41 { CV_VISA
, "A0000000039010" }, // VISA Loyalty
42 { CV_VISA
, "A000000003999910" }, // VISA Proprietary ATM
44 { CV_VISA
, "A000000098" }, // Debit Card
45 { CV_VISA
, "A0000000980848" }, // Debit Card
46 // Mastercard International
47 { CV_MASTERCARD
, "A00000000401" }, // MasterCard PayPass
48 { CV_MASTERCARD
, "A0000000041010" }, // MasterCard Credit
49 { CV_MASTERCARD
, "A00000000410101213" }, // MasterCard Credit
50 { CV_MASTERCARD
, "A00000000410101215" }, // MasterCard Credit
51 { CV_MASTERCARD
, "A0000000042010" }, // MasterCard Specific
52 { CV_MASTERCARD
, "A0000000043010" }, // MasterCard Specific
53 { CV_MASTERCARD
, "A0000000043060" }, // Maestro (Debit)
54 { CV_MASTERCARD
, "A000000004306001" }, // Maestro (Debit)
55 { CV_MASTERCARD
, "A0000000044010" }, // MasterCard Specific
56 { CV_MASTERCARD
, "A0000000045010" }, // MasterCard Specific
57 { CV_MASTERCARD
, "A0000000046000" }, // Cirrus
58 { CV_MASTERCARD
, "A0000000048002" }, // SecureCode Auth EMV-CAP
59 { CV_MASTERCARD
, "A0000000049999" }, // MasterCard PayPass
61 { CV_AMERICANEXPRESS
, "A000000025" },
62 { CV_AMERICANEXPRESS
, "A0000000250000" },
63 { CV_AMERICANEXPRESS
, "A00000002501" },
64 { CV_AMERICANEXPRESS
, "A000000025010402" },
65 { CV_AMERICANEXPRESS
, "A000000025010701" },
66 { CV_AMERICANEXPRESS
, "A000000025010801" },
67 // Groupement des Cartes Bancaires "CB"
68 { CV_CB
, "A0000000421010" }, // Cartes Bancaire EMV Card
69 { CV_CB
, "A0000000422010" },
70 { CV_CB
, "A0000000423010" },
71 { CV_CB
, "A0000000424010" },
72 { CV_CB
, "A0000000425010" },
74 { CV_JCB
, "A00000006510" }, // JCB
75 { CV_JCB
, "A0000000651010" }, // JCB J Smart Credit
77 { CV_OTHER
, "A0000001544442" }, // Banricompras Debito - Banrisul - Banco do Estado do Rio Grande do SUL - S.A.
78 { CV_OTHER
, "F0000000030001" }, // BRADESCO
79 { CV_OTHER
, "A0000005241010" }, // RuPay - RuPay
80 { CV_OTHER
, "D5780000021010" } // Bankaxept - Bankaxept
82 static const size_t AIDlistLen
= sizeof(AIDlist
)/sizeof(TAIDList
);
84 static bool APDULogging
= false;
85 void SetAPDULogging(bool logging
) {
86 APDULogging
= logging
;
89 enum CardPSVendor
GetCardPSVendor(uint8_t * AID
, size_t AIDlen
) {
94 hex_to_buffer((uint8_t *)buf
, AID
, AIDlen
, sizeof(buf
) - 1, 0, 0, true);
96 for(int i
= 0; i
< AIDlistLen
; i
++) {
97 if (strncmp(AIDlist
[i
].aid
, buf
, strlen(AIDlist
[i
].aid
)) == 0){
98 return AIDlist
[i
].vendor
;
105 static bool print_cb(void *data
, const struct tlv
*tlv
, int level
, bool is_leaf
) {
106 emv_tag_dump(tlv
, stdout
, level
);
108 dump_buffer(tlv
->value
, tlv
->len
, stdout
, level
);
114 void TLVPrintFromBuffer(uint8_t *data
, int datalen
) {
115 struct tlvdb
*t
= NULL
;
116 t
= tlvdb_parse_multi(data
, datalen
);
118 PrintAndLog("-------------------- TLV decoded --------------------");
120 tlvdb_visit(t
, print_cb
, NULL
, 0);
123 PrintAndLog("TLV ERROR: Can't parse response as TLV tree.");
127 void TLVPrintFromTLVLev(struct tlvdb
*tlv
, int level
) {
131 tlvdb_visit(tlv
, print_cb
, NULL
, level
);
134 void TLVPrintFromTLV(struct tlvdb
*tlv
) {
135 TLVPrintFromTLVLev(tlv
, 0);
138 void TLVPrintAIDlistFromSelectTLV(struct tlvdb
*tlv
) {
139 PrintAndLog("|------------------|--------|-------------------------|");
140 PrintAndLog("| AID |Priority| Name |");
141 PrintAndLog("|------------------|--------|-------------------------|");
143 struct tlvdb
*ttmp
= tlvdb_find(tlv
, 0x6f);
145 PrintAndLog("| none |");
148 const struct tlv
*tgAID
= tlvdb_get_inchild(ttmp
, 0x84, NULL
);
149 const struct tlv
*tgName
= tlvdb_get_inchild(ttmp
, 0x50, NULL
);
150 const struct tlv
*tgPrio
= tlvdb_get_inchild(ttmp
, 0x87, NULL
);
153 PrintAndLog("|%s| %s |%s|",
154 sprint_hex_inrow_ex(tgAID
->value
, tgAID
->len
, 18),
155 (tgPrio
) ? sprint_hex(tgPrio
->value
, 1) : " ",
156 (tgName
) ? sprint_ascii_ex(tgName
->value
, tgName
->len
, 25) : " ");
158 ttmp
= tlvdb_find_next(ttmp
, 0x6f);
161 PrintAndLog("|------------------|--------|-------------------------|");
164 struct tlvdb
*GetPANFromTrack2(const struct tlv
*track2
) {
165 char track2Hex
[200] = {0};
166 uint8_t PAN
[100] = {0};
168 char *tmp
= track2Hex
;
173 for (int i
= 0; i
< track2
->len
; ++i
, tmp
+= 2)
174 sprintf(tmp
, "%02x", (unsigned int)track2
->value
[i
]);
176 int posD
= strchr(track2Hex
, 'd') - track2Hex
;
181 if (strlen(track2Hex
) % 2) {
182 track2Hex
[posD
] = 'F';
183 track2Hex
[posD
+ 1] = '\0';
186 param_gethex_to_eol(track2Hex
, 0, PAN
, sizeof(PAN
), &PANlen
);
188 return tlvdb_fixed(0x5a, PANlen
, PAN
);
191 struct tlvdb
*GetdCVVRawFromTrack2(const struct tlv
*track2
) {
192 char track2Hex
[200] = {0};
193 char dCVVHex
[100] = {0};
194 uint8_t dCVV
[100] = {0};
196 const int PINlen
= 5; // must calculated from 9F67 MSD Offset but i have not seen this tag)
197 char *tmp
= track2Hex
;
202 for (int i
= 0; i
< track2
->len
; ++i
, tmp
+= 2)
203 sprintf(tmp
, "%02x", (unsigned int)track2
->value
[i
]);
205 int posD
= strchr(track2Hex
, 'd') - track2Hex
;
209 memset(dCVVHex
, '0', 32);
211 memcpy(dCVVHex
+ 0, track2Hex
+ posD
+ PINlen
+ 11, 4);
213 memcpy(dCVVHex
+ 4, track2Hex
, 5);
215 memcpy(dCVVHex
+ 9, track2Hex
+ posD
+ 1, 4);
217 memcpy(dCVVHex
+ 13, track2Hex
+ posD
+ 5, 3);
219 param_gethex_to_eol(dCVVHex
, 0, dCVV
, sizeof(dCVV
), &dCVVlen
);
221 return tlvdb_fixed(0x02, dCVVlen
, dCVV
);
224 int EMVExchangeEx(bool ActivateField
, bool LeaveFieldON
, sAPDU apdu
, uint8_t *Result
, size_t MaxResultLen
, size_t *ResultLen
, uint16_t *sw
, struct tlvdb
*tlv
) {
225 uint8_t data
[APDU_RES_LEN
] = {0};
235 memcpy(data
, &apdu
, 5);
237 memcpy(&data
[5], apdu
.data
, apdu
.Lc
);
240 PrintAndLog(">>>> %s", sprint_hex(data
, 6 + apdu
.Lc
));
242 // 6 byes + data = INS + CLA + P1 + P2 + Lc + <data = Nc> + Le
243 int res
= ExchangeAPDU14a(data
, 6 + apdu
.Lc
, ActivateField
, LeaveFieldON
, Result
, (int)MaxResultLen
, (int *)ResultLen
);
246 PrintAndLog("<<<< %s", sprint_hex(Result
, *ResultLen
));
253 isw
= Result
[*ResultLen
] * 0x0100 + Result
[*ResultLen
+ 1];
259 PrintAndLog("APDU(%02x%02x) ERROR: [%4X] %s", apdu
.CLA
, apdu
.INS
, isw
, GetAPDUCodeDescription(*sw
>> 8, *sw
& 0xff));
265 struct tlvdb
*t
= tlvdb_parse_multi(Result
, *ResultLen
);
272 int EMVExchange(bool LeaveFieldON
, sAPDU apdu
, uint8_t *Result
, size_t MaxResultLen
, size_t *ResultLen
, uint16_t *sw
, struct tlvdb
*tlv
) {
273 return EMVExchangeEx(false, LeaveFieldON
, apdu
, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
276 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
) {
277 return EMVExchangeEx(ActivateField
, LeaveFieldON
, (sAPDU
){0x00, 0xa4, 0x04, 0x00, AIDLen
, AID
}, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
280 int EMVSelectPSE(bool ActivateField
, bool LeaveFieldON
, uint8_t PSENum
, uint8_t *Result
, size_t MaxResultLen
, size_t *ResultLen
, uint16_t *sw
) {
281 uint8_t buf
[APDU_AID_LEN
] = {0};
287 param_gethex_to_eol(PSElist
[1], 0, buf
, sizeof(buf
), &len
);
290 param_gethex_to_eol(PSElist
[0], 0, buf
, sizeof(buf
), &len
);
297 res
= EMVSelect(ActivateField
, LeaveFieldON
, buf
, len
, Result
, MaxResultLen
, ResultLen
, sw
, NULL
);
302 int EMVSearchPSE(bool ActivateField
, bool LeaveFieldON
, bool decodeTLV
, struct tlvdb
*tlv
) {
303 uint8_t data
[APDU_RES_LEN
] = {0};
309 res
= EMVSelectPSE(ActivateField
, true, 2, data
, sizeof(data
), &datalen
, &sw
);
312 struct tlvdb
*t
= NULL
;
313 t
= tlvdb_parse_multi(data
, datalen
);
316 struct tlvdb
*ttmp
= tlvdb_find_path(t
, (tlv_tag_t
[]){0x6f, 0xa5, 0xbf0c, 0x61, 0x00});
318 PrintAndLog("PPSE don't have records.");
321 const struct tlv
*tgAID
= tlvdb_get_inchild(ttmp
, 0x4f, NULL
);
323 res
= EMVSelect(false, true, (uint8_t *)tgAID
->value
, tgAID
->len
, data
, sizeof(data
), &datalen
, &sw
, tlv
);
325 // retry if error and not returned sw error
326 if (res
&& res
!= 5) {
330 // card select error, proxmark error
332 PrintAndLog("Exit...");
337 PrintAndLog("Retry failed [%s]. Skiped...", sprint_hex_inrow(tgAID
->value
, tgAID
->len
));
341 ttmp
= tlvdb_find_next(ttmp
, 0x61);
348 PrintAndLog("%s:", sprint_hex_inrow(tgAID
->value
, tgAID
->len
));
349 TLVPrintFromBuffer(data
, datalen
);
353 ttmp
= tlvdb_find_next(ttmp
, 0x61);
358 PrintAndLog("PPSE ERROR: Can't get TLV from response.");
361 PrintAndLog("PPSE ERROR: Can't select PPSE AID. Error: %d", res
);
370 int EMVSearch(bool ActivateField
, bool LeaveFieldON
, bool decodeTLV
, struct tlvdb
*tlv
) {
371 uint8_t aidbuf
[APDU_AID_LEN
] = {0};
373 uint8_t data
[APDU_RES_LEN
] = {0};
379 for(int i
= 0; i
< AIDlistLen
; i
++) {
380 param_gethex_to_eol(AIDlist
[i
].aid
, 0, aidbuf
, sizeof(aidbuf
), &aidlen
);
381 res
= EMVSelect((i
== 0) ? ActivateField
: false, (i
== AIDlistLen
- 1) ? LeaveFieldON
: true, aidbuf
, aidlen
, data
, sizeof(data
), &datalen
, &sw
, tlv
);
382 // retry if error and not returned sw error
383 if (res
&& res
!= 5) {
387 // card select error, proxmark error
389 PrintAndLog("Exit...");
394 PrintAndLog("Retry failed [%s]. Skiped...", AIDlist
[i
].aid
);
404 PrintAndLog("%s:", AIDlist
[i
].aid
);
405 TLVPrintFromBuffer(data
, datalen
);
412 int EMVSelectApplication(struct tlvdb
*tlv
, uint8_t *AID
, size_t *AIDlen
) {
413 // check priority. 0x00 - highest
418 struct tlvdb
*ttmp
= tlvdb_find(tlv
, 0x6f);
423 const struct tlv
*tgAID
= tlvdb_get_inchild(ttmp
, 0x84, NULL
);
424 const struct tlv
*tgPrio
= tlvdb_get_inchild(ttmp
, 0x87, NULL
);
430 int pt
= bytes_to_num((uint8_t*)tgPrio
->value
, (tgPrio
->len
< 2) ? tgPrio
->len
: 2);
434 memcpy(AID
, tgAID
->value
, tgAID
->len
);
435 *AIDlen
= tgAID
->len
;
438 // takes the first application from list wo priority
440 memcpy(AID
, tgAID
->value
, tgAID
->len
);
441 *AIDlen
= tgAID
->len
;
445 ttmp
= tlvdb_find_next(ttmp
, 0x6f);
451 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
) {
452 return EMVExchange(LeaveFieldON
, (sAPDU
){0x80, 0xa8, 0x00, 0x00, PDOLLen
, PDOL
}, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
455 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
) {
456 return EMVExchange(LeaveFieldON
, (sAPDU
){0x00, 0xb2, SFIrec
, (SFI
<< 3) | 0x04, 0, NULL
}, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
459 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
) {
460 return EMVExchange(LeaveFieldON
, (sAPDU
){0x80, 0xae, RefControl
, 0x00, CDOLLen
, CDOL
}, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
463 int EMVGenerateChallenge(bool LeaveFieldON
, uint8_t *Result
, size_t MaxResultLen
, size_t *ResultLen
, uint16_t *sw
, struct tlvdb
*tlv
) {
464 return EMVExchange(LeaveFieldON
, (sAPDU
){0x00, 0x84, 0x00, 0x00, 0x00, NULL
}, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);
467 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
) {
468 return EMVExchange(LeaveFieldON
, (sAPDU
){0x80, 0x2a, 0x8e, 0x80, UDOLlen
, UDOL
}, Result
, MaxResultLen
, ResultLen
, sw
, tlv
);