NFC: add MIFARE MINI support (#2307)
* NFC: add MIFARE MINI support * Move new value to end of enum * nfc: added missing unit test Co-authored-by: gornekich <n.gorbadey@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									4dc4d34d04
								
							
						
					
					
						commit
						eee5c35400
					
				| @ -466,6 +466,10 @@ static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) { | |||||||
|     nfc_device_free(nfc_keys); |     nfc_device_free(nfc_keys); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | MU_TEST(mf_mini_file_test) { | ||||||
|  |     mf_classic_generator_test(4, MfClassicTypeMini); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| MU_TEST(mf_classic_1k_4b_file_test) { | MU_TEST(mf_classic_1k_4b_file_test) { | ||||||
|     mf_classic_generator_test(4, MfClassicType1k); |     mf_classic_generator_test(4, MfClassicType1k); | ||||||
| } | } | ||||||
| @ -486,6 +490,7 @@ MU_TEST_SUITE(nfc) { | |||||||
|     nfc_test_alloc(); |     nfc_test_alloc(); | ||||||
| 
 | 
 | ||||||
|     MU_RUN_TEST(nfca_file_test); |     MU_RUN_TEST(nfca_file_test); | ||||||
|  |     MU_RUN_TEST(mf_mini_file_test); | ||||||
|     MU_RUN_TEST(mf_classic_1k_4b_file_test); |     MU_RUN_TEST(mf_classic_1k_4b_file_test); | ||||||
|     MU_RUN_TEST(mf_classic_4k_4b_file_test); |     MU_RUN_TEST(mf_classic_4k_4b_file_test); | ||||||
|     MU_RUN_TEST(mf_classic_1k_7b_file_test); |     MU_RUN_TEST(mf_classic_1k_7b_file_test); | ||||||
|  | |||||||
| @ -352,11 +352,27 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType | |||||||
|         } |         } | ||||||
|         // Set SAK to 08
 |         // Set SAK to 08
 | ||||||
|         data->nfc_data.sak = 0x08; |         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; |     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) { | static void nfc_generate_mf_classic_1k_4b_uid(NfcDeviceData* data) { | ||||||
|     nfc_generate_mf_classic(data, 4, MfClassicType1k); |     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, |     .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 = { | static const NfcGenerator mifare_classic_1k_4b_uid_generator = { | ||||||
|     .name = "Mifare Classic 1k 4byte UID", |     .name = "Mifare Classic 1k 4byte UID", | ||||||
|     .generator_func = nfc_generate_mf_classic_1k_4b_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_2k_generator, | ||||||
|     &ntag_i2c_plus_1k_generator, |     &ntag_i2c_plus_1k_generator, | ||||||
|     &ntag_i2c_plus_2k_generator, |     &ntag_i2c_plus_2k_generator, | ||||||
|  |     &mifare_mini_generator, | ||||||
|     &mifare_classic_1k_4b_uid_generator, |     &mifare_classic_1k_4b_uid_generator, | ||||||
|     &mifare_classic_1k_7b_uid_generator, |     &mifare_classic_1k_7b_uid_generator, | ||||||
|     &mifare_classic_4k_4b_uid_generator, |     &mifare_classic_4k_4b_uid_generator, | ||||||
|  | |||||||
| @ -745,7 +745,10 @@ static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice* | |||||||
|     do { |     do { | ||||||
|         if(!flipper_format_write_comment_cstr(file, "Mifare Classic specific data")) break; |         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; |             if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break; | ||||||
|             blocks = 64; |             blocks = 64; | ||||||
|         } else if(data->type == MfClassicType4k) { |         } else if(data->type == MfClassicType4k) { | ||||||
| @ -843,7 +846,10 @@ static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice* | |||||||
|     do { |     do { | ||||||
|         // Read Mifare Classic type
 |         // Read Mifare Classic type
 | ||||||
|         if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) 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; | ||||||
|  |             data_blocks = 20; | ||||||
|  |         } else if(!furi_string_cmp(temp_str, "1K")) { | ||||||
|             data->type = MfClassicType1k; |             data->type = MfClassicType1k; | ||||||
|             data_blocks = 64; |             data_blocks = 64; | ||||||
|         } else if(!furi_string_cmp(temp_str, "4K")) { |         } else if(!furi_string_cmp(temp_str, "4K")) { | ||||||
| @ -918,7 +924,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_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)) |         if(!flipper_format_write_header_cstr(file, nfc_keys_file_header, nfc_keys_file_version)) | ||||||
|             break; |             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; |             if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break; | ||||||
|         } else if(data->type == MfClassicType4k) { |         } else if(data->type == MfClassicType4k) { | ||||||
|             if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "4K")) break; |             if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "4K")) break; | ||||||
| @ -968,7 +976,9 @@ bool nfc_device_load_key_cache(NfcDevice* dev) { | |||||||
|         if(furi_string_cmp_str(temp_str, nfc_keys_file_header)) break; |         if(furi_string_cmp_str(temp_str, nfc_keys_file_header)) break; | ||||||
|         if(version != nfc_keys_file_version) break; |         if(version != nfc_keys_file_version) break; | ||||||
|         if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) 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; |             data->type = MfClassicType1k; | ||||||
|         } else if(!furi_string_cmp(temp_str, "4K")) { |         } else if(!furi_string_cmp(temp_str, "4K")) { | ||||||
|             data->type = MfClassicType4k; |             data->type = MfClassicType4k; | ||||||
|  | |||||||
| @ -55,7 +55,9 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const char* nfc_mf_classic_type(MfClassicType type) { | 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"; |         return "Mifare Classic 1K"; | ||||||
|     } else if(type == MfClassicType4k) { |     } else if(type == MfClassicType4k) { | ||||||
|         return "Mifare Classic 4K"; |         return "Mifare Classic 4K"; | ||||||
|  | |||||||
| @ -13,7 +13,9 @@ | |||||||
| #define MF_CLASSIC_WRITE_BLOCK_CMD (0xA0) | #define MF_CLASSIC_WRITE_BLOCK_CMD (0xA0) | ||||||
| 
 | 
 | ||||||
| const char* mf_classic_get_type_str(MfClassicType type) { | 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"; |         return "MIFARE Classic 1K"; | ||||||
|     } else if(type == MfClassicType4k) { |     } else if(type == MfClassicType4k) { | ||||||
|         return "MIFARE Classic 4K"; |         return "MIFARE Classic 4K"; | ||||||
| @ -73,7 +75,9 @@ MfClassicSectorTrailer* | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t mf_classic_get_total_sectors_num(MfClassicType type) { | 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; |         return MF_CLASSIC_1K_TOTAL_SECTORS_NUM; | ||||||
|     } else if(type == MfClassicType4k) { |     } else if(type == MfClassicType4k) { | ||||||
|         return MF_CLASSIC_4K_TOTAL_SECTORS_NUM; |         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) { | uint16_t mf_classic_get_total_block_num(MfClassicType type) { | ||||||
|     if(type == MfClassicType1k) { |     if(type == MfClassicTypeMini) { | ||||||
|  |         return 20; | ||||||
|  |     } else if(type == MfClassicType1k) { | ||||||
|         return 64; |         return 64; | ||||||
|     } else if(type == MfClassicType4k) { |     } else if(type == MfClassicType4k) { | ||||||
|         return 256; |         return 256; | ||||||
| @ -363,8 +369,12 @@ 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(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { | ||||||
|     UNUSED(ATQA1); |     UNUSED(ATQA1); | ||||||
|     if((ATQA0 == 0x44 || ATQA0 == 0x04) && (SAK == 0x08 || SAK == 0x88 || SAK == 0x09)) { |     if((ATQA0 == 0x44 || ATQA0 == 0x04)) { | ||||||
|  |         if((SAK == 0x08 || SAK == 0x88)) { | ||||||
|             return MfClassicType1k; |             return MfClassicType1k; | ||||||
|  |         } else if(SAK == 0x09) { | ||||||
|  |             return MfClassicTypeMini; | ||||||
|  |         } | ||||||
|     } else if((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01)) { |     } else if((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01)) { | ||||||
|         //skylanders support
 |         //skylanders support
 | ||||||
|         return MfClassicType1k; |         return MfClassicType1k; | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
| 
 | 
 | ||||||
| #define MF_CLASSIC_BLOCK_SIZE (16) | #define MF_CLASSIC_BLOCK_SIZE (16) | ||||||
| #define MF_CLASSIC_TOTAL_BLOCKS_MAX (256) | #define MF_CLASSIC_TOTAL_BLOCKS_MAX (256) | ||||||
|  | #define MF_MINI_TOTAL_SECTORS_NUM (5) | ||||||
| #define MF_CLASSIC_1K_TOTAL_SECTORS_NUM (16) | #define MF_CLASSIC_1K_TOTAL_SECTORS_NUM (16) | ||||||
| #define MF_CLASSIC_4K_TOTAL_SECTORS_NUM (40) | #define MF_CLASSIC_4K_TOTAL_SECTORS_NUM (40) | ||||||
| 
 | 
 | ||||||
| @ -20,6 +21,7 @@ | |||||||
| typedef enum { | typedef enum { | ||||||
|     MfClassicType1k, |     MfClassicType1k, | ||||||
|     MfClassicType4k, |     MfClassicType4k, | ||||||
|  |     MfClassicTypeMini, | ||||||
| } MfClassicType; | } MfClassicType; | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Giacomo Ferretti
						Giacomo Ferretti