Skip to content

Commit 5f52382

Browse files
GMMangornekichskotopes
authored
nfc: Mifare Ultralight C detection (#2668)
* nfc: Add Mifare Ultralight C detection * nfc: Add display name for MFUL C and hide menu items MFUL C unlock and emulation currently not supported, so hide from menu if current card is MFUL C * nfc: Also check response when probing 3DES auth * nfc: Hide emulate option in saved menu for MFUL if not supported * nfc: Remove unlock options from saved menu if Ultralight C Co-authored-by: gornekich <[email protected]> Co-authored-by: あく <[email protected]>
1 parent cce0485 commit 5f52382

File tree

6 files changed

+56
-14
lines changed

6 files changed

+56
-14
lines changed

applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) {
1919
Submenu* submenu = nfc->submenu;
2020
MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data;
2121

22-
if(!mf_ul_is_full_capture(data)) {
22+
if(!mf_ul_is_full_capture(data) && data->type != MfUltralightTypeULC) {
2323
submenu_add_item(
2424
submenu,
2525
"Unlock",
@@ -29,12 +29,14 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) {
2929
}
3030
submenu_add_item(
3131
submenu, "Save", SubmenuIndexSave, nfc_scene_mf_ultralight_menu_submenu_callback, nfc);
32-
submenu_add_item(
33-
submenu,
34-
"Emulate",
35-
SubmenuIndexEmulate,
36-
nfc_scene_mf_ultralight_menu_submenu_callback,
37-
nfc);
32+
if(mf_ul_emulation_supported(data)) {
33+
submenu_add_item(
34+
submenu,
35+
"Emulate",
36+
SubmenuIndexEmulate,
37+
nfc_scene_mf_ultralight_menu_submenu_callback,
38+
nfc);
39+
}
3840
submenu_add_item(
3941
submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_ultralight_menu_submenu_callback, nfc);
4042

applications/main/nfc/scenes/nfc_scene_saved_menu.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ void nfc_scene_saved_menu_on_enter(void* context) {
4242
nfc);
4343
}
4444
} else if(
45-
nfc->dev->format == NfcDeviceSaveFormatMifareUl ||
45+
(nfc->dev->format == NfcDeviceSaveFormatMifareUl &&
46+
mf_ul_emulation_supported(&nfc->dev->dev_data.mf_ul_data)) ||
4647
nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
4748
submenu_add_item(
4849
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
@@ -72,6 +73,7 @@ void nfc_scene_saved_menu_on_enter(void* context) {
7273
submenu_add_item(
7374
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
7475
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl &&
76+
nfc->dev->dev_data.mf_ul_data.type != MfUltralightTypeULC &&
7577
!mf_ul_is_full_capture(&nfc->dev->dev_data.mf_ul_data)) {
7678
submenu_add_item(
7779
submenu,

firmware/targets/f7/api_symbols.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,7 @@ Function,-,mf_df_prepare_read_records,uint16_t,"uint8_t*, uint8_t, uint32_t, uin
20132013
Function,-,mf_df_prepare_select_application,uint16_t,"uint8_t*, uint8_t[3]"
20142014
Function,-,mf_df_read_card,_Bool,"FuriHalNfcTxRxContext*, MifareDesfireData*"
20152015
Function,-,mf_ul_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
2016+
Function,-,mf_ul_emulation_supported,_Bool,MfUltralightData*
20162017
Function,-,mf_ul_is_full_capture,_Bool,MfUltralightData*
20172018
Function,-,mf_ul_prepare_emulation,void,"MfUltralightEmulator*, MfUltralightData*"
20182019
Function,-,mf_ul_prepare_emulation_response,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*"

lib/nfc/nfc_types.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) {
4545
return "NTAG I2C Plus 2K";
4646
} else if(type == MfUltralightTypeNTAG203) {
4747
return "NTAG203";
48+
} else if(type == MfUltralightTypeULC) {
49+
return "Mifare Ultralight C";
4850
} else if(type == MfUltralightTypeUL11 && full_name) {
4951
return "Mifare Ultralight 11";
5052
} else if(type == MfUltralightTypeUL21 && full_name) {

lib/nfc/protocols/mifare_ultralight.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ static MfUltralightFeatures mf_ul_get_features(MfUltralightType type) {
7979
MfUltralightSupportSectorSelect;
8080
case MfUltralightTypeNTAG203:
8181
return MfUltralightSupportCompatWrite | MfUltralightSupportCounterInMemory;
82+
case MfUltralightTypeULC:
83+
return MfUltralightSupportCompatWrite | MfUltralightSupport3DesAuth;
8284
default:
8385
// Assumed original MFUL 512-bit
8486
return MfUltralightSupportCompatWrite;
@@ -95,6 +97,11 @@ static void mf_ul_set_version_ntag203(MfUltralightReader* reader, MfUltralightDa
9597
reader->pages_to_read = 42;
9698
}
9799

100+
static void mf_ul_set_version_ulc(MfUltralightReader* reader, MfUltralightData* data) {
101+
data->type = MfUltralightTypeULC;
102+
reader->pages_to_read = 48;
103+
}
104+
98105
bool mf_ultralight_read_version(
99106
FuriHalNfcTxRxContext* tx_rx,
100107
MfUltralightReader* reader,
@@ -175,7 +182,7 @@ bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint
175182

176183
do {
177184
FURI_LOG_D(TAG, "Authenticating");
178-
tx_rx->tx_data[0] = MF_UL_AUTH;
185+
tx_rx->tx_data[0] = MF_UL_PWD_AUTH;
179186
nfc_util_num2bytes(key, 4, &tx_rx->tx_data[1]);
180187
tx_rx->tx_bits = 40;
181188
tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault;
@@ -716,6 +723,21 @@ bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralight
716723
return flag_read == 2;
717724
}
718725

726+
static bool mf_ul_probe_3des_auth(FuriHalNfcTxRxContext* tx_rx) {
727+
tx_rx->tx_data[0] = MF_UL_AUTHENTICATE_1;
728+
tx_rx->tx_data[1] = 0;
729+
tx_rx->tx_bits = 16;
730+
tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault;
731+
bool rc = furi_hal_nfc_tx_rx(tx_rx, 50) && tx_rx->rx_bits == 9 * 8 &&
732+
tx_rx->rx_data[0] == 0xAF;
733+
734+
// Reset just in case, we're not going to finish authenticating and need to if tag doesn't support auth
735+
furi_hal_nfc_sleep();
736+
furi_hal_nfc_activate_nfca(300, NULL);
737+
738+
return rc;
739+
}
740+
719741
bool mf_ul_read_card(
720742
FuriHalNfcTxRxContext* tx_rx,
721743
MfUltralightReader* reader,
@@ -733,16 +755,20 @@ bool mf_ul_read_card(
733755
mf_ultralight_read_signature(tx_rx, data);
734756
}
735757
} else {
736-
// No GET_VERSION command, check for NTAG203 by reading last page (41)
737758
uint8_t dummy[16];
738-
if(mf_ultralight_read_pages_direct(tx_rx, 41, dummy)) {
759+
// No GET_VERSION command, check if AUTHENTICATE command available (detect UL C).
760+
if(mf_ul_probe_3des_auth(tx_rx)) {
761+
mf_ul_set_version_ulc(reader, data);
762+
} else if(mf_ultralight_read_pages_direct(tx_rx, 41, dummy)) {
763+
// No AUTHENTICATE, check for NTAG203 by reading last page (41)
739764
mf_ul_set_version_ntag203(reader, data);
740-
reader->supported_features = mf_ul_get_features(data->type);
741765
} else {
742766
// We're really an original Mifare Ultralight, reset tag for safety
743767
furi_hal_nfc_sleep();
744768
furi_hal_nfc_activate_nfca(300, NULL);
745769
}
770+
771+
reader->supported_features = mf_ul_get_features(data->type);
746772
}
747773

748774
card_read = mf_ultralight_read_pages(tx_rx, reader, data);
@@ -1228,6 +1254,10 @@ static void mf_ul_emulate_write(
12281254
emulator->data_changed = true;
12291255
}
12301256

1257+
bool mf_ul_emulation_supported(MfUltralightData* data) {
1258+
return data->type != MfUltralightTypeULC;
1259+
}
1260+
12311261
void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle) {
12321262
emulator->comp_write_cmd_started = false;
12331263
emulator->sector_select_cmd_started = false;
@@ -1732,7 +1762,7 @@ bool mf_ul_prepare_emulation_response(
17321762
}
17331763
}
17341764
}
1735-
} else if(cmd == MF_UL_AUTH) {
1765+
} else if(cmd == MF_UL_PWD_AUTH) {
17361766
if(emulator->supported_features & MfUltralightSupportAuth) {
17371767
if(buff_rx_len == (1 + 4) * 8) {
17381768
// Record password sent by PCD

lib/nfc/protocols/mifare_ultralight.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
#define MF_UL_COMP_WRITE (0xA0)
1717
#define MF_UL_READ_CNT (0x39)
1818
#define MF_UL_INC_CNT (0xA5)
19-
#define MF_UL_AUTH (0x1B)
19+
#define MF_UL_AUTHENTICATE_1 (0x1A)
20+
#define MF_UL_PWD_AUTH (0x1B)
2021
#define MF_UL_READ_SIG (0x3C)
2122
#define MF_UL_CHECK_TEARING (0x3E)
2223
#define MF_UL_READ_VCSL (0x4B)
@@ -41,6 +42,7 @@ typedef enum {
4142
typedef enum {
4243
MfUltralightTypeUnknown,
4344
MfUltralightTypeNTAG203,
45+
MfUltralightTypeULC,
4446
// Below have config pages and GET_VERSION support
4547
MfUltralightTypeUL11,
4648
MfUltralightTypeUL21,
@@ -77,6 +79,7 @@ typedef enum {
7779
MfUltralightSupportAsciiMirror = 1 << 11,
7880
// NTAG203 counter that's in memory rather than through a command
7981
MfUltralightSupportCounterInMemory = 1 << 12,
82+
MfUltralightSupport3DesAuth = 1 << 13,
8083
} MfUltralightFeatures;
8184

8285
typedef enum {
@@ -237,6 +240,8 @@ bool mf_ul_read_card(
237240
MfUltralightReader* reader,
238241
MfUltralightData* data);
239242

243+
bool mf_ul_emulation_supported(MfUltralightData* data);
244+
240245
void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle);
241246

242247
void mf_ul_prepare_emulation(MfUltralightEmulator* emulator, MfUltralightData* data);

0 commit comments

Comments
 (0)