Skip to content

Commit 7b685bf

Browse files
committed
nfc magic sync with gen4
1 parent bf06a6f commit 7b685bf

27 files changed

+1263
-428
lines changed

base_pack/nfc_magic/application.fam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ App(
1010
],
1111
stack_size=4 * 1024,
1212
fap_description="Application for writing to NFC tags with modifiable sector 0",
13-
fap_version="1.7",
13+
fap_version="1.8",
1414
fap_icon="assets/Nfc_10px.png",
1515
fap_category="NFC",
1616
fap_icon_assets="assets",

base_pack/nfc_magic/magic/nfc_magic_scanner.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "nfc_magic_scanner.h"
22

3+
#include "core/check.h"
4+
#include "protocols/gen4/gen4.h"
35
#include "protocols/gen1a/gen1a_poller.h"
46
#include "protocols/gen2/gen2_poller.h"
57
#include "protocols/gen4/gen4_poller.h"
@@ -18,7 +20,8 @@ struct NfcMagicScanner {
1820
NfcMagicScannerSessionState session_state;
1921
NfcMagicProtocol current_protocol;
2022

21-
uint32_t gen4_password;
23+
Gen4Password gen4_password;
24+
Gen4* gen4_data;
2225
bool magic_protocol_detected;
2326

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

4447
NfcMagicScanner* instance = malloc(sizeof(NfcMagicScanner));
4548
instance->nfc = nfc;
49+
instance->gen4_data = gen4_alloc();
4650

4751
return instance;
4852
}
4953

5054
void nfc_magic_scanner_free(NfcMagicScanner* instance) {
5155
furi_assert(instance);
5256

57+
gen4_free(instance->gen4_data);
5358
free(instance);
5459
}
5560

56-
void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, uint32_t password) {
61+
void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, Gen4Password password) {
5762
furi_assert(instance);
5863

5964
instance->gen4_password = password;
@@ -73,9 +78,13 @@ static int32_t nfc_magic_scanner_worker(void* context) {
7378
break;
7479
}
7580
} else if(instance->current_protocol == NfcMagicProtocolGen4) {
76-
Gen4PollerError error = gen4_poller_detect(instance->nfc, instance->gen4_password);
81+
gen4_reset(instance->gen4_data);
82+
Gen4 gen4_data;
83+
Gen4PollerError error =
84+
gen4_poller_detect(instance->nfc, instance->gen4_password, &gen4_data);
7785
instance->magic_protocol_detected = (error == Gen4PollerErrorNone);
7886
if(instance->magic_protocol_detected) {
87+
gen4_copy(instance->gen4_data, &gen4_data);
7988
break;
8089
}
8190
} else if(instance->current_protocol == NfcMagicProtocolGen2) {
@@ -162,3 +171,9 @@ void nfc_magic_scanner_stop(NfcMagicScanner* instance) {
162171
instance->callback = NULL;
163172
instance->context = NULL;
164173
}
174+
175+
const Gen4* nfc_magic_scanner_get_gen4_data(NfcMagicScanner* instance) {
176+
furi_assert(instance);
177+
178+
return instance->gen4_data;
179+
}

base_pack/nfc_magic/magic/nfc_magic_scanner.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include "protocols/gen4/gen4.h"
34
#include <nfc/nfc.h>
45
#include "protocols/nfc_magic_protocols.h"
56

@@ -30,7 +31,7 @@ NfcMagicScanner* nfc_magic_scanner_alloc(Nfc* nfc);
3031

3132
void nfc_magic_scanner_free(NfcMagicScanner* instance);
3233

33-
void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, uint32_t password);
34+
void nfc_magic_scanner_set_gen4_password(NfcMagicScanner* instance, Gen4Password password);
3435

