From 2da53a43badc7bd578ab5df850648f14807aecd2 Mon Sep 17 00:00:00 2001 From: laforge Date: Tue, 28 Nov 2006 10:06:24 +0000 Subject: - fix mifare write support - make mifare auth more reliable - add mifare permission / access bit en/decoding - some more 15693 bits - add new 'mifare-tool' program git-svn-id: https://svn.gnumonks.org/trunk/librfid@1928 e0336214-984f-0b4b-a45f-81c69e1f0ede --- utils/Makefile.am | 10 ++- utils/common.c | 125 +++++++++++++++++++++++++++++++ utils/librfid-tool.c | 202 +++++++++++++++++++++++++------------------------ utils/librfid-tool.h | 35 +++++++++ utils/mifare-tool.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 480 insertions(+), 99 deletions(-) create mode 100644 utils/common.c create mode 100644 utils/librfid-tool.h create mode 100644 utils/mifare-tool.c (limited to 'utils') diff --git a/utils/Makefile.am b/utils/Makefile.am index f2b161e..7ad826e 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -1,11 +1,17 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include -bin_PROGRAMS = librfid-tool send_script +bin_PROGRAMS = librfid-tool mifare-tool send_script -librfid_tool_SOURCES = librfid-tool.c +librfid_tool_SOURCES = librfid-tool.c common.c librfid_tool_LDADD = ../src/librfid.la librfid_tool_LDFLAGS = -dynamic send_script_SOURCES= send_script.c send_script_LDADD = ../src/librfid.la send_script_LDFLAGS = -dynamic + +mifare_tool_SOURCES = mifare-tool.c common.c +mifare_tool_LDADD = ../src/librfid.la +mifare_tool_LDFLAGS = -dynamic + + diff --git a/utils/common.c b/utils/common.c new file mode 100644 index 0000000..2966ab4 --- /dev/null +++ b/utils/common.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "librfid-tool.h" + +const char * +hexdump(const void *data, unsigned int len) +{ + static char string[1024]; + unsigned char *d = (unsigned char *) data; + unsigned int i, left; + + string[0] = '\0'; + left = sizeof(string); + for (i = 0; len--; i += 3) { + if (i >= sizeof(string) -4) + break; + snprintf(string+i, 4, " %02x", *d++); + } + return string; +} + +static char parse_hexdigit(const char hexdigit) +{ + if (hexdigit <= '9' && hexdigit >= '0') + return hexdigit - '0'; + if (hexdigit <= 'f' && hexdigit >= 'a') + return 10 + (hexdigit - 'a'); + + return 0; +} + +int +hexread(unsigned char *result, const unsigned char *in, unsigned int len) +{ + const unsigned char *pos; + char dig1, dig2; + unsigned char *res = result; + + for (pos = in; pos-in <= len-2; pos+=2) { + if (*pos == ':') { + pos++; + continue; + } + dig1 = *pos; + dig2 = *(pos+1); + + *res++ = parse_hexdigit(dig1) << 4 | parse_hexdigit(dig2); + } + + return (res - result); +} + +struct rfid_reader_handle *rh; +struct rfid_layer2_handle *l2h; +struct rfid_protocol_handle *ph; + +int reader_init(void) +{ + printf("opening reader handle\n"); + rh = rfid_reader_open(NULL, RFID_READER_CM5121); + if (!rh) { + fprintf(stderr, "No Omnikey Cardman 5121 found\n"); + rh = rfid_reader_open(NULL, RFID_READER_OPENPCD); + if (!rh) { + fprintf(stderr, "No OpenPCD found either\n"); + return -1; + } + } + return 0; +} + +int l2_init(int layer2) +{ + unsigned char buf[0x3f]; + int rc; + + printf("opening layer2 handle\n"); + l2h = rfid_layer2_init(rh, layer2); + if (!l2h) { + fprintf(stderr, "error during iso14443a_init\n"); + return -1; + } + + printf("running layer2 anticol\n"); + rc = rfid_layer2_open(l2h); + if (rc < 0) { + fprintf(stderr, "error during layer2_open\n"); + return rc; + } + + return 0; +} + +int l3_init(int protocol) +{ + printf("running layer3 (ats)\n"); + ph = rfid_protocol_init(l2h, protocol); + if (!ph) { + fprintf(stderr, "error during protocol_init\n"); + return -1; + } + if (rfid_protocol_open(ph) < 0) { + fprintf(stderr, "error during protocol_open\n"); + return -1; + } + + printf("we now have layer3 up and running\n"); + + return 0; +} + diff --git a/utils/librfid-tool.c b/utils/librfid-tool.c index e1270f1..37efadc 100644 --- a/utils/librfid-tool.c +++ b/utils/librfid-tool.c @@ -21,6 +21,7 @@ #include #include #include +#include #define _GNU_SOURCE #include @@ -34,84 +35,8 @@ #include #include -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#include "librfid-tool.h" -static const char * -hexdump(const void *data, unsigned int len) -{ - static char string[1024]; - unsigned char *d = (unsigned char *) data; - unsigned int i, left; - - string[0] = '\0'; - left = sizeof(string); - for (i = 0; len--; i += 3) { - if (i >= sizeof(string) -4) - break; - snprintf(string+i, 4, " %02x", *d++); - } - return string; -} - -static struct rfid_reader_handle *rh; -static struct rfid_layer2_handle *l2h; -static struct rfid_protocol_handle *ph; - -static int reader() { - printf("opening reader handle\n"); - rh = rfid_reader_open(NULL, RFID_READER_CM5121); - if (!rh) { - fprintf(stderr, "No Omnikey Cardman 5121 found\n"); - rh = rfid_reader_open(NULL, RFID_READER_OPENPCD); - if (!rh) { - fprintf(stderr, "No OpenPCD found either\n"); - return -1; - } - } - return 0; -} -static int init(int layer2) -{ - unsigned char buf[0x3f]; - int rc; - - - printf("opening layer2 handle\n"); - l2h = rfid_layer2_init(rh, layer2); - if (!l2h) { - fprintf(stderr, "error during iso14443a_init\n"); - return -1; - } - - //rc632_register_dump(rh->ah, buf); - - printf("running layer2 anticol\n"); - rc = rfid_layer2_open(l2h); - if (rc < 0) { - fprintf(stderr, "error during layer2_open\n"); - return rc; - } - - return 0; -} - -static int l3(int protocol) -{ - printf("running layer3 (ats)\n"); - ph = rfid_protocol_init(l2h, protocol); - if (!ph) { - fprintf(stderr, "error during protocol_init\n"); - return -1; - } - if (rfid_protocol_open(ph) < 0) { - fprintf(stderr, "error during protocol_open\n"); - return -1; - } - - printf("we now have layer3 up and running\n"); - - return 0; -} static int select_mf(void) { @@ -277,15 +202,17 @@ mifare_classic_read_sector(struct rfid_protocol_handle *ph, int sector) int block; /* FIXME: make this work for sectors > 31 */ - printf("reading sector %u\n", sector); + printf("Reading sector %u\n", sector); for (block = sector*4; block < sector*4+4; block++) { - printf("reading block %u\n", block); + printf("Reading block %u: ", block); ret = rfid_protocol_read(ph, block, buf, &len); if(ret == -ETIMEDOUT) fprintf(stderr, "TIMEOUT\n"); - if (ret < 0) + if (ret < 0) { + printf("Error %d reading\n", ret); return ret; + } printf("Page 0x%x: %s\n", block, hexdump(buf, len)); } @@ -348,47 +275,126 @@ static void do_scan(void) } } -static void help(void) -{ - printf( " -s --scan\n" - " -p --protocol {tcl,mifare-ultralight,mifare-classic}\n" - " -l --layer2 {iso14443a,iso14443b,iso15693}\n" - " -h --help\n"); -} +#define OPTION_OFFSET 256 -static struct option opts[] = { +static struct option original_opts[] = { { "help", 0, 0, 'h' }, { "layer2", 1, 0, 'l' }, { "protocol", 1, 0, 'p' }, + { "scan", 0, 0, 's' }, + { "scan-loop", 0, 0, 'S' }, {0, 0, 0, 0} }; +/* module / option merging code */ +static struct option *opts = original_opts; +static unsigned int global_option_offset = 0; + +static char *program_name; +static char *program_version = LIBRFID_TOOL_VERSION; + +static void free_opts(int reset_offset) +{ + if (opts != original_opts) { + free(opts); + opts = original_opts; + if (reset_offset) + global_option_offset = 0; + } +} + +static struct option * +merge_options(struct option *oldopts, const struct option *newopts, + unsigned int *option_offset) +{ + unsigned int num_old, num_new, i; + struct option *merge; + + for (num_old = 0; oldopts[num_old].name; num_old++); + for (num_new = 0; oldopts[num_new].name; num_new++); + + global_option_offset += OPTION_OFFSET; + *option_offset = global_option_offset; + + merge = malloc(sizeof(struct option) * (num_new + num_old + 1)); + memcpy(merge, oldopts, num_old * sizeof(struct option)); + free_opts(0); /* Release previous options merged if any */ + for (i = 0; i < num_new; i++) { + merge[num_old + i] = newopts[i]; + merge[num_old + i].val += *option_offset; + } + memset(merge + num_old + num_new, 0, sizeof(struct option)); + + return merge; +} + +struct rfidtool_module *find_module(const char *name) +{ + return NULL; +} + +void register_module(struct rfidtool_module *me) +{ + struct rfidtool_module *old; + + if (strcmp(me->version, program_version) != 0) { + fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n", + program_name, me->name, me->version, program_version); + exit(1); + } + + old = find_module(me->name); + if (old) { + fprintf(stderr, "%s: target `%s' already registere.\n", + program_name, me->name); + exit(1); + } +} + +static void help(void) +{ + printf( " -s --scan scan until first RFID tag is found\n" + " -S --scan-loop endless scanning loop\n" + " -p --protocol {tcl,mifare-ultralight,mifare-classic}\n" + " -l --layer2 {iso14443a,iso14443b,iso15693}\n" + " -h --help\n"); +} + int main(int argc, char **argv) { int rc; char buf[0x40]; int i, protocol = -1, layer2 = -1; + + program_name = basename(argv[0]); - printf("librfid_tool - (C) 2006 by Harald Welte\n" + printf("%s - (C) 2006 by Harald Welte\n" "This program is Free Software and has " - "ABSOLUTELY NO WARRANTY\n\n"); + "ABSOLUTELY NO WARRANTY\n\n", program_name); printf("initializing librfid\n"); rfid_init(); while (1) { int c, option_index = 0; - c = getopt_long(argc, argv, "hp:l:s", opts, &option_index); + c = getopt_long(argc, argv, "hp:l:sS", opts, &option_index); if (c == -1) break; switch (c) { case 's': - if (reader() < 0) + if (reader_init() < 0) exit(1); do_scan(); exit(0); break; + case 'S': + if (reader_init() < 0) + exit(1); + while (1) + do_scan(); + exit(0); + break; case 'p': protocol = proto_by_name(optarg); if (protocol < 0) { @@ -427,13 +433,13 @@ int main(int argc, char **argv) exit(2); } - if (reader() < 0) + if (reader_init() < 0) exit(1); - if (init(layer2) < 0) + if (l2_init(layer2) < 0) exit(1); - if (l3(protocol) < 0) + if (l3_init(protocol) < 0) exit(1); switch (protocol) { @@ -506,7 +512,9 @@ int main(int argc, char **argv) printf("Protocol Mifare Classic\n"); { int sector; - for (sector = 1; sector < 31; sector++) { + for (sector = 0; sector < 31; sector++) { + printf("Authenticating sector %u: ", sector); + fflush(stdout); rc = mfcl_set_key(ph, MIFARE_CL_KEYA_DEFAULT_INFINEON); if (rc < 0) { printf("key format error\n"); @@ -517,7 +525,7 @@ int main(int argc, char **argv) printf("mifare auth error\n"); exit(1); } else - printf("mifare authe succeeded!\n"); + printf("mifare auth succeeded!\n"); mifare_classic_read_sector(ph, sector); } diff --git a/utils/librfid-tool.h b/utils/librfid-tool.h new file mode 100644 index 0000000..5ca49d4 --- /dev/null +++ b/utils/librfid-tool.h @@ -0,0 +1,35 @@ +#ifndef _RFIDTOOL_H +#define _RFIDTOOL_H + +#define _GNU_SOURCE +#include + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + + +extern const char * +hexdump(const void *data, unsigned int len); + +extern int +hexread(unsigned char *result, const unsigned char *in, unsigned int len); + +extern struct rfid_reader_handle *rh; +extern struct rfid_layer2_handle *l2h; +extern struct rfid_protocol_handle *ph; + +extern int reader_init(void); +extern int l2_init(int layer2); +extern int l3_init(int protocol); + +#define LIBRFID_TOOL_VERSION "0.1" + +struct rfidtool_module { + struct rfidtool_module *next; + char *name; + char *version; + const struct option *extra_opts; + + unsigned int option_offset; +}; + +#endif /* _REFIDTOOL_H */ diff --git a/utils/mifare-tool.c b/utils/mifare-tool.c new file mode 100644 index 0000000..f9a6a49 --- /dev/null +++ b/utils/mifare-tool.c @@ -0,0 +1,207 @@ +/* mifare-tool - a small command-line tool for librfid mifare testing + * + * (C) 2006 by Harald Welte + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#define _GNU_SOURCE +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "librfid-tool.h" + +static char *program_name; + +static void help(void) +{ +} + +static struct option mifare_opts[] = { + { "key", 1, 0, 'k' }, + { "read", 1, 0, 'r' }, + { "loop-read", 1, 0, 'l' }, + { "write", 1 ,0, 'w' }, + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } +}; + +static int mifare_cl_auth(unsigned char *key, int page) +{ + int rc; + + rc = mfcl_set_key(ph, key); + if (rc < 0) { + fprintf(stderr, "key format error\n"); + return rc; + } + rc = mfcl_auth(ph, RFID_CMD_MIFARE_AUTH1A, page); + if (rc < 0) { + fprintf(stderr, "mifare auth error\n"); + return rc; + } else + printf("mifare auth succeeded!\n"); + + return 0; +} + +static void mifare_l3(void) +{ + while (l2_init(RFID_LAYER2_ISO14443A) < 0) ; + + printf("ISO14443-3A anticollision succeeded\n"); + + while (l3_init(RFID_PROTOCOL_MIFARE_CLASSIC) < 0) ; + + printf("Mifare card available\n"); +} + +int main(int argc, char **argv) +{ + int len, rc, c, option_index = 0; + unsigned int page; + char key[MIFARE_CL_KEY_LEN]; + char buf[MIFARE_CL_PAGE_SIZE]; + program_name = basename(argv[0]); + + memcpy(key, MIFARE_CL_KEYA_DEFAULT_INFINEON, + sizeof(MIFARE_CL_KEYA_DEFAULT_INFINEON)); + + printf("%s - (C) 2006 by Harald Welte\n" + "This program is Free Software and has " + "ABSOLUTELY NO WARRANTY\n\n", program_name); + + printf("initializing librfid\n"); + rfid_init(); + + if (reader_init() < 0) { + fprintf(stderr, "error opening reader\n"); + exit(1); + } + + while (1) { + c = getopt_long(argc, argv, "k:r:l:w:", mifare_opts, + &option_index); + if (c == -1) + break; + + switch (c) { + case 'k': + hexread(key, optarg, strlen(optarg)); + printf("key: %s\n", hexdump(key, MIFARE_CL_KEY_LEN)); + break; + case 'r': + page = atoi(optarg); + printf("read(key='%s',page=%u):", + hexdump(key, MIFARE_CL_KEY_LEN), page); + len = MIFARE_CL_PAGE_SIZE; + mifare_l3(); + if (mifare_cl_auth(key, page) < 0) + exit(1); + rc = rfid_protocol_read(ph, page, buf, &len); + if (rc < 0) { + printf("\n"); + fprintf(stderr, "error during read\n"); + break; + } + printf("%s\n", hexdump(buf, len)); + + if (page & 0x3 == 0x3) { + struct mfcl_access_sect s; + struct mfcl_access_exp_sect es; + int b; + u_int8_t recreated[4]; + mfcl_parse_access(&s, buf+6); + printf("access b0:%u b1:%u b2:%u b3:%u\n", + s.block[0], s.block[1], + s.block[2], s.block[3]); + mfcl_access_to_exp(&es, &s); + for (b = 0; b < 3; b++) + printf("%u: %s\n", b, mfcl_access_exp_stringify(&es.block[b])); + printf("3: %s\n", mfcl_access_exp_acc_stringify(&es.acc)); +#if 0 + mfcl_compile_access(recreated, &s); + printf("recreated; %s\n", hexdump(recreated,4)); +#endif + } + break; + case 'l': + page = atoi(optarg); + printf("read_loop(key='%s',page=%u):\n", + hexdump(key, MIFARE_CL_KEY_LEN), page); + while (1) { + mifare_l3(); + if (mifare_cl_auth(key, page) < 0) + continue; + rc = rfid_protocol_read(ph, page, buf, &len); + if (rc < 0) { + printf("\n"); + fprintf(stderr, "error during read\n"); + continue; + } + printf("%s\n", hexdump(buf, len)); + } + break; + case 'w': + page = atoi(optarg); + len = strlen(argv[optind]); + len = hexread(buf, argv[optind], len); + printf("write(key='%s',page=%u):", + hexdump(key, MIFARE_CL_KEY_LEN), page); + printf(" '%s'(%u):", hexdump(buf, len), len); + mifare_l3(); + if (mifare_cl_auth(key, page) < 0) + exit(1); + rc = rfid_protocol_write(ph, page, buf, len); + if (rc < 0) { + printf("\n"); + fprintf(stderr, "error during write\n"); + break; + } + printf("success\n"); + break; + case 'h': + default: + help(); + } + } + +#if 0 + rfid_protocol_close(ph); + rfid_protocol_fini(ph); + + rfid_layer2_close(l2h); + rfid_layer2_fini(l2h); +#endif + rfid_reader_close(rh); + exit(0); +} + -- cgit v1.2.3