NFC fap: EMV protocol added

This commit is contained in:
Methodius 2024-01-11 18:11:54 +09:00
parent 3959827fd4
commit e9454b629b
No known key found for this signature in database
GPG Key ID: 122FA99A00B41679
11 changed files with 281 additions and 7 deletions

View File

@ -0,0 +1,115 @@
#include "emv.h"
#include "emv_render.h"
#include <nfc/protocols/emv/emv_poller.h>
#include "nfc/nfc_app_i.h"
#include "../nfc_protocol_support_common.h"
#include "../nfc_protocol_support_gui_common.h"
#include "../iso14443_4a/iso14443_4a_i.h"
static void nfc_scene_info_on_enter_emv(NfcApp* instance) {
const NfcDevice* device = instance->nfc_device;
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
FuriString* temp_str = furi_string_alloc();
furi_string_cat_printf(
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
nfc_render_emv_info(data, NfcProtocolFormatTypeFull, temp_str);
widget_add_text_scroll_element(
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
furi_string_free(temp_str);
}
static void nfc_scene_more_info_on_enter_emv(NfcApp* instance) {
// Jump to advanced scene right away
scene_manager_next_scene(instance->scene_manager, NfcSceneEmvMoreInfo);
}
static NfcCommand nfc_scene_read_poller_callback_emv(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolEmv);
NfcApp* instance = context;
const EmvPollerEvent* emv_event = event.event_data;
if(emv_event->type == EmvPollerEventTypeReadSuccess) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolEmv, nfc_poller_get_data(instance->poller));
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
return NfcCommandStop;
}
return NfcCommandContinue;
}
static void nfc_scene_read_on_enter_emv(NfcApp* instance) {
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_emv, instance);
}
static void nfc_scene_read_success_on_enter_emv(NfcApp* instance) {
const NfcDevice* device = instance->nfc_device;
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
FuriString* temp_str = furi_string_alloc();
furi_string_cat_printf(
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
nfc_render_emv_info(data, NfcProtocolFormatTypeShort, temp_str);
widget_add_text_scroll_element(
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
furi_string_free(temp_str);
}
// static void nfc_scene_emulate_on_enter_emv(NfcApp* instance) {
// const Iso14443_4aData* iso14443_4a_data =
// nfc_device_get_data(instance->nfc_device, NfcProtocolIso14443_4a);
// instance->listener =
// nfc_listener_alloc(instance->nfc, NfcProtocolIso14443_4a, iso14443_4a_data);
// nfc_listener_start(
// instance->listener, nfc_scene_emulate_listener_callback_iso14443_4a, instance);
// }
const NfcProtocolSupportBase nfc_protocol_support_emv = {
.features = NfcProtocolFeatureNone,
.scene_info =
{
.on_enter = nfc_scene_info_on_enter_emv,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_more_info =
{
.on_enter = nfc_scene_more_info_on_enter_emv,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_read =
{
.on_enter = nfc_scene_read_on_enter_emv,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_read_menu =
{
.on_enter = nfc_protocol_support_common_on_enter_empty,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_read_success =
{
.on_enter = nfc_scene_read_success_on_enter_emv,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_saved_menu =
{
.on_enter = nfc_protocol_support_common_on_enter_empty,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_save_name =
{
.on_enter = nfc_protocol_support_common_on_enter_empty,
.on_event = nfc_protocol_support_common_on_event_empty,
},
};

View File

@ -0,0 +1,5 @@
#pragma once
#include "../nfc_protocol_support_base.h"
extern const NfcProtocolSupportBase nfc_protocol_support_emv;

View File

@ -0,0 +1,35 @@
#include "emv_render.h"
#include "../iso14443_4a/iso14443_4a_render.h"
void nfc_render_emv_info(const EmvData* data, NfcProtocolFormatType format_type, FuriString* str) {
nfc_render_iso14443_4a_brief(emv_get_base_data(data), str);
nfc_render_emv_pan(data->emv_application.pan, data->emv_application.pan_len, str);
nfc_render_emv_name(data->emv_application.name, str);
if(format_type != NfcProtocolFormatTypeFull) return;
furi_string_cat(str, "\n\e#ISO14443-4 data");
nfc_render_iso14443_4a_extra(emv_get_base_data(data), str);
}
void nfc_render_emv_data(const EmvData* data, FuriString* str) {
nfc_render_emv_pan(data->emv_application.pan, data->emv_application.pan_len, str);
nfc_render_emv_name(data->emv_application.name, str);
}
void nfc_render_emv_pan(const uint8_t* data, const uint8_t len, FuriString* str) {
for(uint8_t i = 0; i < len; i++) furi_string_cat_printf(str, "%u", data[i]);
furi_string_cat_printf(str, "\n");
}
void nfc_render_emv_name(const char* data, FuriString* str) {
UNUSED(data);
furi_string_cat_printf(str, "\n");
}
void nfc_render_emv_application(const EmvApplication* data, FuriString* str) {
UNUSED(data);
furi_string_cat_printf(str, "\n");
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <nfc/protocols/emv/emv.h>
#include "../nfc_protocol_support_render_common.h"
#include <stdint.h>
void nfc_render_emv_info(const EmvData* data, NfcProtocolFormatType format_type, FuriString* str);
void nfc_render_emv_data(const EmvData* data, FuriString* str);
void nfc_render_emv_pan(const uint8_t* data, const uint8_t len, FuriString* str);
void nfc_render_emv_name(const char* data, FuriString* str);
void nfc_render_emv_application(const EmvApplication* data, FuriString* str);

View File

@ -18,6 +18,7 @@
#include "mf_ultralight/mf_ultralight.h"
#include "mf_classic/mf_classic.h"
#include "mf_desfire/mf_desfire.h"
#include "emv/emv.h"
#include "slix/slix.h"
#include "st25tb/st25tb.h"
@ -39,6 +40,7 @@ const NfcProtocolSupportBase* nfc_protocol_support[NfcProtocolNum] = {
[NfcProtocolMfUltralight] = &nfc_protocol_support_mf_ultralight,
[NfcProtocolMfClassic] = &nfc_protocol_support_mf_classic,
[NfcProtocolMfDesfire] = &nfc_protocol_support_mf_desfire,
[NfcProtocolEmv] = &nfc_protocol_support_emv,
[NfcProtocolSlix] = &nfc_protocol_support_slix,
[NfcProtocolSt25tb] = &nfc_protocol_support_st25tb,
/* Add new protocol support implementations here */

View File

@ -36,6 +36,8 @@ ADD_SCENE(nfc, mf_ultralight_capture_pass, MfUltralightCapturePass)
ADD_SCENE(nfc, mf_desfire_more_info, MfDesfireMoreInfo)
ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp)
ADD_SCENE(nfc, emv_more_info, EmvMoreInfo)
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
ADD_SCENE(nfc, mf_classic_detect_reader, MfClassicDetectReader)
ADD_SCENE(nfc, mf_classic_mfkey_nonces_info, MfClassicMfkeyNoncesInfo)

View File

@ -0,0 +1,75 @@
#include "../nfc_app_i.h"
#include "../helpers/protocol_support/nfc_protocol_support_gui_common.h"
#include "../helpers/protocol_support/emv/emv_render.h"
enum {
EmvMoreInfoStateMenu,
EmvMoreInfoStateItem, // MUST be last, states >= this correspond with submenu index
};
enum SubmenuIndex {
SubmenuIndexCardInfo,
SubmenuIndexDynamic, // dynamic indices start here
};
void nfc_scene_emv_more_info_on_enter(void* context) {
NfcApp* nfc = context;
Submenu* submenu = nfc->submenu;
text_box_set_font(nfc->text_box, TextBoxFontHex);
submenu_add_item(
submenu,
"Card info",
SubmenuIndexCardInfo,
nfc_protocol_support_common_submenu_callback,
nfc);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
bool nfc_scene_emv_more_info_on_event(void* context, SceneManagerEvent event) {
NfcApp* nfc = context;
bool consumed = false;
const uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmvMoreInfo);
const EmvData* data = nfc_device_get_data(nfc->nfc_device, NfcProtocolEmv);
if(event.type == SceneManagerEventTypeCustom) {
TextBox* text_box = nfc->text_box;
furi_string_reset(nfc->text_box_store);
if(event.event == SubmenuIndexCardInfo) {
nfc_render_emv_data(data, nfc->text_box_store);
text_box_set_text(text_box, furi_string_get_cstr(nfc->text_box_store));
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
scene_manager_set_scene_state(
nfc->scene_manager,
NfcSceneEmvMoreInfo,
EmvMoreInfoStateItem + SubmenuIndexCardInfo);
consumed = true;
}
} else if(event.type == SceneManagerEventTypeBack) {
if(state >= EmvMoreInfoStateItem) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneEmvMoreInfo, EmvMoreInfoStateMenu);
} else {
// Return directly to the Info scene
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneInfo);
}
consumed = true;
}
return consumed;
}
void nfc_scene_emv_more_info_on_exit(void* context) {
NfcApp* nfc = context;
// Clear views
text_box_reset(nfc->text_box);
furi_string_reset(nfc->text_box_store);
submenu_reset(nfc->submenu);
}

View File

@ -22,6 +22,7 @@ env.Append(
File("protocols/mf_ultralight/mf_ultralight.h"),
File("protocols/mf_classic/mf_classic.h"),
File("protocols/mf_desfire/mf_desfire.h"),
File("protocols/emv/emv.h"),
File("protocols/slix/slix.h"),
File("protocols/st25tb/st25tb.h"),
# Pollers
@ -32,6 +33,7 @@ env.Append(
File("protocols/mf_ultralight/mf_ultralight_poller.h"),
File("protocols/mf_classic/mf_classic_poller.h"),
File("protocols/mf_desfire/mf_desfire_poller.h"),
File("protocols/emv/emv_poller.h"),
File("protocols/st25tb/st25tb_poller.h"),
# Listeners
File("protocols/iso14443_3a/iso14443_3a_listener.h"),

View File

@ -41,8 +41,8 @@ typedef struct {
bool app_started;
char name[32];
bool name_found;
uint8_t card_number[10];
uint8_t card_number_len;
uint8_t pan[10];
uint8_t pan_len;
uint8_t exp_month;
uint8_t exp_year;
uint16_t country_code;

View File

@ -186,8 +186,8 @@ static bool emv_decode_response(const uint8_t* buff, uint16_t len, EmvApplicatio
// 0xD0 delimits PAN from expiry (YYMM)
for(int x = 1; x < tlen; x++) {
if(buff[i + x + 1] > 0xD0) {
memcpy(app->card_number, &buff[i], x + 1);
app->card_number_len = x + 1;
memcpy(app->pan, &buff[i], x + 1);
app->pan_len = x + 1;
app->exp_year = (buff[i + x + 1] << 4) | (buff[i + x + 2] >> 4);
app->exp_month = (buff[i + x + 2] << 4) | (buff[i + x + 3] >> 4);
break;
@ -213,8 +213,8 @@ static bool emv_decode_response(const uint8_t* buff, uint16_t len, EmvApplicatio
break;
}
case EMV_TAG_PAN:
memcpy(app->card_number, &buff[i], tlen);
app->card_number_len = tlen;
memcpy(app->pan, &buff[i], tlen);
app->pan_len = tlen;
success = true;
break;
case EMV_TAG_EXP_DATE:

View File

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,50.1,,
Version,v,50.2,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
@ -120,6 +120,8 @@ Header,+,lib/nfc/nfc_device.h,,
Header,+,lib/nfc/nfc_listener.h,,
Header,+,lib/nfc/nfc_poller.h,,
Header,+,lib/nfc/nfc_scanner.h,,
Header,?,lib/nfc/protocols/emv/emv.h,,
Header,?,lib/nfc/protocols/emv/emv_poller.h,,
Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a.h,,
Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.h,,
Header,+,lib/nfc/protocols/iso14443_3a/iso14443_3a_poller.h,,
@ -877,6 +879,25 @@ Function,+,elf_symbolname_hash,uint32_t,const char*
Function,+,empty_screen_alloc,EmptyScreen*,
Function,+,empty_screen_free,void,EmptyScreen*
Function,+,empty_screen_get_view,View*,EmptyScreen*
Function,?,emv_alloc,EmvData*,
Function,?,emv_copy,void,"EmvData*, const EmvData*"
Function,?,emv_free,void,EmvData*
Function,?,emv_get_application,const EmvApplication*,const EmvData*
Function,?,emv_get_base_data,Iso14443_4aData*,const EmvData*
Function,?,emv_get_device_name,const char*,"const EmvData*, NfcDeviceNameType"
Function,?,emv_get_uid,const uint8_t*,"const EmvData*, size_t*"
Function,?,emv_is_equal,_Bool,"const EmvData*, const EmvData*"
Function,?,emv_load,_Bool,"EmvData*, FlipperFormat*, uint32_t"
Function,?,emv_poller_get_processing_options,EmvError,EmvPoller*
Function,?,emv_poller_read,EmvError,EmvPoller*
Function,?,emv_poller_read_files,EmvError,EmvPoller*
Function,?,emv_poller_read_sfi_record,EmvError,"EmvPoller*, uint8_t, uint8_t"
Function,?,emv_poller_select_application,EmvError,EmvPoller*
Function,?,emv_poller_select_ppse,EmvError,EmvPoller*
Function,?,emv_reset,void,EmvData*
Function,?,emv_save,_Bool,"const EmvData*, FlipperFormat*"
Function,?,emv_set_uid,_Bool,"EmvData*, const uint8_t*, size_t"
Function,?,emv_verify,_Bool,"EmvData*, const FuriString*"
Function,-,erand48,double,unsigned short[3]
Function,-,erf,double,double
Function,-,erfc,double,double
@ -3619,6 +3640,7 @@ Variable,+,message_red_255,const NotificationMessage,
Variable,+,message_sound_off,const NotificationMessage,
Variable,+,message_vibro_off,const NotificationMessage,
Variable,+,message_vibro_on,const NotificationMessage,
Variable,?,nfc_device_emv,const NfcDeviceBase,
Variable,-,nfc_device_mf_classic,const NfcDeviceBase,
Variable,-,nfc_device_mf_desfire,const NfcDeviceBase,
Variable,-,nfc_device_mf_ultralight,const NfcDeviceBase,

1 entry status name type params
2 Version + v 50.1 50.2
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/cli/cli.h
120 Header + lib/nfc/nfc_listener.h
121 Header + lib/nfc/nfc_poller.h
122 Header + lib/nfc/nfc_scanner.h
123 Header ? lib/nfc/protocols/emv/emv.h
124 Header ? lib/nfc/protocols/emv/emv_poller.h
125 Header + lib/nfc/protocols/iso14443_3a/iso14443_3a.h
126 Header + lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.h
127 Header + lib/nfc/protocols/iso14443_3a/iso14443_3a_poller.h
879 Function + empty_screen_alloc EmptyScreen*
880 Function + empty_screen_free void EmptyScreen*
881 Function + empty_screen_get_view View* EmptyScreen*
882 Function ? emv_alloc EmvData*
883 Function ? emv_copy void EmvData*, const EmvData*
884 Function ? emv_free void EmvData*
885 Function ? emv_get_application const EmvApplication* const EmvData*
886 Function ? emv_get_base_data Iso14443_4aData* const EmvData*
887 Function ? emv_get_device_name const char* const EmvData*, NfcDeviceNameType
888 Function ? emv_get_uid const uint8_t* const EmvData*, size_t*
889 Function ? emv_is_equal _Bool const EmvData*, const EmvData*
890 Function ? emv_load _Bool EmvData*, FlipperFormat*, uint32_t
891 Function ? emv_poller_get_processing_options EmvError EmvPoller*
892 Function ? emv_poller_read EmvError EmvPoller*
893 Function ? emv_poller_read_files EmvError EmvPoller*
894 Function ? emv_poller_read_sfi_record EmvError EmvPoller*, uint8_t, uint8_t
895 Function ? emv_poller_select_application EmvError EmvPoller*
896 Function ? emv_poller_select_ppse EmvError EmvPoller*
897 Function ? emv_reset void EmvData*
898 Function ? emv_save _Bool const EmvData*, FlipperFormat*
899 Function ? emv_set_uid _Bool EmvData*, const uint8_t*, size_t
900 Function ? emv_verify _Bool EmvData*, const FuriString*
901 Function - erand48 double unsigned short[3]
902 Function - erf double double
903 Function - erfc double double
3640 Variable + message_sound_off const NotificationMessage
3641 Variable + message_vibro_off const NotificationMessage
3642 Variable + message_vibro_on const NotificationMessage
3643 Variable ? nfc_device_emv const NfcDeviceBase
3644 Variable - nfc_device_mf_classic const NfcDeviceBase
3645 Variable - nfc_device_mf_desfire const NfcDeviceBase
3646 Variable - nfc_device_mf_ultralight const NfcDeviceBase