Skip to content

Commit d749d26

Browse files
authored
Merge pull request #85 from wetox-team/ezhevita/mf-ul-auth
Ezhevita/mf ul auth
2 parents ab050e2 + 775087d commit d749d26

File tree

6 files changed

+115
-5
lines changed

6 files changed

+115
-5
lines changed

applications/nfc/nfc_worker.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker) {
294294
if(nfc_data->type == FuriHalNfcTypeA &&
295295
mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
296296
FURI_LOG_D(TAG, "Found Mifare Ultralight tag. Start reading");
297-
if(mf_ul_read_card(&tx_rx, &reader, &data)) {
297+
if(mf_ul_read_card(nfc_data, &tx_rx, &reader, &data)) {
298298
result->protocol = NfcDeviceProtocolMifareUl;
299299
result->mf_ul_data = data;
300300
// Notify caller and exit

lib/SConscript

-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ libs = env.BuildModules(
7272
"subghz",
7373
"appframe",
7474
"misc",
75-
"mbedtls",
7675
"loclass",
7776
],
7877
)

lib/mbedtls.scons

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ env.Append(
1313
libenv = env.Clone(FW_LIB_NAME="mbedtls")
1414
libenv.ApplyLibFlags()
1515

16-
sources = ["mbedtls/library/des.c", "mbedtls/library/platform_util.c"]
16+
sources = ["mbedtls/library/des.c", "mbedtls/library/sha1.c", "mbedtls/library/platform_util.c"]
1717

1818
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
1919
libenv.Install("${LIB_DIST_DIR}", lib)

lib/misc.scons

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ env.Append(
88
"#/lib/mbedtls/include",
99
"#/lib/micro-ecc",
1010
"#/lib/nanopb",
11+
"#/lib/mbedtls/include",
1112
"#/lib/nfc_protocols",
1213
"#/lib/u8g2",
1314
],
@@ -22,6 +23,7 @@ libenv.ApplyLibFlags()
2223

2324
sources = []
2425

26+
libenv.BuildModules(["mbedtls"])
2527
libs_recurse = [
2628
"digital_signal",
2729
"micro-ecc",

lib/nfc_protocols/mifare_ultralight.c

+109-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,45 @@
11
#include <limits.h>
2+
#include <mbedtls/sha1.h>
23
#include "mifare_ultralight.h"
34
#include <furi.h>
5+
#include "furi_hal_nfc.h"
46
#include <m-string.h>
57

68
#define TAG "MfUltralight"
79

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+
843
bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
944
if((ATQA0 == 0x44) && (ATQA1 == 0x00) && (SAK == 0x00)) {
1045
return true;
@@ -120,6 +155,35 @@ bool mf_ultralight_read_version(
120155
return version_read;
121156
}
122157

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+
123187
static int16_t mf_ultralight_page_addr_to_tag_addr(uint8_t sector, uint8_t page) {
124188
return sector * 256 + page;
125189
}
@@ -469,9 +533,12 @@ static bool mf_ultralight_sector_select(FuriHalNfcTxRxContext* tx_rx, uint8_t se
469533
}
470534

471535
bool mf_ultralight_read_pages(
536+
FuriHalNfcDevData* info_data,
472537
FuriHalNfcTxRxContext* tx_rx,
473538
MfUltralightReader* reader,
474539
MfUltralightData* data) {
540+
pwd_generator pwd_gens[] = {pwdgen_default, pwdgen_amiibo, pwdgen_xiaomi};
541+
475542
uint8_t pages_read_cnt = 0;
476543
uint8_t curr_sector_index = 0xff;
477544
reader->pages_read = 0;
@@ -492,14 +559,53 @@ bool mf_ultralight_read_pages(
492559
tx_rx->tx_data[1] = tag_page;
493560
tx_rx->tx_bits = 16;
494561
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) {
496601
FURI_LOG_D(
497602
TAG,
498603
"Failed to read pages %d - %d",
499604
i,
500605
i + (valid_pages > 4 ? 4 : valid_pages) - 1);
501606
break;
502607
}
608+
503609
if(valid_pages > 4) {
504610
pages_read_cnt = 4;
505611
} else {
@@ -617,6 +723,7 @@ bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralight
617723
}
618724

619725
bool mf_ul_read_card(
726+
FuriHalNfcDevData* info_data,
620727
FuriHalNfcTxRxContext* tx_rx,
621728
MfUltralightReader* reader,
622729
MfUltralightData* data) {
@@ -634,7 +741,7 @@ bool mf_ul_read_card(
634741
}
635742
}
636743

637-
card_read = mf_ultralight_read_pages(tx_rx, reader, data);
744+
card_read = mf_ultralight_read_pages(info_data, tx_rx, reader, data);
638745

639746
if(card_read) {
640747
if(reader->supported_features & MfUltralightSupportReadCounter &&

lib/nfc_protocols/mifare_ultralight.h

+2
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ bool mf_ultralight_read_version(
176176
MfUltralightData* data);
177177

178178
bool mf_ultralight_read_pages(
179+
FuriHalNfcDevData* info_data,
179180
FuriHalNfcTxRxContext* tx_rx,
180181
MfUltralightReader* reader,
181182
MfUltralightData* data);
@@ -192,6 +193,7 @@ bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData*
192193
bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data);
193194

194195
bool mf_ul_read_card(
196+
FuriHalNfcDevData* info_data,
195197
FuriHalNfcTxRxContext* tx_rx,
196198
MfUltralightReader* reader,
197199
MfUltralightData* data);

0 commit comments

Comments
 (0)