diff options
author | laforge <laforge@e0336214-984f-0b4b-a45f-81c69e1f0ede> | 2006-11-28 10:06:24 +0000 |
---|---|---|
committer | laforge <laforge@e0336214-984f-0b4b-a45f-81c69e1f0ede> | 2006-11-28 10:06:24 +0000 |
commit | 2da53a43badc7bd578ab5df850648f14807aecd2 (patch) | |
tree | 7041dc431c25664d9ba280a02504157407eb774d /src | |
parent | c972071a03825d8fe595d33f9128b4341b0478bd (diff) |
- 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
Diffstat (limited to 'src')
-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 |
7 files changed, 381 insertions, 22 deletions
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; } |