mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-05 05:09:09 -07:00
Merge remote-tracking branch 'pr3822/nestednonces' into dev
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <lib/nfc/protocols/mf_classic/mf_classic_poller.h>
|
||||
|
||||
#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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <gui/view.h>
|
||||
#include <lib/nfc/protocols/mf_classic/mf_classic_poller.h>
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user