diff options
-rw-r--r-- | include/librfid/Makefile.am | 1 | ||||
-rw-r--r-- | include/librfid/rfid_access_mifare_classic.h | 46 | ||||
-rw-r--r-- | include/librfid/rfid_asic.h | 10 | ||||
-rw-r--r-- | include/librfid/rfid_asic_rc632.h | 86 | ||||
-rw-r--r-- | include/librfid/rfid_layer2_iso15693.h | 47 | ||||
-rw-r--r-- | include/librfid/rfid_protocol.h | 1 | ||||
-rw-r--r-- | include/librfid/rfid_protocol_mifare_classic.h | 4 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/rc632.h | 10 | ||||
-rw-r--r-- | src/rfid_access_mifare_classic.c | 232 | ||||
-rw-r--r-- | src/rfid_asic_rc632.c | 46 | ||||
-rw-r--r-- | src/rfid_layer2_iso15693.c | 39 | ||||
-rw-r--r-- | src/rfid_proto_mifare_classic.c | 65 | ||||
-rw-r--r-- | src/rfid_proto_mifare_ul.c | 8 | ||||
-rw-r--r-- | utils/Makefile.am | 10 | ||||
-rw-r--r-- | utils/common.c | 125 | ||||
-rw-r--r-- | utils/librfid-tool.c | 202 | ||||
-rw-r--r-- | utils/librfid-tool.h | 35 | ||||
-rw-r--r-- | utils/mifare-tool.c | 207 |
19 files changed, 975 insertions, 202 deletions
diff --git a/include/librfid/Makefile.am b/include/librfid/Makefile.am index 1edb60b..9af455b 100644 --- a/include/librfid/Makefile.am +++ b/include/librfid/Makefile.am @@ -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 index 0000000..3c23724 --- /dev/null +++ b/include/librfid/rfid_access_mifare_classic.h @@ -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 diff --git a/include/librfid/rfid_asic.h b/include/librfid/rfid_asic.h index 3686a7c..113eb19 100644 --- a/include/librfid/rfid_asic.h +++ b/include/librfid/rfid_asic.h @@ -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; diff --git a/include/librfid/rfid_asic_rc632.h b/include/librfid/rfid_asic_rc632.h index 642c940..4eac82e 100644 --- a/include/librfid/rfid_asic_rc632.h +++ b/include/librfid/rfid_asic_rc632.h @@ -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); diff --git a/include/librfid/rfid_layer2_iso15693.h b/include/librfid/rfid_layer2_iso15693.h index f84a6e1..d09daa7 100644 --- a/include/librfid/rfid_layer2_iso15693.h +++ b/include/librfid/rfid_layer2_iso15693.h @@ -12,9 +12,10 @@ /* 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 */ }; diff --git a/include/librfid/rfid_protocol.h b/include/librfid/rfid_protocol.h index 2c1d0e8..fd649ef 100644 --- a/include/librfid/rfid_protocol.h +++ b/include/librfid/rfid_protocol.h @@ -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 { diff --git a/include/librfid/rfid_protocol_mifare_classic.h b/include/librfid/rfid_protocol_mifare_classic.h index f1e1403..99c447d 100644 --- a/include/librfid/rfid_protocol_mifare_classic.h +++ b/include/librfid/rfid_protocol_mifare_classic.h @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index 86663a4..3e2bf95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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) diff --git a/src/rc632.h b/src/rc632.h index ff00df0..c7690ed 100644 --- a/src/rc632.h +++ b/src/rc632.h @@ -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 index 0000000..bd362e1 --- /dev/null +++ b/src/rfid_access_mifare_classic.c @@ -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; +} + diff --git a/src/rfid_asic_rc632.c b/src/rfid_asic_rc632.c index b421ca6..2890d6d 100644 --- a/src/rfid_asic_rc632.c +++ b/src/rfid_asic_rc632.c @@ -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, ®); 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 */ diff --git a/src/rfid_layer2_iso15693.c b/src/rfid_layer2_iso15693.c index dab7418..f5da8c2 100644 --- a/src/rfid_layer2_iso15693.c +++ b/src/rfid_layer2_iso15693.c @@ -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, }, }; diff --git a/src/rfid_proto_mifare_classic.c b/src/rfid_proto_mifare_classic.c index d45eefc..4032b80 100644 --- a/src/rfid_proto_mifare_classic.c +++ b/src/rfid_proto_mifare_classic.c @@ -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; } diff --git a/src/rfid_proto_mifare_ul.c b/src/rfid_proto_mifare_ul.c index 0ea55d2..8981b5e 100644 --- a/src/rfid_proto_mifare_ul.c +++ b/src/rfid_proto_mifare_ul.c @@ -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; } 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 <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; +} + 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 <stdlib.h> #include <string.h> #include <errno.h> +#include <libgen.h> #define _GNU_SOURCE #include <getopt.h> @@ -34,84 +35,8 @@ #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 index 0000000..5ca49d4 --- /dev/null +++ b/utils/librfid-tool.h @@ -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 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 <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); +} + |