- fix mifare write support
authorHarald Welte <laforge@gnumonks.org>
Tue, 28 Nov 2006 10:06:24 +0000 (10:06 +0000)
committerHarald Welte <laforge@gnumonks.org>
Tue, 28 Nov 2006 10:06:24 +0000 (10:06 +0000)
- 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

19 files changed:
include/librfid/Makefile.am
include/librfid/rfid_access_mifare_classic.h [new file with mode: 0644]
include/librfid/rfid_asic.h
include/librfid/rfid_asic_rc632.h
include/librfid/rfid_layer2_iso15693.h
include/librfid/rfid_protocol.h
include/librfid/rfid_protocol_mifare_classic.h
src/Makefile.am
src/rc632.h
src/rfid_access_mifare_classic.c [new file with mode: 0644]
src/rfid_asic_rc632.c
src/rfid_layer2_iso15693.c
src/rfid_proto_mifare_classic.c
src/rfid_proto_mifare_ul.c
utils/Makefile.am
utils/common.c [new file with mode: 0644]
utils/librfid-tool.c
utils/librfid-tool.h [new file with mode: 0644]
utils/mifare-tool.c [new file with mode: 0644]

index 1edb60b..9af455b 100644 (file)
@@ -7,6 +7,7 @@ pkginclude_HEADERS = rfid.h rfid_scan.h rfid_asic.h rfid_asic_rc632.h \
                        rfid_protocol_mifare_classic.h \
                        rfid_reader.h \
                        rfid_system.h \
+                       rfid_access_mifare_classic.h \
                        rfid_reader_cm5121.h \
                        rfid_reader_openpcd.h
 
diff --git a/include/librfid/rfid_access_mifare_classic.h b/include/librfid/rfid_access_mifare_classic.h
new file mode 100644 (file)
index 0000000..3c23724
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _RFID_MIFARE_ACCESS_H
+#define _RFID_MIFARE_ACCESS_H
+
+struct mfcl_access_sect {
+       u_int8_t block[4];
+};
+
+int mfcl_compile_access(u_int8_t *encoded,
+                       const struct mfcl_access_sect *ac);
+int mfcl_parse_access(struct mfcl_access_sect *ac, u_int8_t *encoded);
+
+
+enum mfcl_access_exp_data {
+       MFCL_ACCESS_NEVER       = 0,
+       MFCL_ACCESS_KEY_A       = 1,
+       MFCL_ACCESS_KEY_B       = 2,
+};
+
+struct mfcl_access_exp_block {
+       u_int8_t read:2,
+                write:2,
+                inc:2,
+                dec:2;
+};
+
+struct mfcl_access_exp_acc {
+       u_int16_t key_a_rd:2,
+                 key_a_wr:2,
+                 acc_rd:2,
+                 acc_wr:2,
+                 key_b_rd:2,
+                 key_b_wr:2;
+};
+
+
+struct mfcl_access_exp_sect {
+       struct mfcl_access_exp_block block[3];
+       struct mfcl_access_exp_acc acc;
+};
+
+void mfcl_access_to_exp(struct mfcl_access_exp_sect *exp,
+                       const struct mfcl_access_sect *sect);
+
+char *mfcl_access_exp_stringify(const struct mfcl_access_exp_block *exp);
+char *mfcl_access_exp_acc_stringify(const struct mfcl_access_exp_acc *acc);
+#endif
index 3686a7c..113eb19 100644 (file)
@@ -5,6 +5,7 @@ enum rfid_frametype;
 
 #include <librfid/rfid_asic_rc632.h>
 
