- 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
This commit is contained in:
parent
c972071a03
commit
2da53a43ba
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
struct rfid_asic_rc632_impl_proto {
|
||||
u_int8_t mod_conductance;
|
||||
u_int8_t cw_conductance;
|
||||
u_int8_t bitphase;
|
||||
u_int8_t threshold;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
10
src/rc632.h
10
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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
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;
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue