From 647e65cfae869a99bd3c4a0bb5d5ea3f5f6abcb4 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 13 Dec 2025 19:21:15 +0300 Subject: [PATCH] ofw pr 4316 MIFARE Plus 2K Cards in SL1 Mode testing only, for dev branch PR by LuemmelSec https://github.com/flipperdevices/flipperzero-firmware/pull/4316/files TODO: mf_classic_get_total_sectors_num --- .../main/nfc/helpers/mf_classic_key_cache.c | 2 +- .../mf_classic/mf_classic_render.c | 2 +- .../main/nfc/plugins/supported_cards/aime.c | 2 +- .../nfc/plugins/supported_cards/banapass.c | 4 ++-- .../main/nfc/plugins/supported_cards/bip.c | 2 +- .../nfc/plugins/supported_cards/charliecard.c | 2 +- .../plugins/supported_cards/disney_infinity.c | 2 +- .../main/nfc/plugins/supported_cards/hi.c | 4 ++-- .../main/nfc/plugins/supported_cards/hid.c | 2 +- .../main/nfc/plugins/supported_cards/hworld.c | 4 ++-- .../main/nfc/plugins/supported_cards/kazan.c | 2 +- .../nfc/plugins/supported_cards/metromoney.c | 2 +- .../nfc/plugins/supported_cards/microel.c | 4 ++-- .../main/nfc/plugins/supported_cards/mizip.c | 4 ++-- .../main/nfc/plugins/supported_cards/ndef.c | 2 +- .../nfc/plugins/supported_cards/plantain.c | 2 +- .../main/nfc/plugins/supported_cards/saflok.c | 4 ++-- .../nfc/plugins/supported_cards/skylanders.c | 2 +- .../nfc/plugins/supported_cards/smartrider.c | 2 +- .../plugins/supported_cards/social_moscow.c | 2 +- .../main/nfc/plugins/supported_cards/troika.c | 2 +- .../nfc/plugins/supported_cards/two_cities.c | 2 +- .../nfc/plugins/supported_cards/washcity.c | 2 +- .../scenes/nfc_scene_mf_classic_dict_attack.c | 2 +- .../scenes/nfc_scene_mf_classic_show_keys.c | 2 +- lib/nfc/protocols/mf_classic/mf_classic.c | 24 ++++++++++++++++--- lib/nfc/protocols/mf_classic/mf_classic.h | 3 +++ .../protocols/mf_classic/mf_classic_poller.c | 18 +++++++++++++- targets/f7/api_symbols.csv | 3 ++- 29 files changed, 74 insertions(+), 36 deletions(-) diff --git a/applications/main/nfc/helpers/mf_classic_key_cache.c b/applications/main/nfc/helpers/mf_classic_key_cache.c index 763c4dea7..ff16cf0a3 100644 --- a/applications/main/nfc/helpers/mf_classic_key_cache.c +++ b/applications/main/nfc/helpers/mf_classic_key_cache.c @@ -63,7 +63,7 @@ bool mf_classic_key_cache_save(MfClassicKeyCache* instance, const MfClassicData* if(!flipper_format_write_hex_uint64(ff, "Key A map", &data->key_a_mask, 1)) break; if(!flipper_format_write_hex_uint64(ff, "Key B map", &data->key_b_mask, 1)) break; - uint8_t sector_num = mf_classic_get_total_sectors_num(data->type); + uint8_t sector_num = mf_classic_get_scannable_sectors_num(data->type); bool key_save_success = true; for(size_t i = 0; (i < sector_num) && (key_save_success); i++) { MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, i); diff --git a/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic_render.c b/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic_render.c index 0382b3333..78e45365e 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic_render.c +++ b/applications/main/nfc/helpers/protocol_support/mf_classic/mf_classic_render.c @@ -8,7 +8,7 @@ void nfc_render_mf_classic_info( FuriString* str) { nfc_render_iso14443_3a_info(data->iso14443_3a_data, format_type, str); - uint8_t sectors_total = mf_classic_get_total_sectors_num(data->type); + uint8_t sectors_total = mf_classic_get_scannable_sectors_num(data->type); uint8_t keys_total = sectors_total * 2; uint8_t keys_found = 0; uint8_t sectors_read = 0; diff --git a/applications/main/nfc/plugins/supported_cards/aime.c b/applications/main/nfc/plugins/supported_cards/aime.c index a4a04b2db..b48f7324b 100644 --- a/applications/main/nfc/plugins/supported_cards/aime.c +++ b/applications/main/nfc/plugins/supported_cards/aime.c @@ -51,7 +51,7 @@ static bool aime_read(Nfc* nfc, NfcDevice* device) { data->type = type; MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(aime_key, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); bit_lib_num_to_bytes_be(aime_key, sizeof(MfClassicKey), keys.key_b[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/banapass.c b/applications/main/nfc/plugins/supported_cards/banapass.c index ac065c3ac..6832d43a0 100644 --- a/applications/main/nfc/plugins/supported_cards/banapass.c +++ b/applications/main/nfc/plugins/supported_cards/banapass.c @@ -98,7 +98,7 @@ static bool banapass_read(Nfc* nfc, NfcDevice* device) { MfClassicDeviceKeys keys = {}; // Access Code Read Attempt - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( banapass_keys_if_access_code[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); @@ -116,7 +116,7 @@ static bool banapass_read(Nfc* nfc, NfcDevice* device) { } // Value Block Read Attempt - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( banapass_keys_if_value_block[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); diff --git a/applications/main/nfc/plugins/supported_cards/bip.c b/applications/main/nfc/plugins/supported_cards/bip.c index 6bc586bc6..cff4edf01 100644 --- a/applications/main/nfc/plugins/supported_cards/bip.c +++ b/applications/main/nfc/plugins/supported_cards/bip.c @@ -159,7 +159,7 @@ static bool bip_read(Nfc* nfc, NfcDevice* device) { .key_a_mask = 0, .key_b_mask = 0, }; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(bip_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); bit_lib_num_to_bytes_be(bip_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/charliecard.c b/applications/main/nfc/plugins/supported_cards/charliecard.c index da29dbfe6..1f8f2eaac 100644 --- a/applications/main/nfc/plugins/supported_cards/charliecard.c +++ b/applications/main/nfc/plugins/supported_cards/charliecard.c @@ -1230,7 +1230,7 @@ static bool charliecard_read(Nfc* nfc, NfcDevice* device) { .key_a_mask = 0, .key_b_mask = 0, }; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( charliecard_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); diff --git a/applications/main/nfc/plugins/supported_cards/disney_infinity.c b/applications/main/nfc/plugins/supported_cards/disney_infinity.c index a98d39ec2..e07d1d426 100644 --- a/applications/main/nfc/plugins/supported_cards/disney_infinity.c +++ b/applications/main/nfc/plugins/supported_cards/disney_infinity.c @@ -46,7 +46,7 @@ static bool disney_infinity_read(Nfc* nfc, NfcDevice* device) { if(error != MfClassicErrorNone) break; data->type = type; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { di_key(uid_bytes, &keys.key_a[i]); di_key(uid_bytes, &keys.key_b[i]); FURI_BIT_SET(keys.key_a_mask, i); diff --git a/applications/main/nfc/plugins/supported_cards/hi.c b/applications/main/nfc/plugins/supported_cards/hi.c index 1206b807e..b85122139 100644 --- a/applications/main/nfc/plugins/supported_cards/hi.c +++ b/applications/main/nfc/plugins/supported_cards/hi.c @@ -138,7 +138,7 @@ static bool hi_read(Nfc* nfc, NfcDevice* device) { uint8_t keyB[HI_KEY_TO_GEN][KEY_LENGTH]; hi_generate_key(uid, keyA, keyB); - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { if(cfg.keys[i].a == 0x000000000000 && cfg.keys[i].b == 0x000000000000) { cfg.keys[i].a = bit_lib_bytes_to_num_be(keyA[i], KEY_LENGTH); cfg.keys[i].b = bit_lib_bytes_to_num_be(keyB[i], KEY_LENGTH); @@ -146,7 +146,7 @@ static bool hi_read(Nfc* nfc, NfcDevice* device) { } MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(cfg.keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); bit_lib_num_to_bytes_be(cfg.keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/hid.c b/applications/main/nfc/plugins/supported_cards/hid.c index 601351d2d..12717e467 100644 --- a/applications/main/nfc/plugins/supported_cards/hid.c +++ b/applications/main/nfc/plugins/supported_cards/hid.c @@ -51,7 +51,7 @@ static bool hid_read(Nfc* nfc, NfcDevice* device) { data->type = type; MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(hid_key, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); bit_lib_num_to_bytes_be(hid_key, sizeof(MfClassicKey), keys.key_b[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/hworld.c b/applications/main/nfc/plugins/supported_cards/hworld.c index 674e7b955..23dd8e3ee 100644 --- a/applications/main/nfc/plugins/supported_cards/hworld.c +++ b/applications/main/nfc/plugins/supported_cards/hworld.c @@ -116,7 +116,7 @@ static bool hworld_read(Nfc* nfc, NfcDevice* device) { data->type = type; MfClassicDeviceKeys standard_keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( hworld_standard_keys[i].a, sizeof(MfClassicKey), standard_keys.key_a[i].data); FURI_BIT_SET(standard_keys.key_a_mask, i); @@ -130,7 +130,7 @@ static bool hworld_read(Nfc* nfc, NfcDevice* device) { FURI_LOG_I(TAG, "Standard card successfully read"); } else { MfClassicDeviceKeys vip_keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( hworld_vip_keys[i].a, sizeof(MfClassicKey), vip_keys.key_a[i].data); FURI_BIT_SET(vip_keys.key_a_mask, i); diff --git a/applications/main/nfc/plugins/supported_cards/kazan.c b/applications/main/nfc/plugins/supported_cards/kazan.c index 65838e25c..a010cbfbe 100644 --- a/applications/main/nfc/plugins/supported_cards/kazan.c +++ b/applications/main/nfc/plugins/supported_cards/kazan.c @@ -193,7 +193,7 @@ static bool kazan_read(Nfc* nfc, NfcDevice* device) { .key_b_mask = 0, }; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( kazan_1k_keys_v1[i].a, sizeof(MfClassicKey), keys_v1.key_a[i].data); bit_lib_num_to_bytes_be( diff --git a/applications/main/nfc/plugins/supported_cards/metromoney.c b/applications/main/nfc/plugins/supported_cards/metromoney.c index 089bb48bd..937b41776 100644 --- a/applications/main/nfc/plugins/supported_cards/metromoney.c +++ b/applications/main/nfc/plugins/supported_cards/metromoney.c @@ -97,7 +97,7 @@ static bool metromoney_read(Nfc* nfc, NfcDevice* device) { .key_a_mask = 0, .key_b_mask = 0, }; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( metromoney_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); diff --git a/applications/main/nfc/plugins/supported_cards/microel.c b/applications/main/nfc/plugins/supported_cards/microel.c index 469cc847b..ca99f95dc 100644 --- a/applications/main/nfc/plugins/supported_cards/microel.c +++ b/applications/main/nfc/plugins/supported_cards/microel.c @@ -128,7 +128,7 @@ static bool microel_read(Nfc* nfc, NfcDevice* device) { } // Save keys generated to stucture - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { if(microel_1k_keys[i].a == 0x000000000000) { microel_1k_keys[i].a = bit_lib_bytes_to_num_be(keyA, KEY_LENGTH); } @@ -137,7 +137,7 @@ static bool microel_read(Nfc* nfc, NfcDevice* device) { } } MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( microel_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); diff --git a/applications/main/nfc/plugins/supported_cards/mizip.c b/applications/main/nfc/plugins/supported_cards/mizip.c index 240e6dc2f..501dae164 100644 --- a/applications/main/nfc/plugins/supported_cards/mizip.c +++ b/applications/main/nfc/plugins/supported_cards/mizip.c @@ -151,7 +151,7 @@ static bool mizip_read(Nfc* nfc, NfcDevice* device) { uint8_t keyB[MIZIP_KEY_TO_GEN][KEY_LENGTH]; mizip_generate_key(uid, keyA, keyB); - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { if(cfg.keys[i].a == 0x000000000000 && cfg.keys[i].b == 0x000000000000) { cfg.keys[i].a = bit_lib_bytes_to_num_be(keyA[i], KEY_LENGTH); cfg.keys[i].b = bit_lib_bytes_to_num_be(keyB[i], KEY_LENGTH); @@ -159,7 +159,7 @@ static bool mizip_read(Nfc* nfc, NfcDevice* device) { } MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(cfg.keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); bit_lib_num_to_bytes_be(cfg.keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/ndef.c b/applications/main/nfc/plugins/supported_cards/ndef.c index 86d31052e..ccdeb8c9d 100644 --- a/applications/main/nfc/plugins/supported_cards/ndef.c +++ b/applications/main/nfc/plugins/supported_cards/ndef.c @@ -899,7 +899,7 @@ static bool ndef_mfc_parse(const NfcDevice* device, FuriString* parsed_data) { // Check MADs for what sectors contain NDEF data AIDs bool sectors_with_ndef[MF_CLASSIC_TOTAL_SECTORS_MAX] = {0}; - const size_t sector_count = mf_classic_get_total_sectors_num(data->type); + const size_t sector_count = mf_classic_get_scannable_sectors_num(data->type); const struct { size_t block; uint8_t aid_count; diff --git a/applications/main/nfc/plugins/supported_cards/plantain.c b/applications/main/nfc/plugins/supported_cards/plantain.c index add7ab560..5bd4380fb 100644 --- a/applications/main/nfc/plugins/supported_cards/plantain.c +++ b/applications/main/nfc/plugins/supported_cards/plantain.c @@ -176,7 +176,7 @@ static bool plantain_read(Nfc* nfc, NfcDevice* device) { } MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(cfg.keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); bit_lib_num_to_bytes_be(cfg.keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/saflok.c b/applications/main/nfc/plugins/supported_cards/saflok.c index 5036dbffc..ba6ca0927 100644 --- a/applications/main/nfc/plugins/supported_cards/saflok.c +++ b/applications/main/nfc/plugins/supported_cards/saflok.c @@ -240,14 +240,14 @@ static bool saflok_read(Nfc* nfc, NfcDevice* device) { uint64_t num_key = bit_lib_bytes_to_num_be(key, KEY_LENGTH); FURI_LOG_D(TAG, "Saflok: Key generated for UID: %012llX", num_key); - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { if(saflok_1k_keys[i].a == 0x000000000000) { saflok_1k_keys[i].a = num_key; } } MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(saflok_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); bit_lib_num_to_bytes_be(saflok_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/skylanders.c b/applications/main/nfc/plugins/supported_cards/skylanders.c index b5dc0ab86..e57e9a785 100644 --- a/applications/main/nfc/plugins/supported_cards/skylanders.c +++ b/applications/main/nfc/plugins/supported_cards/skylanders.c @@ -124,7 +124,7 @@ static bool skylanders_read(Nfc* nfc, NfcDevice* device) { data->type = type; MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { if(i == 0) { bit_lib_num_to_bytes_be(skylanders_key, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); diff --git a/applications/main/nfc/plugins/supported_cards/smartrider.c b/applications/main/nfc/plugins/supported_cards/smartrider.c index 073f0410d..e53f0debe 100644 --- a/applications/main/nfc/plugins/supported_cards/smartrider.c +++ b/applications/main/nfc/plugins/supported_cards/smartrider.c @@ -134,7 +134,7 @@ static bool smartrider_read(Nfc* nfc, NfcDevice* device) { data->type = type; MfClassicDeviceKeys keys = {.key_a_mask = 0, .key_b_mask = 0}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { memcpy(keys.key_a[i].data, STANDARD_KEYS[i == 0 ? 0 : 1], sizeof(STANDARD_KEYS[0])); if(i > 0) { memcpy(keys.key_b[i].data, STANDARD_KEYS[2], sizeof(STANDARD_KEYS[0])); diff --git a/applications/main/nfc/plugins/supported_cards/social_moscow.c b/applications/main/nfc/plugins/supported_cards/social_moscow.c index ed2ee6c1d..6edf7307f 100644 --- a/applications/main/nfc/plugins/supported_cards/social_moscow.c +++ b/applications/main/nfc/plugins/supported_cards/social_moscow.c @@ -148,7 +148,7 @@ static bool social_moscow_read(Nfc* nfc, NfcDevice* device) { if(!social_moscow_get_card_config(&cfg, data->type)) break; MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(cfg.keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); bit_lib_num_to_bytes_be(cfg.keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/troika.c b/applications/main/nfc/plugins/supported_cards/troika.c index bd36d40e5..9183e8c0c 100644 --- a/applications/main/nfc/plugins/supported_cards/troika.c +++ b/applications/main/nfc/plugins/supported_cards/troika.c @@ -151,7 +151,7 @@ static bool troika_read(Nfc* nfc, NfcDevice* device) { .key_a_mask = 0, .key_b_mask = 0, }; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be(cfg.keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); bit_lib_num_to_bytes_be(cfg.keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data); diff --git a/applications/main/nfc/plugins/supported_cards/two_cities.c b/applications/main/nfc/plugins/supported_cards/two_cities.c index 240c6c585..3f9a26e26 100644 --- a/applications/main/nfc/plugins/supported_cards/two_cities.c +++ b/applications/main/nfc/plugins/supported_cards/two_cities.c @@ -76,7 +76,7 @@ static bool two_cities_read(Nfc* nfc, NfcDevice* device) { data->type = type; MfClassicDeviceKeys keys = {}; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( two_cities_4k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); diff --git a/applications/main/nfc/plugins/supported_cards/washcity.c b/applications/main/nfc/plugins/supported_cards/washcity.c index 22f207a1e..6ad9612d4 100644 --- a/applications/main/nfc/plugins/supported_cards/washcity.c +++ b/applications/main/nfc/plugins/supported_cards/washcity.c @@ -99,7 +99,7 @@ static bool washcity_read(Nfc* nfc, NfcDevice* device) { .key_a_mask = 0, .key_b_mask = 0, }; - for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) { + for(size_t i = 0; i < mf_classic_get_scannable_sectors_num(data->type); i++) { bit_lib_num_to_bytes_be( washcity_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data); FURI_BIT_SET(keys.key_a_mask, i); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index 420f6a834..89915ead8 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -59,7 +59,7 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context) mfc_event->data->poller_mode.data = mfc_data; instance->nfc_dict_context.sectors_total = - mf_classic_get_total_sectors_num(mfc_data->type); + mf_classic_get_scannable_sectors_num(mfc_data->type); mf_classic_get_read_sectors_and_keys( mfc_data, &instance->nfc_dict_context.sectors_read, diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_show_keys.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_show_keys.c index 9493f2e7a..844031552 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_show_keys.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_show_keys.c @@ -23,7 +23,7 @@ void nfc_scene_mf_classic_show_keys_on_enter(void* context) { furi_string_cat_printf(instance->text_box_store, "\e#Found MFC Keys:"); - uint8_t num_sectors = mf_classic_get_total_sectors_num(mfc_data->type); + uint8_t num_sectors = mf_classic_get_scannable_sectors_num(mfc_data->type); uint8_t found_keys_a = 0, found_keys_b = 0; for(uint8_t i = 0; i < num_sectors; i++) { MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(mfc_data, i); diff --git a/lib/nfc/protocols/mf_classic/mf_classic.c b/lib/nfc/protocols/mf_classic/mf_classic.c index b1c5c20c9..e90444a2a 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic.c +++ b/lib/nfc/protocols/mf_classic/mf_classic.c @@ -16,6 +16,8 @@ typedef struct { static const uint32_t mf_classic_data_format_version = 2; +#define MF_CLASSIC_PLUS2K_SCAN_SECTORS 18 + static const MfClassicFeatures mf_classic_features[MfClassicTypeNum] = { [MfClassicTypeMini] = { @@ -31,6 +33,14 @@ static const MfClassicFeatures mf_classic_features[MfClassicTypeNum] = { .full_name = "Mifare Classic 1K", .type_name = "1K", }, + [MfClassicTypePlus2k] = + { + // MIFARE Plus 2K SL1 maps like a 2K Classic: 32 sectors x 4 blocks + .sectors_total = 32, + .blocks_total = 128, + .full_name = "Mifare Plus 2K SL1", + .type_name = "Plus 2K", + }, [MfClassicType4k] = { .sectors_total = 40, @@ -387,6 +397,14 @@ uint8_t mf_classic_get_total_sectors_num(MfClassicType type) { return mf_classic_features[type].sectors_total; } +uint8_t mf_classic_get_scannable_sectors_num(MfClassicType type) { + uint8_t total = mf_classic_get_total_sectors_num(type); + if((type == MfClassicTypePlus2k) && (total > MF_CLASSIC_PLUS2K_SCAN_SECTORS)) { + return MF_CLASSIC_PLUS2K_SCAN_SECTORS; + } + return total; +} + uint16_t mf_classic_get_total_block_num(MfClassicType type) { furi_check(type < MfClassicTypeNum); return mf_classic_features[type].blocks_total; @@ -546,7 +564,7 @@ void mf_classic_set_key_not_found( MfClassicKey mf_classic_get_key(const MfClassicData* data, uint8_t sector_num, MfClassicKeyType key_type) { furi_check(data); - furi_check(sector_num < mf_classic_get_total_sectors_num(data->type)); + furi_check(sector_num < mf_classic_get_scannable_sectors_num(data->type)); furi_check(key_type == MfClassicKeyTypeA || key_type == MfClassicKeyTypeB); const MfClassicSectorTrailer* sector_trailer = @@ -606,7 +624,7 @@ void mf_classic_get_read_sectors_and_keys( *sectors_read = 0; *keys_found = 0; - uint8_t sectors_total = mf_classic_get_total_sectors_num(data->type); + uint8_t sectors_total = mf_classic_get_scannable_sectors_num(data->type); for(size_t i = 0; i < sectors_total; i++) { if(mf_classic_is_key_found(data, i, MfClassicKeyTypeA)) { *keys_found += 1; @@ -630,7 +648,7 @@ void mf_classic_get_read_sectors_and_keys( bool mf_classic_is_card_read(const MfClassicData* data) { furi_check(data); - uint8_t sectors_total = mf_classic_get_total_sectors_num(data->type); + uint8_t sectors_total = mf_classic_get_scannable_sectors_num(data->type); uint8_t sectors_read = 0; uint8_t keys_found = 0; mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found); diff --git a/lib/nfc/protocols/mf_classic/mf_classic.h b/lib/nfc/protocols/mf_classic/mf_classic.h index 6ae7a623e..282cb882d 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic.h +++ b/lib/nfc/protocols/mf_classic/mf_classic.h @@ -48,6 +48,7 @@ typedef enum { typedef enum { MfClassicTypeMini, MfClassicType1k, + MfClassicTypePlus2k, MfClassicType4k, MfClassicTypeNum, @@ -171,6 +172,8 @@ Iso14443_3aData* mf_classic_get_base_data(const MfClassicData* data); uint8_t mf_classic_get_total_sectors_num(MfClassicType type); +uint8_t mf_classic_get_scannable_sectors_num(MfClassicType type); + uint16_t mf_classic_get_total_block_num(MfClassicType type); uint8_t mf_classic_get_first_block_num_of_sector(uint8_t sector); diff --git a/lib/nfc/protocols/mf_classic/mf_classic_poller.c b/lib/nfc/protocols/mf_classic/mf_classic_poller.c index ae2f5467f..2c7777b6a 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_poller.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_poller.c @@ -134,6 +134,22 @@ NfcCommand mf_classic_poller_handler_detect_type(MfClassicPoller* instance) { instance->state = MfClassicPollerStateStart; instance->current_type_check = MfClassicType4k; FURI_LOG_D(TAG, "4K detected"); + } else { + instance->current_type_check = MfClassicTypePlus2k; + } + } else if(instance->current_type_check == MfClassicTypePlus2k) { + // Second-last block in sector 16, which may exist if said sector is not in SL3 mode + MfClassicError error = + mf_classic_poller_get_nt(instance, 66, MfClassicKeyTypeA, NULL, false); + if(error != MfClassicErrorNone) { + // If sector 16 is locked/SL3, try sector 17 as well before falling back + error = mf_classic_poller_get_nt(instance, 70, MfClassicKeyTypeA, NULL, false); + } + if(error == MfClassicErrorNone) { + instance->data->type = MfClassicTypePlus2k; + instance->state = MfClassicPollerStateStart; + instance->current_type_check = MfClassicType4k; + FURI_LOG_D(TAG, "Plus 2K detected"); } else { instance->current_type_check = MfClassicType1k; } @@ -157,7 +173,7 @@ NfcCommand mf_classic_poller_handler_detect_type(MfClassicPoller* instance) { NfcCommand mf_classic_poller_handler_start(MfClassicPoller* instance) { NfcCommand command = NfcCommandContinue; - instance->sectors_total = mf_classic_get_total_sectors_num(instance->data->type); + instance->sectors_total = mf_classic_get_scannable_sectors_num(instance->data->type); memset(&instance->mode_ctx, 0, sizeof(MfClassicPollerModeContext)); instance->mfc_event.type = MfClassicPollerEventTypeRequestMode; diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 1213d09e7..c38200a87 100755 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,87.1,, +Version,+,87.2,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, @@ -2695,6 +2695,7 @@ Function,+,mf_classic_get_device_name,const char*,"const MfClassicData*, NfcDevi Function,+,mf_classic_get_first_block_num_of_sector,uint8_t,uint8_t Function,+,mf_classic_get_key,MfClassicKey,"const MfClassicData*, uint8_t, MfClassicKeyType" Function,+,mf_classic_get_read_sectors_and_keys,void,"const MfClassicData*, uint8_t*, uint8_t*" +Function,+,mf_classic_get_scannable_sectors_num,uint8_t,MfClassicType Function,+,mf_classic_get_sector_by_block,uint8_t,uint8_t Function,+,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"const MfClassicData*, uint8_t" Function,+,mf_classic_get_sector_trailer_num_by_block,uint8_t,uint8_t