back to parser

This commit is contained in:
Methodius 2024-01-29 23:12:17 +09:00
parent 1165e25f00
commit 3612814a18
No known key found for this signature in database
GPG Key ID: 122FA99A00B41679
6 changed files with 155 additions and 11 deletions

View File

@ -173,6 +173,15 @@ App(
sources=["plugins/supported_cards/washcity.c"], sources=["plugins/supported_cards/washcity.c"],
) )
App(
appid="emv_parser",
apptype=FlipperAppType.PLUGIN,
entry_point="emv_plugin_ep",
targets=["f7"],
requires=["nfc"],
sources=["plugins/supported_cards/emv.c"],
)
App( App(
appid="ndef_parser", appid="ndef_parser",
apptype=FlipperAppType.PLUGIN, apptype=FlipperAppType.PLUGIN,
@ -182,7 +191,6 @@ App(
sources=["plugins/supported_cards/ndef.c"], sources=["plugins/supported_cards/ndef.c"],
) )
App( App(
appid="nfc_start", appid="nfc_start",
targets=["f7"], targets=["f7"],

View File

@ -75,7 +75,7 @@ static void nfc_scene_read_success_on_enter_emv(NfcApp* instance) {
// } // }
const NfcProtocolSupportBase nfc_protocol_support_emv = { const NfcProtocolSupportBase nfc_protocol_support_emv = {
.features = NfcProtocolFeatureMoreInfo, .features = NfcProtocolFeatureNone,
.scene_info = .scene_info =
{ {

View File

@ -4,11 +4,12 @@
#include "nfc/nfc_app_i.h" #include "nfc/nfc_app_i.h"
void nfc_render_emv_info(const EmvData* data, NfcProtocolFormatType format_type, FuriString* str) { void nfc_render_emv_info(const EmvData* data, NfcProtocolFormatType format_type, FuriString* str) {
nfc_render_emv_name(data->emv_application.name, str); nfc_render_iso14443_4a_info(data->iso14443_4a_data, format_type, str);
nfc_render_emv_pan(data->emv_application.pan, data->emv_application.pan_len, str); // nfc_render_emv_name(data->emv_application.name, str);
nfc_render_emv_expired(&data->emv_application, str); // nfc_render_emv_pan(data->emv_application.pan, data->emv_application.pan_len, str);
// nfc_render_emv_expired(&data->emv_application, str);
if(format_type == NfcProtocolFormatTypeFull) nfc_render_emv_extra(data, str); // if(format_type == NfcProtocolFormatTypeFull) nfc_render_emv_extra(data, str);
} }
void nfc_render_emv_data(const EmvData* data, FuriString* str) { void nfc_render_emv_data(const EmvData* data, FuriString* str) {

View File

@ -0,0 +1,131 @@
/*
* Parser for EMV cards.
*
* Copyright 2023 Leptoptilos <leptoptilos@icloud.com>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "core/string.h"
#include "furi_hal_rtc.h"
#include "helpers/nfc_emv_parser.h"
#include "nfc_supported_card_plugin.h"
#include "protocols/emv/emv.h"
#include "protocols/nfc_protocol.h"
#include <flipper_application/flipper_application.h>
#include <nfc/nfc_device.h>
#include <nfc/helpers/nfc_util.h>
#define TAG "EMV"
bool emv_get_currency_name(uint16_t cur_code, FuriString* currency_name) {
if(!cur_code) return false;
Storage* storage = furi_record_open(RECORD_STORAGE);
bool succsess = nfc_emv_parser_get_currency_name(storage, cur_code, currency_name);
furi_record_close(RECORD_STORAGE);
return succsess;
}
bool emv_get_country_name(uint16_t country_code, FuriString* country_name) {
if(!country_code) return false;
Storage* storage = furi_record_open(RECORD_STORAGE);
bool succsess = nfc_emv_parser_get_country_name(storage, country_code, country_name);
furi_record_close(RECORD_STORAGE);
return succsess;
}
bool emv_get_aid_name(const EmvApplication* apl, FuriString* aid_name) {
const uint8_t len = apl->aid_len;
if(!len) return false;
Storage* storage = furi_record_open(RECORD_STORAGE);
bool succsess = nfc_emv_parser_get_aid_name(storage, apl->aid, len, aid_name);
furi_record_close(RECORD_STORAGE);
return succsess;
}
static bool emv_parse(const NfcDevice* device, FuriString* parsed_data) {
furi_assert(device);
bool parsed = false;
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
const EmvApplication app = data->emv_application;
do {
if(app.name_found)
furi_string_cat_printf(parsed_data, "\e#%s\n", app.name);
else
furi_string_cat_printf(parsed_data, "\e#%s\n", "EMV");
FuriString* pan = furi_string_alloc();
for(uint8_t i = 0; i < app.pan_len; i += 2) {
furi_string_cat_printf(pan, "%02X%02X ", app.pan[i], app.pan[i + 1]);
}
// Cut padding 'F' from card number
size_t end = furi_string_search_rchar(pan, 'F');
if(end) furi_string_left(pan, end);
furi_string_cat(parsed_data, pan);
furi_string_free(pan);
furi_string_cat_printf(parsed_data, "\nExp: %02X/%02X", app.exp_month, app.exp_year);
FuriString* str = furi_string_alloc();
bool storage_readed = emv_get_country_name(app.country_code, str);
if(storage_readed)
furi_string_cat_printf(parsed_data, "\nCountry: %s", furi_string_get_cstr(str));
storage_readed = emv_get_currency_name(app.currency_code, str);
if(storage_readed)
furi_string_cat_printf(parsed_data, "\nCurrency: %s", furi_string_get_cstr(str));
if(app.pin_try_counter != 0xFF)
furi_string_cat_printf(str, "\nPIN try left: %d\n", app.pin_try_counter);
parsed = true;
} while(false);
return parsed;
}
/* Actual implementation of app<>plugin interface */
static const NfcSupportedCardsPlugin emv_plugin = {
.protocol = NfcProtocolEmv,
.verify = NULL,
.read = NULL,
.parse = emv_parse,
};
/* Plugin descriptor to comply with basic plugin specification */
static const FlipperAppPluginDescriptor emv_plugin_descriptor = {
.appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID,
.ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION,
.entry_point = &emv_plugin,
};
/* Plugin entry point - must return a pointer to const descriptor */
const FlipperAppPluginDescriptor* emv_plugin_ep() {
return &emv_plugin_descriptor;
}

View File

@ -3,15 +3,18 @@
#include <furi.h> #include <furi.h>
#define ISO14443_4_BLOCK_PCB (1U << 1) #define ISO14443_4_BLOCK_PCB (1U << 1)
#define ISO14443_4_BLOCK_PCB_I (0U << 6) #define ISO14443_4_BLOCK_PCB_I (0U)
#define ISO14443_4_BLOCK_PCB_R (2U << 6) #define ISO14443_4_BLOCK_PCB_R (5U << 5)
#define ISO14443_4_BLOCK_PCB_S (3U << 6) #define ISO14443_4_BLOCK_PCB_S (3U << 6)
#define ISO14443_4_BLOCK_PCB_I_ (0U << 6)
#define ISO14443_4_BLOCK_PCB_R_ (2U << 6)
#define ISO14443_4_BLOCK_PCB_TYPE_MASK (3U << 6) #define ISO14443_4_BLOCK_PCB_TYPE_MASK (3U << 6)
#define ISO14443_4_BLOCK_PCB_S_DESELECT (0U << 4) #define ISO14443_4_BLOCK_PCB_S_DESELECT (0U << 4)
#define ISO14443_4_BLOCK_PCB_S_WTX (3U << 4) #define ISO14443_4_BLOCK_PCB_S_WTX (3U << 4)
#define ISO14443_4_BLOCK_PCB_BLOCK_NUMBER (1U << 0) #define ISO14443_4_BLOCK_PCB_BLOCK_NUMBER (1U << 0)
#define ISO14443_4_BLOCK_PCB (1U << 1)
#define ISO14443_4_BLOCK_PCB_NAD (1U << 2) #define ISO14443_4_BLOCK_PCB_NAD (1U << 2)
#define ISO14443_4_BLOCK_PCB_CID (1U << 3) #define ISO14443_4_BLOCK_PCB_CID (1U << 3)
#define ISO14443_4_BLOCK_PCB_CHAINING (1U << 4) #define ISO14443_4_BLOCK_PCB_CHAINING (1U << 4)
@ -85,7 +88,7 @@ Iso14443_4aError iso14443_4_layer_decode_block_pwt_ext(
const uint8_t pcb_field = bit_buffer_get_byte(block_data, 0); const uint8_t pcb_field = bit_buffer_get_byte(block_data, 0);
const uint8_t block_type = pcb_field & ISO14443_4_BLOCK_PCB_TYPE_MASK; const uint8_t block_type = pcb_field & ISO14443_4_BLOCK_PCB_TYPE_MASK;
switch(block_type) { switch(block_type) {
case ISO14443_4_BLOCK_PCB_I: case ISO14443_4_BLOCK_PCB_I_:
if(pcb_field == instance->pcb_prev) { if(pcb_field == instance->pcb_prev) {
bit_buffer_copy_right(output_data, block_data, 1); bit_buffer_copy_right(output_data, block_data, 1);
ret = Iso14443_4aErrorNone; ret = Iso14443_4aErrorNone;
@ -94,7 +97,7 @@ Iso14443_4aError iso14443_4_layer_decode_block_pwt_ext(
ret = Iso14443_4aErrorSendExtra; ret = Iso14443_4aErrorSendExtra;
} }
break; break;
case ISO14443_4_BLOCK_PCB_R: case ISO14443_4_BLOCK_PCB_R_:
// TODO // TODO
break; break;
case ISO14443_4_BLOCK_PCB_S: case ISO14443_4_BLOCK_PCB_S:

View File

@ -20,4 +20,5 @@ const NfcListenerBase* nfc_listeners_api[NfcProtocolNum] = {
[NfcProtocolSlix] = &nfc_listener_slix, [NfcProtocolSlix] = &nfc_listener_slix,
[NfcProtocolSt25tb] = NULL, [NfcProtocolSt25tb] = NULL,
[NfcProtocolFelica] = &nfc_listener_felica, [NfcProtocolFelica] = &nfc_listener_felica,
[NfcProtocolEmv] = NULL,
}; };