Skip to content

Commit

Permalink
NFC Magic: New functions for Gen4 cards (DW to block 0/shadow mode) (#98
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Leptopt1los authored Apr 22, 2024
1 parent 6664fe9 commit 922a87c
Show file tree
Hide file tree
Showing 28 changed files with 1,188 additions and 358 deletions.
8 changes: 8 additions & 0 deletions nfc_magic/.catalog/changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 1.9
- Get revision, get config moved into main Gen4 menu
- New function: Set Gen4 card shadow mode
- New function: Set Gen4 card direct write to block 0 mode
- Fixed: back button did not allow to exit from some scenes while the card is next to the Flipper HF RFID antenna
- Gen4 protocol refactor
- Gen4 UI refactor

## 1.8
- Ultralight Various fixes and improvements

Expand Down
Binary file modified nfc_magic/.catalog/screenshots/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 18 additions & 3 deletions nfc_magic/magic/nfc_magic_scanner.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "nfc_magic_scanner.h"

#include "core/check.h"
#include "protocols/gen4/gen4.h"
#include "protocols/gen1a/gen1a_poller.h"
#include "protocols/gen2/gen2_poller.h"
#include "protocols/gen4/gen4_poller.h"
Expand All @@ -18,7 +20,8 @@ struct NfcMagicScanner {
NfcMagicScannerSessionState session_state;
NfcMagicProtocol current_protocol;

uint32_t gen4_password;
Gen4Password gen4_password;
Gen4* gen4_data;
bool magic_protocol_detected;

NfcMagicScannerCallback callback;
Expand All @@ -43,17 +46,19 @@ NfcMagicScanner* nfc_magic_scanner_alloc(Nfc* nfc) {

NfcMagicScanner* instance = malloc(sizeof(NfcMagicScanner));
instance->nfc = nfc;
instance->gen4_data = gen4_alloc();

return instance;
}

void nfc_magic_scanner_free(NfcMagicScanner* instance) {
furi_assert(instance);

gen4_free(instance->gen4_data);
free(instance);
}

void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, uint32_t password) {
void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, Gen4Password password) {
furi_assert(instance);

instance->gen4_password = password;
Expand All @@ -73,9 +78,13 @@ static int32_t nfc_magic_scanner_worker(void* context) {
break;
}
} else if(instance->current_protocol == NfcMagicProtocolGen4) {
Gen4PollerError error = gen4_poller_detect(instance->nfc, instance->gen4_password);
gen4_reset(instance->gen4_data);
Gen4 gen4_data;
Gen4PollerError error =
gen4_poller_detect(instance->nfc, instance->gen4_password, &gen4_data);
instance->magic_protocol_detected = (error == Gen4PollerErrorNone);
if(instance->magic_protocol_detected) {
gen4_copy(instance->gen4_data, &gen4_data);
break;
}
} else if(instance->current_protocol == NfcMagicProtocolGen2) {
Expand Down Expand Up @@ -162,3 +171,9 @@ void nfc_magic_scanner_stop(NfcMagicScanner* instance) {
instance->callback = NULL;
instance->context = NULL;
}

const Gen4* nfc_magic_scanner_get_gen4_data(NfcMagicScanner* instance) {
furi_assert(instance);

return instance->gen4_data;
}
5 changes: 4 additions & 1 deletion nfc_magic/magic/nfc_magic_scanner.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "protocols/gen4/gen4.h"
#include <nfc/nfc.h>
#include "protocols/nfc_magic_protocols.h"

Expand Down Expand Up @@ -30,7 +31,7 @@ NfcMagicScanner* nfc_magic_scanner_alloc(Nfc* nfc);

void nfc_magic_scanner_free(NfcMagicScanner* instance);

void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, uint32_t password);
void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, Gen4Password password);

