add mifare ultralight support (incomplete)
authorHarald Welte <laforge@gnumonks.org>
Thu, 20 Oct 2005 20:15:49 +0000 (20:15 +0000)
committerHarald Welte <laforge@gnumonks.org>
Thu, 20 Oct 2005 20:15:49 +0000 (20:15 +0000)
git-svn-id: https://svn.gnumonks.org/trunk/librfid@1543 e0336214-984f-0b4b-a45f-81c69e1f0ede

Makefile
include/rfid/rfid_layer2_iso14443a.h
include/rfid/rfid_protocol.h
openct-escape.c
rfid_asic_rc632.c
rfid_layer2_iso14443a.c
rfid_layer2_iso14443b.c
rfid_proto_mifare_ul.c [new file with mode: 0644]
rfid_protocol.c
rfid_reader_cm5121.c

index ac1ca50..ca53ada 100644 (file)
--- 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
index 400f951..9594abb 100644 (file)
@@ -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 {
index f9db318..5172a08 100644 (file)
@@ -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
index 60f60b7..5a4503f 100644 (file)
@@ -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);
index 4626751..94fb48f 100644 (file)
@@ -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
index 0605a89..f8bde7f 100644 (file)
@@ -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;
index c0930b2..8424fde 100644 (file)
@@ -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 (file)
index 0000000..3fec95b
--- /dev/null
@@ -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,
+       },
+};
index 3340b25..28da029 100644 (file)
@@ -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
index 7edadaf..6867ee7 100644 (file)
 #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)