From 3ec9ecf8000b326327eb3069399f692c0b3783ea Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 1 Apr 2017 00:25:14 +0200 Subject: [PATCH] nfc-mfultralight: fix support for MF0UL21 --- utils/mifare.h | 36 +++++++++++++++++++++++++++++------- utils/nfc-mfultralight.c | 37 +++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/utils/mifare.h b/utils/mifare.h index 564b94b..cd6c6f6 100644 --- a/utils/mifare.h +++ b/utils/mifare.h @@ -134,18 +134,38 @@ typedef struct { uint8_t otp[4]; } mifareul_block_manufacturer; -// MIFARE Ultralight EV1 Config Pages +// MIFARE Ultralight EV1 MF0UL11 Config Pages typedef struct { uint8_t mod; - uint8_t rfui[2]; + uint8_t rfui1[2]; uint8_t auth0; uint8_t access; uint8_t vctid; - uint8_t rfui1[2]; + uint8_t rfui2[2]; uint8_t pwd[4]; uint8_t pack[2]; + uint8_t rfui3[2]; +} mifareul_block_config11; + +// MIFARE Ultralight EV1 MF0UL21 ConfigA Pages +typedef struct { + uint8_t lock[3]; + uint8_t rfui0; + uint8_t mod; + uint8_t rfui1[2]; + uint8_t auth0; + uint8_t access; + uint8_t vctid; uint8_t rfui2[2]; -} mifareul_block_config; + uint8_t pwd[4]; +} mifareul_block_config21A; + +// MIFARE Ultralight EV1 MF0UL21 ConfigB Pages +typedef struct { + uint8_t pack[2]; + uint8_t rfui3[2]; + uint8_t dummy[12]; +} mifareul_block_config21B; typedef struct { uint8_t abtData[16]; @@ -154,7 +174,9 @@ typedef struct { typedef union { mifareul_block_manufacturer mbm; mifareul_block_data mbd; - mifareul_block_config mbc; + mifareul_block_config11 mbc11; + mifareul_block_config21A mbc21a; + mifareul_block_config21B mbc21b; } mifareul_block; // standard UL tag - 1 manuf block + 3 user blocks @@ -167,9 +189,9 @@ typedef struct { mifareul_block amb[5]; } mifareul_ev1_mf0ul11_tag; -// UL EV1 MF0UL21 tag - 1 manuf block + 8 user blocks + 1 config block +// UL EV1 MF0UL21 tag - 1 manuf block + 8 user blocks + 1/4 lock block + 1 config block typedef struct { - mifareul_block amb[10]; + mifareul_block amb[11]; } mifareul_ev1_mf0ul21_tag; // Reset struct alignment to default diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 7b73a8d..737a892 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -60,7 +60,6 @@ #define MAX_TARGET_COUNT 16 #define MAX_UID_LEN 10 -#define BLOCK_COUNT 0xf #define EV1_NONE 0 #define EV1_UL11 1 @@ -70,7 +69,7 @@ static nfc_device *pnd; static nfc_target nt; static mifare_param mp; static mifareul_ev1_mf0ul21_tag mtDump; // use the largest tag type for internal storage -static uint32_t uiBlocks = BLOCK_COUNT; +static uint32_t uiBlocks = 0x10; static uint32_t uiReadPages = 0; static uint8_t iPWD[4] = { 0x0 }; static uint8_t iPACK[2] = { 0x0 }; @@ -115,34 +114,32 @@ read_card(void) bool bFailure = false; uint32_t uiFailedPages = 0; - printf("Reading %d pages |", uiBlocks + 1); + printf("Reading %d pages |", uiBlocks); - for (page = 0; page <= uiBlocks; page += 4) { + for (page = 0; page < uiBlocks; page += 4) { // Try to read out the data block if (nfc_initiator_mifare_cmd(pnd, MC_READ, page, &mp)) { - memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16); + memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, uiBlocks - page < 4 ? (uiBlocks - page) * 4 : 16); } else { bFailure = true; } - - print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); - print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); - print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); - print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); + for (uint8_t i=0; i < (uiBlocks - page < 4 ? uiBlocks - page : 4); i++) { + print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); + } } printf("|\n"); - printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks + 1, uiFailedPages); + printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks, uiFailedPages); fflush(stdout); // copy EV1 secrets to dump data switch(iEV1Type) { case EV1_UL11: - memcpy(mtDump.amb[4].mbc.pwd, iPWD, 4); - memcpy(mtDump.amb[4].mbc.pack, iPACK, 2); + memcpy(mtDump.amb[4].mbc11.pwd, iPWD, 4); + memcpy(mtDump.amb[4].mbc11.pack, iPACK, 2); break; case EV1_UL21: - memcpy(mtDump.amb[9].mbc.pwd, iPWD, 4); - memcpy(mtDump.amb[9].mbc.pack, iPACK, 2); + memcpy(mtDump.amb[9].mbc21a.pwd, iPWD, 4); + memcpy(mtDump.amb[9].mbc21b.pack, iPACK, 2); break; case EV1_NONE: default: @@ -347,7 +344,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } - printf("Writing %d pages |", uiBlocks + 1); + printf("Writing %d pages |", uiBlocks); /* We may need to skip 2 first pages. */ if (!write_uid) { printf("ss"); @@ -359,7 +356,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) } } - for (uint32_t page = uiSkippedPages; page <= uiBlocks; page++) { + for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) { if ((page == 0x2) && (!write_lock)) { printf("s"); uiSkippedPages++; @@ -391,7 +388,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid) print_success_or_failure(bFailure, &uiWrittenPages, &uiFailedPages); } printf("|\n"); - printf("Done, %d of %d pages written (%d pages skipped, %d pages failed).\n", uiWrittenPages, uiBlocks + 1, uiSkippedPages, uiFailedPages); + printf("Done, %d of %d pages written (%d pages skipped, %d pages failed).\n", uiWrittenPages, uiBlocks, uiSkippedPages, uiFailedPages); return true; } @@ -602,13 +599,13 @@ main(int argc, const char *argv[]) printf("EV1 storage size: "); if(abtRx[6] == 0x0b) { printf("48 bytes\n"); - uiBlocks= 0x13; + uiBlocks= 0x14; iEV1Type= EV1_UL11; iDumpSize= sizeof(mifareul_ev1_mf0ul11_tag); } else if(abtRx[6] == 0x0e) { printf("128 bytes\n"); - uiBlocks= 0x28; + uiBlocks= 0x29; iEV1Type= EV1_UL21; iDumpSize= sizeof(mifareul_ev1_mf0ul21_tag); }