+/* a low-level transport, over which the ASIC layer can talk to its ASIC */
 struct rfid_asic_transport {
        char *name;
        union {
@@ -12,12 +13,21 @@ struct rfid_asic_transport {
        } priv;
 };
 
+/* An instance handle to 'struct rfid_asic_transport' */
 struct rfid_asic_transport_handle {
        void *data;             /* handle to stuff like even lower layers */
 
        struct rfid_asic_transport *rat;
 };
 
+/* Some implementation-specific data.  A reader will specify one of these for
+ * ASIC-specific parameters such as e.g. RC632 mod conductance */
+
+struct rfid_asic_implementation {
+       union {
+               struct rfid_asic_rc632_impl rc632;
+       } priv;
+};
 
 struct rfid_asic_handle {
        struct rfid_asic_transport_handle *rath;
index 642c940..4eac82e 100644 (file)
@@ -78,82 +78,18 @@ struct rfid_asic_rc632_handle {
        struct rc632_transport_handle th;
 };
 
-#if 0
-int 
-rc632_reg_write(struct rfid_asic_handle *handle,
-               u_int8_t reg,
-               u_int8_t val);
-
-int 
-rc632_reg_read(struct rfid_asic_handle *handle,
-              u_int8_t reg,
-              u_int8_t *val);
-int 
-rc632_fifo_write(struct rfid_asic_handle *handle,
-                u_int8_t len,
-                const u_int32_t *buf,
-                u_int8_t flags);
-
-int 
-rc632_fifo_read(struct rfid_asic_handle *handle,
-               u_int8_t len,
-               u_int8_t *buf);
-
-int
-rc632_set_bits(struct rfid_asic_handle *handle, u_int8_t reg,
-               u_int82_t val);
-
-int 
-rc632_clear_bits(struct rfid_asic_handle *handle, u_int32_t reg,
-                u_int32_t val);
-
-
-int 
-rc632_turn_on_rf(struct rfid_asic_handle *handle);
-
-
-int 
-rc632_turn_off_rf(struct rfid_asic_handle *handle);
-
-int
-rc632_power_up(struct rfid_asic_handle *handle);
-
-int
-rc632_power_down(struct rfid_asic_handle *handle);
-
-
-int
-rc632_wait_idle(struct rfid_asic_handle *handle, u_int64_t time);
-
-int
-rc632_transmit(struct rfid_asic_handle *handle,
-               const u_int32_t *buf,
-               u_int32_t len,
-               u_int64_t timeout);
-
-int
-rc632_transceive(struct rfid_asic_handle *handle,
-                const u_int32_t *tx_buf,
-                u_int32_t tx_len,
-                u_int32_t *rx_buf,
-                u_int32_t *rx_len,
-                unsigned int timer,
-                unsigned int toggle);
-
-int
-rc632_read_eeprom(struct rfid_asic_handle *handle);
-
-
-int
-rc632_calc_crc16_from(struct rfid_asic_handle *handle);
-
-int
-rc632_register_dump(struct rfid_asic_handle *handle, u_int32_t *buf);
-
-
+struct rfid_asic_rc632_impl_proto {
+       u_int8_t mod_conductance;
+       u_int8_t cw_conductance;
+       u_int8_t bitphase;
+       u_int8_t threshold;
+};
 
-extern struct rfid_asic rc632;
-#endif
+struct rfid_asic_rc632_impl {
+       u_int32_t mru;          /* maximum receive unit (PICC->PCD) */
+       u_int32_t mtu;          /* maximum transmit unit (PCD->PICC) */
+       //struct rfid_asic_rc632_impl_proto proto[NUM_RFID_PROTOCOLS];
+};
 
 extern struct rfid_asic_handle * rc632_open(struct rfid_asic_transport_handle *th);
 extern void rc632_close(struct rfid_asic_handle *h);
index f84a6e1..d09daa7 100644 (file)
 
 /* protocol definitions */
 
-struct iso15693_handle;
+#if 0
+struct rfid_15693_handle;
 
-struct iso15693_transport {
+struct rfid_layer2_15693t {
        unsigned char   *name;
 
        struct {
@@ -39,16 +40,46 @@ struct iso15693_transport {
        union {
        } priv;
 };
+#endif
 
 struct iso15693_handle {
        unsigned int state;
+       unsigned int ask100:1,
+                    out256:1;
 };
 
-enum iso15693_state {
+enum rfid_15693_state {
        ISO15693_STATE_ERROR,
        ISO15693_STATE_NONE,
 };
 
+enum rfid_15693_opt {
+       RFID_OPT_15693_MOD_DEPTH        = 0x00010001,
+       RFID_OPT_15693_VCD_CODING       = 0x00010002,
+       RFID_OPT_15693_VICC_SUBC        = 0x00010003,
+       RFID_OPT_15693_VICC_SPEED       = 0x00010004,
+};
+
+enum rfid_15693_opt_mod_depth {
+       RFID_15693_MOD_10ASK    = 0x01,
+       RFID_15693_MOD_100ASK   = 0x02,
+};
+
+enum rfid_15693_opt_vcd_coding {
+       RFID_15693_VCD_CODING_1OUT256   = 0x01,
+       RFID_15693_VCD_CODING_1OUT4     = 0x02,
+};
+
+enum rfid_15693_opt_vicc_subc {
+       RFID_15693_VICC_SUBC_SINGLE     = 0x01,
+       RFID_15693_VICC_SUBC_DUAL       = 0x02,
+};
+
+enum rfid_15693_opt_vicc_speed {
+       RFID_15693_VICC_SPEED_SLOW      = 0x01,
+       RFID_15693_VICC_SPEED_FAST      = 0x02,
+};
+
 #ifdef __LIBRFID__
 
 #define ISO15693_UID_LEN       8
@@ -83,8 +114,6 @@ struct iso15693_request {
        u_int8_t data[0];
 } __attribute__ ((packed));
 
-
-
 /* ISO 15693, Ch. 7.3 Table 6 */
 enum iso15693_response_flags {
        RFID_15693_RF_ERROR     = 0x01,
@@ -129,8 +158,14 @@ enum iso15693_commands {
        ISO15693_CMD_WRITE_DSFID        = 0x29,
        ISO15693_CMD_LOCK_DSFID         = 0x2a,
        ISO15693_CMD_GET_SYSINFO        = 0x2b,
-       ISO15693_CMD_GET_BLOCK_SECURITY = 0x2c
+       ISO15693_CMD_GET_BLOCK_SECURITY = 0x2c,
        /* Custom 0xa0 .. 0xdf */
+       ICODE_CMD_INVENTORY_READ        = 0xa0,
+       ICODE_CMD_FAST_INVENTORY_READ   = 0xa1,
+       ICODE_CMD_EAS_SET               = 0xa2,
+       ICODE_CMD_EAS_RESET             = 0xa3,
+       ICODE_CMD_EAS_LOCK              = 0xa4,
+       ICODE_CMD_EAS_ALARM             = 0xa5,
        /* Proprietary 0xe0 .. 0xff */
 };
 
index 2c1d0e8..fd649ef 100644 (file)
@@ -40,6 +40,7 @@ enum rfid_protocol_id {
        RFID_PROTOCOL_TCL,
        RFID_PROTOCOL_MIFARE_UL,
        RFID_PROTOCOL_MIFARE_CLASSIC,
+       NUM_RFID_PROTOCOLS
 };
 
 enum rfid_protocol_opt {
index f1e1403..99c447d 100644 (file)
@@ -9,7 +9,10 @@
 #define MIFARE_CL_KEYA_DEFAULT_INFINEON        "\xff\xff\xff\xff\xff\xff"
 #define MIFARE_CL_KEYB_DEFAULT_INFINEON MIFARE_CL_KEYA_DEFAULT_INFINEON
 
+#define MIFARE_CL_KEY_LEN      (sizeof(MIFARE_CL_KEYA_DEFAULT)-1)
+
 #define MIFARE_CL_PAGE_MAX     0xff
+#define MIFARE_CL_PAGE_SIZE    20
 
 #define RFID_CMD_MIFARE_AUTH1A 0x60
 #define RFID_CMD_MIFARE_AUTH1B 0x61
@@ -20,6 +23,7 @@ extern const struct rfid_protocol rfid_protocol_mfcl;
 
 
 #define MIFARE_CL_CMD_WRITE16  0xA0
+#define MIFARE_CL_CMD_WRITE4   0xA2
 #define MIFARE_CL_CMD_READ     0x30
 
 #define MIFARE_CL_RESP_ACK     0x0a
index 86663a4..3e2bf95 100644 (file)
@@ -15,6 +15,7 @@ L2=rfid_layer2_iso14443a.c rfid_layer2_iso14443b.c rfid_layer2_iso15693.c rfid_i
 PROTO=rfid_proto_tcl.c rfid_proto_mifare_ul.c rfid_proto_mifare_classic.c
 ASIC=rfid_asic_rc632.c
 READER=rfid_reader_openpcd.c
+MISC=rfid_access_mifare_classic.c
 
 if ENABLE_CM5121
 READER_CM5121=rfid_reader_cm5121.c
@@ -37,7 +38,7 @@ AM_CFLAGS = -std=gnu99 -D__LIBRFID__ $(AM_CFLAGS_FIRMWARE) $(AM_CFLAGS_STATIC) \
 
 lib_LTLIBRARIES = librfid.la
 librfid_la_LDFLAGS = -Wc,-nostartfiles -version-info $(LIBVERSION) -lopenct
-librfid_la_SOURCES = $(CORE) $(L2) $(PROTO) $(ASIC) \
+librfid_la_SOURCES = $(CORE) $(L2) $(PROTO) $(ASIC) $(MISC) \
                     $(READER) \
                     $(READER_CM5121) $(READER_LOW_CCID) $(READER_LOW_OPENCT)
 
index ff00df0..c7690ed 100644 (file)
@@ -94,8 +94,12 @@ enum rc632_reg_interrupt {
 };
 
 enum rc632_reg_control {
+       RC632_CONTROL_FIFO_FLUSH        = 0x01,
+       RC632_CONTROL_TIMER_START       = 0x02,
+       RC632_CONTROL_TIMER_STOP        = 0x04,
        RC632_CONTROL_CRYPTO1_ON        = 0x08,
        RC632_CONTROL_POWERDOWN         = 0x10,
+       RC632_CONTROL_STANDBY           = 0x20,
 };
 
 enum rc632_reg_error_flag {
@@ -235,3 +239,9 @@ enum rc632_reg_timer_irq {
 
        RC632_IRQ_SET                   = 0x80,
 };
+
+enum rc632_reg_secondary_status {
+       RC632_SEC_ST_TMR_RUNNING        = 0x80,
+       RC632_SEC_ST_E2_READY           = 0x40,
+       RC632_SEC_ST_CRC_READY          = 0x20,
+};
diff --git a/src/rfid_access_mifare_classic.c b/src/rfid_access_mifare_classic.c
new file mode 100644 (file)
index 0000000..bd362e1
--- /dev/null
@@ -0,0 +1,232 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <librfid/rfid.h>
+#include <librfid/rfid_access_mifare_classic.h>
+
+/* parse encoded data structure into c1/c2/c3 */
+int mfcl_compile_access(u_int8_t *encoded,
+                       const struct mfcl_access_sect *ac)
+{
+       int b;
+       u_int8_t c1, c2, c3;
+
+       c1 = c2 = c3 = 0;
+
+       for (b = 0; b < 4; b++) {
+               if (ac->block[b] & 0x01)
+                       c1 |= (1 << b);
+               if (ac->block[b] & 0x02)
+                       c2 |= (1 << b);
+               if (ac->block[b] & 0x04)
+                       c3 |= (1 << b);
+       }
+
+       DEBUGP("compile: c1=%u c2=%u c3=%u\n", c1, c2, c3);
+
+       encoded[3] = 0x00;
+       encoded[2] = c2 | (c3 << 4);
+       encoded[1] = (~c3 & 0xf) | (c1 << 4);
+       encoded[0] = (~c1 & 0xf) | ((~c2 & 0xf) << 4);
+
+       return 0;
+}
+
+/* parse mifare classic access conditions from card */
+int mfcl_parse_access(struct mfcl_access_sect *ac, u_int8_t *encoded)
+{
+       int b;
+
+       u_int8_t c1, c2, c3;
+
+       DEBUGP("encoded: %s\n", rfid_hexdump(encoded, 4));
+
+       c1 = encoded[1] >> 4;
+       c2 = encoded[2] & 0xf;
+       c3 = encoded[2] >> 4;
+
+       DEBUGP("c1=0x%x, c2=0x%x, c3=0x%x\n", c1, c2, c3);
+       
+       memset(ac, 0, sizeof(*ac));
+       for (b = 0; b < 4; b++) {
+               if (c1 & (1 << b))
+                       ac->block[b] = 0x1;
+               if (c2 & (1 << b))
+                       ac->block[b] |= 0x2;
+               if (c3 & (1 << b))
+                       ac->block[b] |= 0x4;
+       };
+
+       /* FIXME: verify the inverted access bits */
+
+       return 0;
+}
+
+
+/* functions below here are for our own internal decoded (orthogonal)
+ * format of access bits */
+
+/* In the order of the table 3.7.3 in MFCL Product Specification Rev. 5.1 */
+static const struct mfcl_access_exp_block mfcl_exp_data[] = {
+       [0] = {
+               .read   = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .write  = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .inc    = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .dec    = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+       },
+       [2] = {
+               .read   = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .write  = MFCL_ACCESS_NEVER,
+               .inc    = MFCL_ACCESS_NEVER,
+               .dec    = MFCL_ACCESS_NEVER,
+       },
+       [1] = {
+               .read   = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .write  = MFCL_ACCESS_KEY_B,
+               .inc    = MFCL_ACCESS_NEVER,
+               .dec    = MFCL_ACCESS_NEVER,
+       },
+       [3] = {
+               .read   = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .write  = MFCL_ACCESS_KEY_B,
+               .inc    = MFCL_ACCESS_KEY_B,
+               .dec    = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+       },
+       [4] = {
+               .read   = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .write  = MFCL_ACCESS_NEVER,
+               .inc    = MFCL_ACCESS_NEVER,
+               .dec    = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+       },
+       [6] = {
+               .read   = MFCL_ACCESS_KEY_B,
+               .write  = MFCL_ACCESS_KEY_B,
+               .inc    = MFCL_ACCESS_NEVER,
+               .dec    = MFCL_ACCESS_NEVER,
+       },
+       [5] = {
+               .read   = MFCL_ACCESS_KEY_B,
+               .write  = MFCL_ACCESS_NEVER,
+               .inc    = MFCL_ACCESS_NEVER,
+               .dec    = MFCL_ACCESS_NEVER,
+       },
+       [7] = {
+               .read   = MFCL_ACCESS_NEVER,
+               .write  = MFCL_ACCESS_NEVER,
+               .inc    = MFCL_ACCESS_NEVER,
+               .dec    = MFCL_ACCESS_NEVER,
+       },
+};
+
+static const struct mfcl_access_exp_acc mfcl_exp_trailer[] = {
+       [0] = {
+               .key_a_rd       = MFCL_ACCESS_NEVER,
+               .key_a_wr       = MFCL_ACCESS_KEY_A,
+               .acc_rd         = MFCL_ACCESS_KEY_A,
+               .acc_wr         = MFCL_ACCESS_NEVER,
+               .key_b_rd       = MFCL_ACCESS_KEY_A,
+               .key_b_wr       = MFCL_ACCESS_KEY_A,
+       },
+       [2] = {
+               .key_a_rd       = MFCL_ACCESS_NEVER,
+               .key_a_wr       = MFCL_ACCESS_NEVER,
+               .acc_rd         = MFCL_ACCESS_KEY_A,
+               .acc_wr         = MFCL_ACCESS_NEVER,
+               .key_b_rd       = MFCL_ACCESS_KEY_A,
+               .key_b_wr       = MFCL_ACCESS_NEVER,
+       },
+       [1] = {
+               .key_a_rd       = MFCL_ACCESS_NEVER,
+               .key_a_wr       = MFCL_ACCESS_KEY_B,
+               .acc_rd         = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .acc_wr         = MFCL_ACCESS_NEVER,
+               .key_b_rd       = MFCL_ACCESS_NEVER,
+               .key_b_wr       = MFCL_ACCESS_KEY_B,
+       },
+       [3] = {
+               .key_a_rd       = MFCL_ACCESS_NEVER,
+               .key_a_wr       = MFCL_ACCESS_NEVER,
+               .acc_rd         = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .acc_wr         = MFCL_ACCESS_NEVER,
+               .key_b_rd       = MFCL_ACCESS_NEVER,
+               .key_b_wr       = MFCL_ACCESS_NEVER,
+       },
+       [4] = {
+               .key_a_rd       = MFCL_ACCESS_NEVER,
+               .key_a_wr       = MFCL_ACCESS_KEY_A,
+               .acc_rd         = MFCL_ACCESS_KEY_A,
+               .acc_wr         = MFCL_ACCESS_KEY_A,
+               .key_b_rd       = MFCL_ACCESS_KEY_A,
+               .key_b_wr       = MFCL_ACCESS_KEY_A,
+       },
+       [6] = {
+               .key_a_rd       = MFCL_ACCESS_NEVER,
+               .key_a_wr       = MFCL_ACCESS_KEY_B,
+               .acc_rd         = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .acc_wr         = MFCL_ACCESS_KEY_B,
+               .key_b_rd       = MFCL_ACCESS_NEVER,
+               .key_b_wr       = MFCL_ACCESS_KEY_B,
+       },
+       [5] = {
+               .key_a_rd       = MFCL_ACCESS_NEVER,
+               .key_a_wr       = MFCL_ACCESS_NEVER,
+               .acc_rd         = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .acc_wr         = MFCL_ACCESS_KEY_B,
+               .key_b_rd       = MFCL_ACCESS_NEVER,
+               .key_b_wr       = MFCL_ACCESS_NEVER,
+       },
+       [7] = {
+               .key_a_rd       = MFCL_ACCESS_NEVER,
+               .key_a_wr       = MFCL_ACCESS_NEVER,
+               .acc_rd         = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+               .acc_wr         = MFCL_ACCESS_NEVER,
+               .key_b_rd       = MFCL_ACCESS_NEVER,
+               .key_b_wr       = MFCL_ACCESS_NEVER,
+       },
+};
+
+const char *mfcl_access_str[] = {
+       [MFCL_ACCESS_NEVER] = "NEVER",
+       [MFCL_ACCESS_KEY_A] = "A",
+       [MFCL_ACCESS_KEY_B] = "B",
+       [MFCL_ACCESS_KEY_A|MFCL_ACCESS_KEY_B] = "A|B",
+};
+
+void mfcl_access_to_exp(struct mfcl_access_exp_sect *exp,
+                       const struct mfcl_access_sect *sect)
+{
+       int b;
+       for (b = 0; b < 3; b++)
+               exp->block[b] = mfcl_exp_data[sect->block[b]];
+       exp->acc = mfcl_exp_trailer[sect->block[3]];
+}
+
+char *mfcl_access_exp_stringify(const struct mfcl_access_exp_block *exp)
+{
+       static char buf[80];
+
+       sprintf(buf, "READ: %s, WRITE: %s, INC: %s, DEC: %s",
+               mfcl_access_str[exp->read],
+               mfcl_access_str[exp->write],
+               mfcl_access_str[exp->inc],
+               mfcl_access_str[exp->dec]);
+       return buf;
+}
+
+char *mfcl_access_exp_acc_stringify(const struct mfcl_access_exp_acc *acc)
+{
+       static char buf[80];
+
+       sprintf(buf, "KEY_A_RD: %s, KEY_A_WR: %s, ACC_RD: %s, ACC_WR: %s, "
+               "KEY_B_RD: %s, KEY_B_WR: %s",
+               mfcl_access_str[acc->key_a_rd],
+               mfcl_access_str[acc->key_a_wr],
+               mfcl_access_str[acc->acc_rd],
+               mfcl_access_str[acc->acc_wr],
+               mfcl_access_str[acc->key_b_rd],
+               mfcl_access_str[acc->key_b_wr]);
+       return buf;
+}
+
index b421ca6..2890d6d 100644 (file)
@@ -38,7 +38,7 @@
 //#include "rc632_14443a.h"
 
 
-#define RC632_TMO_AUTH1        14000
+#define RC632_TMO_AUTH1        140
 
 #define ENTER()                DEBUGP("entering\n")
 const struct rfid_asic rc632;
@@ -566,6 +566,13 @@ rc632_init(struct rfid_asic_handle *ah)
        if (ret < 0)
                return ret;
 
+       /* switch off rf */
+       ret = rc632_turn_off_rf(ah);
+       if (ret < 0)
+               return ret;
+
+       usleep(100000);
+
        /* switch on rf */
        ret = rc632_turn_on_rf(ah);
        if (ret < 0)
@@ -639,7 +646,8 @@ rc632_iso14443a_init(struct rfid_asic_handle *handle)
        // FIXME: some fifo work (drain fifo?)
        
        /* flush fifo (our way) */
-       ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01);
+       ret = rc632_reg_write(handle, RC632_REG_CONTROL,
+                             RC632_CONTROL_FIFO_FLUSH);
 
        ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL,
                        (RC632_TXCTRL_TX1_RF_EN |
@@ -1065,7 +1073,8 @@ static int rc632_iso14443b_init(struct rfid_asic_handle *handle)
        // FIXME: some FIFO work
        
        /* flush fifo (our way) */
-       ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01);
+       ret = rc632_reg_write(handle, RC632_REG_CONTROL,
+                             RC632_CONTROL_FIFO_FLUSH);
        if (ret < 0)
                return ret;
 
@@ -1453,7 +1462,8 @@ rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key)
        if (ret < 0)
                return ret;
 
-       ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03);
+       /* Terminate probably running command */
+       ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_IDLE);    
        if (ret < 0)
                return ret;
 
@@ -1461,6 +1471,10 @@ rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key)
        if (ret < 0)
                return ret;
 
+       ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03);
+       if (ret < 0)
+               return ret;
+
        ret = rc632_wait_idle(h, RC632_TMO_AUTH1);
        if (ret < 0)
                return ret;
@@ -1483,8 +1497,10 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
        struct mifare_authcmd acmd;
        u_int8_t reg;
 
-       if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B)
+       if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B) {
+               DEBUGP("invalid auth command\n");
                return -EINVAL;
+       }
 
        /* Initialize acmd */
        acmd.block_address = block & 0xff;
@@ -1492,9 +1508,16 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
        //acmd.serno = htonl(serno);
        acmd.serno = serno;
 
+#if 1
        /* Clear Rx CRC */
        ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY,
                                RC632_CR_RX_CRC_ENABLE);
