From e4e8a8ef2b3567359fcdf2554502aa01ac384912 Mon Sep 17 00:00:00 2001 From: Mykhailo Shevchuk Date: Tue, 7 Jul 2026 23:08:54 +0300 Subject: [PATCH] [NFC] Trim MIFARE Plus generator & admin-key mapping (in-place cleanup) (#1035) * [NFC] Data-drive MIFARE Plus manual-add generators Replace the 18 near-identical MIFARE Plus generator thunks and their handler-table entries with a data-driven mf_plus_generator_configs[] table (uid_len / type / size / ATS per variant), dispatched via a small range predicate. The Ultralight/NTAG and Classic types keep their bespoke handlers, so the handler table now stops before the MF Plus range. Also drop mf_plus_ats_hist_ev, which was byte-identical to mf_plus_ats_hist_s (EV1/EV2 are identified by GetVersion, not the ATS). Pure refactor: the Add-Manually menu entries, the generated cards and the public SDK API are all unchanged. Trims firmware flash by removing the per-variant functions and the duplicate blob; a _Static_assert pins the config table to the enum range so a future type can't desync it. Co-Authored-By: Claude Opus 4.8 * [NFC] MIFARE Plus: single source for admin-key addresses Fold the three copies of the admin-key address<->type mapping (0x9000 CardMaster, 0x9001 CardConfig, 0x9003 L3Switch, 0x9004 SL1CardAuth) into one mf_plus_admin_key_addresses[] table with a forward helper (mf_plus_get_admin_key_address, replaces the poller's local id array) and a reverse helper (mf_plus_admin_key_type_from_address, replaces two identical switch statements in the listener's key-resolve and write-store paths). Behavior-preserving: both listener default fall-throughs are kept (resolve returns false; store falls through to data/config block handling), the poller authenticates the same addresses, and a _Static_assert pins the table to MfPlusAdminKeyNum. Internal helpers only; no SDK API change. Co-Authored-By: Claude Opus 4.8 * [NFC] Changelog: MIFARE Plus generator/admin-map cleanup Co-Authored-By: Claude Opus 4.8 --------- Co-authored-by: Claude Opus 4.8 --- CHANGELOG.md | 1 + lib/nfc/helpers/nfc_data_generator.c | 225 +++++------------- lib/nfc/protocols/mf_plus/mf_plus_i.c | 38 +++ lib/nfc/protocols/mf_plus/mf_plus_i.h | 5 + .../protocols/mf_plus/mf_plus_listener_i.c | 37 +-- lib/nfc/protocols/mf_plus/mf_plus_poller.c | 14 +- 6 files changed, 111 insertions(+), 209 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 722a6c715..570dac3e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * Fix BLE sync, fix possible delay related issues * Disabled debug and trace logs in the FW binary (apps .fap's are not affected) to free up some flash space for new features * NFC: Fix typo in SLIX poller (by @WillyJL) +* NFC: Internal MIFARE Plus cleanup - data-drive the "Add Manually" generator variants and unify the admin-key address mapping into one source of truth; small internal-flash saving, no functional change (by @mishamyte | PR #1035)

---- diff --git a/lib/nfc/helpers/nfc_data_generator.c b/lib/nfc/helpers/nfc_data_generator.c index c82152e54..fe0c2f53c 100644 --- a/lib/nfc/helpers/nfc_data_generator.c +++ b/lib/nfc/helpers/nfc_data_generator.c @@ -446,15 +446,13 @@ static void nfc_generate_mf_classic_4k_7b_uid(NfcDevice* nfc_device) { // detection (see mf_plus_type_from_ats): S/X mask their size with 2F 2F and differ by the caps // byte's SVC bit; SE reveals 21 30. The trailing CRC16 floats between configs -- the SE value is a // real capture (77 C1), the S/X values are AN10833. EV1/EV2 identify via GetVersion, not the ATS, so -// they reuse the generic Plus block. +// they reuse the byte-identical S block. static const uint8_t mf_plus_ats_hist_se[MF_PLUS_ATS_HIST_LEN] = {0xC1, 0x05, 0x21, 0x30, 0x00, 0x77, 0xC1}; static const uint8_t mf_plus_ats_hist_s[MF_PLUS_ATS_HIST_LEN] = {0xC1, 0x05, 0x2F, 0x2F, 0x00, 0x35, 0xC7}; static const uint8_t mf_plus_ats_hist_x[MF_PLUS_ATS_HIST_LEN] = {0xC1, 0x05, 0x2F, 0x2F, 0x01, 0xBC, 0xD6}; -static const uint8_t mf_plus_ats_hist_ev[MF_PLUS_ATS_HIST_LEN] = - {0xC1, 0x05, 0x2F, 0x2F, 0x00, 0x35, 0xC7}; // EV1/EV2 answer GetVersion; fill a plausible response. hw_type low nibble 0x02 = Plus, hw_major // 0x11/0x22 = EV1/EV2, hw_storage 0x16/0x18 = 2K/4K (matches mf_plus_get_type_from_version). The @@ -616,79 +614,52 @@ static void nfc_generate_mf_plus( mf_plus_free(data); } -static void nfc_generate_mf_plus_se_4b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 4, MfPlusTypeSE, MfPlusSize1K, mf_plus_ats_hist_se); +// The 18 MIFARE Plus variants differ only by parameters (UID length, product type, memory size and +// ATS historical bytes), so they are data-driven from this table rather than a thunk each. Indexed +// by (type - NfcDataGeneratorTypeMfPlusSE_4b), so the row order must track the enum. EV1/EV2 reuse +// the S ATS block (byte-identical; those products are identified by GetVersion, not the ATS). +typedef struct { + const char* name; + uint8_t uid_len; + uint8_t type; // MfPlusType + uint8_t size; // MfPlusSize + const uint8_t* ats_hist; +} MfPlusGeneratorConfig; + +static const MfPlusGeneratorConfig mf_plus_generator_configs[] = { + {"Mifare Plus SE 4byte UID", 4, MfPlusTypeSE, MfPlusSize1K, mf_plus_ats_hist_se}, + {"Mifare Plus SE 7byte UID", 7, MfPlusTypeSE, MfPlusSize1K, mf_plus_ats_hist_se}, + {"Mifare Plus S 2K 4byte UID", 4, MfPlusTypeS, MfPlusSize2K, mf_plus_ats_hist_s}, + {"Mifare Plus S 2K 7byte UID", 7, MfPlusTypeS, MfPlusSize2K, mf_plus_ats_hist_s}, + {"Mifare Plus S 4K 4byte UID", 4, MfPlusTypeS, MfPlusSize4K, mf_plus_ats_hist_s}, + {"Mifare Plus S 4K 7byte UID", 7, MfPlusTypeS, MfPlusSize4K, mf_plus_ats_hist_s}, + {"Mifare Plus X 2K 4byte UID", 4, MfPlusTypeX, MfPlusSize2K, mf_plus_ats_hist_x}, + {"Mifare Plus X 2K 7byte UID", 7, MfPlusTypeX, MfPlusSize2K, mf_plus_ats_hist_x}, + {"Mifare Plus X 4K 4byte UID", 4, MfPlusTypeX, MfPlusSize4K, mf_plus_ats_hist_x}, + {"Mifare Plus X 4K 7byte UID", 7, MfPlusTypeX, MfPlusSize4K, mf_plus_ats_hist_x}, + {"Mifare Plus EV1 2K 4byte UID", 4, MfPlusTypeEV1, MfPlusSize2K, mf_plus_ats_hist_s}, + {"Mifare Plus EV1 2K 7byte UID", 7, MfPlusTypeEV1, MfPlusSize2K, mf_plus_ats_hist_s}, + {"Mifare Plus EV1 4K 4byte UID", 4, MfPlusTypeEV1, MfPlusSize4K, mf_plus_ats_hist_s}, + {"Mifare Plus EV1 4K 7byte UID", 7, MfPlusTypeEV1, MfPlusSize4K, mf_plus_ats_hist_s}, + {"Mifare Plus EV2 2K 4byte UID", 4, MfPlusTypeEV2, MfPlusSize2K, mf_plus_ats_hist_s}, + {"Mifare Plus EV2 2K 7byte UID", 7, MfPlusTypeEV2, MfPlusSize2K, mf_plus_ats_hist_s}, + {"Mifare Plus EV2 4K 4byte UID", 4, MfPlusTypeEV2, MfPlusSize4K, mf_plus_ats_hist_s}, + {"Mifare Plus EV2 4K 7byte UID", 7, MfPlusTypeEV2, MfPlusSize4K, mf_plus_ats_hist_s}, +}; + +_Static_assert( + COUNT_OF(mf_plus_generator_configs) == + (size_t)(NfcDataGeneratorTypeMfPlusEV2_4k_7b - NfcDataGeneratorTypeMfPlusSE_4b + 1), + "mf_plus_generator_configs must cover every MIFARE Plus generator type"); + +static bool nfc_data_generator_type_is_mf_plus(NfcDataGeneratorType type) { + return type >= NfcDataGeneratorTypeMfPlusSE_4b && type <= NfcDataGeneratorTypeMfPlusEV2_4k_7b; } -static void nfc_generate_mf_plus_se_7b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 7, MfPlusTypeSE, MfPlusSize1K, mf_plus_ats_hist_se); -} - -static void nfc_generate_mf_plus_s2k_4b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 4, MfPlusTypeS, MfPlusSize2K, mf_plus_ats_hist_s); -} - -static void nfc_generate_mf_plus_s2k_7b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 7, MfPlusTypeS, MfPlusSize2K, mf_plus_ats_hist_s); -} - -static void nfc_generate_mf_plus_s4k_4b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 4, MfPlusTypeS, MfPlusSize4K, mf_plus_ats_hist_s); -} - -static void nfc_generate_mf_plus_s4k_7b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 7, MfPlusTypeS, MfPlusSize4K, mf_plus_ats_hist_s); -} - -static void nfc_generate_mf_plus_x2k_4b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 4, MfPlusTypeX, MfPlusSize2K, mf_plus_ats_hist_x); -} - -static void nfc_generate_mf_plus_x2k_7b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 7, MfPlusTypeX, MfPlusSize2K, mf_plus_ats_hist_x); -} - -static void nfc_generate_mf_plus_x4k_4b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 4, MfPlusTypeX, MfPlusSize4K, mf_plus_ats_hist_x); -} - -static void nfc_generate_mf_plus_x4k_7b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 7, MfPlusTypeX, MfPlusSize4K, mf_plus_ats_hist_x); -} - -static void nfc_generate_mf_plus_ev1_2k_4b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 4, MfPlusTypeEV1, MfPlusSize2K, mf_plus_ats_hist_ev); -} - -static void nfc_generate_mf_plus_ev1_2k_7b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 7, MfPlusTypeEV1, MfPlusSize2K, mf_plus_ats_hist_ev); -} - -static void nfc_generate_mf_plus_ev1_4k_4b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 4, MfPlusTypeEV1, MfPlusSize4K, mf_plus_ats_hist_ev); -} - -static void nfc_generate_mf_plus_ev1_4k_7b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 7, MfPlusTypeEV1, MfPlusSize4K, mf_plus_ats_hist_ev); -} - -static void nfc_generate_mf_plus_ev2_2k_4b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 4, MfPlusTypeEV2, MfPlusSize2K, mf_plus_ats_hist_ev); -} - -static void nfc_generate_mf_plus_ev2_2k_7b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 7, MfPlusTypeEV2, MfPlusSize2K, mf_plus_ats_hist_ev); -} - -static void nfc_generate_mf_plus_ev2_4k_4b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 4, MfPlusTypeEV2, MfPlusSize4K, mf_plus_ats_hist_ev); -} - -static void nfc_generate_mf_plus_ev2_4k_7b(NfcDevice* nfc_device) { - nfc_generate_mf_plus(nfc_device, 7, MfPlusTypeEV2, MfPlusSize4K, mf_plus_ats_hist_ev); -} - -static const NfcDataGenerator nfc_data_generator[NfcDataGeneratorTypeNum] = { +// Handler-based table for the Ultralight/NTAG and Classic types, whose per-variant layouts are +// bespoke. The MIFARE Plus types are parametric and dispatched from mf_plus_generator_configs, so +// this table intentionally stops before them. +static const NfcDataGenerator nfc_data_generator[NfcDataGeneratorTypeMfPlusSE_4b] = { [NfcDataGeneratorTypeMfUltralight] = { .name = "Mifare Ultralight", @@ -779,101 +750,15 @@ static const NfcDataGenerator nfc_data_generator[NfcDataGeneratorTypeNum] = { .name = "Mifare Classic 4k 7byte UID", .handler = nfc_generate_mf_classic_4k_7b_uid, }, - [NfcDataGeneratorTypeMfPlusSE_4b] = - { - .name = "Mifare Plus SE 4byte UID", - .handler = nfc_generate_mf_plus_se_4b, - }, - [NfcDataGeneratorTypeMfPlusSE_7b] = - { - .name = "Mifare Plus SE 7byte UID", - .handler = nfc_generate_mf_plus_se_7b, - }, - [NfcDataGeneratorTypeMfPlusS2k_4b] = - { - .name = "Mifare Plus S 2K 4byte UID", - .handler = nfc_generate_mf_plus_s2k_4b, - }, - [NfcDataGeneratorTypeMfPlusS2k_7b] = - { - .name = "Mifare Plus S 2K 7byte UID", - .handler = nfc_generate_mf_plus_s2k_7b, - }, - [NfcDataGeneratorTypeMfPlusS4k_4b] = - { - .name = "Mifare Plus S 4K 4byte UID", - .handler = nfc_generate_mf_plus_s4k_4b, - }, - [NfcDataGeneratorTypeMfPlusS4k_7b] = - { - .name = "Mifare Plus S 4K 7byte UID", - .handler = nfc_generate_mf_plus_s4k_7b, - }, - [NfcDataGeneratorTypeMfPlusX2k_4b] = - { - .name = "Mifare Plus X 2K 4byte UID", - .handler = nfc_generate_mf_plus_x2k_4b, - }, - [NfcDataGeneratorTypeMfPlusX2k_7b] = - { - .name = "Mifare Plus X 2K 7byte UID", - .handler = nfc_generate_mf_plus_x2k_7b, - }, - [NfcDataGeneratorTypeMfPlusX4k_4b] = - { - .name = "Mifare Plus X 4K 4byte UID", - .handler = nfc_generate_mf_plus_x4k_4b, - }, - [NfcDataGeneratorTypeMfPlusX4k_7b] = - { - .name = "Mifare Plus X 4K 7byte UID", - .handler = nfc_generate_mf_plus_x4k_7b, - }, - [NfcDataGeneratorTypeMfPlusEV1_2k_4b] = - { - .name = "Mifare Plus EV1 2K 4byte UID", - .handler = nfc_generate_mf_plus_ev1_2k_4b, - }, - [NfcDataGeneratorTypeMfPlusEV1_2k_7b] = - { - .name = "Mifare Plus EV1 2K 7byte UID", - .handler = nfc_generate_mf_plus_ev1_2k_7b, - }, - [NfcDataGeneratorTypeMfPlusEV1_4k_4b] = - { - .name = "Mifare Plus EV1 4K 4byte UID", - .handler = nfc_generate_mf_plus_ev1_4k_4b, - }, - [NfcDataGeneratorTypeMfPlusEV1_4k_7b] = - { - .name = "Mifare Plus EV1 4K 7byte UID", - .handler = nfc_generate_mf_plus_ev1_4k_7b, - }, - [NfcDataGeneratorTypeMfPlusEV2_2k_4b] = - { - .name = "Mifare Plus EV2 2K 4byte UID", - .handler = nfc_generate_mf_plus_ev2_2k_4b, - }, - [NfcDataGeneratorTypeMfPlusEV2_2k_7b] = - { - .name = "Mifare Plus EV2 2K 7byte UID", - .handler = nfc_generate_mf_plus_ev2_2k_7b, - }, - [NfcDataGeneratorTypeMfPlusEV2_4k_4b] = - { - .name = "Mifare Plus EV2 4K 4byte UID", - .handler = nfc_generate_mf_plus_ev2_4k_4b, - }, - [NfcDataGeneratorTypeMfPlusEV2_4k_7b] = - { - .name = "Mifare Plus EV2 4K 7byte UID", - .handler = nfc_generate_mf_plus_ev2_4k_7b, - }, }; const char* nfc_data_generator_get_name(NfcDataGeneratorType type) { furi_check(type < NfcDataGeneratorTypeNum); + if(nfc_data_generator_type_is_mf_plus(type)) { + return mf_plus_generator_configs[type - NfcDataGeneratorTypeMfPlusSE_4b].name; + } + return nfc_data_generator[type].name; } @@ -881,5 +766,17 @@ void nfc_data_generator_fill_data(NfcDataGeneratorType type, NfcDevice* nfc_devi furi_check(type < NfcDataGeneratorTypeNum); furi_check(nfc_device); + if(nfc_data_generator_type_is_mf_plus(type)) { + const MfPlusGeneratorConfig* config = + &mf_plus_generator_configs[type - NfcDataGeneratorTypeMfPlusSE_4b]; + nfc_generate_mf_plus( + nfc_device, + config->uid_len, + (MfPlusType)config->type, + (MfPlusSize)config->size, + config->ats_hist); + return; + } + nfc_data_generator[type].handler(nfc_device); } diff --git a/lib/nfc/protocols/mf_plus/mf_plus_i.c b/lib/nfc/protocols/mf_plus/mf_plus_i.c index e541208db..845f70ffd 100644 --- a/lib/nfc/protocols/mf_plus/mf_plus_i.c +++ b/lib/nfc/protocols/mf_plus/mf_plus_i.c @@ -444,6 +444,44 @@ const char* mf_plus_get_admin_key_name(MfPlusAdminKeyType type) { return mf_plus_admin_key_names[type]; } +// Single source of truth for the admin keys' 0x90xx auth addresses. The enum skips 0x9002 (the +// SL2->SL3 key we never recover), so this is a table rather than 0x9000 + index. Both the poller +// (which address to authenticate) and the listener (which key a reader is addressing) derive from it. +typedef struct { + uint16_t address; + MfPlusAdminKeyType type; +} MfPlusAdminKeyAddress; + +static const MfPlusAdminKeyAddress mf_plus_admin_key_addresses[] = { + {0x9000, MfPlusAdminKeyCardMaster}, + {0x9001, MfPlusAdminKeyCardConfig}, + {0x9003, MfPlusAdminKeyL3Switch}, + {0x9004, MfPlusAdminKeySL1CardAuth}, +}; + +_Static_assert( + COUNT_OF(mf_plus_admin_key_addresses) == MfPlusAdminKeyNum, + "mf_plus_admin_key_addresses must cover every admin key type"); + +uint16_t mf_plus_get_admin_key_address(MfPlusAdminKeyType type) { + for(size_t i = 0; i < COUNT_OF(mf_plus_admin_key_addresses); i++) { + if(mf_plus_admin_key_addresses[i].type == type) { + return mf_plus_admin_key_addresses[i].address; + } + } + furi_crash("Invalid MfPlusAdminKeyType"); +} + +bool mf_plus_admin_key_type_from_address(uint16_t address, MfPlusAdminKeyType* type) { + for(size_t i = 0; i < COUNT_OF(mf_plus_admin_key_addresses); i++) { + if(mf_plus_admin_key_addresses[i].address == address) { + *type = mf_plus_admin_key_addresses[i].type; + return true; + } + } + return false; +} + // Lock the mask-fits-domain invariants at compile time. _Static_assert(MfPlusAdminKeyNum <= 8, "admin_key_mask (uint8_t) too small"); _Static_assert(MF_PLUS_CONFIG_BLOCK_NUM <= 8, "config_read_mask (uint8_t) too small"); diff --git a/lib/nfc/protocols/mf_plus/mf_plus_i.h b/lib/nfc/protocols/mf_plus/mf_plus_i.h index 2985fd145..b21d9948e 100644 --- a/lib/nfc/protocols/mf_plus/mf_plus_i.h +++ b/lib/nfc/protocols/mf_plus/mf_plus_i.h @@ -50,6 +50,11 @@ void mf_plus_set_admin_key_found(MfPlusData* data, MfPlusAdminKeyType type, cons void mf_plus_set_config_block_read(MfPlusData* data, uint8_t index, const MfPlusBlock* block); +// Map an admin key <-> its 0x90xx auth address (single source: mf_plus_admin_key_addresses). +uint16_t mf_plus_get_admin_key_address(MfPlusAdminKeyType type); + +bool mf_plus_admin_key_type_from_address(uint16_t address, MfPlusAdminKeyType* type); + // Serialize / parse the SL3 payload (data format version, signature, blocks, keys, config). // Save writes the payload after the identity metadata; load tolerates legacy dumps that have // no "Data format version" key (returns true, leaving the SL3 fields zeroed). diff --git a/lib/nfc/protocols/mf_plus/mf_plus_listener_i.c b/lib/nfc/protocols/mf_plus/mf_plus_listener_i.c index 7139e0f05..8e5a942c0 100644 --- a/lib/nfc/protocols/mf_plus/mf_plus_listener_i.c +++ b/lib/nfc/protocols/mf_plus/mf_plus_listener_i.c @@ -59,22 +59,7 @@ static bool } MfPlusAdminKeyType admin_type; - switch(key_id) { - case 0x9000: - admin_type = MfPlusAdminKeyCardMaster; - break; - case 0x9001: - admin_type = MfPlusAdminKeyCardConfig; - break; - case 0x9003: - admin_type = MfPlusAdminKeyL3Switch; - break; - case 0x9004: - admin_type = MfPlusAdminKeySL1CardAuth; - break; - default: - return false; - } + if(!mf_plus_admin_key_type_from_address(key_id, &admin_type)) return false; if(!mf_plus_is_admin_key_found(data, admin_type)) return false; *key = data->admin_key[admin_type]; return true; @@ -291,25 +276,7 @@ static bool mf_plus_listener_store_write( } MfPlusAdminKeyType admin_type; - bool is_admin = true; - switch(block_addr) { - case 0x9000: - admin_type = MfPlusAdminKeyCardMaster; - break; - case 0x9001: - admin_type = MfPlusAdminKeyCardConfig; - break; - case 0x9003: - admin_type = MfPlusAdminKeyL3Switch; - break; - case 0x9004: - admin_type = MfPlusAdminKeySL1CardAuth; - break; - default: - is_admin = false; - break; - } - if(is_admin) { + if(mf_plus_admin_key_type_from_address(block_addr, &admin_type)) { MfPlusKey key; memcpy(key.data, plain, MF_PLUS_KEY_SIZE); mf_plus_set_admin_key_found(data, admin_type, &key); diff --git a/lib/nfc/protocols/mf_plus/mf_plus_poller.c b/lib/nfc/protocols/mf_plus/mf_plus_poller.c index 20fa55b07..223d16a5e 100644 --- a/lib/nfc/protocols/mf_plus/mf_plus_poller.c +++ b/lib/nfc/protocols/mf_plus/mf_plus_poller.c @@ -151,15 +151,6 @@ static NfcCommand mf_plus_poller_handler_read_success(MfPlusPoller* instance) { return command; } -// Auth addresses for the admin keys we recover, indexed by MfPlusAdminKeyType. The enum skips -// 0x9002 (SL2 switch), so this is not simply 0x9000 + index. -static const uint16_t mf_plus_admin_key_id[MfPlusAdminKeyNum] = { - [MfPlusAdminKeyCardMaster] = 0x9000, - [MfPlusAdminKeyCardConfig] = 0x9001, - [MfPlusAdminKeyL3Switch] = 0x9003, - [MfPlusAdminKeySL1CardAuth] = 0x9004, -}; - #define MF_PLUS_CONFIG_BLOCK_HIGH (0xB0) // config blocks live at 0xB000..0xB003 // Advance the read scan to the next (sector, key type): key A -> key B for the same sector, then @@ -438,7 +429,10 @@ static NfcCommand mf_plus_poller_handler_auth_admin_key(MfPlusPoller* instance) const MfPlusAdminKeyType admin_type = (MfPlusAdminKeyType)instance->current_admin; MfPlusError error = mf_plus_poller_authenticate_key_id( - instance, mf_plus_admin_key_id[admin_type], &instance->current_key, &instance->session); + instance, + mf_plus_get_admin_key_address(admin_type), + &instance->current_key, + &instance->session); if(error == MfPlusErrorNone) { mf_plus_set_admin_key_found(instance->data, admin_type, &instance->current_key);