]> git.zerfleddert.de Git - proxmark3-svn/blame_incremental - client/emv/emvcore.c
part of changes
[proxmark3-svn] / client / emv / emvcore.c
... / ...
CommitLineData
1//-----------------------------------------------------------------------------
2// Copyright (C) 2017 Merlok
3//
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
6// the license.
7//-----------------------------------------------------------------------------
8// EMV core functions
9//-----------------------------------------------------------------------------
10
11#include "emvcore.h"
12
13// Got from here. Thanks)
14// https://eftlab.co.uk/index.php/site-map/knowledge-base/211-emv-aid-rid-pix
15const char *PSElist [] = {
16 "325041592E5359532E4444463031", // 2PAY.SYS.DDF01 - Visa Proximity Payment System Environment - PPSE
17 "315041592E5359532E4444463031" // 1PAY.SYS.DDF01 - Visa Payment System Environment - PSE
18};
19const size_t PSElistLen = sizeof(PSElist)/sizeof(char*);
20
21const char *AIDlist [] = {
22 // Visa International
23 "A00000000305076010", // VISA ELO Credit
24 "A0000000031010", // VISA Debit/Credit (Classic)
25 "A0000000031010", // ddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
26 "A000000003101001", // VISA Credit
27 "A000000003101002", // VISA Debit
28 "A0000000032010", // VISA Electron
29 "A0000000032020", // VISA
30 "A0000000033010", // VISA Interlink
31 "A0000000034010", // VISA Specific
32 "A0000000035010", // VISA Specific
33 "A0000000036010", // Domestic Visa Cash Stored Value
34 "A0000000036020", // International Visa Cash Stored Value
35 "A0000000038002", // VISA Auth, VisaRemAuthen EMV-CAP (DPA)
36 "A0000000038010", // VISA Plus
37 "A0000000039010", // VISA Loyalty
38 "A000000003999910", // VISA Proprietary ATM
39 // Visa USA
40 "A000000098", // Debit Card
41 "A0000000980848", // Debit Card
42 // Mastercard International
43 "A00000000401", // MasterCard PayPass
44 "A0000000041010", // MasterCard Credit
45 "A00000000410101213", // MasterCard Credit
46 "A00000000410101215", // MasterCard Credit
47 "A0000000042010", // MasterCard Specific
48 "A0000000043010", // MasterCard Specific
49 "A0000000043060", // Maestro (Debit)
50 "A000000004306001", // Maestro (Debit)
51 "A0000000044010", // MasterCard Specific
52 "A0000000045010", // MasterCard Specific
53 "A0000000046000", // Cirrus
54 "A0000000048002", // SecureCode Auth EMV-CAP
55 "A0000000049999", // MasterCard PayPass
56 // American Express
57 "A000000025",
58 "A0000000250000",
59 "A00000002501",
60 "A000000025010402",
61 "A000000025010701",
62 "A000000025010801",
63 // Groupement des Cartes Bancaires "CB"
64 "A0000000421010", // Cartes Bancaire EMV Card
65 "A0000000422010",
66 "A0000000423010",
67 "A0000000424010",
68 "A0000000425010",
69 // JCB CO., LTD.
70 "A00000006510", // JCB
71 "A0000000651010", // JCB J Smart Credit
72 "A0000001544442", // Banricompras Debito - Banrisul - Banco do Estado do Rio Grande do SUL - S.A.
73 "F0000000030001", // BRADESCO
74 "A0000005241010", // RuPay - RuPay
75 "D5780000021010" // Bankaxept - Bankaxept
76};
77const size_t AIDlistLen = sizeof(AIDlist)/sizeof(char*);
78
79static bool APDULogging = false;
80void SetAPDULogging(bool logging) {
81 APDULogging = logging;
82}
83
84static bool print_cb(void *data, const struct tlv *tlv, int level, bool is_leaf) {
85 emv_tag_dump(tlv, stdout, level);
86 if (is_leaf) {
87 dump_buffer(tlv->value, tlv->len, stdout, level);
88 }
89
90 return true;
91}
92
93void TLVPrintFromBuffer(uint8_t *data, int datalen) {
94 struct tlvdb *t = NULL;
95 t = tlvdb_parse_multi(data, datalen);
96 if (t) {
97 PrintAndLog("-------------------- TLV decoded --------------------");
98
99 tlvdb_visit(t, print_cb, NULL, 0);
100 tlvdb_free(t);
101 } else {
102 PrintAndLog("TLV ERROR: Can't parse response as TLV tree.");
103 }
104}
105
106void TLVPrintFromTLV(struct tlvdb *tlv) {
107 if (!tlv)
108 return;
109
110 tlvdb_visit(tlv, print_cb, NULL, 0);
111}
112
113void TLVPrintAIDlistFromSelectTLV(struct tlvdb *tlv) {
114 PrintAndLog("|------------------|--------|-------------------------|");
115 PrintAndLog("| AID |Priority| Name |");
116 PrintAndLog("|------------------|--------|-------------------------|");
117
118 struct tlvdb *ttmp = tlvdb_find(tlv, 0x6f);
119 if (!ttmp)
120 PrintAndLog("| none |");
121
122 while (ttmp) {
123 const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x84, NULL);
124 const struct tlv *tgName = tlvdb_get_inchild(ttmp, 0x50, NULL);
125 const struct tlv *tgPrio = tlvdb_get_inchild(ttmp, 0x87, NULL);
126 if (!tgAID)
127 break;
128 PrintAndLog("|%s| %s |%s|",
129 sprint_hex_inrow_ex(tgAID->value, tgAID->len, 18),
130 (tgPrio) ? sprint_hex(tgPrio->value, 1) : " ",
131 (tgName) ? sprint_ascii_ex(tgName->value, tgName->len, 25) : " ");
132
133 ttmp = tlvdb_find_next(ttmp, 0x6f);
134 }
135
136 PrintAndLog("|------------------|--------|-------------------------|");
137}
138
139
140int 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) {
141 uint8_t data[APDU_RES_LEN] = {0};
142 *ResultLen = 0;
143 if (sw) *sw = 0;
144 uint16_t isw = 0;
145
146 // select APDU
147 data[0] = 0x00;
148 data[1] = 0xA4;
149 data[2] = 0x04;
150 data[3] = 0x00;
151 data[4] = AIDLen;
152 memcpy(&data[5], AID, AIDLen);
153
154 if (ActivateField)
155 DropField();
156
157 if (APDULogging)
158 PrintAndLog(">>>> %s", sprint_hex(data, AIDLen + 6));
159
160 int res = ExchangeAPDU14a(data, AIDLen + 6, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
161
162 if (APDULogging)
163 PrintAndLog("<<<< %s", sprint_hex(Result, *ResultLen));
164
165 if (res) {
166 return res;
167 }
168
169 if (*ResultLen < 2) {
170 PrintAndLog("SELECT ERROR: returned %d bytes", *ResultLen);
171 return 5;
172 }
173
174 *ResultLen -= 2;
175 isw = Result[*ResultLen] * 0x0100 + Result[*ResultLen + 1];
176 if (sw)
177 *sw = isw;
178
179 if (isw != 0x9000) {
180 if (APDULogging)
181 PrintAndLog("SELECT ERROR: [%4X] %s", isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xff));
182 return 5;
183 }
184
185 // add to tlv tree
186 if (tlv) {
187 struct tlvdb *t = tlvdb_parse_multi(Result, *ResultLen);
188 tlvdb_add(tlv, t);
189 }
190
191 return 0;
192}
193
194int EMVSelectPSE(bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) {
195 uint8_t buf[APDU_AID_LEN] = {0};
196 *ResultLen = 0;
197 int len = 0;
198 int res = 0;
199 switch (PSENum) {
200 case 1:
201 param_gethex_to_eol(PSElist[1], 0, buf, sizeof(buf), &len);
202 break;
203 case 2:
204 param_gethex_to_eol(PSElist[0], 0, buf, sizeof(buf), &len);
205 break;
206 default:
207 return -1;
208 }
209
210 // select
211 res = EMVSelect(ActivateField, LeaveFieldON, buf, len, Result, MaxResultLen, ResultLen, sw, NULL);
212
213 return res;
214}
215
216int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) {
217 uint8_t data[APDU_RES_LEN] = {0};
218 size_t datalen = 0;
219 uint16_t sw = 0;
220 int res;
221
222 // select PPSE
223 res = EMVSelectPSE(ActivateField, true, 2, data, sizeof(data), &datalen, &sw);
224
225 if (!res){
226 struct tlvdb *t = NULL;
227 t = tlvdb_parse_multi(data, datalen);
228 if (t) {
229 int retrycnt = 0;
230 struct tlvdb *ttmp = tlvdb_find_path(t, (tlv_tag_t[]){0x6f, 0xa5, 0xbf0c, 0x61, 0x00});
231 if (!ttmp)
232 PrintAndLog("PPSE don't have records.");
233
234 while (ttmp) {
235 const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x4f, NULL);
236 if (tgAID) {
237 res = EMVSelect(false, true, (uint8_t *)tgAID->value, tgAID->len, data, sizeof(data), &datalen, &sw, tlv);
238
239 // retry if error and not returned sw error
240 if (res && res != 5) {
241 if (++retrycnt < 3){
242 continue;
243 } else {
244 // card select error, proxmark error
245 if (res == 1) {
246 PrintAndLog("Exit...");
247 return 1;
248 }
249
250 retrycnt = 0;
251 PrintAndLog("Retry failed [%s]. Skiped...", sprint_hex_inrow(tgAID->value, tgAID->len));
252 }
253
254 // next element
255 ttmp = tlvdb_find_next(ttmp, 0x61);
256 continue;
257 }
258 retrycnt = 0;
259
260 // all is ok
261 if (decodeTLV){
262 PrintAndLog("%s:", sprint_hex_inrow(tgAID->value, tgAID->len));
263 TLVPrintFromBuffer(data, datalen);
264 }
265 }
266
267 ttmp = tlvdb_find_next(ttmp, 0x61);
268 }
269
270 tlvdb_free(t);
271 } else {
272 PrintAndLog("PPSE ERROR: Can't get TLV from response.");
273 }
274 } else {
275 PrintAndLog("PPSE ERROR: Can't select PPSE AID. Error: %d", res);
276 }
277
278 if(!LeaveFieldON)
279 DropField();
280
281 return res;
282}
283
284int EMVSearch(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) {
285 uint8_t aidbuf[APDU_AID_LEN] = {0};
286 int aidlen = 0;
287 uint8_t data[APDU_RES_LEN] = {0};
288 size_t datalen = 0;
289 uint16_t sw = 0;
290
291 int res = 0;
292 int retrycnt = 0;
293 for(int i = 0; i < AIDlistLen; i ++) {
294 param_gethex_to_eol(AIDlist[i], 0, aidbuf, sizeof(aidbuf), &aidlen);
295 res = EMVSelect((i == 0) ? ActivateField : false, (i == AIDlistLen - 1) ? LeaveFieldON : true, aidbuf, aidlen, data, sizeof(data), &datalen, &sw, tlv);
296 // retry if error and not returned sw error
297 if (res && res != 5) {
298 if (++retrycnt < 3){
299 i--;
300 } else {
301 // card select error, proxmark error
302 if (res == 1) {
303 PrintAndLog("Exit...");
304 return 1;
305 }
306
307 retrycnt = 0;
308 PrintAndLog("Retry failed [%s]. Skiped...", AIDlist[i]);
309 }
310 continue;
311 }
312 retrycnt = 0;
313
314 if (res)
315 continue;
316
317 if (decodeTLV){
318 PrintAndLog("%s:", AIDlist[i]);
319 TLVPrintFromBuffer(data, datalen);
320 }
321 }
322
323 return 0;
324}
325
326int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen) {
327 // needs to check priority. 0x00 - highest
328 int prio = 0xffff;
329
330 *AIDlen = 0;
331
332 struct tlvdb *ttmp = tlvdb_find(tlv, 0x6f);
333 if (!ttmp)
334 return 1;
335
336 while (ttmp) {
337 const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x84, NULL);
338 const struct tlv *tgPrio = tlvdb_get_inchild(ttmp, 0x87, NULL);
339
340 if (!tgAID)
341 break;
342
343 if (tgPrio) {
344 int pt = bytes_to_num((uint8_t*)tgPrio->value, (tgPrio->len < 2) ? tgPrio->len : 2);
345 if (pt < prio) {
346 prio = pt;
347
348 memcpy(AID, tgAID->value, tgAID->len);
349 *AIDlen = tgAID->len;
350 }
351 } else {
352 // takes the first application from list wo priority
353 if (!*AIDlen) {
354 memcpy(AID, tgAID->value, tgAID->len);
355 *AIDlen = tgAID->len;
356 }
357 }
358
359 ttmp = tlvdb_find_next(ttmp, 0x6f);
360 }
361
362 return 0;
363}
364
365int EMVGPO(bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
366 uint8_t data[APDU_RES_LEN] = {0};
367 *ResultLen = 0;
368 if (sw) *sw = 0;
369 uint16_t isw = 0;
370
371 // GPO APDU
372 data[0] = 0x80;
373 data[1] = 0xA8;
374 data[2] = 0x00;
375 data[3] = 0x00;
376 data[4] = PDOLLen;
377 if (PDOL)
378 memcpy(&data[5], PDOL, PDOLLen);
379
380
381 if (APDULogging)
382 PrintAndLog(">>>> %s", sprint_hex(data, PDOLLen + 5));
383
384 int res = ExchangeAPDU14a(data, PDOLLen + 5, false, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
385
386 if (APDULogging)
387 PrintAndLog("<<<< %s", sprint_hex(Result, *ResultLen));
388
389 if (res) {
390 return res;
391 }
392
393 if (*ResultLen < 2) {
394 PrintAndLog("GPO ERROR: returned %d bytes", *ResultLen);
395 return 5;
396 }
397
398 *ResultLen -= 2;
399 isw = Result[*ResultLen] * 0x0100 + Result[*ResultLen + 1];
400 if (sw)
401 *sw = isw;
402
403 if (isw != 0x9000) {
404 if (APDULogging)
405 PrintAndLog("GPO ERROR: [%4X] %s", isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xff));
406 return 5;
407 }
408
409 // add to tlv tree
410 if (tlv) {
411 struct tlvdb *t = tlvdb_parse_multi(Result, *ResultLen);
412 tlvdb_add(tlv, t);
413 }
414
415 return 0;
416}
417
418int EMVReadRecord(bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
419 uint8_t data[10] = {0};
420 *ResultLen = 0;
421 if (sw) *sw = 0;
422 uint16_t isw = 0;
423
424 // read record APDU
425 data[0] = 0x00;
426 data[1] = 0xb2;
427 data[2] = SFIrec;
428 data[3] = (SFI << 3) | 0x04;
429 data[4] = 0;
430
431 if (APDULogging)
432 PrintAndLog(">>>> %s", sprint_hex(data, 5));
433
434 int res = ExchangeAPDU14a(data, 5, false, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
435
436 if (APDULogging)
437 PrintAndLog("<<<< %s", sprint_hex(Result, *ResultLen));
438
439 if (res) {
440 return res;
441 }
442
443 *ResultLen -= 2;
444 isw = Result[*ResultLen] * 0x0100 + Result[*ResultLen + 1];
445 if (sw)
446 *sw = isw;
447
448 if (isw != 0x9000) {
449 if (APDULogging)
450 PrintAndLog("Read record ERROR: [%4X] %s", isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xff));
451 return 5;
452 }
453
454 // add to tlv tree
455 if (tlv) {
456 struct tlvdb *t = tlvdb_parse_multi(Result, *ResultLen);
457 tlvdb_add(tlv, t);
458 }
459
460 return 0;
461}
462
463
Impressum, Datenschutz