+#else
+       /* Clear Rx CRC, Set Tx CRC and Odd Parity */
+       ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY,
+                               RC632_CR_TX_CRC_ENABLE | RC632_CR_PARITY_ODD |
+                               RC632_CR_PARITY_ENABLE);
+#endif
        if (ret < 0)
                return ret;
 
@@ -1504,8 +1527,10 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
                return ret;
 
        ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT1);
-       if (ret < 0)
+       if (ret < 0) {
+               DEBUGP("error during AUTHENT1");
                return ret;
+       }
 
        /* Wait until transmitter is idle */
        ret = rc632_wait_idle(h, RC632_TMO_AUTH1);
@@ -1515,8 +1540,10 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
        ret = rc632_reg_read(h, RC632_REG_SECONDARY_STATUS, &reg);
        if (ret < 0)
                return ret;
-       if (reg & 0x07)
+       if (reg & 0x07) {
+               DEBUGP("bitframe?");
                return -EIO;
+       }
 
        /* Clear Tx CRC */
        ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY,
@@ -1539,11 +1566,12 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
        if (ret < 0)
                return ret;
 
-       if (!(reg & RC632_CONTROL_CRYPTO1_ON))
+       if (!(reg & RC632_CONTROL_CRYPTO1_ON)) {
+               DEBUGP("authentication not successful");
                return -EACCES;
+       }
 
        return 0;
