nfc-mfultralight: fix support for MF0UL21

This commit is contained in:
Philippe Teuwen 2017-04-01 00:25:14 +02:00
parent 560f6a6413
commit 3ec9ecf800
2 changed files with 46 additions and 27 deletions

View file

@ -134,18 +134,38 @@ typedef struct {
uint8_t otp[4]; uint8_t otp[4];
} mifareul_block_manufacturer; } mifareul_block_manufacturer;
// MIFARE Ultralight EV1 Config Pages // MIFARE Ultralight EV1 MF0UL11 Config Pages
typedef struct { typedef struct {
uint8_t mod; uint8_t mod;
uint8_t rfui[2]; uint8_t rfui1[2];
uint8_t auth0; uint8_t auth0;
uint8_t access; uint8_t access;
uint8_t vctid; uint8_t vctid;
uint8_t rfui1[2]; uint8_t rfui2[2];
uint8_t pwd[4]; uint8_t pwd[4];
uint8_t pack[2]; 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]; 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 { typedef struct {
uint8_t abtData[16]; uint8_t abtData[16];
@ -154,7 +174,9 @@ typedef struct {
typedef union { typedef union {
mifareul_block_manufacturer mbm; mifareul_block_manufacturer mbm;
mifareul_block_data mbd; mifareul_block_data mbd;
mifareul_block_config mbc; mifareul_block_config11 mbc11;
mifareul_block_config21A mbc21a;
mifareul_block_config21B mbc21b;
} mifareul_block; } mifareul_block;
// standard UL tag - 1 manuf block + 3 user blocks // standard UL tag - 1 manuf block + 3 user blocks
@ -167,9 +189,9 @@ typedef struct {
mifareul_block amb[5]; mifareul_block amb[5];
} mifareul_ev1_mf0ul11_tag; } 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 { typedef struct {
mifareul_block amb[10]; mifareul_block amb[11];
} mifareul_ev1_mf0ul21_tag; } mifareul_ev1_mf0ul21_tag;
// Reset struct alignment to default // Reset struct alignment to default

View file

@ -60,7 +60,6 @@
#define MAX_TARGET_COUNT 16 #define MAX_TARGET_COUNT 16
#define MAX_UID_LEN 10 #define MAX_UID_LEN 10
#define BLOCK_COUNT 0xf
#define EV1_NONE 0 #define EV1_NONE 0
#define EV1_UL11 1 #define EV1_UL11 1
@ -70,7 +69,7 @@ static nfc_device *pnd;
static nfc_target nt; static nfc_target nt;
static mifare_param mp; static mifare_param mp;
static mifareul_ev1_mf0ul21_tag mtDump; // use the largest tag type for internal storage 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 uint32_t uiReadPages = 0;
static uint8_t iPWD[4] = { 0x0 }; static uint8_t iPWD[4] = { 0x0 };
static uint8_t iPACK[2] = { 0x0 }; static uint8_t iPACK[2] = { 0x0 };
@ -115,34 +114,32 @@ read_card(void)
bool bFailure = false; bool bFailure = false;
uint32_t uiFailedPages = 0; 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 // Try to read out the data block
if (nfc_initiator_mifare_cmd(pnd, MC_READ, page, &mp)) { 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 { } else {
bFailure = true; bFailure = true;
} }
for (uint8_t i=0; i < (uiBlocks - page < 4 ? uiBlocks - page : 4); i++) {
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); print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages);
} }
}
printf("|\n"); 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); fflush(stdout);
// copy EV1 secrets to dump data // copy EV1 secrets to dump data
switch(iEV1Type) { switch(iEV1Type) {
case EV1_UL11: case EV1_UL11:
memcpy(mtDump.amb[4].mbc.pwd, iPWD, 4); memcpy(mtDump.amb[4].mbc11.pwd, iPWD, 4);
memcpy(mtDump.amb[4].mbc.pack, iPACK, 2); memcpy(mtDump.amb[4].mbc11.pack, iPACK, 2);
break; break;
case EV1_UL21: case EV1_UL21:
memcpy(mtDump.amb[9].mbc.pwd, iPWD, 4); memcpy(mtDump.amb[9].mbc21a.pwd, iPWD, 4);
memcpy(mtDump.amb[9].mbc.pack, iPACK, 2); memcpy(mtDump.amb[9].mbc21b.pack, iPACK, 2);
break; break;
case EV1_NONE: case EV1_NONE:
default: default:
@ -347,7 +344,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid)
write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y')); 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. */ /* We may need to skip 2 first pages. */
if (!write_uid) { if (!write_uid) {
printf("ss"); 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)) { if ((page == 0x2) && (!write_lock)) {
printf("s"); printf("s");
uiSkippedPages++; uiSkippedPages++;
@ -391,7 +388,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid)
print_success_or_failure(bFailure, &uiWrittenPages, &uiFailedPages); print_success_or_failure(bFailure, &uiWrittenPages, &uiFailedPages);
} }
printf("|\n"); 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; return true;
} }
@ -602,13 +599,13 @@ main(int argc, const char *argv[])
printf("EV1 storage size: "); printf("EV1 storage size: ");
if(abtRx[6] == 0x0b) { if(abtRx[6] == 0x0b) {
printf("48 bytes\n"); printf("48 bytes\n");
uiBlocks= 0x13; uiBlocks= 0x14;
iEV1Type= EV1_UL11; iEV1Type= EV1_UL11;
iDumpSize= sizeof(mifareul_ev1_mf0ul11_tag); iDumpSize= sizeof(mifareul_ev1_mf0ul11_tag);
} }
else if(abtRx[6] == 0x0e) { else if(abtRx[6] == 0x0e) {
printf("128 bytes\n"); printf("128 bytes\n");
uiBlocks= 0x28; uiBlocks= 0x29;
iEV1Type= EV1_UL21; iEV1Type= EV1_UL21;
iDumpSize= sizeof(mifareul_ev1_mf0ul21_tag); iDumpSize= sizeof(mifareul_ev1_mf0ul21_tag);
} }