@@ -10,6 +10,9 @@ const PDOLValue pdol_merchant_type = {0x9F58, {0x01}}; // Merchant type indicato
10
10
const PDOLValue pdol_term_trans_qualifies = {
11
11
0x9F66 ,
12
12
{0x79 , 0x00 , 0x40 , 0x80 }}; // Terminal transaction qualifiers
13
+ const PDOLValue pdol_addtnl_term_qualifies = {
14
+ 0x9F40 ,
15
+ {0x79 , 0x00 , 0x40 , 0x80 }}; // Terminal transaction qualifiers
13
16
const PDOLValue pdol_amount_authorise = {
14
17
0x9F02 ,
15
18
{0x00 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 }}; // Amount, authorised
@@ -30,6 +33,7 @@ const PDOLValue* const pdol_values[] = {
30
33
& pdol_term_type ,
31
34
& pdol_merchant_type ,
32
35
& pdol_term_trans_qualifies ,
36
+ & pdol_addtnl_term_qualifies ,
33
37
& pdol_amount_authorise ,
34
38
& pdol_amount ,
35
39
& pdol_country_code ,
@@ -61,49 +65,121 @@ static const uint8_t pdol_ans[] = {0x77, 0x40, 0x82, 0x02, 0x20, 0x00, 0x57, 0x1
61
65
static void emv_trace (FuriHalNfcTxRxContext * tx_rx , const char * message ) {
62
66
if (furi_log_get_level () == FuriLogLevelTrace ) {
63
67
FURI_LOG_T (TAG , "%s" , message );
68
+ printf ("TX: " );
69
+ for (size_t i = 0 ; i < tx_rx -> tx_bits / 8 ; i ++ ) {
70
+ printf ("%02X " , tx_rx -> tx_data [i ]);
71
+ }
72
+ printf ("\r\nRX: " );
64
73
for (size_t i = 0 ; i < tx_rx -> rx_bits / 8 ; i ++ ) {
65
74
printf ("%02X " , tx_rx -> rx_data [i ]);
66
75
}
67
76
printf ("\r\n" );
68
77
}
69
78
}
70
79
71
- static uint16_t emv_parse_TLV (uint8_t * dest , uint8_t * src , uint16_t * idx ) {
72
- uint8_t len = src [* idx + 1 ];
73
- memcpy (dest , & src [* idx + 2 ], len );
74
- * idx = * idx + len + 1 ;
75
- return len ;
76
- }
77
-
78
- static bool emv_decode_search_tag_u16_r (uint16_t tag , uint8_t * buff , uint16_t * idx ) {
79
- if ((buff [* idx ] << 8 | buff [* idx + 1 ]) == tag ) {
80
- * idx = * idx + 3 ;
81
- return true;
82
- }
83
- return false;
84
- }
85
-
86
- bool emv_decode_ppse_response (uint8_t * buff , uint16_t len , EmvApplication * app ) {
80
+ static bool emv_decode_response (uint8_t * buff , uint16_t len , EmvApplication * app ) {
87
81
uint16_t i = 0 ;
88
- bool app_aid_found = false;
82
+ uint16_t tag = 0 , fb = 0 ;
83
+ uint16_t tlen = 0 ;
84
+ bool success = false;
89
85
90
86
while (i < len ) {
91
- if (buff [i ] == EMV_TAG_APP_TEMPLATE ) {
92
- uint8_t app_len = buff [++ i ];
93
- for (uint16_t j = i ; j < MIN (i + app_len , len - 1 ); j ++ ) {
94
- if (buff [j ] == EMV_TAG_AID ) {
95
- app_aid_found = true;
96
- app -> aid_len = buff [j + 1 ];
97
- emv_parse_TLV (app -> aid , buff , & j );
98
- } else if (buff [j ] == EMV_TAG_PRIORITY ) {
99
- emv_parse_TLV (& app -> priority , buff , & j );
87
+ fb = buff [i ]; // first byte
88
+ if ((fb & 31 ) == 31 ) { // 2-byte tag
89
+ tag = buff [i ] << 8 | buff [i + 1 ];
90
+ i ++ ;
91
+ FURI_LOG_T (TAG , " 2-byte TLV EMV tag: %x" , tag );
92
+ } else {
93
+ tag = buff [i ];
94
+ FURI_LOG_T (TAG , " 1-byte TLV EMV tag: %x" , tag );
95
+ }
96
+ i ++ ;
97
+ tlen = buff [i ];
98
+ if ((tlen & 128 ) == 128 ) { // long length value
99
+ i ++ ;
100
+ tlen = buff [i ];
101
+ FURI_LOG_T (TAG , " 2-byte TLV length: %d" , tlen );
102
+ } else {
103
+ FURI_LOG_T (TAG , " 1-byte TLV length: %d" , tlen );
104
+ }
105
+ i ++ ;
106
+ if ((fb & 32 ) == 32 ) { // "Constructed" -- contains more TLV data to parse
107
+ FURI_LOG_T (TAG , "Constructed TLV %x" , tag );
108
+ if (!emv_decode_response (& buff [i ], tlen , app )) {
109
+ printf ("Failed to decode response for %x \r\n" , tag );
110
+ // return false;
111
+ } else {
112
+ success = true;
113
+ }
114
+ } else {
115
+ switch (tag ) {
116
+ case EMV_TAG_AID :
117
+ app -> aid_len = tlen ;
118
+ memcpy (app -> aid , & buff [i ], tlen );
119
+ success = true;
120
+ FURI_LOG_T (TAG , "found EMV_TAG_AID %x" , tag );
121
+ break ;
122
+ case EMV_TAG_PRIORITY :
123
+ memcpy (& app -> priority , & buff [i ], tlen );
124
+ success = true;
125
+ break ;
126
+ case EMV_TAG_CARD_NAME :
127
+ memcpy (app -> name , & buff [i ], tlen );
128
+ app -> name [tlen ] = '\0' ;
129
+ app -> name_found = true;
130
+ success = true;
131
+ FURI_LOG_T (TAG , "found EMV_TAG_CARD_NAME %x : %s" , tag , app -> name );
132
+ break ;
133
+ case EMV_TAG_PDOL :
134
+ memcpy (app -> pdol .data , & buff [i ], tlen );
135
+ app -> pdol .size = tlen ;
136
+ success = true;
137
+ FURI_LOG_T (TAG , "found EMV_TAG_PDOL %x (len=%d)" , tag , tlen );
138
+ break ;
139
+ case EMV_TAG_AFL :
140
+ memcpy (app -> afl .data , & buff [i ], tlen );
141
+ app -> afl .size = tlen ;
142
+ success = true;
143
+ FURI_LOG_T (TAG , "found EMV_TAG_AFL %x (len=%d)" , tag , tlen );
144
+ break ;
145
+ case EMV_TAG_CARD_NUM : // Track 2 Equivalent Data. 0xD0 delimits PAN from expiry (YYMM)
146
+ for (int x = 1 ; x < tlen ; x ++ ) {
147
+ if (buff [i + x + 1 ] > 0xD0 ) {
148
+ memcpy (app -> card_number , & buff [i ], x + 1 );
149
+ app -> card_number_len = x + 1 ;
150
+ break ;
151
+ }
100
152
}
153
+ success = true;
154
+ FURI_LOG_T (
155
+ TAG ,
156
+ "found EMV_TAG_CARD_NUM %x (len=%d)" ,
157
+ EMV_TAG_CARD_NUM ,
158
+ app -> card_number_len );
159
+ break ;
160
+ case EMV_TAG_PAN :
161
+ memcpy (app -> card_number , & buff [i ], tlen );
162
+ app -> card_number_len = tlen ;
163
+ success = true;
164
+ break ;
165
+ case EMV_TAG_EXP_DATE :
166
+ app -> exp_year = buff [i ];
167
+ app -> exp_month = buff [i + 1 ];
168
+ success = true;
169
+ break ;
170
+ case EMV_TAG_CURRENCY_CODE :
171
+ app -> currency_code = (buff [i ] << 8 | buff [i + 1 ]);
172
+ success = true;
173
+ break ;
174
+ case EMV_TAG_COUNTRY_CODE :
175
+ app -> country_code = (buff [i ] << 8 | buff [i + 1 ]);
176
+ success = true;
177
+ break ;
101
178
}
102
- i += app_len ;
103
179
}
104
- i ++ ;
180
+ i += tlen ;
105
181
}
106
- return app_aid_found ;
182
+ return success ;
107
183
}
108
184
109
185
bool emv_select_ppse (FuriHalNfcTxRxContext * tx_rx , EmvApplication * app ) {
@@ -124,7 +200,7 @@ bool emv_select_ppse(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) {
124
200
FURI_LOG_D (TAG , "Send select PPSE" );
125
201
if (furi_hal_nfc_tx_rx (tx_rx , 300 )) {
126
202
emv_trace (tx_rx , "Select PPSE answer:" );
127
- if (emv_decode_ppse_response (tx_rx -> rx_data , tx_rx -> rx_bits / 8 , app )) {
203
+ if (emv_decode_response (tx_rx -> rx_data , tx_rx -> rx_bits / 8 , app )) {
128
204
app_aid_found = true;
129
205
} else {
130
206
FURI_LOG_E (TAG , "Failed to parse application" );
@@ -136,28 +212,6 @@ bool emv_select_ppse(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) {
136
212
return app_aid_found ;
137
213
}
138
214
139
- static bool emv_decode_select_app_response (uint8_t * buff , uint16_t len , EmvApplication * app ) {
140
- uint16_t i = 0 ;
141
- bool decode_success = false;
142
-
143
- while (i < len ) {
144
- if (buff [i ] == EMV_TAG_CARD_NAME ) {
145
- uint8_t name_len = buff [i + 1 ];
146
- emv_parse_TLV ((uint8_t * )app -> name , buff , & i );
147
- app -> name [name_len ] = '\0' ;
148
- app -> name_found = true;
149
- decode_success = true;
150
- } else if (((buff [i ] << 8 ) | buff [i + 1 ]) == EMV_TAG_PDOL ) {
151
- i ++ ;
152
- app -> pdol .size = emv_parse_TLV (app -> pdol .data , buff , & i );
153
- decode_success = true;
154
- }
155
- i ++ ;
156
- }
157
-
158
- return decode_success ;
159
- }
160
-
161
215
bool emv_select_app (FuriHalNfcTxRxContext * tx_rx , EmvApplication * app ) {
162
216
bool select_app_success = false;
163
217
const uint8_t emv_select_header [] = {
@@ -181,7 +235,7 @@ bool emv_select_app(FuriHalNfcTxRxContext* tx_rx, EmvApplication* app) {
181
235
FURI_LOG_D (TAG , "Start application" );
182
236
if (furi_hal_nfc_tx_rx (tx_rx , 300 )) {
183
237
emv_trace (tx_rx , "Start application answer:" );
184
- if (emv_decode_select_app_response (tx_rx -> rx_data , tx_rx -> rx_bits / 8 , app )) {
238
+ if (emv_decode_response (tx_rx -> rx_data , tx_rx -> rx_bits / 8 , app )) {
185
239
select_app_success = true;
186
240
} else {
187
241
FURI_LOG_E (TAG , "Failed to read PAN or PDOL" );
@@ -226,22 +280,6 @@ static uint16_t emv_prepare_pdol(APDU* dest, APDU* src) {
226
280
return dest -> size ;
227
281
}
228
282
229
- static bool emv_decode_get_proc_opt (uint8_t * buff , uint16_t len , EmvApplication * app ) {
230
- bool card_num_read = false;
231
-
232
- for (uint16_t i = 0 ; i < len ; i ++ ) {
233
- if (buff [i ] == EMV_TAG_CARD_NUM ) {
234
- app -> card_number_len = 8 ;
235
- memcpy (app -> card_number , & buff [i + 2 ], app -> card_number_len );
236
- card_num_read = true;
237
- } else if (buff [i ] == EMV_TAG_AFL ) {
238
- app -> afl .size = emv_parse_TLV (app -> afl .data , buff , & i );
239
- }
240
- }
241
-
242
- return card_num_read ;
243
- }
244
-
245
283
static bool emv_get_processing_options (FuriHalNfcTxRxContext * tx_rx , EmvApplication * app ) {
246
284
bool card_num_read = false;
247
285
const uint8_t emv_gpo_header [] = {0x80 , 0xA8 , 0x00 , 0x00 };
@@ -264,8 +302,10 @@ static bool emv_get_processing_options(FuriHalNfcTxRxContext* tx_rx, EmvApplicat
264
302
FURI_LOG_D (TAG , "Get proccessing options" );
265
303
if (furi_hal_nfc_tx_rx (tx_rx , 300 )) {
266
304
emv_trace (tx_rx , "Get processing options answer:" );
267
- if (emv_decode_get_proc_opt (tx_rx -> rx_data , tx_rx -> rx_bits / 8 , app )) {
268
- card_num_read = true;
305
+ if (emv_decode_response (tx_rx -> rx_data , tx_rx -> rx_bits / 8 , app )) {
306
+ if (app -> card_number_len > 0 ) {
307
+ card_num_read = true;
308
+ }
269
309
}
270
310
} else {
271
311
FURI_LOG_E (TAG , "Failed to get processing options" );
@@ -274,31 +314,6 @@ static bool emv_get_processing_options(FuriHalNfcTxRxContext* tx_rx, EmvApplicat
274
314
return card_num_read ;
275
315
}
276
316
277
- static bool emv_decode_read_sfi_record (uint8_t * buff , uint16_t len , EmvApplication * app ) {
278
- bool pan_parsed = false;
279
-
280
- for (uint16_t i = 0 ; i < len ; i ++ ) {
281
- if (buff [i ] == EMV_TAG_PAN ) {
282
- if (buff [i + 1 ] == 8 || buff [i + 1 ] == 10 ) {
283
- app -> card_number_len = buff [i + 1 ];
284
- memcpy (app -> card_number , & buff [i + 2 ], app -> card_number_len );
285
- pan_parsed = true;
286
- }
287
- } else if (emv_decode_search_tag_u16_r (EMV_TAG_EXP_DATE , buff , & i )) {
288
- app -> exp_year = buff [i ++ ];
289
- app -> exp_month = buff [i ++ ];
290
- } else if (emv_decode_search_tag_u16_r (EMV_TAG_CURRENCY_CODE , buff , & i )) {
291
- app -> currency_code = (buff [i ] << 8 ) | buff [i + 1 ];
292
- i += 2 ;
293
- } else if (emv_decode_search_tag_u16_r (EMV_TAG_COUNTRY_CODE , buff , & i )) {
294
- app -> country_code = (buff [i ] << 8 ) | buff [i + 1 ];
295
- i += 1 ;
296
- }
297
- }
298
-
299
- return pan_parsed ;
300
- }
301
-
302
317
static bool emv_read_sfi_record (
303
318
FuriHalNfcTxRxContext * tx_rx ,
304
319
EmvApplication * app ,
@@ -320,7 +335,7 @@ static bool emv_read_sfi_record(
320
335
321
336
if (furi_hal_nfc_tx_rx (tx_rx , 300 )) {
322
337
emv_trace (tx_rx , "SFI record:" );
323
- if (emv_decode_read_sfi_record (tx_rx -> rx_data , tx_rx -> rx_bits / 8 , app )) {
338
+ if (emv_decode_response (tx_rx -> rx_data , tx_rx -> rx_bits / 8 , app )) {
324
339
card_num_read = true;
325
340
}
326
341
} else {
0 commit comments