Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ezhevita/mf ul auth #83

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion applications/nfc/nfc_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker) {
if(nfc_data->type == FuriHalNfcTypeA &&
mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
FURI_LOG_D(TAG, "Found Mifare Ultralight tag. Start reading");
if(mf_ul_read_card(&tx_rx, &reader, &data)) {
if(mf_ul_read_card(nfc_data, &tx_rx, &reader, &data)) {
result->protocol = NfcDeviceProtocolMifareUl;
result->mf_ul_data = data;
// Notify caller and exit
Expand Down
1 change: 0 additions & 1 deletion lib/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ libs = env.BuildModules(
"subghz",
"appframe",
"misc",
"mbedtls",
"loclass",
],
)
Expand Down
2 changes: 1 addition & 1 deletion lib/mbedtls.scons
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ env.Append(
libenv = env.Clone(FW_LIB_NAME="mbedtls")
libenv.ApplyLibFlags()

sources = ["mbedtls/library/des.c", "mbedtls/library/platform_util.c"]
sources = ["mbedtls/library/des.c", "mbedtls/library/sha1.c", "mbedtls/library/platform_util.c"]

lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
libenv.Install("${LIB_DIST_DIR}", lib)
Expand Down
2 changes: 2 additions & 0 deletions lib/misc.scons
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ env.Append(
"#/lib/heatshrink",
"#/lib/micro-ecc",
"#/lib/nanopb",
"#/lib/mbedtls/include",
"#/lib/nfc_protocols",
"#/lib/u8g2",
],
Expand All @@ -21,6 +22,7 @@ libenv.ApplyLibFlags()

sources = []

libenv.BuildModules(["mbedtls"])
libs_recurse = [
"digital_signal",
"micro-ecc",
Expand Down
111 changes: 109 additions & 2 deletions lib/nfc_protocols/mifare_ultralight.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,45 @@
#include <limits.h>
#include <mbedtls/sha1.h>
#include "mifare_ultralight.h"
#include <furi.h>
#include "furi_hal_nfc.h"
#include <m-string.h>

#define TAG "MfUltralight"

typedef uint32_t (*pwd_generator)(FuriHalNfcDevData*);

uint32_t pwdgen_default(FuriHalNfcDevData* data) {
UNUSED(data);
return 0xFFFFFFFF;
}

// Algorithms from: https://github.com/RfidResearchGroup/proxmark3/blob/0f6061c16f072372b7d4d381911f1542afbc3a69/common/generator.c#L110
uint32_t pwdgen_xiaomi(FuriHalNfcDevData* data) {
uint8_t hash[20];
mbedtls_sha1(data->uid, data->uid_len, hash);

uint32_t pwd = 0;
pwd |= (hash[hash[0] % 20]) << 24;
pwd |= (hash[(hash[0] + 5) % 20]) << 16;
pwd |= (hash[(hash[0] + 13) % 20]) << 8;
pwd |= (hash[(hash[0] + 17) % 20]);

return pwd;
}

uint32_t pwdgen_amiibo(FuriHalNfcDevData* data) {
uint8_t* uid = data->uid;

uint32_t pwd = 0;
pwd |= (uid[1] ^ uid[3] ^ 0xAA) << 24;
pwd |= (uid[2] ^ uid[4] ^ 0x55) << 16;
pwd |= (uid[3] ^ uid[5] ^ 0xAA) << 8;
pwd |= uid[4] ^ uid[6] ^ 0x55;

return pwd;
}

bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
if((ATQA0 == 0x44) && (ATQA1 == 0x00) && (SAK == 0x00)) {
return true;
Expand Down Expand Up @@ -120,6 +155,35 @@ bool mf_ultralight_read_version(
return version_read;
}

bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key) {
bool authenticated = false;

do {
FURI_LOG_D(TAG, "Authenticating");
tx_rx->tx_data[0] = MF_UL_AUTH;
tx_rx->tx_data[1] = (key >> 24) & 0xFF;
tx_rx->tx_data[2] = (key >> 16) & 0xFF;
tx_rx->tx_data[3] = (key >> 8) & 0xFF;
tx_rx->tx_data[4] = key & 0xFF;

tx_rx->tx_bits = 40;
tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault;
if(!furi_hal_nfc_tx_rx(tx_rx, 50)) {
FURI_LOG_D(TAG, "Tag did not respond to authentication");
break;
}

if(tx_rx->tx_data[0] <= 0x09) {
FURI_LOG_D(TAG, "Authentication failed");
break;
}

authenticated = true;
} while(false);

return authenticated;
}

static int16_t mf_ultralight_page_addr_to_tag_addr(uint8_t sector, uint8_t page) {
return sector * 256 + page;
}
Expand Down Expand Up @@ -469,9 +533,12 @@ static bool mf_ultralight_sector_select(FuriHalNfcTxRxContext* tx_rx, uint8_t se
}

bool mf_ultralight_read_pages(
FuriHalNfcDevData* info_data,
FuriHalNfcTxRxContext* tx_rx,
MfUltralightReader* reader,
MfUltralightData* data) {
pwd_generator pwd_gens[] = {pwdgen_default, pwdgen_amiibo, pwdgen_xiaomi};

uint8_t pages_read_cnt = 0;
uint8_t curr_sector_index = 0xff;
reader->pages_read = 0;
Expand All @@ -492,14 +559,53 @@ bool mf_ultralight_read_pages(
tx_rx->tx_data[1] = tag_page;
tx_rx->tx_bits = 16;
tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault;
if(!furi_hal_nfc_tx_rx(tx_rx, 50) || tx_rx->rx_bits < 16 * 8) {

if(!furi_hal_nfc_tx_rx(tx_rx, 50)) {
FURI_LOG_D(
TAG,
"Failed to read pages %d - %d",
i,
i + (valid_pages > 4 ? 4 : valid_pages) - 1);
break;
}

if(tx_rx->rx_bits == 4 && tx_rx->rx_data[0] >> 4 == 0x00) {
// This page is locked by a password
i -= 4;

uint32_t key;
bool key_found = false;
for(size_t j = 0; j < (sizeof(pwd_gens) / sizeof(int32_t)); j++) {
furi_hal_nfc_sleep();
furi_hal_nfc_activate_nfca(300, NULL);

key = pwd_gens[j](info_data);

if(mf_ultralight_authenticate(tx_rx, key)) {
key_found = true;
break;
}
}

if(key_found) {
continue;
} else {
FURI_LOG_D(
TAG,
"Failed to read pages %d - %d",
i,
i + (valid_pages > 4 ? 4 : valid_pages) - 1);
break;
}
} else if(tx_rx->rx_bits < 16 * 8) {
FURI_LOG_D(
TAG,
"Failed to read pages %d - %d",
i,
i + (valid_pages > 4 ? 4 : valid_pages) - 1);
break;
}

if(valid_pages > 4) {
pages_read_cnt = 4;
} else {
Expand Down Expand Up @@ -617,6 +723,7 @@ bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralight
}

bool mf_ul_read_card(
FuriHalNfcDevData* info_data,
FuriHalNfcTxRxContext* tx_rx,
MfUltralightReader* reader,
MfUltralightData* data) {
Expand All @@ -634,7 +741,7 @@ bool mf_ul_read_card(
}
}

card_read = mf_ultralight_read_pages(tx_rx, reader, data);
card_read = mf_ultralight_read_pages(info_data, tx_rx, reader, data);

if(card_read) {
if(reader->supported_features & MfUltralightSupportReadCounter &&
Expand Down
2 changes: 2 additions & 0 deletions lib/nfc_protocols/mifare_ultralight.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ bool mf_ultralight_read_version(
MfUltralightData* data);

bool mf_ultralight_read_pages(
FuriHalNfcDevData* info_data,
FuriHalNfcTxRxContext* tx_rx,
MfUltralightReader* reader,
MfUltralightData* data);
Expand All @@ -190,6 +191,7 @@ bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData*
bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data);

bool mf_ul_read_card(
FuriHalNfcDevData* info_data,
FuriHalNfcTxRxContext* tx_rx,
MfUltralightReader* reader,
MfUltralightData* data);
Expand Down