7
7
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
8
8
#include <flipper_format/flipper_format.h>
9
9
10
- #define TAG "Skylanders"
10
+ #define TAG "Skylanders"
11
+ #define POLY UINT64_C(0x42f0e1eba9ea3693)
12
+ #define TOP UINT64_C(0x800000000000)
13
+ #define UID_LEN 4
14
+ #define KEY_MASK 0xFFFFFFFFFFFF
11
15
12
16
static const uint64_t skylanders_key = 0x4b0b20107ccb ;
13
17
14
18
static const char * nfc_resources_header = "Flipper NFC resources" ;
15
19
static const uint32_t nfc_resources_file_version = 1 ;
16
20
21
+ uint64_t crc64_like (uint64_t result , uint8_t sector ) {
22
+ result ^= (uint64_t )sector << 40 ;
23
+ for (int i = 0 ; i < 8 ; i ++ ) {
24
+ result = (result & TOP ) ? (result << 1 ) ^ POLY : result << 1 ;
25
+ }
26
+ return result ;
27
+ }
28
+
29
+ uint64_t taghash (uint32_t uid ) {
30
+ uint64_t result = 0x9AE903260CC4 ;
31
+ uint8_t uidBytes [UID_LEN ] = {0 };
32
+ memcpy (uidBytes , & uid , UID_LEN );
33
+
34
+ for (int i = 0 ; i < UID_LEN ; i ++ ) {
35
+ result = crc64_like (result , uidBytes [i ]);
36
+ }
37
+ return result ;
38
+ }
39
+
17
40
static bool skylanders_search_data (
18
41
Storage * storage ,
19
42
const char * file_name ,
@@ -88,6 +111,12 @@ static bool skylanders_read(Nfc* nfc, NfcDevice* device) {
88
111
MfClassicData * data = mf_classic_alloc ();
89
112
nfc_device_copy_data (device , NfcProtocolMfClassic , data );
90
113
114
+ size_t * uid_len = 0 ;
115
+ const uint8_t * uid_bytes = mf_classic_get_uid (data , uid_len );
116
+ uint32_t uid = 0 ;
117
+ memcpy (& uid , uid_bytes , sizeof (uid ));
118
+ uint64_t hash = taghash (uid );
119
+
91
120
do {
92
121
MfClassicType type = MfClassicType1k ;
93
122
MfClassicError error = mf_classic_poller_sync_detect_type (nfc , & type );
@@ -96,10 +125,18 @@ static bool skylanders_read(Nfc* nfc, NfcDevice* device) {
96
125
data -> type = type ;
97
126
MfClassicDeviceKeys keys = {};
98
127
for (size_t i = 0 ; i < mf_classic_get_total_sectors_num (data -> type ); i ++ ) {
99
- bit_lib_num_to_bytes_be (skylanders_key , sizeof (MfClassicKey ), keys .key_a [i ].data );
100
- FURI_BIT_SET (keys .key_a_mask , i );
101
- bit_lib_num_to_bytes_be (skylanders_key , sizeof (MfClassicKey ), keys .key_b [i ].data );
102
- FURI_BIT_SET (keys .key_b_mask , i );
128
+ if (i == 0 ) {
129
+ bit_lib_num_to_bytes_be (skylanders_key , sizeof (MfClassicKey ), keys .key_a [i ].data );
130
+ FURI_BIT_SET (keys .key_a_mask , i );
131
+ } else {
132
+ uint64_t sectorhash = crc64_like (hash , i );
133
+ uint64_t key = sectorhash & KEY_MASK ;
134
+ uint8_t * keyBytes = (uint8_t * )& key ;
135
+ memcpy (keys .key_a [i ].data , keyBytes , sizeof (MfClassicKey ));
136
+ FURI_BIT_SET (keys .key_a_mask , i );
137
+ memset (keys .key_b [i ].data , 0 , sizeof (MfClassicKey ));
138
+ FURI_BIT_SET (keys .key_b_mask , i );
139
+ }
103
140
}
104
141
105
142
error = mf_classic_poller_sync_read (nfc , & keys , data );
@@ -134,7 +171,7 @@ static bool skylanders_parse(const NfcDevice* device, FuriString* parsed_data) {
134
171
uint64_t key = bit_lib_bytes_to_num_be (sec_tr -> key_a .data , 6 );
135
172
if (key != skylanders_key ) break ;
136
173
137
- const uint16_t id = ( uint16_t ) * data -> block [1 ].data ;
174
+ const uint16_t id = data -> block [1 ].data [ 1 ] << 8 | data -> block [ 1 ]. data [ 0 ] ;
138
175
if (id == 0 ) break ;
139
176
140
177
Storage * storage = furi_record_open (RECORD_STORAGE );
0 commit comments