1
1
#include <limits.h>
2
+ #include <mbedtls/sha1.h>
2
3
#include "mifare_ultralight.h"
3
4
#include <furi.h>
5
+ #include "furi_hal_nfc.h"
4
6
#include <m-string.h>
5
7
6
8
#define TAG "MfUltralight"
7
9
10
+ typedef uint32_t (* pwd_generator )(FuriHalNfcDevData * );
11
+
12
+ uint32_t pwdgen_default (FuriHalNfcDevData * data ) {
13
+ UNUSED (data );
14
+ return 0xFFFFFFFF ;
15
+ }
16
+
17
+ // Algorithms from: https://github.com/RfidResearchGroup/proxmark3/blob/0f6061c16f072372b7d4d381911f1542afbc3a69/common/generator.c#L110
18
+ uint32_t pwdgen_xiaomi (FuriHalNfcDevData * data ) {
19
+ uint8_t hash [20 ];
20
+ mbedtls_sha1 (data -> uid , data -> uid_len , hash );
21
+
22
+ uint32_t pwd = 0 ;
23
+ pwd |= (hash [hash [0 ] % 20 ]) << 24 ;
24
+ pwd |= (hash [(hash [0 ] + 5 ) % 20 ]) << 16 ;
25
+ pwd |= (hash [(hash [0 ] + 13 ) % 20 ]) << 8 ;
26
+ pwd |= (hash [(hash [0 ] + 17 ) % 20 ]);
27
+
28
+ return pwd ;
29
+ }
30
+
31
+ uint32_t pwdgen_amiibo (FuriHalNfcDevData * data ) {
32
+ uint8_t * uid = data -> uid ;
33
+
34
+ uint32_t pwd = 0 ;
35
+ pwd |= (uid [1 ] ^ uid [3 ] ^ 0xAA ) << 24 ;
36
+ pwd |= (uid [2 ] ^ uid [4 ] ^ 0x55 ) << 16 ;
37
+ pwd |= (uid [3 ] ^ uid [5 ] ^ 0xAA ) << 8 ;
38
+ pwd |= uid [4 ] ^ uid [6 ] ^ 0x55 ;
39
+
40
+ return pwd ;
41
+ }
42
+
8
43
bool mf_ul_check_card_type (uint8_t ATQA0 , uint8_t ATQA1 , uint8_t SAK ) {
9
44
if ((ATQA0 == 0x44 ) && (ATQA1 == 0x00 ) && (SAK == 0x00 )) {
10
45
return true;
@@ -120,6 +155,35 @@ bool mf_ultralight_read_version(
120
155
return version_read ;
121
156
}
122
157
158
+ bool mf_ultralight_authenticate (FuriHalNfcTxRxContext * tx_rx , uint32_t key ) {
159
+ bool authenticated = false;
160
+
161
+ do {
162
+ FURI_LOG_D (TAG , "Authenticating" );
163
+ tx_rx -> tx_data [0 ] = MF_UL_AUTH ;
164
+ tx_rx -> tx_data [1 ] = (key >> 24 ) & 0xFF ;
165
+ tx_rx -> tx_data [2 ] = (key >> 16 ) & 0xFF ;
166
+ tx_rx -> tx_data [3 ] = (key >> 8 ) & 0xFF ;
167
+ tx_rx -> tx_data [4 ] = key & 0xFF ;
168
+
169
+ tx_rx -> tx_bits = 40 ;
170
+ tx_rx -> tx_rx_type = FuriHalNfcTxRxTypeDefault ;
171
+ if (!furi_hal_nfc_tx_rx (tx_rx , 50 )) {
172
+ FURI_LOG_D (TAG , "Tag did not respond to authentication" );
173
+ break ;
174
+ }
175
+
176
+ if (tx_rx -> tx_data [0 ] <= 0x09 ) {
177
+ FURI_LOG_D (TAG , "Authentication failed" );
178
+ break ;
179
+ }
180
+
181
+ authenticated = true;
182
+ } while (false);
183
+
184
+ return authenticated ;
185
+ }
186
+
123
187
static int16_t mf_ultralight_page_addr_to_tag_addr (uint8_t sector , uint8_t page ) {
124
188
return sector * 256 + page ;
125
189
}
@@ -469,9 +533,12 @@ static bool mf_ultralight_sector_select(FuriHalNfcTxRxContext* tx_rx, uint8_t se
469
533
}
470
534
471
535
bool mf_ultralight_read_pages (
536
+ FuriHalNfcDevData * info_data ,
472
537
FuriHalNfcTxRxContext * tx_rx ,
473
538
MfUltralightReader * reader ,
474
539
MfUltralightData * data ) {
540
+ pwd_generator pwd_gens [] = {pwdgen_default , pwdgen_amiibo , pwdgen_xiaomi };
541
+
475
542
uint8_t pages_read_cnt = 0 ;
476
543
uint8_t curr_sector_index = 0xff ;
477
544
reader -> pages_read = 0 ;
@@ -492,14 +559,53 @@ bool mf_ultralight_read_pages(
492
559
tx_rx -> tx_data [1 ] = tag_page ;
493
560
tx_rx -> tx_bits = 16 ;
494
561
tx_rx -> tx_rx_type = FuriHalNfcTxRxTypeDefault ;
495
- if (!furi_hal_nfc_tx_rx (tx_rx , 50 ) || tx_rx -> rx_bits < 16 * 8 ) {
562
+
563
+ if (!furi_hal_nfc_tx_rx (tx_rx , 50 )) {
564
+ FURI_LOG_D (
565
+ TAG ,
566
+ "Failed to read pages %d - %d" ,
567
+ i ,
568
+ i + (valid_pages > 4 ? 4 : valid_pages ) - 1 );
569
+ break ;
570
+ }
571
+
572
+ if (tx_rx -> rx_bits == 4 && tx_rx -> rx_data [0 ] >> 4 == 0x00 ) {
573
+ // This page is locked by a password
574
+ i -= 4 ;
575
+
576
+ uint32_t key ;
577
+ bool key_found = false;
578
+ for (size_t j = 0 ; j < (sizeof (pwd_gens ) / sizeof (int32_t )); j ++ ) {
579
+ furi_hal_nfc_sleep ();
580
+ furi_hal_nfc_activate_nfca (300 , NULL );
581
+
582
+ key = pwd_gens [j ](info_data );
583
+
584
+ if (mf_ultralight_authenticate (tx_rx , key )) {
585
+ key_found = true;
586
+ break ;
587
+ }
588
+ }
589
+
590
+ if (key_found ) {
591
+ continue ;
592
+ } else {
593
+ FURI_LOG_D (
594
+ TAG ,
595
+ "Failed to read pages %d - %d" ,
596
+ i ,
597
+ i + (valid_pages > 4 ? 4 : valid_pages ) - 1 );
598
+ break ;
599
+ }
600
+ } else if (tx_rx -> rx_bits < 16 * 8 ) {
496
601
FURI_LOG_D (
497
602
TAG ,
498
603
"Failed to read pages %d - %d" ,
499
604
i ,
500
605
i + (valid_pages > 4 ? 4 : valid_pages ) - 1 );
501
606
break ;
502
607
}
608
+
503
609
if (valid_pages > 4 ) {
504
610
pages_read_cnt = 4 ;
505
611
} else {
@@ -617,6 +723,7 @@ bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralight
617
723
}
618
724
619
725
bool mf_ul_read_card (
726
+ FuriHalNfcDevData * info_data ,
620
727
FuriHalNfcTxRxContext * tx_rx ,
621
728
MfUltralightReader * reader ,
622
729
MfUltralightData * data ) {
@@ -634,7 +741,7 @@ bool mf_ul_read_card(
634
741
}
635
742
}
636
743
637
- card_read = mf_ultralight_read_pages (tx_rx , reader , data );
744
+ card_read = mf_ultralight_read_pages (info_data , tx_rx , reader , data );
638
745
639
746
if (card_read ) {
640
747
if (reader -> supported_features & MfUltralightSupportReadCounter &&
0 commit comments