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 c1320a077b..811ea29e3b 100644 --- a/applications/main/nfc/helpers/protocol_support/emv/emv_render.c +++ b/applications/main/nfc/helpers/protocol_support/emv/emv_render.c @@ -88,11 +88,32 @@ void nfc_render_emv_application(const EmvApplication* apl, FuriString* str) { return; } - furi_string_cat_printf(str, "AID: "); + furi_string_cat_printf(str, "Application:\n"); - for(uint8_t i = 0; i < len; i++) furi_string_cat_printf(str, "%02X", apl->aid[i]); + if(strlen(apl->label)) { + furi_string_cat_printf(str, " Label: %s", apl->label); + furi_string_cat_printf(str, "\n"); + } + + if(strlen(apl->name)) { + furi_string_cat_printf(str, " Name: %s", apl->name); + furi_string_cat_printf(str, "\n"); + } + furi_string_cat_printf(str, " AID:"); + for(uint8_t i = 0; i < len; i++) furi_string_cat_printf(str, "%02X", apl->aid[i]); furi_string_cat_printf(str, "\n"); + + if(apl->eff_month) { + furi_string_cat_printf( + str, " Effective: 20%02X/%02X/%02X", apl->eff_year, apl->eff_month, apl->eff_day); + furi_string_cat_printf(str, "\n"); + } + if(apl->exp_month) { + furi_string_cat_printf( + str, " Expire: 20%02X/%02X/%02X", apl->exp_year, apl->exp_month, apl->exp_day); + furi_string_cat_printf(str, "\n"); + } } static void nfc_render_emv_pin_try_counter(uint8_t counter, FuriString* str) { diff --git a/applications/main/nfc/plugins/supported_cards/emv.c b/applications/main/nfc/plugins/supported_cards/emv.c index ebcc392c8a..9bc00cd6e4 100644 --- a/applications/main/nfc/plugins/supported_cards/emv.c +++ b/applications/main/nfc/plugins/supported_cards/emv.c @@ -73,8 +73,8 @@ static bool emv_parse(const NfcDevice* device, FuriString* parsed_data) { const EmvApplication app = data->emv_application; do { - if(app.name_found) - furi_string_cat_printf(parsed_data, "\e#%s\n", app.name); + if(strlen(app.label)) + furi_string_cat_printf(parsed_data, "\e#%s\n", app.label); else furi_string_cat_printf(parsed_data, "\e#%s\n", "EMV"); diff --git a/lib/nfc/protocols/emv/emv.c b/lib/nfc/protocols/emv/emv.c index 4cdacaefe3..73020535b0 100644 --- a/lib/nfc/protocols/emv/emv.c +++ b/lib/nfc/protocols/emv/emv.c @@ -76,10 +76,12 @@ bool emv_load(EmvData* data, FlipperFormat* ff, uint32_t version) { EmvApplication* app = &data->emv_application; - //Read name if(!flipper_format_read_string(ff, "Name", temp_str)) break; strcpy(app->name, furi_string_get_cstr(temp_str)); - if(app->name[0] != '\0') app->name_found = true; + + //Read label + if(!flipper_format_read_string(ff, "Label", temp_str)) break; + strcpy(app->label, furi_string_get_cstr(temp_str)); uint32_t pan_len; if(!flipper_format_read_uint32(ff, "PAN length", &pan_len, 1)) break; @@ -99,6 +101,11 @@ bool emv_load(EmvData* data, FlipperFormat* ff, uint32_t version) { if(!flipper_format_read_hex(ff, "Expiration year", &app->exp_year, 1)) break; if(!flipper_format_read_hex(ff, "Expiration month", &app->exp_month, 1)) break; + if(!flipper_format_read_hex(ff, "Expiration day", &app->exp_day, 1)) break; + + if(!flipper_format_read_hex(ff, "Effective year", &app->eff_year, 1)) break; + if(!flipper_format_read_hex(ff, "Effective month", &app->eff_month, 1)) break; + if(!flipper_format_read_hex(ff, "Effective day", &app->eff_day, 1)) break; uint32_t pin_try_counter; if(!flipper_format_read_uint32(ff, "PIN counter", &pin_try_counter, 1)) break; @@ -126,6 +133,8 @@ bool emv_save(const EmvData* data, FlipperFormat* ff) { if(!flipper_format_write_string_cstr(ff, "Name", app.name)) break; + if(!flipper_format_write_string_cstr(ff, "Label", app.label)) break; + uint32_t pan_len = app.pan_len; if(!flipper_format_write_uint32(ff, "PAN length", &pan_len, 1)) break; @@ -141,8 +150,12 @@ bool emv_save(const EmvData* data, FlipperFormat* ff) { if(!flipper_format_write_hex(ff, "Currency code", (uint8_t*)&app.currency_code, 2)) break; if(!flipper_format_write_hex(ff, "Expiration year", (uint8_t*)&app.exp_year, 1)) break; - if(!flipper_format_write_hex(ff, "Expiration month", (uint8_t*)&app.exp_month, 1)) break; + if(!flipper_format_write_hex(ff, "Expiration day", (uint8_t*)&app.exp_day, 1)) break; + + if(!flipper_format_write_hex(ff, "Effective year", (uint8_t*)&app.eff_year, 1)) break; + if(!flipper_format_write_hex(ff, "Effective month", (uint8_t*)&app.eff_month, 1)) break; + if(!flipper_format_write_hex(ff, "Effective day", (uint8_t*)&app.eff_day, 1)) break; if(!flipper_format_write_uint32(ff, "PIN counter", (uint32_t*)&app.pin_try_counter, 1)) break; diff --git a/lib/nfc/protocols/emv/emv.h b/lib/nfc/protocols/emv/emv.h index 42aa1a703b..f47211662b 100644 --- a/lib/nfc/protocols/emv/emv.h +++ b/lib/nfc/protocols/emv/emv.h @@ -10,12 +10,12 @@ extern "C" { #define EMV_REQ_GET_DATA 0x80CA -#define EMV_TAG_APP_TEMPLATE 0x61 #define EMV_TAG_AID 0x4F #define EMV_TAG_PRIORITY 0x87 #define EMV_TAG_PDOL 0x9F38 -#define EMV_TAG_CARD_NAME 0x50 -#define EMV_TAG_FCI 0xBF0C +#define EMV_TAG_APPL_LABEL 0x50 +#define EMV_TAG_APPL_NAME 0x9F12 +#define EMV_TAG_APPL_EFFECTIVE 0x5F25 #define EMV_TAG_PIN_TRY_COUNTER 0x9F17 #define EMV_TAG_LOG_ENTRY 0x9F4D #define EMV_TAG_LOG_FMT 0x9F4F @@ -42,6 +42,12 @@ extern "C" { #define EMV_TAG_RESP_BUF_SIZE 0x6C #define EMV_TAG_RESP_BYTES_AVAILABLE 0x61 +// Not used tags +#define EMV_TAG_FORM_FACTOR 0x9F6E +#define EMV_TAG_APP_TEMPLATE 0x61 +#define EMV_TAG_FCI 0xBF0C +#define EMV_TAG_DEPOSIT_LOG_ENTRY 0xDF4D + typedef struct { uint16_t tag; uint8_t data[]; @@ -72,12 +78,16 @@ typedef struct { uint8_t priority; uint8_t aid[16]; uint8_t aid_len; - char name[32]; - bool name_found; + char name[16 + 1]; + char label[16 + 1]; uint8_t pan[10]; // card_number uint8_t pan_len; + uint8_t exp_day; uint8_t exp_month; uint8_t exp_year; + uint8_t eff_day; + uint8_t eff_month; + uint8_t eff_year; uint16_t country_code; uint16_t currency_code; uint8_t pin_try_counter; diff --git a/lib/nfc/protocols/emv/emv_poller_i.c b/lib/nfc/protocols/emv/emv_poller_i.c index bdf1ecce44..bdfcf7fe22 100644 --- a/lib/nfc/protocols/emv/emv_poller_i.c +++ b/lib/nfc/protocols/emv/emv_poller_i.c @@ -114,12 +114,25 @@ static bool success = true; FURI_LOG_T(TAG, "found EMV_TAG_APP_PRIORITY %X: %d", tag, app->priority); break; - case EMV_TAG_CARD_NAME: + case EMV_TAG_APPL_LABEL: + memcpy(app->label, &buff[i], tlen); + app->label[tlen] = '\0'; + success = true; + FURI_LOG_T(TAG, "found EMV_TAG_APPL_LABEL %x: %s", tag, app->label); + break; + case EMV_TAG_APPL_NAME: + furi_check(tlen < sizeof(app->name)); memcpy(app->name, &buff[i], tlen); app->name[tlen] = '\0'; - app->name_found = true; success = true; - FURI_LOG_T(TAG, "found EMV_TAG_CARD_NAME %x : %s", tag, app->name); + FURI_LOG_T(TAG, "found EMV_TAG_APPL_NAME %x: %s", tag, app->name); + break; + case EMV_TAG_APPL_EFFECTIVE: + app->eff_year = buff[i]; + app->eff_month = buff[i + 1]; + app->eff_day = buff[i + 2]; + success = true; + FURI_LOG_T(TAG, "found EMV_TAG_APPL_EFFECTIVE %x:", tag); break; case EMV_TAG_PDOL: memcpy(app->pdol.data, &buff[i], tlen); @@ -192,6 +205,7 @@ static bool case EMV_TAG_EXP_DATE: app->exp_year = buff[i]; app->exp_month = buff[i + 1]; + app->exp_day = buff[i + 2]; success = true; FURI_LOG_T(TAG, "found EMV_TAG_EXP_DATE %x", tag); break;