Mifare Ultralight authentication (#1365)
* mifare ultralight auth prototype * it works! * Reference source * use countof * rework everything * oops forgot scenes * build: revert changes in manifest, stack size * build: fix buid, format sources * nfc: update unlock ultralight GUI * nfc: fix byte input header * nfc: add new scenes for locked ultralight * nfc: add data read to ultralights * nfc: add unlock option in mf ultralight menu * nfc: add data read init in ultralight generation * nfc: lin sources, fix unlocked save * nfc: format python sources * nfc: clean up Co-authored-by: gornekich <n.gorbadey@gmail.com>
This commit is contained in:
committed by
GitHub
parent
d147190d61
commit
9ffcc52ada
@@ -7,7 +7,7 @@ env.Append(
|
||||
"lib/drivers",
|
||||
"lib/flipper_format",
|
||||
"lib/infrared",
|
||||
"lib/nfc_protocols",
|
||||
"lib/nfc",
|
||||
"lib/one_wire",
|
||||
"lib/ST25RFAL002",
|
||||
"lib/subghz",
|
||||
@@ -44,7 +44,7 @@ env.Append(
|
||||
# fnv1a-hash
|
||||
# micro-ecc
|
||||
# microtar
|
||||
# nfc_protocols
|
||||
# nfc
|
||||
# one_wire
|
||||
# qrcode
|
||||
# u8g2
|
||||
@@ -71,11 +71,11 @@ libs = env.BuildModules(
|
||||
"flipper_format",
|
||||
"infrared",
|
||||
"littlefs",
|
||||
"mbedtls",
|
||||
"subghz",
|
||||
"nfc",
|
||||
"appframe",
|
||||
"misc",
|
||||
"mbedtls",
|
||||
"loclass",
|
||||
],
|
||||
)
|
||||
|
@@ -11,7 +11,11 @@ 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)
|
||||
|
@@ -19,6 +19,7 @@ static const uint32_t nfc_keys_file_version = 1;
|
||||
|
||||
// Protocols format versions
|
||||
static const uint32_t nfc_mifare_classic_data_format_version = 2;
|
||||
static const uint32_t nfc_mifare_ultralight_data_format_version = 1;
|
||||
|
||||
NfcDevice* nfc_device_alloc() {
|
||||
NfcDevice* nfc_dev = malloc(sizeof(NfcDevice));
|
||||
@@ -97,6 +98,9 @@ static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev)
|
||||
// Save Mifare Ultralight specific data
|
||||
do {
|
||||
if(!flipper_format_write_comment_cstr(file, "Mifare Ultralight specific data")) break;
|
||||
if(!flipper_format_write_uint32(
|
||||
file, "Data format version", &nfc_mifare_ultralight_data_format_version, 1))
|
||||
break;
|
||||
if(!flipper_format_write_hex(file, "Signature", data->signature, sizeof(data->signature)))
|
||||
break;
|
||||
if(!flipper_format_write_hex(
|
||||
@@ -121,6 +125,8 @@ static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev)
|
||||
// Write pages data
|
||||
uint32_t pages_total = data->data_size / 4;
|
||||
if(!flipper_format_write_uint32(file, "Pages total", &pages_total, 1)) break;
|
||||
uint32_t pages_read = data->data_read / 4;
|
||||
if(!flipper_format_write_uint32(file, "Pages read", &pages_read, 1)) break;
|
||||
bool pages_saved = true;
|
||||
for(uint16_t i = 0; i < data->data_size; i += 4) {
|
||||
string_printf(temp_str, "Page %d", i / 4);
|
||||
@@ -148,8 +154,14 @@ bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) {
|
||||
MfUltralightData* data = &dev->dev_data.mf_ul_data;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
uint32_t data_format_version = 0;
|
||||
|
||||
do {
|
||||
// Read Mifare Ultralight format version
|
||||
if(!flipper_format_read_uint32(file, "Data format version", &data_format_version, 1)) {
|
||||
if(!flipper_format_rewind(file)) break;
|
||||
}
|
||||
|
||||
// Read signature
|
||||
if(!flipper_format_read_hex(file, "Signature", data->signature, sizeof(data->signature)))
|
||||
break;
|
||||
@@ -173,11 +185,18 @@ bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) {
|
||||
}
|
||||
if(!counters_parsed) break;
|
||||
// Read pages
|
||||
uint32_t pages = 0;
|
||||
if(!flipper_format_read_uint32(file, "Pages total", &pages, 1)) break;
|
||||
data->data_size = pages * 4;
|
||||
uint32_t pages_total = 0;
|
||||
if(!flipper_format_read_uint32(file, "Pages total", &pages_total, 1)) break;
|
||||
uint32_t pages_read = 0;
|
||||
if(data_format_version < nfc_mifare_ultralight_data_format_version) {
|
||||
pages_read = pages_total;
|
||||
} else {
|
||||
if(!flipper_format_read_uint32(file, "Pages read", &pages_read, 1)) break;
|
||||
}
|
||||
data->data_size = pages_total * 4;
|
||||
data->data_read = pages_read * 4;
|
||||
bool pages_parsed = true;
|
||||
for(uint16_t i = 0; i < pages; i++) {
|
||||
for(uint16_t i = 0; i < pages_total; i++) {
|
||||
string_printf(temp_str, "Page %d", i);
|
||||
if(!flipper_format_read_hex(file, string_get_cstr(temp_str), &data->data[i * 4], 4)) {
|
||||
pages_parsed = false;
|
||||
@@ -1186,7 +1205,7 @@ void nfc_device_data_clear(NfcDeviceData* dev_data) {
|
||||
} else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
|
||||
memset(&dev_data->mf_classic_data, 0, sizeof(MfClassicData));
|
||||
} else if(dev_data->protocol == NfcDeviceProtocolMifareUl) {
|
||||
memset(&dev_data->mf_ul_data, 0, sizeof(MfUltralightData));
|
||||
mf_ul_reset(&dev_data->mf_ul_data);
|
||||
} else if(dev_data->protocol == NfcDeviceProtocolEMV) {
|
||||
memset(&dev_data->emv_data, 0, sizeof(EmvData));
|
||||
}
|
||||
|
@@ -101,6 +101,8 @@ int32_t nfc_worker_task(void* context) {
|
||||
nfc_worker_emulate_mf_ultralight(nfc_worker);
|
||||
} else if(nfc_worker->state == NfcWorkerStateMfClassicEmulate) {
|
||||
nfc_worker_emulate_mf_classic(nfc_worker);
|
||||
} else if(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) {
|
||||
nfc_worker_mf_ultralight_read_auth(nfc_worker);
|
||||
} else if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) {
|
||||
nfc_worker_mf_classic_dict_attack(nfc_worker);
|
||||
}
|
||||
@@ -416,10 +418,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Start Dictionary attack, Key Count %d",
|
||||
mf_classic_dict_get_total_keys(dict));
|
||||
FURI_LOG_D(TAG, "Start Dictionary attack, Key Count %d", mf_classic_dict_get_total_keys(dict));
|
||||
for(size_t i = 0; i < total_sectors; i++) {
|
||||
FURI_LOG_I(TAG, "Sector %d", i);
|
||||
nfc_worker->callback(NfcWorkerEventNewSector, nfc_worker->context);
|
||||
@@ -462,20 +461,17 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
}
|
||||
}
|
||||
if(is_key_a_found && is_key_b_found) break;
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack)
|
||||
break;
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
|
||||
} else {
|
||||
if(!card_removed_notified) {
|
||||
nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
|
||||
card_removed_notified = true;
|
||||
card_found_notified = false;
|
||||
}
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack)
|
||||
break;
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
|
||||
}
|
||||
}
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack)
|
||||
break;
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
|
||||
mf_classic_read_sector(&tx_rx, data, i);
|
||||
mf_classic_dict_rewind(dict);
|
||||
}
|
||||
@@ -518,3 +514,57 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) {
|
||||
|
||||
rfal_platform_spi_release();
|
||||
}
|
||||
|
||||
void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker) {
|
||||
furi_assert(nfc_worker);
|
||||
furi_assert(nfc_worker->callback);
|
||||
|
||||
MfUltralightData* data = &nfc_worker->dev_data->mf_ul_data;
|
||||
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
|
||||
FuriHalNfcTxRxContext tx_rx = {};
|
||||
MfUltralightReader reader = {};
|
||||
mf_ul_reset(data);
|
||||
|
||||
uint32_t key = 0;
|
||||
uint16_t pack = 0;
|
||||
while(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) {
|
||||
furi_hal_nfc_sleep();
|
||||
if(furi_hal_nfc_detect(nfc_data, 300) && nfc_data->type == FuriHalNfcTypeA) {
|
||||
if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
|
||||
nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
|
||||
if(data->auth_method == MfUltralightAuthMethodManual) {
|
||||
nfc_worker->callback(NfcWorkerEventMfUltralightPassKey, nfc_worker->context);
|
||||
key = nfc_util_bytes2num(data->auth_key, 4);
|
||||
} else if(data->auth_method == MfUltralightAuthMethodAmeebo) {
|
||||
key = mf_ul_pwdgen_amiibo(nfc_data);
|
||||
} else if(data->auth_method == MfUltralightAuthMethodXiaomi) {
|
||||
key = mf_ul_pwdgen_xiaomi(nfc_data);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Incorrect auth method");
|
||||
break;
|
||||
}
|
||||
|
||||
data->auth_success = mf_ultralight_authenticate(&tx_rx, key, &pack);
|
||||
mf_ul_read_card(&tx_rx, &reader, data);
|
||||
if(data->auth_success) {
|
||||
MfUltralightConfigPages* config_pages = mf_ultralight_get_config_pages(data);
|
||||
if(config_pages != NULL) {
|
||||
config_pages->auth_data.pwd.value = REVERSE_BYTES_U32(key);
|
||||
config_pages->auth_data.pack.value = pack;
|
||||
}
|
||||
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
|
||||
break;
|
||||
} else {
|
||||
nfc_worker->callback(NfcWorkerEventFail, nfc_worker->context);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context);
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
} else {
|
||||
nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ typedef enum {
|
||||
NfcWorkerStateUidEmulate,
|
||||
NfcWorkerStateMfUltralightEmulate,
|
||||
NfcWorkerStateMfClassicEmulate,
|
||||
NfcWorkerStateReadMfUltralightReadAuth,
|
||||
NfcWorkerStateMfClassicDictAttack,
|
||||
// Debug
|
||||
NfcWorkerStateEmulateApdu,
|
||||
@@ -44,6 +45,7 @@ typedef enum {
|
||||
NfcWorkerEventAborted,
|
||||
NfcWorkerEventCardDetected,
|
||||
NfcWorkerEventNoCardDetected,
|
||||
NfcWorkerEventWrongCardDetected,
|
||||
|
||||
// Mifare Classic events
|
||||
NfcWorkerEventNoDictFound,
|
||||
@@ -51,6 +53,9 @@ typedef enum {
|
||||
NfcWorkerEventNewDictKeyBatch,
|
||||
NfcWorkerEventFoundKeyA,
|
||||
NfcWorkerEventFoundKeyB,
|
||||
|
||||
// Mifare Ultralight events
|
||||
NfcWorkerEventMfUltralightPassKey,
|
||||
} NfcWorkerEvent;
|
||||
|
||||
typedef bool (*NfcWorkerCallback)(NfcWorkerEvent event, void* context);
|
||||
|
@@ -44,4 +44,8 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker);
|
||||
|
||||
void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker);
|
||||
|
||||
void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker);
|
||||
|
||||
void nfc_worker_mf_ul_auth_attack(NfcWorker* nfc_worker);
|
||||
|
||||
void nfc_worker_emulate_apdu(NfcWorker* nfc_worker);
|
||||
|
@@ -3,10 +3,11 @@
|
||||
#include "troyka_parser.h"
|
||||
|
||||
NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd] = {
|
||||
[NfcSupportedCardTypeTroyka] = {
|
||||
.protocol = NfcDeviceProtocolMifareClassic,
|
||||
.verify = troyka_parser_verify,
|
||||
.read = troyka_parser_read,
|
||||
.parse = troyka_parser_parse,
|
||||
},
|
||||
[NfcSupportedCardTypeTroyka] =
|
||||
{
|
||||
.protocol = NfcDeviceProtocolMifareClassic,
|
||||
.verify = troyka_parser_verify,
|
||||
.read = troyka_parser_read,
|
||||
.parse = troyka_parser_parse,
|
||||
},
|
||||
};
|
||||
|
@@ -1,10 +1,39 @@
|
||||
#include <limits.h>
|
||||
#include <mbedtls/sha1.h>
|
||||
#include "mifare_ultralight.h"
|
||||
#include "nfc_util.h"
|
||||
#include <furi.h>
|
||||
#include "furi_hal_nfc.h"
|
||||
#include <m-string.h>
|
||||
|
||||
#define TAG "MfUltralight"
|
||||
|
||||
// Algorithms from: https://github.com/RfidResearchGroup/proxmark3/blob/0f6061c16f072372b7d4d381911f1542afbc3a69/common/generator.c#L110
|
||||
uint32_t mf_ul_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 mf_ul_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;
|
||||
@@ -12,6 +41,20 @@ bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void mf_ul_reset(MfUltralightData* data) {
|
||||
furi_assert(data);
|
||||
data->type = MfUltralightTypeUnknown;
|
||||
memset(&data->version, 0, sizeof(MfUltralightVersion));
|
||||
memset(data->signature, 0, sizeof(data->signature));
|
||||
memset(data->counter, 0, sizeof(data->counter));
|
||||
memset(data->tearing, 0, sizeof(data->tearing));
|
||||
memset(data->data, 0, sizeof(data->data));
|
||||
data->data_size = 0;
|
||||
data->data_read = 0;
|
||||
data->curr_authlim = 0;
|
||||
data->has_auth = false;
|
||||
}
|
||||
|
||||
static MfUltralightFeatures mf_ul_get_features(MfUltralightType type) {
|
||||
switch(type) {
|
||||
case MfUltralightTypeUL11:
|
||||
@@ -127,6 +170,37 @@ bool mf_ultralight_read_version(
|
||||
return version_read;
|
||||
}
|
||||
|
||||
bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint16_t* pack) {
|
||||
bool authenticated = false;
|
||||
|
||||
do {
|
||||
FURI_LOG_D(TAG, "Authenticating");
|
||||
tx_rx->tx_data[0] = MF_UL_AUTH;
|
||||
nfc_util_num2bytes(key, 4, &tx_rx->tx_data[1]);
|
||||
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;
|
||||
}
|
||||
|
||||
// PACK
|
||||
if(tx_rx->rx_bits < 2 * 8) {
|
||||
FURI_LOG_D(TAG, "Authentication failed");
|
||||
break;
|
||||
}
|
||||
|
||||
if(pack != NULL) {
|
||||
*pack = (tx_rx->rx_data[0] << 8) | tx_rx->rx_data[1];
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Auth success. Password: %08X. PACK: %04X", key, *pack);
|
||||
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;
|
||||
}
|
||||
@@ -413,7 +487,7 @@ static int16_t mf_ultralight_ntag_i2c_addr_tag_to_lin(
|
||||
}
|
||||
}
|
||||
|
||||
static MfUltralightConfigPages* mf_ultralight_get_config_pages(MfUltralightData* data) {
|
||||
MfUltralightConfigPages* mf_ultralight_get_config_pages(MfUltralightData* data) {
|
||||
if(data->type >= MfUltralightTypeUL11 && data->type <= MfUltralightTypeNTAG216) {
|
||||
return (MfUltralightConfigPages*)&data->data[data->data_size - 4 * 4];
|
||||
} else if(
|
||||
@@ -516,6 +590,7 @@ 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) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
@@ -524,17 +599,19 @@ bool mf_ultralight_read_pages(
|
||||
i + (valid_pages > 4 ? 4 : valid_pages) - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if(valid_pages > 4) {
|
||||
pages_read_cnt = 4;
|
||||
} else {
|
||||
pages_read_cnt = valid_pages;
|
||||
}
|
||||
reader->pages_read += pages_read_cnt;
|
||||
data->data_size = reader->pages_read * 4;
|
||||
memcpy(&data->data[i * 4], tx_rx->rx_data, pages_read_cnt * 4);
|
||||
}
|
||||
data->data_size = reader->pages_to_read * 4;
|
||||
data->data_read = reader->pages_read * 4;
|
||||
|
||||
return reader->pages_read == reader->pages_to_read;
|
||||
return reader->pages_read > 0;
|
||||
}
|
||||
|
||||
bool mf_ultralight_fast_read_pages(
|
||||
@@ -620,6 +697,48 @@ bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData*
|
||||
return counter_read == (is_single_counter ? 1 : 3);
|
||||
}
|
||||
|
||||
int16_t mf_ultralight_get_authlim(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
MfUltralightReader* reader,
|
||||
MfUltralightData* data) {
|
||||
mf_ultralight_read_version(tx_rx, reader, data);
|
||||
if(!(reader->supported_features & MfUltralightSupportAuth)) {
|
||||
// No authentication
|
||||
return -2;
|
||||
}
|
||||
|
||||
uint8_t config_pages_index;
|
||||
if(data->type >= MfUltralightTypeUL11 && data->type <= MfUltralightTypeNTAG216) {
|
||||
config_pages_index = reader->pages_to_read - 4;
|
||||
} else if(
|
||||
data->type >= MfUltralightTypeNTAGI2CPlus1K &&
|
||||
data->type <= MfUltralightTypeNTAGI2CPlus1K) {
|
||||
config_pages_index = 0xe3;
|
||||
} else {
|
||||
// No config pages
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(!mf_ultralight_read_pages_direct(tx_rx, config_pages_index, data->data)) {
|
||||
// Config pages are not readable due to protection
|
||||
return -1;
|
||||
}
|
||||
|
||||
MfUltralightConfigPages* config_pages = (MfUltralightConfigPages*)&data->data;
|
||||
if(config_pages->auth0 >= reader->pages_to_read) {
|
||||
// Authentication is not configured
|
||||
return -2;
|
||||
}
|
||||
|
||||
int16_t authlim = config_pages->access.authlim;
|
||||
if(authlim > 0 && data->type >= MfUltralightTypeNTAGI2CPlus1K &&
|
||||
data->type <= MfUltralightTypeNTAGI2CPlus2K) {
|
||||
authlim = 1 << authlim;
|
||||
}
|
||||
|
||||
return authlim;
|
||||
}
|
||||
|
||||
bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data) {
|
||||
uint8_t flag_read = 0;
|
||||
|
||||
|
@@ -28,6 +28,12 @@
|
||||
|
||||
#define MF_UL_NTAG203_COUNTER_PAGE (41)
|
||||
|
||||
typedef enum {
|
||||
MfUltralightAuthMethodManual,
|
||||
MfUltralightAuthMethodAmeebo,
|
||||
MfUltralightAuthMethodXiaomi,
|
||||
} MfUltralightAuthMethod;
|
||||
|
||||
// Important: order matters; some features are based on positioning in this enum
|
||||
typedef enum {
|
||||
MfUltralightTypeUnknown,
|
||||
@@ -50,6 +56,13 @@ typedef enum {
|
||||
MfUltralightTypeNum,
|
||||
} MfUltralightType;
|
||||
|
||||
typedef enum {
|
||||
MfUltralightAuthLimitUnknown,
|
||||
MfUltralightAuthLimitNotSupported,
|
||||
MfUltralightAuthLimitConfigured,
|
||||
MfUltralightAuthLimitNotConfigured,
|
||||
} MfUltralightAuthLimit;
|
||||
|
||||
typedef enum {
|
||||
MfUltralightSupportNone = 0,
|
||||
MfUltralightSupportFastRead = 1 << 0,
|
||||
@@ -104,9 +117,14 @@ typedef struct {
|
||||
uint8_t signature[32];
|
||||
uint32_t counter[3];
|
||||
uint8_t tearing[3];
|
||||
bool has_auth;
|
||||
MfUltralightAuthMethod auth_method;
|
||||
uint8_t auth_key[4];
|
||||
bool auth_success;
|
||||
uint16_t curr_authlim;
|
||||
uint16_t data_size;
|
||||
uint8_t data[MF_UL_MAX_DUMP_SIZE];
|
||||
uint16_t data_read;
|
||||
} MfUltralightData;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
@@ -176,6 +194,8 @@ typedef struct {
|
||||
bool read_counter_incremented;
|
||||
} MfUltralightEmulator;
|
||||
|
||||
void mf_ul_reset(MfUltralightData* data);
|
||||
|
||||
bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
|
||||
|
||||
bool mf_ultralight_read_version(
|
||||
@@ -204,6 +224,10 @@ bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData*
|
||||
|
||||
bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data);
|
||||
|
||||
bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint16_t* pack);
|
||||
|
||||
MfUltralightConfigPages* mf_ultralight_get_config_pages(MfUltralightData* data);
|
||||
|
||||
bool mf_ul_read_card(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
MfUltralightReader* reader,
|
||||
@@ -220,3 +244,12 @@ bool mf_ul_prepare_emulation_response(
|
||||
uint16_t* buff_tx_len,
|
||||
uint32_t* data_type,
|
||||
void* context);
|
||||
|
||||
int16_t mf_ultralight_get_authlim(
|
||||
FuriHalNfcTxRxContext* tx_rx,
|
||||
MfUltralightReader* reader,
|
||||
MfUltralightData* data);
|
||||
|
||||
uint32_t mf_ul_pwdgen_amiibo(FuriHalNfcDevData* data);
|
||||
|
||||
uint32_t mf_ul_pwdgen_xiaomi(FuriHalNfcDevData* data);
|
||||
|
Reference in New Issue
Block a user