mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-16 20:09:44 -07:00
Add Mifare Mini, fix char type & fix sector reads in edge-cases
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,12.0,,
|
||||
Version,+,12.1,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@@ -1913,7 +1913,7 @@ Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*"
|
||||
Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*"
|
||||
Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict*
|
||||
Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*"
|
||||
Function,-,mf_classic_get_classic_type,MfClassicType,"int8_t, uint8_t, uint8_t"
|
||||
Function,-,mf_classic_get_classic_type,MfClassicType,"uint8_t, uint8_t, uint8_t"
|
||||
Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*"
|
||||
Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t
|
||||
Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t
|
||||
|
||||
|
@@ -352,11 +352,27 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType
|
||||
}
|
||||
// Set SAK to 08
|
||||
data->nfc_data.sak = 0x08;
|
||||
} else if(type == MfClassicTypeMini) {
|
||||
// Set every block to 0xFF
|
||||
for(uint16_t i = 1; i < MF_MINI_TOTAL_SECTORS_NUM * 4; i += 1) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
nfc_generate_mf_classic_sector_trailer(mfc, i);
|
||||
} else {
|
||||
memset(&mfc->block[i].value, 0xFF, 16);
|
||||
}
|
||||
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
|
||||
}
|
||||
// Set SAK to 09
|
||||
data->nfc_data.sak = 0x09;
|
||||
}
|
||||
|
||||
mfc->type = type;
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_mini(NfcDeviceData* data) {
|
||||
nfc_generate_mf_classic(data, 4, MfClassicTypeMini);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_1k_4b_uid(NfcDeviceData* data) {
|
||||
nfc_generate_mf_classic(data, 4, MfClassicType1k);
|
||||
}
|
||||
@@ -438,6 +454,11 @@ static const NfcGenerator ntag_i2c_plus_2k_generator = {
|
||||
.generator_func = nfc_generate_ntag_i2c_plus_2k,
|
||||
};
|
||||
|
||||
static const NfcGenerator mifare_mini_generator = {
|
||||
.name = "Mifare Mini",
|
||||
.generator_func = nfc_generate_mf_mini,
|
||||
};
|
||||
|
||||
static const NfcGenerator mifare_classic_1k_4b_uid_generator = {
|
||||
.name = "Mifare Classic 1k 4byte UID",
|
||||
.generator_func = nfc_generate_mf_classic_1k_4b_uid,
|
||||
@@ -472,6 +493,7 @@ const NfcGenerator* const nfc_generators[] = {
|
||||
&ntag_i2c_2k_generator,
|
||||
&ntag_i2c_plus_1k_generator,
|
||||
&ntag_i2c_plus_2k_generator,
|
||||
&mifare_mini_generator,
|
||||
&mifare_classic_1k_4b_uid_generator,
|
||||
&mifare_classic_1k_7b_uid_generator,
|
||||
&mifare_classic_4k_4b_uid_generator,
|
||||
|
||||
+14
-4
@@ -1055,7 +1055,10 @@ static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice*
|
||||
do {
|
||||
if(!flipper_format_write_comment_cstr(file, "Mifare Classic specific data")) break;
|
||||
|
||||
if(data->type == MfClassicType1k) {
|
||||
if(data->type == MfClassicTypeMini) {
|
||||
if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "MINI")) break;
|
||||
blocks = 20;
|
||||
} else if(data->type == MfClassicType1k) {
|
||||
if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break;
|
||||
blocks = 64;
|
||||
} else if(data->type == MfClassicType4k) {
|
||||
@@ -1153,7 +1156,10 @@ static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice*
|
||||
do {
|
||||
// Read Mifare Classic type
|
||||
if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break;
|
||||
if(!furi_string_cmp(temp_str, "1K")) {
|
||||
if(!furi_string_cmp(temp_str, "MINI")) {
|
||||
data->type = MfClassicTypeMini;
|
||||
data_blocks = 20;
|
||||
} else if(!furi_string_cmp(temp_str, "1K")) {
|
||||
data->type = MfClassicType1k;
|
||||
data_blocks = 64;
|
||||
} else if(!furi_string_cmp(temp_str, "4K")) {
|
||||
@@ -1228,7 +1234,9 @@ static bool nfc_device_save_mifare_classic_keys(NfcDevice* dev) {
|
||||
if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break;
|
||||
if(!flipper_format_write_header_cstr(file, nfc_keys_file_header, nfc_keys_file_version))
|
||||
break;
|
||||
if(data->type == MfClassicType1k) {
|
||||
if(data->type == MfClassicTypeMini) {
|
||||
if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "MINI")) break;
|
||||
} else if(data->type == MfClassicType1k) {
|
||||
if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break;
|
||||
} else if(data->type == MfClassicType4k) {
|
||||
if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "4K")) break;
|
||||
@@ -1278,7 +1286,9 @@ bool nfc_device_load_key_cache(NfcDevice* dev) {
|
||||
if(furi_string_cmp_str(temp_str, nfc_keys_file_header)) break;
|
||||
if(version != nfc_keys_file_version) break;
|
||||
if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break;
|
||||
if(!furi_string_cmp(temp_str, "1K")) {
|
||||
if(!furi_string_cmp(temp_str, "MINI")) {
|
||||
data->type = MfClassicTypeMini;
|
||||
} else if(!furi_string_cmp(temp_str, "1K")) {
|
||||
data->type = MfClassicType1k;
|
||||
} else if(!furi_string_cmp(temp_str, "4K")) {
|
||||
data->type = MfClassicType4k;
|
||||
|
||||
+3
-1
@@ -55,7 +55,9 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) {
|
||||
}
|
||||
|
||||
const char* nfc_mf_classic_type(MfClassicType type) {
|
||||
if(type == MfClassicType1k) {
|
||||
if(type == MfClassicTypeMini) {
|
||||
return "Mifare Mini 0.3K";
|
||||
} else if(type == MfClassicType1k) {
|
||||
return "Mifare Classic 1K";
|
||||
} else if(type == MfClassicType4k) {
|
||||
return "Mifare Classic 4K";
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
#define MF_CLASSIC_WRITE_BLOCK_CMD (0xA0)
|
||||
|
||||
const char* mf_classic_get_type_str(MfClassicType type) {
|
||||
if(type == MfClassicType1k) {
|
||||
if(type == MfClassicTypeMini) {
|
||||
return "MIFARE Mini 0.3K";
|
||||
} else if(type == MfClassicType1k) {
|
||||
return "MIFARE Classic 1K";
|
||||
} else if(type == MfClassicType4k) {
|
||||
return "MIFARE Classic 4K";
|
||||
@@ -73,7 +75,9 @@ MfClassicSectorTrailer*
|
||||
}
|
||||
|
||||
uint8_t mf_classic_get_total_sectors_num(MfClassicType type) {
|
||||
if(type == MfClassicType1k) {
|
||||
if(type == MfClassicTypeMini) {
|
||||
return MF_MINI_TOTAL_SECTORS_NUM;
|
||||
} else if(type == MfClassicType1k) {
|
||||
return MF_CLASSIC_1K_TOTAL_SECTORS_NUM;
|
||||
} else if(type == MfClassicType4k) {
|
||||
return MF_CLASSIC_4K_TOTAL_SECTORS_NUM;
|
||||
@@ -83,7 +87,9 @@ uint8_t mf_classic_get_total_sectors_num(MfClassicType type) {
|
||||
}
|
||||
|
||||
uint16_t mf_classic_get_total_block_num(MfClassicType type) {
|
||||
if(type == MfClassicType1k) {
|
||||
if(type == MfClassicTypeMini) {
|
||||
return 20;
|
||||
} else if(type == MfClassicType1k) {
|
||||
return 64;
|
||||
} else if(type == MfClassicType4k) {
|
||||
return 256;
|
||||
@@ -361,10 +367,14 @@ bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
|
||||
}
|
||||
}
|
||||
|
||||
MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
|
||||
MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
|
||||
UNUSED(ATQA1);
|
||||
if((ATQA0 == 0x44 || ATQA0 == 0x04) && (SAK == 0x08 || SAK == 0x88 || SAK == 0x09)) {
|
||||
return MfClassicType1k;
|
||||
if((ATQA0 == 0x44 || ATQA0 == 0x04)) {
|
||||
if((SAK == 0x08 || SAK == 0x88)) {
|
||||
return MfClassicType1k;
|
||||
} else if(SAK == 0x09) {
|
||||
return MfClassicTypeMini;
|
||||
}
|
||||
} else if((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01)) {
|
||||
//skylanders support
|
||||
return MfClassicType1k;
|
||||
@@ -589,13 +599,14 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u
|
||||
if(!key_a_found) break;
|
||||
FURI_LOG_D(TAG, "Try to read blocks with key A");
|
||||
key = nfc_util_bytes2num(sec_tr->key_a, sizeof(sec_tr->key_a));
|
||||
if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyA, &crypto, false, 0)) break;
|
||||
for(size_t i = start_block; i < start_block + total_blocks; i++) {
|
||||
if(!mf_classic_is_block_read(data, i)) {
|
||||
if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyA, &crypto, false, 0)) continue;
|
||||
if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
|
||||
mf_classic_set_block_read(data, i, &block_tmp);
|
||||
blocks_read++;
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
} else {
|
||||
blocks_read++;
|
||||
}
|
||||
@@ -607,14 +618,14 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u
|
||||
if(!key_b_found) break;
|
||||
FURI_LOG_D(TAG, "Try to read blocks with key B");
|
||||
key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->key_b));
|
||||
furi_hal_nfc_sleep();
|
||||
if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break;
|
||||
for(size_t i = start_block; i < start_block + total_blocks; i++) {
|
||||
if(!mf_classic_is_block_read(data, i)) {
|
||||
if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyB, &crypto, false, 0)) continue;
|
||||
if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
|
||||
mf_classic_set_block_read(data, i, &block_tmp);
|
||||
blocks_read++;
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
} else {
|
||||
blocks_read++;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define MF_CLASSIC_TOTAL_BLOCKS_MAX (256)
|
||||
#define MF_CLASSIC_1K_TOTAL_SECTORS_NUM (16)
|
||||
#define MF_CLASSIC_4K_TOTAL_SECTORS_NUM (40)
|
||||
#define MF_MINI_TOTAL_SECTORS_NUM (5)
|
||||
|
||||
#define MF_CLASSIC_SECTORS_MAX (40)
|
||||
#define MF_CLASSIC_BLOCKS_IN_SECTOR_MAX (16)
|
||||
@@ -18,6 +19,7 @@
|
||||
#define MF_CLASSIC_ACCESS_BYTES_SIZE (4)
|
||||
|
||||
typedef enum {
|
||||
MfClassicTypeMini,
|
||||
MfClassicType1k,
|
||||
MfClassicType4k,
|
||||
} MfClassicType;
|
||||
@@ -94,7 +96,7 @@ const char* mf_classic_get_type_str(MfClassicType type);
|
||||
|
||||
bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
|
||||
|
||||
MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
|
||||
MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
|
||||
|
||||
uint8_t mf_classic_get_total_sectors_num(MfClassicType type);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user