/* ISO 14443-4 (T=CL) implementation, PCD side. * * (C) 2005-2006 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 #include "rfid_iso14443_common.h" #define RFID_MAX_FRAMELEN 256 #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 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 Type B 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 (h->priv.tcl.fsc > h->l2h->rh->ah->mtu) h->priv.tcl.fsc = h->l2h->rh->ah->mtu; 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; DEBUGP("This PICC supports NAD\n"); } if (*cur & 0x02) { h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED; DEBUGP("This PICC supports CID\n"); } 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); /* transceive (with CRC) */ ret = rfid_layer2_transceive(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("transceive 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]; /* FIXME: this stinks like hell. IF we reduce pps_response size to one, we'll get stack corruption! */ unsigned char pps_response[10]; 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; ppss[2] = 0x00; /* 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_transceive(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 (!is_s_block(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 */ if ((th->flags & TCL_HANDLE_F_NAD_USED) && is_i_block(pcb)) { /* 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_transceive(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; } struct fr_buff { unsigned int frame_len; /* length of frame */ unsigned int hdr_len; /* length of header within frame */ unsigned char data[RFID_MAX_FRAMELEN]; }; #define frb_payload(x) (x.data + x.hdr_len) /* RFID transceive buffer. */ struct rfid_xcvb { struct rfix_xcvb *next; /* next in queue of buffers */ u_int64_t timeout; /* timeout to wait for reply */ struct fr_buff tx; struct fr_buff rx; //struct rfid_protocol_handle *h; /* connection to which we belong */ }; struct tcl_tx_context { const unsigned char *tx; unsigned char *rx; const unsigned char *next_tx_byte; unsigned char *next_rx_byte; unsigned int rx_len; unsigned int tx_len; struct rfid_protocol_handle *h; }; #define tcl_ctx_todo(ctx) (ctx->tx_len - (ctx->next_tx_byte - ctx->tx)) static int tcl_refill_xcvb(struct rfid_xcvb *xcvb, struct tcl_tx_context *ctx) { struct tcl_handle *th = &ctx->h->priv.tcl; if (ctx->next_tx_byte >= ctx->tx + ctx->tx_len) { DEBUGP("tyring to refill tx xcvb but no data left!\n"); return -1; } if (tcl_build_prologue_i(th, xcvb->tx.data, &xcvb->tx.hdr_len) < 0) return -1; if (tcl_ctx_todo(ctx) > th->fsc - xcvb->tx.hdr_len) xcvb->tx.frame_len = max_net_tx_framesize(th); else xcvb->tx.frame_len = tcl_ctx_todo(ctx); memcpy(frb_payload(xcvb->tx), ctx->next_tx_byte, xcvb->tx.frame_len); ctx->next_tx_byte += xcvb->tx.frame_len; /* check whether we need to set the chaining bit */ if (ctx->next_tx_byte < ctx->tx + ctx->tx_len) xcvb->tx.data[0] |= 0x10; /* add hdr_len after copying the net payload */ xcvb->tx.frame_len += xcvb->tx.hdr_len; xcvb->timeout = th->fwt; return 0; } static void fill_xcvb_wtxm(struct tcl_handle *th, struct rfid_xcvb *xcvb, unsigned char inf) { /* Acknowledge WTXM */ tcl_build_prologue_s(th, xcvb->tx.data, &xcvb->tx.hdr_len); /* set two bits that make this block a wtx */ xcvb->tx.data[0] |= 0x30; xcvb->tx.data[xcvb->tx.hdr_len] = inf; xcvb->tx.frame_len = xcvb->tx.hdr_len+1; xcvb->timeout = th->fwt * inf; } static int check_cid(struct tcl_handle *th, struct rfid_xcvb *xcvb) { if (xcvb->rx.data[0] & TCL_PCB_CID_FOLLOWING) { if (xcvb->rx.data[1] != th->cid) { DEBUGP("CID %u is not valid, we expected %u\n", xcvb->rx.data[1], th->cid); return 0; } } return 1; } static int tcl_transceive(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; struct rfid_xcvb xcvb; struct tcl_tx_context tcl_ctx; struct tcl_handle *th = &h->priv.tcl; unsigned char ack[10]; unsigned int ack_len; /* initialize context */ tcl_ctx.next_tx_byte = tcl_ctx.tx = tx_data; tcl_ctx.next_rx_byte = tcl_ctx.rx = rx_data; tcl_ctx.rx_len = *rx_len; tcl_ctx.tx_len = tx_len; tcl_ctx.h = h; /* initialize xcvb */ xcvb.timeout = th->fwt; tx_refill: if (tcl_refill_xcvb(&xcvb, &tcl_ctx) < 0) { ret = -1; goto out; } do_tx: xcvb.rx.frame_len = sizeof(xcvb.rx.data); ret = rfid_layer2_transceive(h->l2h, l2_to_frame(h->l2h->l2->id), xcvb.tx.data, xcvb.tx.frame_len, xcvb.rx.data, &xcvb.rx.frame_len, xcvb.timeout, 0); DEBUGP("l2 transceive finished\n"); if (ret < 0) goto out; if (is_r_block(xcvb.rx.data[0])) { DEBUGP("R-Block\n"); if ((xcvb.rx.data[0] & 0x01) != h->priv.tcl.toggle) { DEBUGP("response with wrong toggle bit\n"); goto out; } /* Handle ACK frame in case of chaining */ if (!check_cid(th, &xcvb)) goto out; goto tx_refill; } else if (is_s_block(xcvb.rx.data[0])) { unsigned char inf; unsigned int prlg_len; DEBUGP("S-Block\n"); /* Handle Wait Time Extension */ if (!check_cid(th, &xcvb)) goto out; if (xcvb.rx.data[0] & TCL_PCB_CID_FOLLOWING) { if (xcvb.rx.frame_len < 3) { DEBUGP("S-Block with CID but short len\n"); ret = -1; goto out; } inf = xcvb.rx.data[2]; } else inf = xcvb.rx.data[1]; if ((xcvb.rx.data[0] & 0x30) != 0x30) { DEBUGP("S-Block but not WTX?\n"); ret = -1; goto out; } 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; } fill_xcvb_wtxm(th, &xcvb, inf); /* start over with next transceive */ goto do_tx; } else if (is_i_block(xcvb.rx.data[0])) { unsigned int net_payload_len; /* we're actually receiving payload data */ DEBUGP("I-Block: "); if ((xcvb.rx.data[0] & 0x01) != h->priv.tcl.toggle) { DEBUGP("response with wrong toggle bit\n"); goto out; } xcvb.rx.hdr_len = 1; if (!check_cid(th, &xcvb)) goto out; if (xcvb.rx.data[0] & TCL_PCB_CID_FOLLOWING) xcvb.rx.hdr_len++; if (xcvb.rx.data[0] & TCL_PCB_NAD_FOLLOWING) xcvb.rx.hdr_len++; net_payload_len = xcvb.rx.frame_len - xcvb.rx.hdr_len; DEBUGPC("%u bytes\n", net_payload_len); memcpy(tcl_ctx.next_rx_byte, &xcvb.rx.data[xcvb.rx.hdr_len], net_payload_len); tcl_ctx.next_rx_byte += net_payload_len; if (xcvb.rx.data[0] & 0x10) { /* we're not the last frame in the chain, continue rx */ DEBUGP("not the last frame in the chain, continue\n"); ack_len = sizeof(ack); tcl_build_prologue_r(th, xcvb.tx.data, &xcvb.tx.frame_len, 0); xcvb.timeout = th->fwt; goto do_tx; } } out: *rx_len = tcl_ctx.next_rx_byte - tcl_ctx.rx; 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_protocol_handle(sizeof(struct rfid_protocol_handle)); 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)); /* 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_protocol_handle(ph); return 0; } int tcl_getopt(struct rfid_protocol_handle *h, int optname, void *optval, unsigned int *optlen) { u_int8_t *opt_str = optval; switch (optname) { case RFID_OPT_P_TCL_ATS: if (h->priv.tcl.ats_len < *optlen) *optlen = h->priv.tcl.ats_len; memcpy(opt_str, h->priv.tcl.ats, *optlen); break; case RFID_OPT_P_TCL_ATS_LEN: if (*optlen < sizeof(u_int8_t)) return -E2BIG; *optlen = sizeof(u_int8_t); *opt_str = h->priv.tcl.ats_len & 0xff; break; default: return -EINVAL; } return 0; } int tcl_setopt(struct rfid_protocol_handle *h, int optname, const void *optval, unsigned int optlen) { int ret = -EINVAL; switch (optname) { default: break; } return ret; } const struct rfid_protocol rfid_protocol_tcl = { .id = RFID_PROTOCOL_TCL, .name = "ISO 14443-4 / T=CL", .fn = { .init = &tcl_init, .open = &tcl_connect, .transceive = &tcl_transceive, .close = &tcl_deselect, .fini = &tcl_fini, .getopt = &tcl_getopt, .setopt = &tcl_setopt, }, };