-
 }
 
 /* transceive regular frame */
index dab7418..f5da8c2 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
 
 #include <librfid/rfid.h>
 #include <librfid/rfid_layer2.h>
@@ -92,6 +93,42 @@ iso15693_anticol(struct rfid_layer2_handle *handle)
        return -1;
 }
 
+static int
+iso15693_getopt(struct rfid_layer2_handle *handle,
+               int optname, void *optval, unsigned int optlen)
+{
+       switch (optname) {
+       case RFID_OPT_15693_MOD_DEPTH:
+       case RFID_OPT_15693_VCD_CODING:
+       case RFID_OPT_15693_VICC_SUBC:
+       case RFID_OPT_15693_VICC_SPEED:
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+static int
+iso15693_setopt(struct rfid_layer2_handle *handle, int optname,
+               const void *optval, unsigned int optlen)
+{
+       switch (optname) {
+       case RFID_OPT_15693_MOD_DEPTH:
+       case RFID_OPT_15693_VCD_CODING:
+       case RFID_OPT_15693_VICC_SUBC:
+       case RFID_OPT_15693_VICC_SPEED:
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+static int transceive_inventory(struct rfid_layer2_handle *l2h)
+{
+}
+
 static struct rfid_layer2_handle *
 iso15693_init(struct rfid_reader_handle *rh)
 {
@@ -129,6 +166,8 @@ const struct rfid_layer2 rfid_layer2_iso15693 = {
                //.transceive   = &iso15693_transceive,
                //.close                = &iso14443a_hlta,
                .fini           = &iso15693_fini,
+               .setopt         = &iso15693_setopt,
+               .getopt         = &iso15693_getopt,
        },
 };
 
index d45eefc..4032b80 100644 (file)
@@ -85,23 +85,57 @@ mfcl_write(struct rfid_protocol_handle *ph, unsigned int page,
        unsigned int rx_len;
        int ret;
 
-       if (tx_len != 16 || page > MIFARE_CL_PAGE_MAX)
+       if (page > MIFARE_CL_PAGE_MAX)
                return -EINVAL;
 
-       tx[0] = MIFARE_CL_CMD_WRITE16;
-       tx[1] = page & 0xff;
+       if (tx_len != 16 && tx_len != 4)
+               return -EINVAL;
+       
+       if (tx_len == 16) {
+               tx[0] = MIFARE_CL_CMD_WRITE16;
+               tx[1] = page & 0xff;
 
-       memcpy(tx+2, tx_data, 16);
+               ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx,
+                                            2, rx, &rx_len, 
+                                            MIFARE_CL_WRITE_FWT, 0);
+               if (ret < 0)
+                       return ret;
 
-       ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx,
-                                    sizeof(tx), rx, &rx_len, 
-                                    MIFARE_CL_WRITE_FWT, 0);
-                                       
-       if (ret < 0)
-               return ret;
+               ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx_data,
+                                            tx_len, rx, &rx_len,
+                                            MIFARE_CL_WRITE_FWT, 0);
+               if (ret < 0)
+                       return ret;
+
+               if (rx[0] != MIFARE_UL_RESP_ACK)
+                       return -EIO;
+
+               ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx,
+                                            sizeof(tx), rx, &rx_len, 
+                                            MIFARE_CL_WRITE_FWT, 0);
+               if (ret < 0)
+                       return ret;
+
+               if (rx[0] != MIFARE_UL_RESP_ACK)
+                       return -EIO;
 
-       if (rx[0] != MIFARE_UL_RESP_ACK)
-               return -EIO;
+       } else if (tx_len == 4) {
+
+               tx[0] = MIFARE_CL_CMD_WRITE4;
+               tx[1] = page & 0xff;
+
+               memcpy(tx+2, tx_data, 4);
+
+               ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx,
+                                            2+4, rx, &rx_len, 
+                                            MIFARE_CL_WRITE_FWT, 0);
+               if (ret < 0)
+                       return ret;
+
+               if (rx[0] != MIFARE_UL_RESP_ACK)
+                       return -EIO;
+
+       }
 
        return ret;
 }
