From 3612814a18e4ceaa85d3f2ac5b10e95b7d46433c Mon Sep 17 00:00:00 2001 From: Methodius Date: Mon, 29 Jan 2024 23:12:17 +0900 Subject: [PATCH] back to parser --- applications/main/nfc/application.fam | 10 +- .../nfc/helpers/protocol_support/emv/emv.c | 2 +- .../helpers/protocol_support/emv/emv_render.c | 9 +- .../main/nfc/plugins/supported_cards/emv.c | 131 ++++++++++++++++++ lib/nfc/helpers/iso14443_4_layer.c | 13 +- lib/nfc/protocols/nfc_listener_defs.c | 1 + 6 files changed, 155 insertions(+), 11 deletions(-) create mode 100644 applications/main/nfc/plugins/supported_cards/emv.c diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 86eefe620..569c680eb 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -173,6 +173,15 @@ App( 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( appid="ndef_parser", apptype=FlipperAppType.PLUGIN, @@ -182,7 +191,6 @@ App( sources=["plugins/supported_cards/ndef.c"], ) - App( appid="nfc_start", targets=["f7"], diff --git a/applications/main/nfc/helpers/protocol_support/emv/emv.c b/applications/main/nfc/helpers/protocol_support/emv/emv.c index e543291cc..0b60bea6e 100644 --- a/applications/main/nfc/helpers/protocol_support/emv/emv.c +++ b/applications/main/nfc/helpers/protocol_support/emv/emv.c @@ -75,7 +75,7 @@ static void nfc_scene_read_success_on_enter_emv(NfcApp* instance) { // } const NfcProtocolSupportBase nfc_protocol_support_emv = { - .features = NfcProtocolFeatureMoreInfo, + .features = NfcProtocolFeatureNone, .scene_info = { diff --git a/applications/main/nfc/helpers/protocol_support/emv/emv_render.c b/applications/main/nfc/helpers/protocol_support/emv/emv_render.c index cc8a46efe..2d76a3fb9 100644 --- a/applications/main/nfc/helpers/protocol_support/emv/emv_render.c +++ b/applications/main/nfc/helpers/protocol_support/emv/emv_render.c @@ -4,11 +4,12 @@ #include "nfc/nfc_app_i.h" void nfc_render_emv_info(const EmvData* data, NfcProtocolFormatType format_type, FuriString* str) { - nfc_render_emv_name(data->emv_application.name, str); - nfc_render_emv_pan(data->emv_application.pan, data->emv_application.pan_len, str); - nfc_render_emv_expired(&data->emv_application, str); + nfc_render_iso14443_4a_info(data->iso14443_4a_data, format_type, str); + // nfc_render_emv_name(data->emv_application.name, 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) { diff --git a/applications/main/nfc/plugins/supported_cards/emv.c b/applications/main/nfc/plugins/supported_cards/emv.c new file mode 100644 index 000000000..99842f2d6 --- /dev/null +++ b/applications/main/nfc/plugins/supported_cards/emv.c @@ -0,0 +1,131 @@ +/* + * Parser for EMV cards. + * + * Copyright 2023 Leptoptilos + * + * 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 . + */ +#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 + +#include +#include + +#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; +} \ No newline at end of file diff --git a/lib/nfc/helpers/iso14443_4_layer.c b/lib/nfc/helpers/iso14443_4_layer.c index 7f0f0a25e..b21e22423 100644 --- a/lib/nfc/helpers/iso14443_4_layer.c +++ b/lib/nfc/helpers/iso14443_4_layer.c @@ -3,15 +3,18 @@ #include #define ISO14443_4_BLOCK_PCB (1U << 1) -#define ISO14443_4_BLOCK_PCB_I (0U << 6) -#define ISO14443_4_BLOCK_PCB_R (2U << 6) +#define ISO14443_4_BLOCK_PCB_I (0U) +#define ISO14443_4_BLOCK_PCB_R (5U << 5) #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_S_DESELECT (0U << 4) #define ISO14443_4_BLOCK_PCB_S_WTX (3U << 4) #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_CID (1U << 3) #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 block_type = pcb_field & ISO14443_4_BLOCK_PCB_TYPE_MASK; switch(block_type) { - case ISO14443_4_BLOCK_PCB_I: + case ISO14443_4_BLOCK_PCB_I_: if(pcb_field == instance->pcb_prev) { bit_buffer_copy_right(output_data, block_data, 1); ret = Iso14443_4aErrorNone; @@ -94,7 +97,7 @@ Iso14443_4aError iso14443_4_layer_decode_block_pwt_ext( ret = Iso14443_4aErrorSendExtra; } break; - case ISO14443_4_BLOCK_PCB_R: + case ISO14443_4_BLOCK_PCB_R_: // TODO break; case ISO14443_4_BLOCK_PCB_S: diff --git a/lib/nfc/protocols/nfc_listener_defs.c b/lib/nfc/protocols/nfc_listener_defs.c index 2a6167e9c..ecfe98c10 100644 --- a/lib/nfc/protocols/nfc_listener_defs.c +++ b/lib/nfc/protocols/nfc_listener_defs.c @@ -20,4 +20,5 @@ const NfcListenerBase* nfc_listeners_api[NfcProtocolNum] = { [NfcProtocolSlix] = &nfc_listener_slix, [NfcProtocolSt25tb] = NULL, [NfcProtocolFelica] = &nfc_listener_felica, + [NfcProtocolEmv] = NULL, };