diff --git a/applications/main/nfc/nfc_app_i.h b/applications/main/nfc/nfc_app_i.h index 9656eae11..14e484622 100644 --- a/applications/main/nfc/nfc_app_i.h +++ b/applications/main/nfc/nfc_app_i.h @@ -97,9 +97,9 @@ typedef struct { bool is_key_attack; uint8_t key_attack_current_sector; bool is_card_present; - uint8_t nested_phase; - uint8_t prng_type; - uint8_t backdoor; + MfClassicNestedPhase nested_phase; + MfClassicPrngType prng_type; + MfClassicBackdoor backdoor; uint16_t nested_target_key; uint16_t msb_count; bool enhanced_dict; diff --git a/applications/main/nfc/plugins/supported_cards/clipper.c b/applications/main/nfc/plugins/supported_cards/clipper.c index 04a2afcda..35d0c7039 100644 --- a/applications/main/nfc/plugins/supported_cards/clipper.c +++ b/applications/main/nfc/plugins/supported_cards/clipper.c @@ -106,7 +106,7 @@ static const IdMapping bart_zones[] = { {.id = 0x0023, .name = "South Hayward"}, {.id = 0x0024, .name = "Union City"}, {.id = 0x0025, .name = "Fremont"}, - {.id = 0x0026, .name = "Daly City(2)?"}, + {.id = 0x0026, .name = "Castro Valley"}, {.id = 0x0027, .name = "Dublin/Pleasanton"}, {.id = 0x0028, .name = "South San Francisco"}, {.id = 0x0029, .name = "San Bruno"}, @@ -115,6 +115,8 @@ static const IdMapping bart_zones[] = { {.id = 0x002c, .name = "West Dublin/Pleasanton"}, {.id = 0x002d, .name = "OAK Airport"}, {.id = 0x002e, .name = "Warm Springs/South Fremont"}, + {.id = 0x002f, .name = "Milpitas"}, + {.id = 0x0030, .name = "Berryessa/North San Jose"}, }; static const size_t kNumBARTZones = COUNT(bart_zones); 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 5ff014a1c..526a89a74 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 @@ -2,7 +2,6 @@ #include #include -#include #define TAG "NfcMfClassicDictAttack" @@ -141,14 +140,14 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) { uint32_t state = scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfClassicDictAttack); if(state == DictAttackStateCUIDDictInProgress) { - do { - size_t cuid_len = 0; - const uint8_t* cuid = nfc_device_get_uid(instance->nfc_device, &cuid_len); - FuriString* cuid_dict_path = furi_string_alloc_printf( - "%s/mf_classic_dict_%08lx.nfc", - EXT_PATH("nfc/assets"), - (uint32_t)bit_lib_bytes_to_num_be(cuid + (cuid_len - 4), 4)); + size_t cuid_len = 0; + const uint8_t* cuid = nfc_device_get_uid(instance->nfc_device, &cuid_len); + FuriString* cuid_dict_path = furi_string_alloc_printf( + "%s/mf_classic_dict_%08lx.nfc", + EXT_PATH("nfc/assets"), + (uint32_t)bit_lib_bytes_to_num_be(cuid + (cuid_len - 4), 4)); + do { if(!keys_dict_check_presence(furi_string_get_cstr(cuid_dict_path))) { state = DictAttackStateUserDictInProgress; break; @@ -159,8 +158,6 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) { KeysDictModeOpenExisting, sizeof(MfClassicKey)); - furi_string_free(cuid_dict_path); - if(keys_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) { keys_dict_free(instance->nfc_dict_context.dict); state = DictAttackStateUserDictInProgress; @@ -169,6 +166,8 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) { dict_attack_set_header(instance->dict_attack, "MF Classic CUID Dictionary"); } while(false); + + furi_string_free(cuid_dict_path); } if(state == DictAttackStateUserDictInProgress) { do { diff --git a/applications/main/nfc/views/dict_attack.c b/applications/main/nfc/views/dict_attack.c index 5138dd912..4efbe6d60 100644 --- a/applications/main/nfc/views/dict_attack.c +++ b/applications/main/nfc/views/dict_attack.c @@ -316,21 +316,21 @@ void dict_attack_reset_key_attack(DictAttack* instance) { instance->view, DictAttackViewModel * model, { model->is_key_attack = false; }, true); } -void dict_attack_set_nested_phase(DictAttack* instance, uint8_t nested_phase) { +void dict_attack_set_nested_phase(DictAttack* instance, MfClassicNestedPhase nested_phase) { furi_assert(instance); with_view_model( instance->view, DictAttackViewModel * model, { model->nested_phase = nested_phase; }, true); } -void dict_attack_set_prng_type(DictAttack* instance, uint8_t prng_type) { +void dict_attack_set_prng_type(DictAttack* instance, MfClassicPrngType prng_type) { furi_assert(instance); with_view_model( instance->view, DictAttackViewModel * model, { model->prng_type = prng_type; }, true); } -void dict_attack_set_backdoor(DictAttack* instance, uint8_t backdoor) { +void dict_attack_set_backdoor(DictAttack* instance, MfClassicBackdoor backdoor) { furi_assert(instance); with_view_model( diff --git a/applications/main/nfc/views/dict_attack.h b/applications/main/nfc/views/dict_attack.h index 8dc9b9708..b6c6fdbdc 100644 --- a/applications/main/nfc/views/dict_attack.h +++ b/applications/main/nfc/views/dict_attack.h @@ -2,6 +2,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -9,32 +10,6 @@ extern "C" { typedef struct DictAttack DictAttack; -typedef enum { - MfClassicNestedPhaseNone, - MfClassicNestedPhaseAnalyzePRNG, - MfClassicNestedPhaseDictAttack, - MfClassicNestedPhaseDictAttackResume, - MfClassicNestedPhaseCalibrate, - MfClassicNestedPhaseRecalibrate, - MfClassicNestedPhaseCollectNtEnc, - MfClassicNestedPhaseFinished, -} MfClassicNestedPhase; - -typedef enum { - MfClassicPrngTypeUnknown, // Tag not yet tested - MfClassicPrngTypeNoTag, // No tag detected during test - MfClassicPrngTypeWeak, // Weak PRNG, standard Nested - MfClassicPrngTypeHard, // Hard PRNG, Hardnested -} MfClassicPrngType; - -typedef enum { - MfClassicBackdoorUnknown, // Tag not yet tested - MfClassicBackdoorNone, // No observed backdoor - MfClassicBackdoorAuth1, // Tag responds to v1 auth backdoor - MfClassicBackdoorAuth2, // Tag responds to v2 auth backdoor - MfClassicBackdoorAuth3, // Tag responds to v3 auth backdoor (static encrypted nonce) -} MfClassicBackdoor; - typedef enum { DictAttackEventSkipPressed, } DictAttackEvent; @@ -71,11 +46,11 @@ void dict_attack_set_key_attack(DictAttack* instance, uint8_t sector); void dict_attack_reset_key_attack(DictAttack* instance); -void dict_attack_set_nested_phase(DictAttack* instance, uint8_t nested_phase); +void dict_attack_set_nested_phase(DictAttack* instance, MfClassicNestedPhase nested_phase); -void dict_attack_set_prng_type(DictAttack* instance, uint8_t prng_type); +void dict_attack_set_prng_type(DictAttack* instance, MfClassicPrngType prng_type); -void dict_attack_set_backdoor(DictAttack* instance, uint8_t backdoor); +void dict_attack_set_backdoor(DictAttack* instance, MfClassicBackdoor backdoor); void dict_attack_set_nested_target_key(DictAttack* instance, uint16_t target_key); diff --git a/lib/nfc/protocols/mf_classic/mf_classic_poller.c b/lib/nfc/protocols/mf_classic/mf_classic_poller.c index e8f660b16..7417322e9 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_poller.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_poller.c @@ -20,8 +20,7 @@ const MfClassicBackdoorKeyPair mf_classic_backdoor_keys[] = { {{{0xa3, 0x16, 0x67, 0xa8, 0xce, 0xc1}}, MfClassicBackdoorAuth1}, // Fudan, Infineon, NXP {{{0x51, 0x8b, 0x33, 0x54, 0xe7, 0x60}}, MfClassicBackdoorAuth2}, // Fudan }; -const size_t mf_classic_backdoor_keys_count = - sizeof(mf_classic_backdoor_keys) / sizeof(mf_classic_backdoor_keys[0]); +const size_t mf_classic_backdoor_keys_count = COUNT_OF(mf_classic_backdoor_keys); const uint16_t valid_sums[] = {0, 32, 56, 64, 80, 96, 104, 112, 120, 128, 136, 144, 152, 160, 176, 192, 200, 224, 256}; diff --git a/lib/nfc/protocols/mf_classic/mf_classic_poller.h b/lib/nfc/protocols/mf_classic/mf_classic_poller.h index 5c2550b7e..7dfd3b6ab 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_poller.h +++ b/lib/nfc/protocols/mf_classic/mf_classic_poller.h @@ -48,6 +48,41 @@ typedef enum { MfClassicPollerModeDictAttackEnhanced, /**< Poller enhanced dictionary attack mode. */ } MfClassicPollerMode; +/** + * @brief MfClassic poller nested attack phase. + */ +typedef enum { + MfClassicNestedPhaseNone, + MfClassicNestedPhaseAnalyzePRNG, + MfClassicNestedPhaseDictAttack, + MfClassicNestedPhaseDictAttackResume, + MfClassicNestedPhaseCalibrate, + MfClassicNestedPhaseRecalibrate, + MfClassicNestedPhaseCollectNtEnc, + MfClassicNestedPhaseFinished, +} MfClassicNestedPhase; + +/** + * @brief MfClassic pseudorandom number generator (PRNG) type. + */ +typedef enum { + MfClassicPrngTypeUnknown, // Tag not yet tested + MfClassicPrngTypeNoTag, // No tag detected during test + MfClassicPrngTypeWeak, // Weak PRNG, standard Nested + MfClassicPrngTypeHard, // Hard PRNG, Hardnested +} MfClassicPrngType; + +/** + * @brief MfClassic authentication backdoor type. + */ +typedef enum { + MfClassicBackdoorUnknown, // Tag not yet tested + MfClassicBackdoorNone, // No observed backdoor + MfClassicBackdoorAuth1, // Tag responds to v1 auth backdoor + MfClassicBackdoorAuth2, // Tag responds to v2 auth backdoor (sometimes static encrypted) + MfClassicBackdoorAuth3, // Tag responds to v3 auth backdoor (static encrypted nonce) +} MfClassicBackdoor; + /** * @brief MfClassic poller request mode event data. * @@ -78,9 +113,9 @@ typedef struct { uint8_t sectors_read; /**< Number of sectors read. */ uint8_t keys_found; /**< Number of keys found. */ uint8_t current_sector; /**< Current sector number. */ - uint8_t nested_phase; /**< Nested attack phase. */ - uint8_t prng_type; /**< PRNG (weak or hard). */ - uint8_t backdoor; /**< Backdoor type. */ + MfClassicNestedPhase nested_phase; /**< Nested attack phase. */ + MfClassicPrngType prng_type; /**< PRNG (weak or hard). */ + MfClassicBackdoor backdoor; /**< Backdoor type. */ uint16_t nested_target_key; /**< Target key for nested attack. */ uint16_t msb_count; /**< Number of unique most significant bytes seen during Hardnested attack. */ diff --git a/lib/nfc/protocols/mf_classic/mf_classic_poller_i.h b/lib/nfc/protocols/mf_classic/mf_classic_poller_i.h index 7b05ce240..915c899c3 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_poller_i.h +++ b/lib/nfc/protocols/mf_classic/mf_classic_poller_i.h @@ -48,32 +48,6 @@ typedef enum { MfClassicCardStateLost, } MfClassicCardState; -typedef enum { - MfClassicNestedPhaseNone, - MfClassicNestedPhaseAnalyzePRNG, - MfClassicNestedPhaseDictAttack, - MfClassicNestedPhaseDictAttackResume, - MfClassicNestedPhaseCalibrate, - MfClassicNestedPhaseRecalibrate, - MfClassicNestedPhaseCollectNtEnc, - MfClassicNestedPhaseFinished, -} MfClassicNestedPhase; - -typedef enum { - MfClassicPrngTypeUnknown, // Tag not yet tested - MfClassicPrngTypeNoTag, // No tag detected during test - MfClassicPrngTypeWeak, // Weak PRNG, standard Nested - MfClassicPrngTypeHard, // Hard PRNG, Hardnested -} MfClassicPrngType; - -typedef enum { - MfClassicBackdoorUnknown, // Tag not yet tested - MfClassicBackdoorNone, // No observed backdoor - MfClassicBackdoorAuth1, // Tag responds to v1 auth backdoor - MfClassicBackdoorAuth2, // Tag responds to v2 auth backdoor - MfClassicBackdoorAuth3, // Tag responds to v3 auth backdoor (static encrypted nonce) -} MfClassicBackdoor; - typedef struct { MfClassicKey key; MfClassicBackdoor type;