NFC: fix creating MF Classic tags from "Add Manually" menu (BCC calulation and ATQA/SAK writing) (#2342)

* NFC: fix creating MF Classic cards from "Add Manually" menu (BCC calculation and AQTA/SAK writing)
* NFC: Fix BCC/SAK/ATQA in unit_tests and SAK in nfc_generate_mf_classic

Co-authored-by: gornekich <n.gorbadey@gmail.com>
This commit is contained in:
AloneLiberty 2023-02-02 15:18:39 +00:00 committed by GitHub
parent 01a9854f8a
commit 46fb86265c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 7 deletions

View File

@ -348,13 +348,37 @@ static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) {
memcpy(atqa, nfc_dev->dev_data.nfc_data.atqa, 2); memcpy(atqa, nfc_dev->dev_data.nfc_data.atqa, 2);
MfClassicData* mf_data = &nfc_dev->dev_data.mf_classic_data; MfClassicData* mf_data = &nfc_dev->dev_data.mf_classic_data;
// Check the manufacturer block (should be uid[uid_len] + 0xFF[rest]) // Check the manufacturer block (should be uid[uid_len] + BCC (for 4byte only) + SAK + ATQA0 + ATQA1 + 0xFF[rest])
uint8_t manufacturer_block[16] = {0}; uint8_t manufacturer_block[16] = {0};
memcpy(manufacturer_block, nfc_dev->dev_data.mf_classic_data.block[0].value, 16); memcpy(manufacturer_block, nfc_dev->dev_data.mf_classic_data.block[0].value, 16);
mu_assert( mu_assert(
memcmp(manufacturer_block, uid, uid_len) == 0, memcmp(manufacturer_block, uid, uid_len) == 0,
"manufacturer_block uid doesn't match the file\r\n"); "manufacturer_block uid doesn't match the file\r\n");
for(uint8_t i = uid_len; i < 16; i++) {
uint8_t position = 0;
if(uid_len == 4) {
position = uid_len;
uint8_t bcc = 0;
for(int i = 0; i < uid_len; i++) {
bcc ^= uid[i];
}
mu_assert(manufacturer_block[position] == bcc, "manufacturer_block bcc assert failed\r\n");
} else {
position = uid_len - 1;
}
mu_assert(manufacturer_block[position + 1] == sak, "manufacturer_block sak assert failed\r\n");
mu_assert(
manufacturer_block[position + 2] == atqa[0], "manufacturer_block atqa0 assert failed\r\n");
mu_assert(
manufacturer_block[position + 3] == atqa[1], "manufacturer_block atqa1 assert failed\r\n");
for(uint8_t i = position + 4; i < 16; i++) {
mu_assert( mu_assert(
manufacturer_block[i] == 0xFF, "manufacturer_block[i] == 0xFF assert failed\r\n"); manufacturer_block[i] == 0xFF, "manufacturer_block[i] == 0xFF assert failed\r\n");
} }

View File

@ -30,12 +30,32 @@ static void nfc_generate_mf_classic_uid(uint8_t* uid, uint8_t length) {
furi_hal_random_fill_buf(&uid[1], length - 1); furi_hal_random_fill_buf(&uid[1], length - 1);
} }
static void nfc_generate_mf_classic_block_0(uint8_t* block, uint8_t uid_len) { static void nfc_generate_mf_classic_block_0(
uint8_t* block,
uint8_t uid_len,
uint8_t sak,
uint8_t atqa0,
uint8_t atqa1) {
// Block length is always 16 bytes, and the UID can be either 4 or 7 bytes // Block length is always 16 bytes, and the UID can be either 4 or 7 bytes
furi_assert(uid_len == 4 || uid_len == 7); furi_assert(uid_len == 4 || uid_len == 7);
furi_assert(block); furi_assert(block);
nfc_generate_mf_classic_uid(block, uid_len);
for(int i = uid_len; i < 16; i++) { if(uid_len == 4) {
// Calculate BCC
block[uid_len] = 0;
for(int i = 0; i < uid_len; i++) {
block[uid_len] ^= block[i];
}
} else {
uid_len -= 1;
}
block[uid_len + 1] = sak;
block[uid_len + 2] = atqa0;
block[uid_len + 3] = atqa1;
for(int i = uid_len + 4; i < 16; i++) {
block[i] = 0xFF; block[i] = 0xFF;
} }
} }
@ -74,7 +94,6 @@ static void
data->nfc_data.type = FuriHalNfcTypeA; data->nfc_data.type = FuriHalNfcTypeA;
data->nfc_data.interface = FuriHalNfcInterfaceRf; data->nfc_data.interface = FuriHalNfcInterfaceRf;
data->nfc_data.uid_len = uid_len; data->nfc_data.uid_len = uid_len;
nfc_generate_mf_classic_block_0(data->mf_classic_data.block[0].value, uid_len);
data->nfc_data.atqa[0] = 0x44; data->nfc_data.atqa[0] = 0x44;
data->nfc_data.atqa[1] = 0x00; data->nfc_data.atqa[1] = 0x00;
data->nfc_data.sak = 0x08; data->nfc_data.sak = 0x08;
@ -316,6 +335,7 @@ static void nfc_generate_ntag_i2c_plus_2k(NfcDeviceData* data) {
void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) { void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) {
nfc_generate_common_start(data); nfc_generate_common_start(data);
nfc_generate_mf_classic_uid(data->mf_classic_data.block[0].value, uid_len);
nfc_generate_mf_classic_common(data, uid_len, type); nfc_generate_mf_classic_common(data, uid_len, type);
// Set the UID // Set the UID
@ -339,7 +359,6 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType
} }
// Set SAK to 18 // Set SAK to 18
data->nfc_data.sak = 0x18; data->nfc_data.sak = 0x18;
} else if(type == MfClassicType1k) { } else if(type == MfClassicType1k) {
// Set every block to 0xFF // Set every block to 0xFF
for(uint16_t i = 1; i < MF_CLASSIC_1K_TOTAL_SECTORS_NUM * 4; i += 1) { for(uint16_t i = 1; i < MF_CLASSIC_1K_TOTAL_SECTORS_NUM * 4; i += 1) {
@ -366,6 +385,13 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType
data->nfc_data.sak = 0x09; data->nfc_data.sak = 0x09;
} }
nfc_generate_mf_classic_block_0(
data->mf_classic_data.block[0].value,
uid_len,
data->nfc_data.sak,
data->nfc_data.atqa[0],
data->nfc_data.atqa[1]);
mfc->type = type; mfc->type = type;
} }