3536
void nfc_magic_scanner_start(
3637
NfcMagicScanner* instance,
@@ -39,6 +40,8 @@ void nfc_magic_scanner_start(
3940

4041
void nfc_magic_scanner_stop(NfcMagicScanner* instance);
4142

43+
const Gen4* nfc_magic_scanner_get_gen4_data(NfcMagicScanner* instance);
44+
4245
#ifdef __cplusplus
4346
}
4447
#endif
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#include "gen4.h"
2+
#include "core/check.h"
3+
4+
Gen4* gen4_alloc() {
5+
Gen4* instance = (Gen4*)malloc(sizeof(Gen4));
6+
return instance;
7+
}
8+
9+
void gen4_free(Gen4* instance) {
10+
furi_check(instance);
11+
free(instance);
12+
}
13+
14+
void gen4_reset(Gen4* instance) {
15+
furi_check(instance);
16+
memset(&instance->config, 0, sizeof(Gen4Config));
17+
memset(&instance->revision, 0, sizeof(Gen4Revision));
18+
}
19+
20+
void gen4_copy(Gen4* dest, const Gen4* source) {
21+
furi_check(dest);
22+
furi_check(source);
23+
memcpy(dest, source, sizeof(Gen4));
24+
}
25+
26+
bool gen4_password_is_set (const Gen4Password* instance){
27+
return (instance->bytes[0] || instance->bytes[1] || instance->bytes[2] || instance->bytes[3]);
28+
}
29+
30+
void gen4_password_reset (Gen4Password* instance){
31+
memset(instance->bytes, 0, GEN4_PASSWORD_LEN);
32+
}
33+
34+
void gen4_password_copy (Gen4Password* dest, const Gen4Password* source){
35+
memcpy(dest->bytes, source->bytes, GEN4_PASSWORD_LEN);
36+
}
37+
38+
const char* gen4_get_shadow_mode_name(Gen4ShadowMode mode) {
39+
switch(mode) {
40+
case Gen4ShadowModePreWrite:
41+
return "Pre-Write";
42+
case Gen4ShadowModeRestore:
43+
return "Restore";
44+
case Gen4ShadowModeDisabled:
45+
return "Disabled";
46+
case Gen4ShadowModeHighSpeedDisabled:
47+
return "Disabled (High-speed)";
48+
case Gen4ShadowModeSplit:
49+
return "Split";
50+
default:
51+
return "Unknown";
52+
}
53+
}
54+
55+
const char* gen4_get_direct_write_mode_name(Gen4DirectWriteBlock0Mode mode) {
56+
switch(mode) {
57+
case Gen4DirectWriteBlock0ModeEnabled:
58+
return "Enabled";
59+
case Gen4DirectWriteBlock0ModeDisabled:
60+
return "Disabled";
61+
case Gen4DirectWriteBlock0ModeDefault:
62+
return "Default";
63+
default:
64+
return "Unknown";
65+
}
66+
}
67+
68+
const char* gen4_get_uid_len_num(Gen4UIDLength code) {
69+
switch(code) {
70+
case Gen4UIDLengthSingle:
71+
return "4";
72+
case Gen4UIDLengthDouble:
73+
return "7";
74+
case Gen4UIDLengthTriple:
75+
return "10";
76+
default:
77+
return "Unknown";
78+
}
79+
}
80+
81+
const char* gen4_get_configuration_name(const Gen4Config* config) {
82+
switch(config->data_parsed.protocol) {
83+
case Gen4ProtocolMfClassic: {
84+
switch(config->data_parsed.total_blocks) {
85+
case 255:
86+
return "MIFARE Classic 4K";
87+
case 63:
88+
return "MIFARE Classic 1K";
89+
case 19:
90+
return "MIFARE Classic Mini (0.3K)";
91+
default:
92+
return "Unknown";
93+
}
94+
} break;
95+
case Gen4ProtocolMfUltralight: {
96+
switch(config->data_parsed.total_blocks) {
97+
case 63:
98+
return "MIFARE Ultralight";
99+
case 127:
100+
return "NTAG 2XX";
101+
default:
102+
return "Unknown";
103+
}
104+
} break;
105+
default:
106+
return "Unknown";
107+
break;
108+
};
109+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#pragma once
2+
3+
#include "core/common_defines.h"
4+
#include <stdint.h>
5+
6+
#define GEN4_CONFIG_SIZE (32)
7+
#define GEN4_REVISION_SIZE (5)
8+
9+
#define GEN4_PASSWORD_LEN (4)
10+
#define GEN4_ATS_MAX_LEN (16)
11+
#define GEN4_ATQA_LEN (2)
12+
#define GEN4_CRC_LEN (2)
13+
14+
typedef enum {
15+
Gen4ProtocolMfClassic = 0x00,
16+
Gen4ProtocolMfUltralight = 0x01,
17+
} Gen4Protocol;
18+
19+
typedef struct {
20+
uint8_t bytes[GEN4_PASSWORD_LEN];
21+
} Gen4Password;
22+
23+
typedef enum {
24+
Gen4UIDLengthSingle = 0x00,
25+
Gen4UIDLengthDouble = 0x01,
26+
Gen4UIDLengthTriple = 0x02
27+
} Gen4UIDLength;
28+
29+
typedef enum {
30+
Gen4UltralightModeUL_EV1 = 0x00,
31+
Gen4UltralightModeNTAG = 0x01,
32+
Gen4UltralightModeUL_C = 0x02,
33+
Gen4UltralightModeUL = 0x03
34+
} Gen4UltralightMode;
35+
36+
typedef enum {
37+
// for writing original (shadow) data
38+
Gen4ShadowModePreWrite = 0x00,
39+
// written data can be read once before restored to original
40+
Gen4ShadowModeRestore = 0x01,
41+
// shadow mode disabled
42+
Gen4ShadowModeDisabled = 0x02,
43+
// apparently for UL?
44+
Gen4ShadowModeHighSpeedDisabled = 0x03,
45+
// work with new UMC. With old UMC is untested
46+
Gen4ShadowModeSplit = 0x04,
47+
} Gen4ShadowMode;
48+
49+
typedef enum {
50+
// gen2 card behavour
51+
Gen4DirectWriteBlock0ModeEnabled = 0x00,
52+
// common card behavour
53+
Gen4DirectWriteBlock0ModeDisabled = 0x01,
54+
// default mode. same behavour as Gen4DirectWriteBlock0ModeActivate
55+
Gen4DirectWriteBlock0ModeDefault = 0x02,
56+
} Gen4DirectWriteBlock0Mode;
57+
58+
typedef union {
59+
uint8_t data_raw[GEN4_CONFIG_SIZE];
60+
struct {
61+
Gen4Protocol protocol;
62+
Gen4UIDLength uid_len_code;
63+
Gen4Password password;
64+
Gen4ShadowMode gtu_mode;
65+
uint8_t ats_len;
66+
uint8_t ats[GEN4_ATS_MAX_LEN]; // mb another class?
67+
uint8_t atqa[GEN4_ATQA_LEN];
68+
uint8_t sak;
69+
Gen4UltralightMode mfu_mode;
70+
uint8_t total_blocks;
71+
Gen4DirectWriteBlock0Mode direct_write_mode;
72+
uint8_t crc[GEN4_CRC_LEN];
73+
} FURI_PACKED data_parsed;
74+
} Gen4Config;
75+
76+
typedef struct {
77+
uint8_t data[GEN4_REVISION_SIZE];
78+
} Gen4Revision;
79+
80+
typedef struct {
81+
Gen4Config config;
82+
Gen4Revision revision;
83+
} Gen4;
84+
85+
Gen4* gen4_alloc();
86+
87+
void gen4_free(Gen4* instance);
88+
89+
void gen4_reset(Gen4* instance);
90+
91+
void gen4_copy(Gen4* dest, const Gen4* source);
92+
93+
bool gen4_password_is_set (const Gen4Password* instance);
94+
95+
void gen4_password_reset (Gen4Password* instance);
96+
97+
void gen4_password_copy (Gen4Password* dest, const Gen4Password* source);
98+
99+
const char* gen4_get_shadow_mode_name(Gen4ShadowMode mode);
100+
101+
const char* gen4_get_direct_write_mode_name(Gen4DirectWriteBlock0Mode mode);
102+
103+
const char* gen4_get_uid_len_num(Gen4UIDLength code);
104+
105+
const char* gen4_get_configuration_name(const Gen4Config* config);

0 commit comments

Comments
 (0)