Update the mifare-classic-format example.
This commit is contained in:
parent
d8b0a18752
commit
935ab47c54
2 changed files with 79 additions and 180 deletions
|
@ -1,4 +1,4 @@
|
||||||
AM_CFLAGS = -I. @LIBNFC_CFLAGS@
|
AM_CFLAGS = -I. -I$(top_builddir)/libfreefare @LIBNFC_CFLAGS@
|
||||||
AM_LDFLAGS = @LIBNFC_LIBS@
|
AM_LDFLAGS = @LIBNFC_LIBS@
|
||||||
|
|
||||||
bin_PROGRAMS = mifare-classic-format
|
bin_PROGRAMS = mifare-classic-format
|
||||||
|
|
|
@ -1,200 +1,99 @@
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <err.h>
|
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include <freefare.h>
|
#include <freefare.h>
|
||||||
|
|
||||||
#define DEBUG
|
#define block_address(sector, block) ((sector * 4) + block)
|
||||||
|
|
||||||
// Useful macros
|
MifareClassicKey default_keys[] = {
|
||||||
#ifdef DEBUG
|
{ 0xff,0xff,0xff,0xff,0xff,0xff },
|
||||||
// #define DBG(x, args...) printf("DBG %s:%d: " x "\n", __FILE__, __LINE__,## args )
|
{ 0xd3,0xf7,0xd3,0xf7,0xd3,0xf7 },
|
||||||
#define DBG(x, ...) fprintf(stderr, "DBG %s:%d: " x "\n", __FILE__, __LINE__, ## __VA_ARGS__ )
|
{ 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5 },
|
||||||
#else
|
{ 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5 },
|
||||||
#define DBG(...) do {} while (0)
|
{ 0x4d,0x3a,0x99,0xc3,0x51,0xdd },
|
||||||
#endif
|
{ 0x1a,0x98,0x2c,0x7e,0x45,0x9a },
|
||||||
|
{ 0xaa,0xbb,0xcc,0xdd,0xee,0xff },
|
||||||
static nfc_device_t *device = NULL;
|
{ 0x00,0x00,0x00,0x00,0x00,0x00 }
|
||||||
static MifareClassicTag *tags = NULL;
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
mifare_classic_setup (MifareClassicTag *tag)
|
try_format_sector (MifareClassicTag tag, MifareSectorNumber sector)
|
||||||
{
|
{
|
||||||
int res = 0;
|
for (int i = 0; i < (sizeof (default_keys) / sizeof (MifareClassicKey)); i++) {
|
||||||
|
printf (" s=%d i=%d \n", sector, i);
|
||||||
|
if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block_address (sector, 0), default_keys[i], MFC_KEY_A))) {
|
||||||
|
if (0 == mifare_classic_format_sector (tag, sector)) {
|
||||||
|
mifare_classic_disconnect (tag);
|
||||||
|
return 0;
|
||||||
|
} else if (EIO == errno) {
|
||||||
|
err (EXIT_FAILURE, "sector %d", sector);
|
||||||
|
}
|
||||||
|
mifare_classic_disconnect (tag);
|
||||||
|
}
|
||||||
|
|
||||||
*tag = NULL;
|
if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block_address (sector, 0), default_keys[i], MFC_KEY_B))) {
|
||||||
|
if (0 == mifare_classic_format_sector (tag, sector)) {
|
||||||
|
mifare_classic_disconnect (tag);
|
||||||
|
return 0;
|
||||||
|
} else if (EIO == errno) {
|
||||||
|
err (EXIT_FAILURE, "sector %d", sector);
|
||||||
|
}
|
||||||
|
mifare_classic_disconnect (tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
nfc_device_t *device = NULL;
|
||||||
|
MifareClassicTag *tags = NULL;
|
||||||
|
MifareClassicTag *tag = NULL;
|
||||||
|
|
||||||
device = nfc_connect (NULL);
|
device = nfc_connect (NULL);
|
||||||
if (!device)
|
if (!device)
|
||||||
res = -1;
|
errx (EXIT_FAILURE, "No NFC device found.");
|
||||||
|
|
||||||
if (0 == res) {
|
tags = mifare_classic_get_tags (device);
|
||||||
tags = mifare_classic_get_tags (device);
|
if (!tags) {
|
||||||
if (!tags) {
|
nfc_disconnect (device);
|
||||||
nfc_disconnect (device);
|
errx (EXIT_FAILURE, "Error listing MIFARE classic tag.");
|
||||||
device = NULL;
|
}
|
||||||
res = -2;
|
|
||||||
|
if (!tags[0]) {
|
||||||
|
mifare_classic_free_tags (tags);
|
||||||
|
nfc_disconnect (device);
|
||||||
|
errx (EXIT_FAILURE, "No MIFARE classic tag on NFC device.");
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = tags;
|
||||||
|
|
||||||
|
while (*tag) {
|
||||||
|
char *tag_uid = mifare_classic_get_uid (*tag);
|
||||||
|
|
||||||
|
/* FIXME get the tag size */
|
||||||
|
size_t sector_count = 15;
|
||||||
|
|
||||||
|
for (size_t n = 0; n < sector_count; n++) {
|
||||||
|
if (try_format_sector (*tag, n) < 0) {
|
||||||
|
warnx ("%s: Can't format sector %d (0x%02x)", tag_uid, n, n);
|
||||||
|
error = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(tag_uid);
|
||||||
|
tag++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == res) {
|
mifare_classic_free_tags (tags);
|
||||||
if (!tags[0]) {
|
nfc_disconnect (device);
|
||||||
mifare_classic_free_tags (tags);
|
|
||||||
tags = NULL;
|
|
||||||
nfc_disconnect (device);
|
|
||||||
device = NULL;
|
|
||||||
res = -4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == res) {
|
exit (error);
|
||||||
*tag = tags[0];
|
|
||||||
|
|
||||||
res = mifare_classic_connect (*tag);
|
|
||||||
if (res != 0) {
|
|
||||||
mifare_classic_disconnect (*tag);
|
|
||||||
nfc_disconnect (device);
|
|
||||||
*tag = NULL;
|
|
||||||
device = NULL;
|
|
||||||
res = -3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
mifare_classic_teardown (MifareClassicTag tag)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (tag)
|
|
||||||
res = mifare_classic_disconnect (tag);
|
|
||||||
|
|
||||||
if (0 == res) {
|
|
||||||
if (tags)
|
|
||||||
mifare_classic_free_tags (tags);
|
|
||||||
|
|
||||||
if (device)
|
|
||||||
nfc_disconnect (device);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_block(MifareClassicBlock *data)
|
|
||||||
{
|
|
||||||
for(size_t n=0;n<sizeof(MifareClassicBlock);n++) {
|
|
||||||
printf("0x%02x ", (*data)[n]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define block(s,b) ((s * 4) + b)
|
|
||||||
bool
|
|
||||||
sector_is_empty(MifareClassicTag tag, MifareSectorNumber sector)
|
|
||||||
{
|
|
||||||
MifareClassicKey default_key = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
||||||
|
|
||||||
if( 0 != mifare_classic_authenticate(tag, block(sector, 0), default_key, MFC_KEY_A) ) {
|
|
||||||
mifare_classic_connect(tag);
|
|
||||||
DBG("%s", "Unable to authenticate using default key A.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MifareClassicBlock default_block = {
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
MifareClassicBlock block;
|
|
||||||
if( 0 != mifare_classic_read(tag, block(sector, 1), &block) ) {
|
|
||||||
DBG("Unable to read block %d of sector %d (%02x).", 1, sector, block(sector, 1));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( 0 != memcmp( &block, &default_block, sizeof(MifareClassicBlock))) {
|
|
||||||
DBG("Block %d of sector %d (%02x) doesn't match with default data.", 1, sector, block(sector, 1));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( 0 != mifare_classic_read(tag, block(sector, 2), &block) ) {
|
|
||||||
DBG("Unable to read block %d of sector %d (%02x).", 2, sector, block(sector, 2));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( 0 != memcmp( &block, &default_block, sizeof(MifareClassicBlock))) {
|
|
||||||
DBG("Block %d of sector %d (%02x) doesn't match with default data.", 2, sector, block(sector, 2));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( 0 != mifare_classic_read(tag, block(sector, 3), &block) ) {
|
|
||||||
DBG("Unable to read block %d of sector %d (%02x).", 3, sector, block(sector, 3));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MifareClassicBlock default_trailer_block = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Key A could not be read */
|
|
||||||
0xff, 0x07, 0x80, /* Default access bits */
|
|
||||||
0x69, /* Default GPB */
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Default Key B */
|
|
||||||
};
|
|
||||||
if( 0 != memcmp( &block, &default_trailer_block, sizeof(MifareClassicBlock))) {
|
|
||||||
DBG("Block %d of sector %d (%02x) doesn't match with default data.", 3, sector, block(sector, 3));
|
|
||||||
printf("attemped data = "); print_block(&default_trailer_block); printf("\n");
|
|
||||||
printf("tag data = "); print_block(&block); printf("\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
MifareClassicTag tag;
|
|
||||||
if( 0 == mifare_classic_setup(&tag) ) {
|
|
||||||
for(MifareSectorNumber s = 0; s < 16; s++) {
|
|
||||||
printf("Sector %d is %s empty.\n", s, sector_is_empty(tag, s) ? "" : "_not_");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
MifareClassicKey key_b = { 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7 };
|
|
||||||
/*
|
|
||||||
if( 0 != mifare_classic_authenticate(tag, 0x04, key_b, MFC_KEY_B) ) {
|
|
||||||
errx(1, "Unable to authenticate.");
|
|
||||||
}
|
|
||||||
mifare_classic_format_sector(tag, 0x04);
|
|
||||||
if( 0 != mifare_classic_authenticate(tag, 0x08, key_b, MFC_KEY_B) ) {
|
|
||||||
errx(1, "Unable to authenticate.");
|
|
||||||
}
|
|
||||||
mifare_classic_format_sector(tag, 0x08);
|
|
||||||
*/
|
|
||||||
if( 0 != mifare_classic_authenticate(tag, 0x08 + 4, key_b, MFC_KEY_B) ) {
|
|
||||||
errx(1, "Unable to authenticate.");
|
|
||||||
}
|
|
||||||
mifare_classic_format_sector(tag, 0x08 + 4);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if( 0 != mifare_classic_authenticate(tag, 0x00, key_b, MFC_KEY_B) ) {
|
|
||||||
errx(1, "Unable to authenticate.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if( 0 != mifare_classic_write(tag, 0x01, empty) )
|
|
||||||
errx(1, "Unable to write on block @0x01");
|
|
||||||
if( 0 != mifare_classic_write(tag, 0x02, empty) )
|
|
||||||
errx(1, "Unable to write on block @0x02");
|
|
||||||
|
|
||||||
if( 0 != mifare_classic_write(tag, 0x03, trailer) )
|
|
||||||
errx(1, "Unable to write trailer block");
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mifare_classic_teardown(tag);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
} else {
|
|
||||||
errx(1, "Unable to connect to a MIFARE Classic tag.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue