librfid/src/rfid_proto_tcl.c

730 lines
17 KiB
C

/* ISO 14443-4 (T=CL) 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 <librfid/rfid.h>
#include <librfid/rfid_protocol_tcl.h>
#include <librfid/rfid_protocol.h>
#include <librfid/rfid_layer2.h>
#include <librfid/rfid_layer2_iso14443b.h>
#include <librfid/rfid_asic.h>
#include <librfid/rfid_reader.h>
#include "rfid_iso14443_common.h"
#if 0
#ifdef DEBUGP
#undef DEBUGP
#define DEBUGP(x, ...)
#endif
#ifdef DEBUGPC
#undef DEBUGPC
#define DEBUGPC(x, ...)
#endif
#endif
static enum rfid_frametype l2_to_frame(unsigned int layer2)
{
switch (layer2) {
case RFID_LAYER2_ISO14443A:
return RFID_14443A_FRAME_REGULAR;
break;
case RFID_LAYER2_ISO14443B:
return RFID_14443B_FRAME_REGULAR;
break;
}
return 0;
}
static unsigned int sfgi_to_sfgt(struct rfid_protocol_handle *h,
unsigned char sfgi)
{
unsigned int multiplier;
unsigned int tmp;
if (sfgi > 14)
sfgi = 14;
multiplier = 1 << sfgi; /* 2 to the power of sfgi */
/* ISO 14443-4:2000(E) Section 5.2.5:
* (256 * 16 / h->l2h->rh->ah->fc) * (2 ^ sfgi) */
tmp = (unsigned int) 1000000 * 256 * 16;
return (tmp / h->l2h->rh->ah->fc) * multiplier;
}
static unsigned int fwi_to_fwt(struct rfid_protocol_handle *h,
unsigned char fwi)
{
unsigned int multiplier, tmp;
if (fwi > 14)
fwi = 14;
multiplier = 1 << fwi; /* 2 to the power of fwi */
/* ISO 14443-4:2000(E) Section 7.2.:
* (256*16 / h->l2h->rh->ah->fc) * (2 ^ fwi) */
tmp = (unsigned int) 1000000 * 256 * 16;
return (tmp / h->l2h->rh->ah->fc) * multiplier;
}
/* 4.9seconds as microseconds (4.9 billion seconds) exceeds 2^32 */
#define activation_fwt(x) (((u_int64_t)1000000 * 65536 / x->l2h->rh->ah->fc))
#define deactivation_fwt(x) activation_fwt(x)
static int
tcl_parse_ats(struct rfid_protocol_handle *h,
unsigned char *ats, unsigned int size)
{
unsigned char len = ats[0];
unsigned char t0;
unsigned char *cur;
if (len == 0 || size == 0)
return -1;
if (size < len)
len = size;
h->priv.tcl.ta = 0;
if (len == 1) {
/* FIXME: assume some default values */
h->priv.tcl.fsc = 32;
h->priv.tcl.ta = 0x80; /* 0x80 (same d for both dirs) */
h->priv.tcl.sfgt = sfgi_to_sfgt(h, 0);
if (h->l2h->l2->id == RFID_LAYER2_ISO14443A) {
/* Section 7.2: fwi default for type A is 4 */
h->priv.tcl.fwt = fwi_to_fwt(h, 4);
} else {
/* Section 7.2: fwi for type B is always in ATQB */
/* Value is assigned in tcl_connect() */
/* This function is never called for Type B, since it has no (R)ATS */
}
return 0;
}
/* guarateed to be at least 2 bytes in size */
t0 = ats[1];
cur = &ats[2];
iso14443_fsdi_to_fsd(&h->priv.tcl.fsc, t0 & 0x0f);
if (t0 & (1 << 4)) {
/* TA is transmitted */
h->priv.tcl.ta = *cur++;
}
if (t0 & (1 << 5)) {
/* TB is transmitted */
h->priv.tcl.sfgt = sfgi_to_sfgt(h, *cur & 0x0f);
h->priv.tcl.fwt = fwi_to_fwt(h, (*cur & 0xf0) >> 4);
cur++;
}
if (t0 & (1 << 6)) {
/* TC is transmitted */
if (*cur & 0x01)
h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED;
if (*cur & 0x02)
h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED;
cur++;
}
h->priv.tcl.historical_len = (ats+len) - cur;
h->priv.tcl.historical_bytes = cur;
return 0;
}
/* request an ATS from the PICC */
static int
tcl_request_ats(struct rfid_protocol_handle *h)
{
int ret;
unsigned char rats[2];
unsigned char fsdi;
if (h->priv.tcl.state != TCL_STATE_INITIAL)
return -1;
ret = iso14443_fsd_to_fsdi(&fsdi, h->priv.tcl.fsd);
if (ret < 0) {
DEBUGP("unable to encode FSD of %u as FSDI\n", h->priv.tcl.fsd);
return ret;
}
rats[0] = 0xe0;
rats[1] = (h->priv.tcl.cid & 0x0f) | ((fsdi << 4) & 0xf0);
/* transcieve (with CRC) */
ret = rfid_layer2_transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
rats, 2, h->priv.tcl.ats,
&h->priv.tcl.ats_len, activation_fwt(h),
TCL_TRANSP_F_TX_CRC);
if (ret < 0) {
DEBUGP("transcieve of rats failed\n");
h->priv.tcl.state = TCL_STATE_RATS_SENT;
/* FIXME: retransmit */
return ret;
}
h->priv.tcl.state = TCL_STATE_ATS_RCVD;
ret = tcl_parse_ats(h, h->priv.tcl.ats, h->priv.tcl.ats_len);
if (ret < 0) {
DEBUGP("parsing of ats failed\n");
return ret;
}
return 0;
}
#define ATS_TA_DIV_2 1
#define ATS_TA_DIV_4 2
#define ATS_TA_DIV_8 4
#define PPS_DIV_8 3
#define PPS_DIV_4 2
#define PPS_DIV_2 1
#define PPS_DIV_1 0
static unsigned char d_to_di(struct rfid_protocol_handle *h, unsigned char D)
{
static char DI;
unsigned int speed = h->l2h->rh->reader->iso14443a.speed;
if ((D & ATS_TA_DIV_8) && (speed & RFID_14443A_SPEED_848K))
DI = PPS_DIV_8;
else if ((D & ATS_TA_DIV_4) && (speed & RFID_14443A_SPEED_424K))
DI = PPS_DIV_4;
else if ((D & ATS_TA_DIV_2) && (speed & RFID_14443A_SPEED_212K))
DI = PPS_DIV_2;
else
DI = PPS_DIV_1;
return DI;
}
static unsigned int di_to_speed(unsigned char DI)
{
switch (DI) {
case PPS_DIV_8:
return RFID_14443A_SPEED_848K;
break;
case PPS_DIV_4:
return RFID_14443A_SPEED_424K;
break;
case PPS_DIV_2:
return RFID_14443A_SPEED_212K;
break;
case PPS_DIV_1:
return RFID_14443A_SPEED_106K;
break;
}
}
/* start a PPS run (autimatically configure highest possible speed */
static int
tcl_do_pps(struct rfid_protocol_handle *h)
{
int ret;
unsigned char ppss[3];
unsigned char pps_response[1];
unsigned int rx_len = 1;
unsigned char Dr, Ds, DrI, DsI;
unsigned int speed;
if (h->priv.tcl.state != TCL_STATE_ATS_RCVD)
return -1;
Dr = h->priv.tcl.ta & 0x07;
Ds = h->priv.tcl.ta & 0x70 >> 4;
DEBUGP("Dr = 0x%x, Ds = 0x%x\n", Dr, Ds);
if (Dr != Ds && !(h->priv.tcl.ta & 0x80)) {
/* device supports different divisors for rx and tx, but not
* really ?!? */
DEBUGP("PICC has contradictory TA, aborting PPS\n");
return -1;
};
/* ISO 14443-4:2000(E) Section 5.3. */
ppss[0] = 0xd0 | (h->priv.tcl.cid & 0x0f);
ppss[1] = 0x11;
/* FIXME: deal with different speed for each direction */
DrI = d_to_di(h, Dr);
DsI = d_to_di(h, Ds);
DEBUGP("DrI = 0x%x, DsI = 0x%x\n", DrI, DsI);
ppss[2] = (ppss[2] & 0xf0) | (DrI | DsI << 2);
ret = rfid_layer2_transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
ppss, 3, pps_response, &rx_len,
h->priv.tcl.fwt, TCL_TRANSP_F_TX_CRC);
if (ret < 0)
return ret;
if (pps_response[0] != ppss[0]) {
DEBUGP("PPS Response != PPSS\n");
return -1;
}
speed = di_to_speed(DrI);
ret = rfid_layer2_setopt(h->l2h, RFID_OPT_14443A_SPEED_RX,
&speed, sizeof(speed));
if (ret < 0)
return ret;
ret = rfid_layer2_setopt(h->l2h, RFID_OPT_14443A_SPEED_TX,
&speed, sizeof(speed));
if (ret < 0)
return ret;
return 0;
}
static int
tcl_build_prologue2(struct tcl_handle *th,
unsigned char *prlg, unsigned int *prlg_len,
unsigned char pcb)
{
*prlg_len = 1;
*prlg = pcb;
if (th->toggle) {
/* we've sent a toggle bit last time */
th->toggle = 0;
} else {
/* we've not sent a toggle last time: send one */
th->toggle = 1;
*prlg |= 0x01;
}
if (th->flags & TCL_HANDLE_F_CID_USED) {
/* ISO 14443-4:2000(E) Section 7.1.1.2 */
*prlg |= TCL_PCB_CID_FOLLOWING;
(*prlg_len)++;
prlg[*prlg_len] = th->cid & 0x0f;
}
/* nad only for I-block (0xc0 == 00) */
if ((th->flags & TCL_HANDLE_F_NAD_USED) &&
((pcb & 0xc0) == 0x00)) {
/* ISO 14443-4:2000(E) Section 7.1.1.3 */
/* FIXME: in case of chaining only for first frame */
*prlg |= TCL_PCB_NAD_FOLLOWING;
prlg[*prlg_len] = th->nad;
(*prlg_len)++;
}
return 0;
}
static int
tcl_build_prologue_i(struct tcl_handle *th,
unsigned char *prlg, unsigned int *prlg_len)
{
/* ISO 14443-4:2000(E) Section 7.1.1.1 */
return tcl_build_prologue2(th, prlg, prlg_len, 0x02);
}
static int
tcl_build_prologue_r(struct tcl_handle *th,
unsigned char *prlg, unsigned int *prlg_len,
unsigned int nak)
{
unsigned char pcb = 0xa2;
/* ISO 14443-4:2000(E) Section 7.1.1.1 */
if (nak)
pcb |= 0x10;
return tcl_build_prologue2(th, prlg, prlg_len, pcb);
}
static int
tcl_build_prologue_s(struct tcl_handle *th,
unsigned char *prlg, unsigned int *prlg_len)
{
/* ISO 14443-4:2000(E) Section 7.1.1.1 */
/* the only S-block from PCD->PICC is DESELECT,
* well, actually there is the S(WTX) response. */
return tcl_build_prologue2(th, prlg, prlg_len, 0xc2);
}
/* FIXME: WTXM implementation */
static int tcl_prlg_len(struct tcl_handle *th)
{
int prlg_len = 1;
if (th->flags & TCL_HANDLE_F_CID_USED)
prlg_len++;
if (th->flags & TCL_HANDLE_F_NAD_USED)
prlg_len++;
return prlg_len;
}
#define max_net_tx_framesize(x) (x->fsc - tcl_prlg_len(x))
static int
tcl_connect(struct rfid_protocol_handle *h)
{
int ret;
if (h->priv.tcl.state != TCL_STATE_DESELECTED &&
h->priv.tcl.state != TCL_STATE_INITIAL)
return -1;
switch (h->l2h->l2->id) {
case RFID_LAYER2_ISO14443A:
/* Start Type A T=CL Activation Sequence */
ret = tcl_request_ats(h);
if (ret < 0)
return ret;
/* Only do PPS if any non-default divisors supported */
if (h->priv.tcl.ta & 0x77) {
ret = tcl_do_pps(h);
if (ret < 0)
return ret;
}
break;
case RFID_LAYER2_ISO14443B:
/* initialized T=CL state from Type B Activation Data */
h->priv.tcl.cid = h->l2h->priv.iso14443b.cid;
h->priv.tcl.fsc = h->l2h->priv.iso14443b.fsc;
h->priv.tcl.fsd = h->l2h->priv.iso14443b.fsd;
h->priv.tcl.fwt = h->l2h->priv.iso14443b.fwt;
/* what about ta? sfgt? */
if (h->l2h->priv.iso14443b.flags & ISO14443B_CID_SUPPORTED)
h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED;
if (h->l2h->priv.iso14443b.flags & ISO14443B_NAD_SUPPORTED)
h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED;
switch (h->l2h->priv.iso14443b.state) {
case ISO14443B_STATE_SELECTED:
h->priv.tcl.state = TCL_STATE_ATS_RCVD;
break;
case ISO14443B_STATE_ATTRIB_SENT:
h->priv.tcl.state = TCL_STATE_RATS_SENT;
break;
}
/* PUPI will be presented as ATS/historical bytes */
memcpy(h->priv.tcl.ats, h->l2h->uid, 4);
h->priv.tcl.ats_len = 4;
h->priv.tcl.historical_bytes = h->priv.tcl.ats;
break;
default:
DEBUGP("unsupported l2: %u\n", h->l2h->l2->id);
return -1;
break;
}
h->priv.tcl.state = TCL_STATE_ESTABLISHED;
return 0;
}
static int
tcl_deselect(struct rfid_protocol_handle *h)
{
/* ISO 14443-4:2000(E) Section 8 */
int ret;
unsigned char frame[3]; /* 3 bytes prologue, no information */
unsigned char rx[3];
unsigned int rx_len = sizeof(rx);
unsigned int prlg_len;
struct tcl_handle *th = &h->priv.tcl;
if (th->state != TCL_STATE_ESTABLISHED) {
/* FIXME: not sure whether deselect is possible here,
* probably better send a HLTA? */
}
/* build DESELECT S-block */
ret = tcl_build_prologue_s(th, frame, &prlg_len);
if (ret < 0)
return ret;
ret = rfid_layer2_transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
frame, prlg_len, rx,
&rx_len, deactivation_fwt(h),
TCL_TRANSP_F_TX_CRC);
if (ret < 0) {
/* FIXME: retransmit, HLT(A|B) */
return ret;
}
th->state = TCL_STATE_DESELECTED;
return 0;
}
#define is_s_block(x) ((x & 0xc0) == 0xc0)
#define is_r_block(x) ((x & 0xc0) == 0x80)
#define is_i_block(x) ((x & 0xc0) == 0x00)
static int
tcl_transcieve(struct rfid_protocol_handle *h,
const unsigned char *tx_data, unsigned int tx_len,
unsigned char *rx_data, unsigned int *rx_len,
unsigned int timeout, unsigned int flags)
{
int ret;
unsigned char *tx_buf, *rx_buf;
unsigned char *_rx_data = rx_data;
unsigned int _rx_len;
unsigned int max_rx_len = *rx_len; /* maximum number of payoload that
caller has requested */
unsigned int prlg_len;
struct tcl_handle *th = &h->priv.tcl;
unsigned char *_tx;
unsigned int _tx_len, _timeout;
unsigned char wtx_resp[3];
unsigned char ack[10];
unsigned int ack_len;
if (tx_len > max_net_tx_framesize(th)) {
/* slow path: we need to use chaining */
return -1;
}
tx_buf = malloc(tcl_prlg_len(th) + tx_len);
if (!tx_buf) {
ret = -ENOMEM;
goto out;
}
rx_buf = malloc(tcl_prlg_len(th) + *rx_len);
if (!rx_buf) {
ret = -ENOMEM;
goto out_txb;
}
if (tcl_build_prologue_i(th, tx_buf, &prlg_len) < 0) {
ret = -1;
goto out_rxb;
}
memcpy(tx_buf + prlg_len, tx_data, tx_len);
/* intialize to data-to-be-transferred */
_tx = tx_buf;
_tx_len = tx_len+prlg_len;
_timeout = th->fwt;
_rx_len = *rx_len;
*rx_len = 0;
do_tx:
ret = rfid_layer2_transcieve(h->l2h, l2_to_frame(h->l2h->l2->id),
_tx, _tx_len,
rx_buf, &_rx_len, _timeout, 0);
DEBUGP("l2 transcieve finished\n");
if (ret < 0)
goto out_rxb;
if ((*rx_buf & 0x01) != h->priv.tcl.toggle) {
DEBUGP("response with wrong toggle bit\n");
goto out_rxb;
}
if (is_r_block(*rx_buf)) {
unsigned int txed = _tx - tx_buf;
DEBUGP("R-Block\n");
/* Handle ACK frame in case of chaining */
if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
if (*(rx_buf+1) != h->priv.tcl.cid) {
DEBUGP("CID %u is not valid\n", *(rx_buf)+1);
goto out_rxb;
}
}
/* set up parameters for next frame in chain */
if (txed < tx_len) {
/* move tx pointer by the amount of bytes transferred
* in last frame */
_tx += _tx_len;
_tx_len = (tx_len - txed);
if (_tx_len > max_net_tx_framesize(th)) {
/* not last frame in chain */
_tx_len = max_net_tx_framesize(th);
} else {
/* last frame in chain */
}
goto do_tx;
} else {
DEBUGP("Received ACK in response to last frame in "
"chain?!? Expected I-frame.\n");
ret = -1;
goto out_rxb;
}
} else if (is_s_block(*rx_buf)) {
unsigned char inf;
unsigned int prlg_len;
DEBUGP("S-Block\n");
/* Handle Wait Time Extension */
if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
if (_rx_len < 3) {
DEBUGP("S-Block with CID but short len\n");
ret = -1;
goto out_rxb;
}
if (*(rx_buf+1) != h->priv.tcl.cid) {
DEBUGP("CID %u is not valid\n", *(rx_buf)+1);
goto out_rxb;
}
inf = *(rx_buf+2);
} else
inf = *(rx_buf+1);
if ((*rx_buf & 0x30) != 0x30) {
DEBUGP("S-Block but not WTX?\n");
ret = -1;
goto out_rxb;
}
inf &= 0x3f; /* only lower 6 bits code WTXM */
if (inf == 0 || (inf >= 60 && inf <= 63)) {
DEBUGP("WTXM %u is RFU!\n", inf);
ret = -1;
goto out_rxb;
}
/* Acknowledge WTXM */
tcl_build_prologue_s(&h->priv.tcl, wtx_resp, &prlg_len);
/* set two bits that make this block a wtx */
wtx_resp[0] |= 0x30;
wtx_resp[prlg_len] = inf;
_tx = wtx_resp;
_tx_len = prlg_len+1;
_timeout = th->fwt * inf;
/* start over with next transcieve */
goto do_tx; /* FIXME: do transcieve locally since we use
totally different buffer */
} else if (is_i_block(*rx_buf)) {
unsigned char *inf = rx_buf+1;
unsigned int net_payload_len;
/* we're actually receiving payload data */
DEBUGP("I-Block: ");
if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
if (*(rx_buf+1) != h->priv.tcl.cid) {
DEBUGPC("CID %u is not valid\n", *(rx_buf)+1);
goto out_rxb;
}
inf++;
}
if (*rx_buf & TCL_PCB_NAD_FOLLOWING) {
inf++;
}
net_payload_len = _rx_len - (inf - rx_buf);
DEBUGPC("%u bytes\n", net_payload_len);
memcpy(_rx_data, inf, net_payload_len);
/* increment the number of payload bytes that we actually received */
*rx_len += net_payload_len;
_rx_data += net_payload_len;
if (*rx_buf & 0x10) {
/* we're not the last frame in the chain, continue rx */
DEBUGP("we're not the last frame in the chain, continue\n");
ack_len = sizeof(ack);
tcl_build_prologue_r(&h->priv.tcl, ack, &ack_len, 0);
_tx = ack;
_tx_len = ack_len;
goto do_tx;
}
}
out_rxb:
free(rx_buf);
out_txb:
free(tx_buf);
out:
return ret;
}
static struct rfid_protocol_handle *
tcl_init(struct rfid_layer2_handle *l2h)
{
struct rfid_protocol_handle *th;
unsigned int mru = l2h->rh->ah->mru;
th = malloc(sizeof(struct rfid_protocol_handle) + mru);
if (!th)
return NULL;
/* FIXME: mru should be attribute of layer2 (in case it adds/removes
* some overhead */
memset(th, 0, sizeof(struct rfid_protocol_handle) + mru);
/* maximum received ats length equals mru of asic/reader */
th->priv.tcl.state = TCL_STATE_INITIAL;
th->priv.tcl.ats_len = mru;
th->priv.tcl.toggle = 1;
th->priv.tcl.fsd = iso14443_fsd_approx(mru);
return th;
}
static int
tcl_fini(struct rfid_protocol_handle *ph)
{
free(ph);
return 0;
}
struct rfid_protocol rfid_protocol_tcl = {
.id = RFID_PROTOCOL_TCL,
.name = "ISO 14443-4 / T=CL",
.fn = {
.init = &tcl_init,
.open = &tcl_connect,
.transcieve = &tcl_transcieve,
.close = &tcl_deselect,
.fini = &tcl_fini,
},
};