summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaforge <laforge@e0336214-984f-0b4b-a45f-81c69e1f0ede>2005-10-20 20:15:49 +0000
committerlaforge <laforge@e0336214-984f-0b4b-a45f-81c69e1f0ede>2005-10-20 20:15:49 +0000
commitd222d836a7a97c7164e0f96920b148d532fa574a (patch)
tree80fbd5c4138c5b91bf95a53d87ec96a35fe7fb55
parent95b1a39e943eb22d73dc1ddccd1e372c1176d210 (diff)
add mifare ultralight support (incomplete)
git-svn-id: https://svn.gnumonks.org/trunk/librfid@1543 e0336214-984f-0b4b-a45f-81c69e1f0ede
-rw-r--r--Makefile2
-rw-r--r--include/rfid/rfid_layer2_iso14443a.h2
-rw-r--r--include/rfid/rfid_protocol.h23
-rw-r--r--openct-escape.c106
-rw-r--r--rfid_asic_rc632.c1
-rw-r--r--rfid_layer2_iso14443a.c47
-rw-r--r--rfid_layer2_iso14443b.c1
-rw-r--r--rfid_proto_mifare_ul.c135
-rw-r--r--rfid_protocol.c33
-rw-r--r--rfid_reader_cm5121.c8
10 files changed, 329 insertions, 29 deletions
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 <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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_protocol.h>
+#include <rfid/rfid_layer2.h>
+//#include <rfid/rfid_layer2_iso14443b.h>
+
+//#include <rfid/rfid_asic.h>
+//#include <rfid/rfid_reader.h>
+
+#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 <stdlib.h>
#include <unistd.h>
+#include <errno.h>
#include <rfid/rfid_layer2.h>
#include <rfid/rfid_protocol.h>
@@ -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)
personal git repositories of Harald Welte. Your mileage may vary