diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index 7d78fa74752..4aa0b92e356 100644 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -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 diff --git a/lib/SConscript b/lib/SConscript index a3617c5d14d..c36c0a62097 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -72,7 +72,6 @@ libs = env.BuildModules( "subghz", "appframe", "misc", - "mbedtls", "loclass", ], ) diff --git a/lib/mbedtls.scons b/lib/mbedtls.scons index 35de7e6fc75..0458acb0323 100644 --- a/lib/mbedtls.scons +++ b/lib/mbedtls.scons @@ -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) diff --git a/lib/misc.scons b/lib/misc.scons index 91a11ff6409..adbd3bdd441 100644 --- a/lib/misc.scons +++ b/lib/misc.scons @@ -7,6 +7,7 @@ env.Append( "#/lib/heatshrink", "#/lib/micro-ecc", "#/lib/nanopb", + "#/lib/mbedtls/include", "#/lib/nfc_protocols", "#/lib/u8g2", ], @@ -21,6 +22,7 @@ libenv.ApplyLibFlags() sources = [] +libenv.BuildModules(["mbedtls"]) libs_recurse = [ "digital_signal", "micro-ecc", diff --git a/lib/nfc_protocols/mifare_ultralight.c b/lib/nfc_protocols/mifare_ultralight.c index 21dbd9c4c58..92b04852581 100644 --- a/lib/nfc_protocols/mifare_ultralight.c +++ b/lib/nfc_protocols/mifare_ultralight.c @@ -1,10 +1,45 @@ #include +#include #include "mifare_ultralight.h" #include +#include "furi_hal_nfc.h" #include #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; @@ -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; } @@ -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; @@ -492,7 +559,45 @@ 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", @@ -500,6 +605,7 @@ bool mf_ultralight_read_pages( i + (valid_pages > 4 ? 4 : valid_pages) - 1); break; } + if(valid_pages > 4) { pages_read_cnt = 4; } else { @@ -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) { @@ -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 && diff --git a/lib/nfc_protocols/mifare_ultralight.h b/lib/nfc_protocols/mifare_ultralight.h index 36b81fdf15f..6bca6bc8de4 100644 --- a/lib/nfc_protocols/mifare_ultralight.h +++ b/lib/nfc_protocols/mifare_ultralight.h @@ -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); @@ -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);