void nfc_magic_scanner_start(
NfcMagicScanner* instance,
Expand All @@ -39,6 +40,8 @@ void nfc_magic_scanner_start(

void nfc_magic_scanner_stop(NfcMagicScanner* instance);

const Gen4* nfc_magic_scanner_get_gen4_data(NfcMagicScanner* instance);

#ifdef __cplusplus
}
#endif
120 changes: 120 additions & 0 deletions nfc_magic/magic/protocols/gen4/gen4.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "gen4.h"
#include "core/check.h"

Gen4* gen4_alloc() {
Gen4* instance = malloc(sizeof(Gen4));

return instance;
}

void gen4_free(Gen4* instance) {
furi_check(instance);

free(instance);
}

void gen4_reset(Gen4* instance) {
furi_check(instance);

memset(&instance->config, 0, sizeof(Gen4Config));
memset(&instance->revision, 0, sizeof(Gen4Revision));
}

void gen4_copy(Gen4* dest, const Gen4* source) {
furi_check(dest);
furi_check(source);

memcpy(dest, source, sizeof(Gen4));
}

bool gen4_password_is_set(const Gen4Password* instance) {
furi_check(instance);

return (instance->bytes[0] || instance->bytes[1] || instance->bytes[2] || instance->bytes[3]);
}

void gen4_password_reset(Gen4Password* instance) {
furi_check(instance);

memset(instance->bytes, 0, GEN4_PASSWORD_LEN);
}

void gen4_password_copy(Gen4Password* dest, const Gen4Password* source) {
furi_check(dest);
furi_check(source);

memcpy(dest->bytes, source->bytes, GEN4_PASSWORD_LEN);
}

const char* gen4_get_shadow_mode_name(Gen4ShadowMode mode) {
switch(mode) {
case Gen4ShadowModePreWrite:
return "Pre-Write";
case Gen4ShadowModeRestore:
return "Restore";
case Gen4ShadowModeDisabled:
return "Disabled";
case Gen4ShadowModeHighSpeedDisabled:
return "Disabled (High-speed)";
case Gen4ShadowModeSplit:
return "Split";
default:
return "Unknown";
}
}

const char* gen4_get_direct_write_mode_name(Gen4DirectWriteBlock0Mode mode) {
switch(mode) {
case Gen4DirectWriteBlock0ModeEnabled:
return "Enabled";
case Gen4DirectWriteBlock0ModeDisabled:
return "Disabled";
case Gen4DirectWriteBlock0ModeDefault:
return "Default";
default:
return "Unknown";
}
}

const char* gen4_get_uid_len_num(Gen4UIDLength code) {
switch(code) {
case Gen4UIDLengthSingle:
return "4";
case Gen4UIDLengthDouble:
return "7";
case Gen4UIDLengthTriple:
return "10";
default:
return "Unknown";
}
}

const char* gen4_get_configuration_name(const Gen4Config* config) {
switch(config->data_parsed.protocol) {
case Gen4ProtocolMfClassic: {
switch(config->data_parsed.total_blocks) {
case 255:
return "MIFARE Classic 4K";
case 63:
return "MIFARE Classic 1K";
case 19:
return "MIFARE Classic Mini (0.3K)";
default:
return "Unknown";
}
} break;
case Gen4ProtocolMfUltralight: {
switch(config->data_parsed.total_blocks) {
case 63:
return "MIFARE Ultralight";
case 127:
return "NTAG 2XX";
default:
return "Unknown";
}
} break;
default:
return "Unknown";
break;
};
}
105 changes: 105 additions & 0 deletions nfc_magic/magic/protocols/gen4/gen4.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#pragma once

#include "core/common_defines.h"
#include <stdint.h>

#define GEN4_CONFIG_SIZE (32)
#define GEN4_REVISION_SIZE (5)

#define GEN4_PASSWORD_LEN (4)
#define GEN4_ATS_MAX_LEN (16)
#define GEN4_ATQA_LEN (2)
#define GEN4_CRC_LEN (2)

typedef enum {
Gen4ProtocolMfClassic = 0x00,
Gen4ProtocolMfUltralight = 0x01,
} Gen4Protocol;

typedef struct {
uint8_t bytes[GEN4_PASSWORD_LEN];
} Gen4Password;

typedef enum {
Gen4UIDLengthSingle = 0x00,
Gen4UIDLengthDouble = 0x01,
Gen4UIDLengthTriple = 0x02
} Gen4UIDLength;

typedef enum {
Gen4UltralightModeUL_EV1 = 0x00,
Gen4UltralightModeNTAG = 0x01,
Gen4UltralightModeUL_C = 0x02,
Gen4UltralightModeUL = 0x03
} Gen4UltralightMode;

typedef enum {
// for writing original (shadow) data
Gen4ShadowModePreWrite = 0x00,
// written data can be read once before restored to original
Gen4ShadowModeRestore = 0x01,
// shadow mode disabled
Gen4ShadowModeDisabled = 0x02,
// apparently for UL?
Gen4ShadowModeHighSpeedDisabled = 0x03,
// work with new UMC. With old UMC is untested
Gen4ShadowModeSplit = 0x04,
} Gen4ShadowMode;

typedef enum {
// gen2 card behavour
Gen4DirectWriteBlock0ModeEnabled = 0x00,
// common card behavour
Gen4DirectWriteBlock0ModeDisabled = 0x01,
// default mode. same behavour as Gen4DirectWriteBlock0ModeActivate
Gen4DirectWriteBlock0ModeDefault = 0x02,
} Gen4DirectWriteBlock0Mode;

typedef union {
uint8_t data_raw[GEN4_CONFIG_SIZE];
struct {
Gen4Protocol protocol;
Gen4UIDLength uid_len_code;
Gen4Password password;
Gen4ShadowMode gtu_mode;
uint8_t ats_len;
uint8_t ats[GEN4_ATS_MAX_LEN]; // mb another class?
uint8_t atqa[GEN4_ATQA_LEN];
uint8_t sak;
Gen4UltralightMode mfu_mode;
uint8_t total_blocks;
Gen4DirectWriteBlock0Mode direct_write_mode;
uint8_t crc[GEN4_CRC_LEN];
} FURI_PACKED data_parsed;
} Gen4Config;

typedef struct {
uint8_t data[GEN4_REVISION_SIZE];
} Gen4Revision;

typedef struct {
Gen4Config config;
Gen4Revision revision;
} Gen4;

Gen4* gen4_alloc();

void gen4_free(Gen4* instance);

void gen4_reset(Gen4* instance);

void gen4_copy(Gen4* dest, const Gen4* source);

bool gen4_password_is_set(const Gen4Password* instance);

void gen4_password_reset(Gen4Password* instance);

void gen4_password_copy(Gen4Password* dest, const Gen4Password* source);

const char* gen4_get_shadow_mode_name(Gen4ShadowMode mode);

const char* gen4_get_direct_write_mode_name(Gen4DirectWriteBlock0Mode mode);

const char* gen4_get_uid_len_num(Gen4UIDLength code);

const char* gen4_get_configuration_name(const Gen4Config* config);
Loading

0 comments on commit 922a87c

Please sign in to comment.