@@ -110,6 +144,13 @@ static struct rfid_protocol_handle *
 mfcl_init(struct rfid_layer2_handle *l2h)
 {
        struct rfid_protocol_handle *ph;
+
+       if (l2h->l2->id != RFID_LAYER2_ISO14443A)
+               return NULL;
+
+       if (l2h->uid_len != 4)
+               return NULL;
+
        ph = malloc_protocol_handle(sizeof(struct rfid_protocol_handle));
        return ph;
 }
index 0ea55d2..8981b5e 100644 (file)
@@ -112,6 +112,14 @@ static struct rfid_protocol_handle *
 mful_init(struct rfid_layer2_handle *l2h)
 {
        struct rfid_protocol_handle *ph;
+
+       if (l2h->l2->id != RFID_LAYER2_ISO14443A)
+               return NULL;
+       
+       /* according to "Functional Specification Rev. 3.0 */
+       if (l2h->uid_len != 7)
+               return NULL;
+
        ph = malloc_protocol_handle(sizeof(struct rfid_protocol_handle));
        return ph;
 }
index f2b161e..7ad826e 100644 (file)
@@ -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 (file)
index 0000000..2966ab4
--- /dev/null
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <libgen.h>
+
+#include <librfid/rfid.h>
+#include <librfid/rfid_scan.h>
+#include <librfid/rfid_reader.h>
+#include <librfid/rfid_layer2.h>
+#include <librfid/rfid_protocol.h>
+
+#include <librfid/rfid_protocol_mifare_classic.h>
+#include <librfid/rfid_protocol_mifare_ul.h>
+
+#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;
+}
+
index e1270f1..37efadc 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <libgen.h>
 
 #define _GNU_SOURCE
 #include <getopt.h>
 #include <librfid/rfid_protocol_mifare_classic.h>
 #include <librfid/rfid_protocol_mifare_ul.h>
 
-#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 (file)
index 0000000..5ca49d4
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _RFIDTOOL_H
+#define _RFIDTOOL_H
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#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 (file)
index 0000000..f9a6a49
--- /dev/null
@@ -0,0 +1,207 @@
+/* mifare-tool - a small command-line tool for librfid mifare testing
+ *
+ * (C) 2006 by Harald Welte <laforge@gnumonks.org>
+ *
+ *  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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <libgen.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <librfid/rfid.h>
+#include <librfid/rfid_scan.h>
+#include <librfid/rfid_reader.h>
+#include <librfid/rfid_layer2.h>
+#include <librfid/rfid_protocol.h>
+
+#include <librfid/rfid_protocol_mifare_classic.h>
+#include <librfid/rfid_protocol_mifare_ul.h>
+
+#include <librfid/rfid_access_mifare_classic.h>
+
+#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);
+}
+