- 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:
laforge 2006-11-28 10:06:24 +00:00
parent c972071a03
commit 2da53a43ba
19 changed files with 975 additions and 202 deletions

View 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

View File

@ -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

View 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;

View 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);
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);

View File

@ -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 */
};

View 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 {

View 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

View 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)

View 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,
};

View File

@ -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;
}

View 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 */

View 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,
},
};

View 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;
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;
}

View 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;
}

View 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

125
utils/common.c Normal file
View File

@ -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;
}

View File

@ -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);
}

35
utils/librfid-tool.h Normal file
View File

@ -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 */

207
utils/mifare-tool.c Normal file
View File

@ -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);
}