From d222d836a7a97c7164e0f96920b148d532fa574a Mon Sep 17 00:00:00 2001 From: laforge Date: Thu, 20 Oct 2005 20:15:49 +0000 Subject: add mifare ultralight support (incomplete) git-svn-id: https://svn.gnumonks.org/trunk/librfid@1543 e0336214-984f-0b4b-a45f-81c69e1f0ede --- Makefile | 2 +- include/rfid/rfid_layer2_iso14443a.h | 2 + include/rfid/rfid_protocol.h | 23 ++++++ openct-escape.c | 106 ++++++++++++++++++++++++++- rfid_asic_rc632.c | 1 + rfid_layer2_iso14443a.c | 47 ++++++------ rfid_layer2_iso14443b.c | 1 + rfid_proto_mifare_ul.c | 135 +++++++++++++++++++++++++++++++++++ rfid_protocol.c | 33 ++++++++- rfid_reader_cm5121.c | 8 +++ 10 files changed, 329 insertions(+), 29 deletions(-) create mode 100644 rfid_proto_mifare_ul.c diff --git a/Makefile b/Makefile index ac1ca50..ca53ada 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ all: openct-escape openct-escape: openct-escape.o librfid.a $(CC) $(LDFLAGS) -o $@ $^ -librfid.a: rfid_layer2.o rfid_layer2_iso14443a.o rfid_layer2_iso14443b.o rfid_layer2_iso15693.o rfid_asic_rc632.o rfid_reader_cm5121.o rfid.o rfid_protocol.o rfid_proto_tcl.o rfid_iso14443_common.o rfid_reader.o +librfid.a: rfid_layer2.o rfid_layer2_iso14443a.o rfid_layer2_iso14443b.o rfid_layer2_iso15693.o rfid_asic_rc632.o rfid_reader_cm5121.o rfid.o rfid_protocol.o rfid_proto_tcl.o rfid_proto_mifare_ul.o rfid_iso14443_common.o rfid_reader.o ar r $@ $^ %.o: %.c diff --git a/include/rfid/rfid_layer2_iso14443a.h b/include/rfid/rfid_layer2_iso14443a.h index 400f951..9594abb 100644 --- a/include/rfid/rfid_layer2_iso14443a.h +++ b/include/rfid/rfid_layer2_iso14443a.h @@ -68,6 +68,8 @@ struct iso14443a_handle { unsigned int state; unsigned int level; unsigned int tcl_capable; + unsigned int uid_len; + unsigned char uid[10]; /* Triple size UID is 10 bytes */ }; enum iso14443a_level { diff --git a/include/rfid/rfid_protocol.h b/include/rfid/rfid_protocol.h index f9db318..5172a08 100644 --- a/include/rfid/rfid_protocol.h +++ b/include/rfid/rfid_protocol.h @@ -16,6 +16,7 @@ struct rfid_protocol { int (*open)(struct rfid_protocol_handle *ph); int (*close)(struct rfid_protocol_handle *ph); int (*fini)(struct rfid_protocol_handle *ph); + /* transcieve for session based transport protocols */ int (*transcieve)(struct rfid_protocol_handle *ph, const unsigned char *tx_buf, unsigned int tx_len, @@ -23,6 +24,15 @@ struct rfid_protocol { unsigned int *rx_len, unsigned int timeout, unsigned int flags); + /* read/write for synchronous memory cards */ + int (*read)(struct rfid_protocol_handle *ph, + unsigned int page, + unsigned char *rx_data, + unsigned int *rx_len); + int (*write)(struct rfid_protocol_handle *ph, + unsigned int page, + unsigned char *tx_data, + unsigned int tx_len); } fn; }; @@ -44,6 +54,18 @@ int rfid_protocol_transcieve(struct rfid_protocol_handle *ph, const unsigned char *tx_buf, unsigned int tx_len, unsigned char *rx_buf, unsigned int *rx_len, unsigned int timeout, unsigned int flags); +int +rfid_protocol_read(struct rfid_protocol_handle *ph, + unsigned int page, + unsigned char *rx_data, + unsigned int rx_len); + +int +rfid_protocol_write(struct rfid_protocol_handle *ph, + unsigned int page, + unsigned char *tx_data, + unsigned int tx_len); + int rfid_protocol_fini(struct rfid_protocol_handle *ph); int rfid_protocol_close(struct rfid_protocol_handle *ph); @@ -52,5 +74,6 @@ int rfid_protocol_register(struct rfid_protocol *p); enum rfid_protocol_id { RFID_PROTOCOL_UNKNOWN, RFID_PROTOCOL_TCL, + RFID_PROTOCOL_MIFARE_UL, }; #endif diff --git a/openct-escape.c b/openct-escape.c index 60f60b7..5a4503f 100644 --- a/openct-escape.c +++ b/openct-escape.c @@ -88,6 +88,8 @@ static int init() return -1; } + sleep(2); + printf("opening layer2 handle\n"); l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443A); //l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443B); @@ -133,7 +135,7 @@ static int select_mf(void) if (rv < 0) return rv; - //printf("%s\n", rfid_hexdump(ret, rlen)); + printf("%s\n", rfid_hexdump(ret, rlen)); return 0; } @@ -158,6 +160,95 @@ static int get_challenge(unsigned char len) return 0; } +int +iso7816_select_application(void) +{ + char cmd[] = { 0x00, 0xa4, 0x04, 0x0c, 0x07, + 0x0a, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01 }; + char resp[7]; + unsigned int rlen = sizeof(resp); + + int rv; + + rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0); + if (rv < 0) + return rv; + + /* FIXME: parse response */ + return 0; +} + +int +iso7816_select_ef(u_int16_t fid) +{ + unsigned char cmd[7] = { 0x00, 0xa4, 0x02, 0x0c, 0x02, 0x00, 0x00 }; + unsigned char resp[7]; + unsigned int rlen = sizeof(resp); + + int rv; + + cmd[5] = (fid >> 8) & 0xff; + cmd[6] = fid & 0xff; + + rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0); + if (rv < 0) + return rv; + + /* FIXME: parse response */ + + return 0; +} + +int +iso7816_read_binary(unsigned char *buf, unsigned int *len) +{ + unsigned char cmd[] = { 0x00, 0xb0, 0x00, 0x00, 0x00 }; + unsigned char resp[256]; + unsigned int rlen = sizeof(resp); + + int rv; + + rv = rfid_protocol_transcieve(ph, cmd, sizeof(cmd), resp, &rlen, 0, 0); + if (rv < 0) + return rv; + + /* FIXME: parse response, determine whether we need additional reads */ + + /* FIXME: copy 'len' number of response bytes to 'buf' */ + return 0; +} + +/* wrapper function around SELECT EF and READ BINARY */ +int +iso7816_read_ef(u_int16_t fid, unsigned char *buf, unsigned int *len) +{ + int rv; + + rv = iso7816_select_ef(fid); + if (rv < 0) + return rv; + + return iso7816_read_binary(buf, len); +} + +int +mifare_ulight_read(struct rfid_protocol_handle *ph) +{ + unsigned char buf[16]; + unsigned int len = sizeof(buf); + int ret; + int i; + + for (i = 0; i < 7; i++) { + ret = rfid_protocol_read(ph, i, buf, &len); + if (ret < 0) + return ret; + + rfid_hexdump(buf, 4); + } + return 0; +} + int main(int argc, char **argv) { int rc; @@ -170,10 +261,21 @@ int main(int argc, char **argv) /* we've established T=CL at this point */ select_mf(); +#if 1 + select_mf(); + iso7816_select_application(); + iso7816_select_ef(0x011e); + iso7816_select_ef(0x0101); +#endif + +#if 1 for (i = 0; i < 4; i++) get_challenge(0x60); - +#endif + +// mifare_ulight_read(ph); + rfid_reader_close(rh); exit(0); diff --git a/rfid_asic_rc632.c b/rfid_asic_rc632.c index 4626751..94fb48f 100644 --- a/rfid_asic_rc632.c +++ b/rfid_asic_rc632.c @@ -622,6 +622,7 @@ rc632_iso14443a_transcieve(struct rfid_asic_handle *handle, int ret; unsigned char rxl = *rx_len & 0xff; + DEBUGP("entered\n"); memset(rx_buf, 0, *rx_len); #if 0 diff --git a/rfid_layer2_iso14443a.c b/rfid_layer2_iso14443a.c index 0605a89..f8bde7f 100644 --- a/rfid_layer2_iso14443a.c +++ b/rfid_layer2_iso14443a.c @@ -96,31 +96,31 @@ iso14443a_anticol(struct rfid_layer2_handle *handle) { int ret; unsigned int uid_size; + struct iso14443a_handle *h = &handle->priv.iso14443a; struct iso14443a_atqa atqa; struct iso14443a_anticol_cmd acf; unsigned int bit_of_col; unsigned char sak[3]; - unsigned char uid[10]; // triple size equals 10 bytes; unsigned int rx_len = sizeof(sak); char *aqptr = (char *) &atqa; - memset(uid, 0, sizeof(uid)); + memset(h->uid, 0, sizeof(h->uid)); memset(sak, 0, sizeof(sak)); memset(&atqa, 0, sizeof(atqa)); memset(&acf, 0, sizeof(acf)); ret = iso14443a_transcieve_sf(handle, ISO14443A_SF_CMD_REQA, &atqa); if (ret < 0) { - handle->priv.iso14443a.state = ISO14443A_STATE_REQA_SENT; + h->state = ISO14443A_STATE_REQA_SENT; DEBUGP("error during transcieve_sf: %d\n", ret); return ret; } - handle->priv.iso14443a.state = ISO14443A_STATE_ATQA_RCVD; + h->state = ISO14443A_STATE_ATQA_RCVD; DEBUGP("ATQA: 0x%02x 0x%02x\n", *aqptr, *(aqptr+1)); if (!atqa.bf_anticol) { - handle->priv.iso14443a.state =ISO14443A_STATE_NO_BITFRAME_ANTICOL; + h->state = ISO14443A_STATE_NO_BITFRAME_ANTICOL; DEBUGP("no bitframe anticollission bits set, aborting\n"); return -1; } @@ -134,8 +134,8 @@ iso14443a_anticol(struct rfid_layer2_handle *handle) acf.sel_code = ISO14443A_AC_SEL_CODE_CL1; - handle->priv.iso14443a.state = ISO14443A_STATE_ANTICOL_RUNNING; - handle->priv.iso14443a.level = ISO14443A_LEVEL_CL1; + h->state = ISO14443A_STATE_ANTICOL_RUNNING; + h->level = ISO14443A_LEVEL_CL1; cascade: iso14443a_code_nvb_bits(&acf.nvb, 16); @@ -170,19 +170,19 @@ cascade: DEBUGP("Cascade bit set, but UID0 != 0x88\n"); return -1; } - memcpy(&uid[0], &acf.uid_bits[1], 3); + memcpy(&h->uid[0], &acf.uid_bits[1], 3); acf.sel_code = ISO14443A_AC_SEL_CODE_CL2; - handle->priv.iso14443a.level = ISO14443A_LEVEL_CL2; + h->level = ISO14443A_LEVEL_CL2; break; case ISO14443A_AC_SEL_CODE_CL2: /* cascading from CL2 to CL3 */ - memcpy(&uid[3], &acf.uid_bits[1], 3); + memcpy(&h->uid[3], &acf.uid_bits[1], 3); acf.sel_code = ISO14443A_AC_SEL_CODE_CL3; - handle->priv.iso14443a.level = ISO14443A_LEVEL_CL3; + h->level = ISO14443A_LEVEL_CL3; break; default: DEBUGP("cannot cascade any further than CL3\n"); - handle->priv.iso14443a.state = ISO14443A_STATE_ERROR; + h->state = ISO14443A_STATE_ERROR; return -1; break; } @@ -192,40 +192,39 @@ cascade: switch (acf.sel_code) { case ISO14443A_AC_SEL_CODE_CL1: /* single size UID (4 bytes) */ - memcpy(&uid[0], &acf.uid_bits[0], 4); + memcpy(&h->uid[0], &acf.uid_bits[0], 4); break; case ISO14443A_AC_SEL_CODE_CL2: /* double size UID (7 bytes) */ - memcpy(&uid[3], &acf.uid_bits[0], 4); + memcpy(&h->uid[3], &acf.uid_bits[0], 4); break; case ISO14443A_AC_SEL_CODE_CL3: /* triple size UID (10 bytes) */ - memcpy(&uid[6], &acf.uid_bits[0], 4); + memcpy(&h->uid[6], &acf.uid_bits[0], 4); break; } } - handle->priv.iso14443a.level = ISO14443A_LEVEL_NONE; - handle->priv.iso14443a.state = ISO14443A_STATE_SELECTED; + h->level = ISO14443A_LEVEL_NONE; + h->state = ISO14443A_STATE_SELECTED; { - int uid_len; if (uid_size == 1) - uid_len = 4; + h->uid_len = 4; else if (uid_size == 2) - uid_len = 7; + h->uid_len = 7; else - uid_len = 10; + h->uid_len = 10; - DEBUGP("UID %s\n", rfid_hexdump(uid, uid_len)); + DEBUGP("UID %s\n", rfid_hexdump(h->uid, h->uid_len)); } if (sak[0] & 0x20) { DEBUGP("we have a T=CL compliant PICC\n"); - handle->priv.iso14443a.tcl_capable = 1; + h->tcl_capable = 1; } else { DEBUGP("we have a T!=CL PICC\n"); - handle->priv.iso14443a.tcl_capable = 0; + h->tcl_capable = 0; } return 0; diff --git a/rfid_layer2_iso14443b.c b/rfid_layer2_iso14443b.c index c0930b2..8424fde 100644 --- a/rfid_layer2_iso14443b.c +++ b/rfid_layer2_iso14443b.c @@ -321,6 +321,7 @@ iso14443b_transcieve(struct rfid_layer2_handle *handle, unsigned char *rx_buf, unsigned int *rx_len, u_int64_t timeout, unsigned int flags) { + DEBUGP("transcieving %u bytes, expecting max %u\n", tx_len, *rx_len); return handle->rh->reader->transcieve(handle->rh, tx_buf, tx_len, rx_buf, rx_len, timeout, flags); } diff --git a/rfid_proto_mifare_ul.c b/rfid_proto_mifare_ul.c new file mode 100644 index 0000000..3fec95b --- /dev/null +++ b/rfid_proto_mifare_ul.c @@ -0,0 +1,135 @@ + +/* Mifare Ultralight implementation, PCD side. + * + * (C) 2005 by Harald Welte + * + */ + +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include +//#include + +//#include +//#include + +#include "rfid_iso14443_common.h" + + +#define MIFARE_UL_CMD_WRITE 0xA2 +#define MIFARE_UL_CMD_READ 0x30 + +/* FIXME */ +#define MIFARE_UL_READ_FWT 100 +#define MIFARE_UL_WRITE_FWT 100 + +static int +mful_read(struct rfid_protocol_handle *ph, unsigned int page, + unsigned char *rx_data, unsigned int *rx_len) +{ + unsigned char rx_buf[16]; + unsigned int real_rx_len = sizeof(rx_buf); + unsigned char tx[2]; + int ret; + + if (page > 7) + return -EINVAL; + + tx[0] = MIFARE_UL_CMD_READ; + tx[1] = page & 0xff; + + ret = ph->l2h->l2->fn.transcieve(ph->l2h, tx, sizeof(tx), rx_buf, + &real_rx_len, MIFARE_UL_READ_FWT, 0); + + if (ret < 0) + return ret; + + if (real_rx_len < *rx_len) + *rx_len = real_rx_len; + + memcpy(rx_data, rx_buf, *rx_len); + + return ret; +} + +static int +mful_write(struct rfid_protocol_handle *ph, unsigned int page, + unsigned char *tx_data, unsigned int tx_len) +{ + unsigned int i; + unsigned char tx[6]; + unsigned char rx[1]; + unsigned int rx_len; + int ret; + + if (tx_len != 4 || page > 7) + return -EINVAL; + + tx[0] = MIFARE_UL_CMD_WRITE; + tx[1] = page & 0xff; + + for (i = 0; i < 4; i++) + tx[2+i] = tx_data[i]; + + ret = ph->l2h->l2->fn.transcieve(ph->l2h, tx, sizeof(tx), rx, + &rx_len, MIFARE_UL_WRITE_FWT, 0); + + /* FIXME:look at RX, check for ACK/NAK */ + + return ret; +} + +static int +mful_transcieve(struct rfid_protocol_handle *ph, + const unsigned char *tx_data, unsigned int tx_len, + unsigned char *rx_data, unsigned int *rx_len, + unsigned int timeout, unsigned int flags) +{ + return -EINVAL; +} + +static struct rfid_protocol_handle * +mful_init(struct rfid_layer2_handle *l2h) +{ + struct rfid_protocol_handle *ph; + ph = malloc(sizeof(struct rfid_protocol_handle)); + return ph; +} + +static int mful_fini(struct rfid_protocol_handle *ph) +{ + free(ph); + return 0; +} + +struct rfid_protocol rfid_protocol_mful = { + .id = RFID_PROTOCOL_MIFARE_UL, + .name = "Mifare Ultralight", + .fn = { + .init = &mful_init, + /* .transcieve = &mful_transcieve,*/ + .read = &mful_read, + .write = &mful_write, + .fini = &mful_fini, + }, +}; diff --git a/rfid_protocol.c b/rfid_protocol.c index 3340b25..28da029 100644 --- a/rfid_protocol.c +++ b/rfid_protocol.c @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -40,7 +41,9 @@ rfid_protocol_init(struct rfid_layer2_handle *l2h, unsigned int id) int rfid_protocol_open(struct rfid_protocol_handle *ph) { - return ph->proto->fn.open(ph); + if (ph->proto->fn.open) + return ph->proto->fn.open(ph); + return 0; } int @@ -53,6 +56,30 @@ rfid_protocol_transcieve(struct rfid_protocol_handle *ph, timeout, flags); } +int +rfid_protocol_read(struct rfid_protocol_handle *ph, + unsigned int page, + unsigned char *rx_data, + unsigned int rx_len) +{ + if (ph->proto->fn.read) + return ph->proto->fn.read(ph, page, rx_data, rx_len); + else + return -EINVAL; +} + +int +rfid_protocol_write(struct rfid_protocol_handle *ph, + unsigned int page, + unsigned char *tx_data, + unsigned int tx_len) +{ + if (ph->proto->fn.write) + return ph->proto->fn.write(ph, page, tx_data, tx_len); + else + return -EINVAL; +} + int rfid_protocol_fini(struct rfid_protocol_handle *ph) { return ph->proto->fn.fini(ph); @@ -61,7 +88,9 @@ int rfid_protocol_fini(struct rfid_protocol_handle *ph) int rfid_protocol_close(struct rfid_protocol_handle *ph) { - return ph->proto->fn.close(ph); + if (ph->proto->fn.close) + return ph->proto->fn.close(ph); + return 0; } int diff --git a/rfid_reader_cm5121.c b/rfid_reader_cm5121.c index 7edadaf..6867ee7 100644 --- a/rfid_reader_cm5121.c +++ b/rfid_reader_cm5121.c @@ -40,6 +40,14 @@ #define SENDBUF_LEN 40 #define RECVBUF_LEN 40 +#if 0 +#ifdef DEBUGP +#undef DEBUGP +#define DEBUGP(x, ...) +#define DEBUGPC(x, ...) +#endif +#endif + static int Write1ByteToReg(struct rfid_asic_transport_handle *rath, unsigned char reg, unsigned char value) -- cgit v1.2.3