source: trunk/src/ifd/ifd-kaan.c @ 950

Revision 950, 26.7 KB checked in by aj, 5 years ago (diff)

work on lots of warnings, mostly things once declared with static and later without.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Driver for Kobil Kaan Professional and Telesec B1
3 *
4 * Copyright (C) 2003 Olaf Kirch <okir@suse.de>
5 * Copyright (C) 2003 Michael Haardt (B1 support)
6 */
7
8#include "internal.h"
9#include <sys/poll.h>
10#include <stdlib.h>
11#include <string.h>
12#include <time.h>
13#include <unistd.h>
14#include "ctbcs.h"
15
16/* Freeze after that many seconds of inactivity */
17#define FREEZE_DELAY            5
18
19enum {
20        TYPE_KAAN,
21        TYPE_B1
22};
23
24/*
25 * CT status
26 */
27typedef struct kaan_status {
28        int reader_type;
29        ifd_protocol_t *p;
30        time_t last_activity;
31        unsigned int frozen:1;
32        int icc_proto[OPENCT_MAX_SLOTS];
33} kaan_status_t;
34
35static int kaan_reset_ct(ifd_reader_t * reader);
36static int kaan_get_units(ifd_reader_t * reader);
37static int kaan_freeze(ifd_reader_t * reader);
38static int kaan_sync_detect(ifd_reader_t * reader, int nslot);
39static int kaan_set_protocol(ifd_reader_t *, int, int);
40static int __kaan_apdu_xcv(ifd_reader_t *,
41                           const unsigned char *, size_t,
42                           unsigned char *, size_t, time_t, int);
43static int kaan_get_tlv_from_file(ifd_reader_t *,
44                                  unsigned int, unsigned int,
45                                  unsigned char, unsigned char *, size_t);
46static int kaan_get_tlv(unsigned char *, size_t,
47                        unsigned char tag, unsigned char **ptr);
48static int kaan_select_file(ifd_reader_t *, unsigned char,
49                            unsigned int, size_t *);
50static int kaan_read_binary(ifd_reader_t *, unsigned char,
51                            unsigned int, unsigned char *, size_t);
52static int kaan_update_binary(ifd_reader_t *, unsigned char,
53                              unsigned int, const unsigned char *, size_t);
54static int kaan_check_sw(const char *, const unsigned char *, int);
55static int kaan_get_sw(const unsigned char *, unsigned int, unsigned short *);
56static int kaan_select_app(ifd_reader_t * reader, int nad,
57                           const void *, size_t);
58
59#define kaan_apdu_xcv(reader, sbuf, slen, rbug, rlen, timeout) \
60        __kaan_apdu_xcv(reader, sbuf, slen, rbug, rlen, timeout, 1)
61
62/*
63 * Initialize the device
64 */
65static int kaan_open(ifd_reader_t * reader, const char *device_name)
66{
67        kaan_status_t *st;
68        ifd_device_t *dev;
69        ifd_device_params_t params;
70        int r;
71
72        reader->name = "Kobil Kaan PRO";
73        reader->nslots = 1;
74
75        if (!(dev = ifd_device_open(device_name)))
76                return -1;
77
78        if (ifd_device_type(dev) == IFD_DEVICE_TYPE_SERIAL
79            && ifd_device_get_parameters(dev, &params) >= 0) {
80                /* The default configuration for Kobil serial
81                 * readers is 8E1 at 9600bps */
82                params.serial.bits = 8;
83                params.serial.parity = IFD_SERIAL_PARITY_EVEN;
84                params.serial.stopbits = 1;
85                ifd_device_set_parameters(dev, &params);
86        }
87        if (ifd_device_type(dev) == IFD_DEVICE_TYPE_USB) {
88                params = dev->settings;
89                params.usb.interface = 0;
90                if (ifd_device_set_parameters(dev, &params) < 0) {
91                        ct_error("kaan: setting parameters failed", device_name);
92                        ifd_device_close(dev);
93                        return -1;
94                }
95        }
96
97        reader->device = dev;
98        if ((st = (kaan_status_t *) calloc(1, sizeof(*st))) == NULL) {
99                ct_error("out of memory");
100                return IFD_ERROR_NO_MEMORY;
101        }
102        st->reader_type = TYPE_KAAN;
103        st->icc_proto[0] = -1;
104        st->icc_proto[1] = -1;
105
106        reader->driver_data = st;
107        if (!(st->p = ifd_protocol_new(IFD_PROTOCOL_T1, reader, 0x12))) {
108                /* Something is badly hosed */
109                ct_error("unable to get T1 protocol handler");
110                return IFD_ERROR_GENERIC;
111        }
112
113        /* Force a T=1 resync. We don't know what state the reader's
114         * T=1 engine is in. */
115        if ((r = ifd_protocol_resynchronize(st->p, 0x12)) < 0)
116                return r;
117
118        /* Reset the CT */
119        if ((r = kaan_reset_ct(reader)) < 0)
120                return r;
121
122        /* Get list of functional units */
123        if ((r = kaan_get_units(reader)) < 0)
124                return r;
125
126#if 0
127        /* Clear the display */
128        reader->ops->display(reader, "");
129#endif
130
131        return 0;
132}
133
134/*
135 * Initialize the device
136 */
137static int b1_open(ifd_reader_t * reader, const char *device_name)
138{
139        kaan_status_t *st;
140        ifd_device_t *dev;
141        ifd_device_params_t params;
142        unsigned long w;
143        int r;
144
145        reader->name = "DTAG/T-TeleSec B1 standard";
146        reader->nslots = 1;
147
148        if (!(dev = ifd_device_open(device_name)))
149                return -1;
150
151        if (ifd_device_type(dev) == IFD_DEVICE_TYPE_SERIAL) {
152                if (ifd_device_get_parameters(dev, &params) >= 0) {
153                        /* The default configuration for B1 serial
154                         * readers is 8E1 at 9600 bps */
155                        params.serial.bits = 8;
156                        params.serial.parity = IFD_SERIAL_PARITY_EVEN;
157                        params.serial.stopbits = 1;
158                        params.serial.dtr = 0;
159                        params.serial.rts = 0;
160                        ifd_device_set_parameters(dev, &params);
161                        /* wait 35+-15 = 50 ms for DSR low */
162                        poll((struct pollfd *)0, 0, 50);
163                        if (ifd_serial_get_dsr(dev))
164                                return -1;
165                        /* wait further 300 ms until setting DTR */
166                        poll((struct pollfd *)0, 0, 300);
167                        /* set DTR */
168                        params.serial.dtr = 1;
169                        ifd_device_set_parameters(dev, &params);
170                        /* wait until DSR is set, which may take up to 5 s (typically 0.8 s) */
171                        for (w = 0; w <= 5000; w += 210) {
172                                poll((struct pollfd *)0, 0, 210);
173                                if (ifd_serial_get_dsr(dev))
174                                        break;
175                        }
176                        if (w > 5000)
177                                return -1;
178                } else
179                        return -1;
180        }
181
182        reader->device = dev;
183        if ((st = (kaan_status_t *) calloc(1, sizeof(*st))) == NULL) {
184                ct_error("out of memory");
185                return IFD_ERROR_NO_MEMORY;
186        }
187        st->reader_type = TYPE_B1;
188        st->icc_proto[0] = -1;
189        st->icc_proto[1] = -1;
190
191        reader->driver_data = st;
192        if (!(st->p = ifd_protocol_new(IFD_PROTOCOL_T1, reader, 0x12))) {
193                ct_error("unable to get T1 protocol handler");
194                return IFD_ERROR_GENERIC;
195        }
196
197        /* Reset the CT */
198        if ((r = kaan_reset_ct(reader)) < 0)
199                return r;
200
201        /* Get list of functional units */
202        if ((r = kaan_get_units(reader)) < 0)
203                return r;
204
205        return 0;
206}
207
208/*
209 * Reset the card reader
210 */
211static int kaan_reset_ct(ifd_reader_t * reader)
212{
213        unsigned char cmd1[] = { 0x20, 0x10, 0x00, 0x00 };
214        unsigned char cmd2[] = { 0x20, 0x11, 0x00, 0x00 };
215        unsigned char resp[2];
216        int rc;
217        unsigned short sw;
218
219        if ((rc =
220             kaan_apdu_xcv(reader, cmd1, sizeof(cmd1), resp, sizeof(resp),
221                           0)) < 0) {
222                ct_error("kaan_reset_ct: %s", ct_strerror(rc));
223                return rc;
224        }
225        ifd_debug(1, "kaan_reset_ct: rc=%d", rc);
226        if ((rc = kaan_get_sw(resp, rc, &sw)) < 0)
227                return rc;
228        if (sw == 0x6b00) {
229                /* Reset for older readers */
230                if ((rc =
231                     kaan_apdu_xcv(reader, cmd2, sizeof(cmd2), resp,
232                                   sizeof(resp), 0)) < 0) {
233                        ct_error("kaan_reset_ct: %s", ct_strerror(rc));
234                        return rc;
235                }
236                if ((rc = kaan_get_sw(resp, rc, &sw)) < 0)
237                        return rc;
238        }
239        if (sw != 0x9000) {
240                ct_error("kaan_reset_ct: failure, status code %04X", sw);
241                return IFD_ERROR_COMM_ERROR;
242        }
243        return rc;
244}
245
246/*
247 * Get functional units
248 */
249static int kaan_get_units(ifd_reader_t * reader)
250{
251        unsigned char cmd[] = { 0x20, 0x13, 0x00, 0x81, 0x00 };
252        unsigned char buffer[16], *units;
253        int rc, n;
254        unsigned short sw;
255
256        reader->slot[0].dad = 0x02;
257        if ((rc =
258             kaan_apdu_xcv(reader, cmd, sizeof(cmd), buffer, sizeof(buffer),
259                           0)) < 0) {
260                ct_error("kaan_get_units: %s", ct_strerror(rc));
261                return rc;
262        }
263        if ((rc = kaan_get_sw(buffer, rc, &sw)) < 0)
264                return rc;
265        if (sw != 0x9000) {
266                return 0;
267        }
268        if ((n = kaan_get_tlv(buffer, rc, 0x81, &units)) < 0)
269                return 0;
270
271        while (n--) {
272                switch (units[n]) {
273                case 0x01:      /* ICC1 */
274                        break;
275                case 0x02:      /* ICC2 */
276                        reader->slot[1].dad = 0x32;
277                        reader->nslots = 2;
278                        break;
279                case 0x40:      /* Display */
280                        reader->flags |= IFD_READER_KEYPAD;
281                        break;
282                case 0x50:      /* Display */
283                        reader->flags |= IFD_READER_DISPLAY;
284                        break;
285                }
286        }
287
288        return 0;
289}
290
291/*
292 * Power up the reader
293 */
294static int kaan_activate(ifd_reader_t * reader)
295{
296        ifd_debug(1, "called.");
297        return 0;
298}
299
300static int kaan_deactivate(ifd_reader_t * reader)
301{
302        ifd_debug(1, "called.");
303        return 0;
304}
305
306/*
307 * Get the card status
308 */
309static int kaan_card_status(ifd_reader_t * reader, int slot, int *status)
310{
311        kaan_status_t *st = (kaan_status_t *) reader->driver_data;
312        unsigned char buffer[16] = { 0x20, 0x13, 0x00, 0x80, 0x00 };
313        unsigned char *byte;
314        int rc, n;
315
316        buffer[2] = slot + 1;
317        ifd_debug(1, "slot=%d", slot);
318        if (!st->frozen && st->last_activity + FREEZE_DELAY < time(NULL)
319            && ifd_device_type(reader->device) == IFD_DEVICE_TYPE_SERIAL) {
320                if ((rc = kaan_freeze(reader)) < 0)
321                        return rc;
322                usleep(10000);
323                st->frozen = 1;
324        }
325
326        if (st->frozen) {
327                /* Get the DSR status */
328                if (!ifd_serial_get_dsr(reader->device)) {
329                        *status = reader->slot[slot].status;
330                        return 0;
331                }
332
333                /* Activity detected - go on an get status */
334                st->last_activity = time(NULL);
335                st->frozen = 0;
336        }
337
338        rc = __kaan_apdu_xcv(reader, buffer, 5, buffer, sizeof(buffer), 0, 0);
339        if ((rc = kaan_check_sw("kaan_card_status", buffer, rc)) < 0)
340                return rc;
341        if (buffer[0] == 0x80) {
342                if ((n = kaan_get_tlv(buffer, rc, 0x80, &byte)) >= 0) {
343                        if (*byte & 0x01)
344                                *status |= IFD_CARD_PRESENT;
345                }
346        } else /* older implementations may return only value part */
347    if (buffer[0] & 0x01)
348                *status |= IFD_CARD_PRESENT;
349        return 0;
350}
351
352/*
353 * Get the card status
354 */
355static int b1_card_status(ifd_reader_t * reader, int slot, int *status)
356{
357        kaan_status_t *st = (kaan_status_t *) reader->driver_data;
358        unsigned char buffer[16];
359        int rc;
360
361        buffer[2] = slot + 1;
362        ifd_debug(1, "slot=%d", slot);
363        if (!st->frozen && st->last_activity + FREEZE_DELAY < time(NULL)
364            && ifd_device_type(reader->device) == IFD_DEVICE_TYPE_SERIAL) {
365                if ((rc = kaan_freeze(reader)) < 0)
366                        return rc;
367                usleep(10000);
368                st->frozen = 1;
369        }
370
371        if (st->frozen) {
372                /* Get the DSR status */
373                if (!ifd_serial_get_dsr(reader->device)) {
374                        *status = reader->slot[slot].status;
375                        return 0;
376                }
377
378                /* Activity detected - go on an get status */
379                st->last_activity = time(NULL);
380                st->frozen = 0;
381        }
382
383        rc = kaan_get_tlv_from_file(reader,
384                                    0x7F70 | (slot),
385                                    0x7021 | (slot << 8), 0x21, buffer, 1);
386        if (rc < 0)
387                return rc;
388
389        ct_error("buffer[0] = %i\n", buffer[0] );
390        if (buffer[0]) {
391                *status |= IFD_CARD_PRESENT;
392        }
393        return 0;
394}
395
396/*
397 * Send the Freeze command to the reader
398 */
399static int kaan_freeze(ifd_reader_t * reader)
400{
401        unsigned char freeze[16] = { 0x80, 0x70, 0x00, 0x00, 0x00, 0x30, 00 };
402        unsigned int m, n;
403        int rc;
404
405        ifd_debug(1, "trying to freeze reader");
406        for (n = 0, m = 7; n < reader->nslots; n++, m++) {
407                freeze[m] = n + 1;
408                if (reader->slot[n].status != 0)
409                        freeze[m] |= 0x02;
410        }
411        freeze[6] = n;
412        freeze[4] = n + 2;
413
414        rc = __kaan_apdu_xcv(reader, freeze, m, freeze, sizeof(freeze), 0, 0);
415        return kaan_check_sw("kaan_card_freeze", freeze, rc);
416}
417
418/*
419 * Common code for card_reset and card_request
420 */
421static int kaan_do_reset(ifd_reader_t * reader, int nslot,
422                         const unsigned char *cmd, size_t cmd_len,
423                         unsigned char *atr, size_t atr_len,
424                         unsigned int timeout)
425{
426        kaan_status_t *st = (kaan_status_t *) reader->driver_data;
427        unsigned char buffer[64];
428        unsigned short sw;
429        size_t got;
430        int rc;
431
432        st->icc_proto[nslot] = -1;
433        if ((rc =
434             kaan_apdu_xcv(reader, cmd, cmd_len, buffer, sizeof(buffer),
435                           timeout)) < 0)
436                return rc;
437
438        if ((rc = kaan_get_sw(buffer, rc, &sw)) < 0)
439                return rc;
440
441        if ((got = rc) > atr_len)
442                got = atr_len;
443
444        switch (sw) {
445        case 0x9000:
446        case 0x62a6:
447                /* Synchronous ICC, CT has already done everything we need
448                 * to know. Now just get the info from the CT. */
449                memcpy(atr, buffer, got);
450                if ((rc = kaan_sync_detect(reader, nslot)) < 0)
451                        return rc;
452
453                if (got == 4 && st->reader_type == TYPE_B1) {
454                        /* Try to select KVK file.  This is required for
455                         * B1 readers and failure is ignored.
456                         */
457                        static unsigned char aid[] =
458                            { 0xd2, 0x80, 0x00, 0x00, 0x01, 0x01 };
459                        kaan_select_app(reader, 0x02, aid, sizeof(aid));
460                }
461                break;
462        case 0x62a5:
463                /* ATR was read, but protocol is unknown.  B1 readers */
464                /* use that for phone cards, because their size can not */
465                /* automatically be detected.  Chose the largest possible */
466                /* size. */
467                memcpy(atr, buffer, got);
468                if (got == 4 && st->reader_type == TYPE_B1)
469                        kaan_set_protocol(reader, nslot, IFD_PROTOCOL_EUROCHIP);
470                if ((rc = kaan_sync_detect(reader, nslot)) < 0)
471                        return rc;
472                break;
473        case 0x9001:
474                /* asynchronous ICC, just copy the ATR */
475                memcpy(atr, buffer, got);
476                break;
477        case 0x62a7:
478                /* synchronous ICC, unknown proto - try to detect
479                 * the standard way */
480                return ifd_sync_detect_icc(reader, nslot, atr, atr_len);
481        default:
482                ifd_debug(1, "kaan_card_reset: unable to reset card, sw=0x%04x",
483                          sw);
484                return IFD_ERROR_COMM_ERROR;
485        }
486
487        return got;
488}
489
490/*
491 * Reset card and get ATR
492 */
493static int kaan_card_reset(ifd_reader_t * reader, int nslot, void *result,
494                           size_t size)
495{
496        unsigned char cmd[5] = { 0x20, 0x10, 0x00, 0x01, 0x00 };
497
498        cmd[2] = nslot + 1;
499        ifd_debug(1, "called.");
500        return kaan_do_reset(reader, nslot, cmd, 5, (unsigned char *)result,
501                             size, 0);
502}
503
504/*
505 * Request ICC
506 */
507static int kaan_card_request(ifd_reader_t * reader, int slot, time_t timeout,
508                             const char *message, void *atr, size_t atr_len)
509{
510        ct_buf_t buf;
511        unsigned char buffer[256] = { 0x20, 0x17, 0x00, 0x01, 0x00 };
512        int n;
513
514        buffer[2] = slot + 1;
515        /* Build the APDU, which is basically a modified CTBCS OUTPUT command */
516        ct_buf_init(&buf, buffer, sizeof(buffer) - 1);
517        ctbcs_begin(&buf, 0x17, slot + 1, 0x01);
518        ctbcs_add_timeout(&buf, timeout);
519        ctbcs_add_message(&buf, message);
520        if ((n = ctbcs_finish(&buf)) < 0)
521                return n;
522        buffer[n++] = 0x00;
523
524        return kaan_do_reset(reader, slot, buffer, n, (unsigned char *)atr,
525                             atr_len, timeout);
526}
527
528/*
529 * Select a protocol for communication with the ICC.
530 * Note that we continue to communicate with the terminal
531 * using T=1; internally, the terminal talks to the
532 * card using whatever protocol we selected.
533 */
534static int kaan_set_protocol(ifd_reader_t * reader, int nslot, int proto)
535{
536        kaan_status_t *st = (kaan_status_t *) reader->driver_data;
537        unsigned char cmd[] =
538            { 0x80, 0x60, 0x00, 0x00, 0x03, 0x22, 0x01, 0x00 };
539        unsigned char buffer[2];
540        unsigned short sw;
541        ifd_slot_t *slot;
542        int rc;
543
544        cmd[2] = nslot + 1;
545        ifd_debug(1, "proto=%d", proto);
546
547        switch (proto) {
548        case IFD_PROTOCOL_T0:
549                cmd[7] = 0x01;
550                break;
551        case IFD_PROTOCOL_T1:
552                cmd[7] = 0x02;
553                break;
554        case IFD_PROTOCOL_I2C_SHORT:
555                cmd[7] = 0x80;
556                break;
557        case IFD_PROTOCOL_I2C_LONG:
558                cmd[7] = 0x80;
559                break;
560        case IFD_PROTOCOL_3WIRE:
561                cmd[7] = 0x81;
562                break;
563        case IFD_PROTOCOL_2WIRE:
564                cmd[7] = 0x82;
565                break;
566        case IFD_PROTOCOL_EUROCHIP:
567                cmd[7] = 0x93;
568                break;
569        default:
570                ifd_debug(1, "kaan_set_protocol: protocol %d not supported",
571                          proto);
572                return -1;
573        }
574
575        if ((rc =
576             kaan_apdu_xcv(reader, cmd, sizeof(cmd), buffer, sizeof(buffer),
577                           0)) < 0 || (rc = kaan_get_sw(buffer, rc, &sw)) < 0)
578                return rc;
579        /* B1 returns 6985 for German KVK health care cards */
580        if (sw != 0x9000 && sw != 0x6985) {
581                ifd_debug(1,
582                          "kaan_set_protocol: protocol %d not supported, sw=%04hx",
583                          proto, sw);
584                return -1;
585        }
586
587        slot = &reader->slot[nslot];
588        slot->proto = ifd_protocol_new(IFD_PROTOCOL_TRANSPARENT,
589                                       reader, slot->dad);
590        if (slot->proto == NULL) {
591                ct_error("%s: internal error", reader->name);
592                return -1;
593        }
594
595        st->icc_proto[nslot] = proto;
596        return 0;
597}
598
599/*
600 * APDU exchange with ICC
601 */
602static int kaan_transparent(ifd_reader_t * reader, int dad, const void *sbuf,
603                            size_t slen, void *rbuf, size_t rlen)
604{
605        kaan_status_t *st = (kaan_status_t *) reader->driver_data;
606        ifd_iso_apdu_t iso;
607        int rc, nslot, n, prot;
608
609        nslot = (dad == 0x02) ? 0 : 1;
610        prot = st->icc_proto[nslot];
611
612        /* Parse the APDU; extract class byte, case, etc */
613        if ((rc = ifd_iso_apdu_parse(sbuf, slen, &iso)) < 0)
614                return rc;
615
616        if (prot == IFD_PROTOCOL_T0) {
617                if (iso.cse == IFD_APDU_CASE_4S)
618                        slen--;
619        }
620
621        n = ifd_protocol_transceive(st->p, dad, sbuf, slen, rbuf, rlen);
622
623        if (iso.cse == IFD_APDU_CASE_4S && n == 2) {
624                unsigned char cmd[5], *sw;
625
626                sw = (unsigned char *)rbuf;
627                if (sw[0] == 0x61) {
628                        cmd[0] = iso.cla;
629                        cmd[1] = 0xC0;
630                        cmd[2] = 0x00;
631                        cmd[3] = 0x00;
632                        cmd[4] = sw[1];
633
634                        n = ifd_protocol_transceive(st->p, dad,
635                                                    cmd, 5, rbuf, rlen);
636                }
637        }
638
639        if (n < 0)
640                return n;
641        if (n < 2) {
642                ct_error("kaan: T=1 protocol failure, not enough bytes for SW");
643                return IFD_ERROR_COMM_ERROR;
644        }
645
646        return n;
647}
648
649/*
650 * Output a string to the display
651 */
652static int kaan_display(ifd_reader_t * reader, const char *string)
653{
654        unsigned char buffer[256] = { 0x20, 0x17, 0x40, 00 };
655        int rc, n;
656
657        if (!(reader->flags & IFD_READER_DISPLAY))
658                return 0;
659
660        n = ctbcs_build_output(buffer, sizeof(buffer), string);
661        if (n < 0)
662                return n;
663
664        rc = kaan_apdu_xcv(reader, buffer, n, buffer, sizeof(buffer), 0);
665        return kaan_check_sw("kaan_display", buffer, rc);
666}
667
668/*
669 * Perform a PIN verification
670 */
671static int kaan_perform_verify(ifd_reader_t * reader, int nslot,
672                               unsigned int timeout, const char *prompt,
673                               const unsigned char *data, size_t data_len,
674                               unsigned char *resp, size_t resp_len)
675{
676        unsigned char buffer[256];
677        int n;
678        unsigned short sw;
679
680        if (!(reader->flags & IFD_READER_KEYPAD))
681                return 0;
682
683        n = ctbcs_build_perform_verify_apdu(buffer, sizeof(buffer),
684                                            nslot + 1, prompt, timeout,
685                                            data, data_len);
686        if (n < 0)
687                return n;
688
689        n = kaan_apdu_xcv(reader, buffer, n, resp, resp_len, 0);
690        if (n < 0) {
691                ct_error("perform_verify failed: %s", ct_strerror(n));
692                return n;
693        }
694        if ((n = kaan_get_sw(resp, n, &sw)) < 0)
695                return n;
696
697        switch (sw) {
698        case 0x6400:
699                ct_error("perform_verify failed: timeout");
700                return IFD_ERROR_USER_TIMEOUT;
701        case 0x6401:
702                ct_error("perform_verify failed: user pressed cancel");
703                return IFD_ERROR_USER_ABORT;
704        case 0x6402:
705                ct_error("perform_verify failed: PIN mismatch");
706                return IFD_ERROR_PIN_MISMATCH;
707        }
708
709        return 2;
710}
711
712/*
713 * Read from synchronous ICC
714 */
715static int kaan_sync_read(ifd_reader_t * reader, int slot, int proto,
716                          unsigned short addr, unsigned char *data, size_t len)
717{
718        kaan_status_t *st = (kaan_status_t *) reader->driver_data;
719        int r;
720
721        ifd_debug(1, "called, addr=0x%04x, len=%u", addr, len);
722
723        if (st->icc_proto[slot] != proto) {
724                r = kaan_set_protocol(reader, slot, proto);
725                if (r < 0)
726                        return r;
727        }
728
729        return kaan_read_binary(reader, reader->slot[slot].dad, addr, data,
730                                len);
731}
732
733static int kaan_sync_write(ifd_reader_t * reader, int slot, int proto,
734                           unsigned short addr, const unsigned char *buffer,
735                           size_t len)
736{
737        kaan_status_t *st = (kaan_status_t *) reader->driver_data;
738        int r;
739
740        ifd_debug(1, "called, addr=0x%04x, len=%u", addr, len);
741
742        if (st->icc_proto[slot] != proto) {
743                r = kaan_set_protocol(reader, slot, proto);
744                if (r < 0)
745                        return r;
746        }
747
748        return kaan_update_binary(reader, reader->slot[slot].dad,
749                                  addr, buffer, len);
750}
751
752/*
753 * Detect type and size of synchronous card.
754 * When we get here, the CT has done most of the work for us
755 * already, we just need to get the information from it.
756 *
757 * XXX - there does not seem to be a way to find out the size
758 * of the card, so we have to resort to poking around the
759 * card.
760 */
761static int kaan_sync_detect(ifd_reader_t * reader, int nslot)
762{
763        kaan_status_t *st = (kaan_status_t *) reader->driver_data;
764        ifd_slot_t *slot = &reader->slot[nslot];
765        unsigned char protocol;
766        int rc;
767
768        rc = kaan_get_tlv_from_file(reader,
769                                    0x7F70 | nslot,
770                                    0x7021 | (nslot << 8), 0x22, &protocol, 1);
771        if (rc < 0)
772                return rc;
773
774        switch (protocol) {
775        case 0x80:
776                protocol = IFD_PROTOCOL_I2C_LONG;
777                break;
778        case 0x81:
779                protocol = IFD_PROTOCOL_3WIRE;
780                break;
781        case 0x82:
782                protocol = IFD_PROTOCOL_2WIRE;
783                break;
784        case 0x90:
785        case 0x91:
786        case 0x92:
787        case 0x93:
788                protocol = IFD_PROTOCOL_EUROCHIP;
789                break;
790        default:
791                ct_error("kaan_sync_detect: unknown card protocol 0x%x",
792                         protocol);
793                return IFD_ERROR_NOT_SUPPORTED;
794        }
795
796        slot->proto = ifd_protocol_new(protocol, reader, slot->dad);
797        st->icc_proto[nslot] = protocol;
798
799        return 0;
800}
801
802/*
803 * Read from config/status file
804 */
805static int kaan_get_tlv_from_file(ifd_reader_t * reader, unsigned int df_id,
806                           unsigned int ef_id, unsigned char tag,
807                           unsigned char *data, size_t len)
808{
809        unsigned char buffer[256 + 2], *ptr;
810        size_t size;
811        int rc;
812
813        if ((rc = kaan_select_file(reader, 0x12, 0x3F00, &size)) < 0
814            || (rc = kaan_select_file(reader, 0x12, df_id, &size)) < 0
815            || (rc = kaan_select_file(reader, 0x12, ef_id, &size)) < 0)
816                return rc;
817        if (size > 256)
818                size = 256;
819        if ((rc = kaan_read_binary(reader, 0x12, 0, buffer, 256)) < 0)
820                return rc;
821
822        if ((rc = kaan_get_tlv(buffer, rc, tag, &ptr)) < 0)
823                return rc;
824        if ((size_t) rc > len)
825                rc = len;
826        memcpy(data, ptr, rc);
827        return rc;
828}
829
830/*
831 * Stuff to interface with the Kaan's internal file system
832 */
833static int kaan_select_file(ifd_reader_t * reader, unsigned char nad,
834                     unsigned int fid, size_t * sizep)
835{
836        unsigned char cmd[] = { 0x00, 0xa4, 0x00, 0x00, 2, 0x00, 0x00 };
837        unsigned char resp[64];
838        int r;
839
840        ifd_debug(1, "called, fid=0x%04x", fid);
841
842        cmd[5] = fid >> 8;
843        cmd[6] = fid & 0xFF;
844
845        r = kaan_transparent(reader, nad, cmd, sizeof(cmd), resp, sizeof(resp));
846        if (r < 0)
847                return r;
848        if ((r = kaan_check_sw("kaan_select_file", resp, r)) < 0)
849                return r;
850
851        if (sizep)
852                *sizep = (resp[0] << 8) | resp[1];
853
854        return 0;
855}
856
857static int kaan_select_app(ifd_reader_t * reader, int nad, const void *aid,
858                                size_t len)
859{
860        unsigned char cmd[32] = { 0x00, 0xa4, 0x04, 0x00 };
861        unsigned char resp[64];
862        int r;
863
864        if (len > sizeof(cmd) - 5)
865                return IFD_ERROR_BUFFER_TOO_SMALL;
866
867        cmd[4] = len;
868        memcpy(cmd + 5, aid, len);
869
870        r = kaan_transparent(reader, nad, cmd, len + 5, resp, sizeof(resp));
871        if (r < 0)
872                return r;
873        return kaan_check_sw("kaan_select_app", resp, r);
874}
875
876static int kaan_read_binary(ifd_reader_t * reader, unsigned char nad,
877                     unsigned int offset, unsigned char *data, size_t len)
878{
879        unsigned char cmd[] = { 0x00, 0xB0, 0x00, 0x00, 0x00 };
880        unsigned char buffer[258];
881        size_t count, total = 0, got;
882        unsigned short sw;
883        int r;
884
885        ifd_debug(1, "called, offset=0x%04x, len=%u", offset, len);
886        while (total < len) {
887                if ((count = len) > 256)
888                        count = 256;
889                cmd[2] = offset >> 8;
890                cmd[3] = offset & 0xFF;
891                cmd[4] = count;
892
893                r = kaan_transparent(reader, nad, cmd, sizeof(cmd), buffer,
894                                     sizeof(buffer));
895                if (r < 0)
896                        return r;
897                got = r - 2;
898
899                if ((r = kaan_get_sw(buffer, r, &sw)) < 0)
900                        return r;
901
902                switch (sw) {
903                case 0x6B00:    /* offset outside of file */
904                        goto done;
905                case 0x9000:
906                case 0x6282:    /* EOF reached */
907                        memcpy(data + total, buffer, got);
908                        offset += got;
909                        total += got;
910                        break;
911                default:
912                        ct_error("kaan_read_binary: "
913                                 "failure, status code %04X", sw);
914                        return IFD_ERROR_COMM_ERROR;
915                }
916
917                /* end of file? */
918                if (got == 0 || sw == 0x6282)
919                        break;
920        }
921
922      done:
923        return total;
924}
925
926static int kaan_update_binary(ifd_reader_t * reader, unsigned char nad,
927                       unsigned int offset, const unsigned char *data,
928                       size_t len)
929{
930        unsigned char cmd[256 + 5] = { 0x00, 0xD0, 0x00, 0x00, 0x00 };
931        unsigned char resp[2];
932        size_t count, total = 0;
933        int r;
934
935        ifd_debug(2, "called, offset=0x%04x, len=%u", offset, len);
936        while (total < len) {
937                if ((count = len) > 256)
938                        count = 256;
939                cmd[2] = offset >> 8;
940                cmd[3] = offset & 0xFF;
941                cmd[4] = count;
942                memcpy(cmd + 5, data + total, count);
943
944                r = kaan_transparent(reader, nad, cmd, 5 + count, resp,
945                                     sizeof(resp));
946                if (r < 0)
947                        return r;
948                if ((r = kaan_check_sw("kaan_update_binary", resp, r)) < 0)
949                        return r;
950
951                if (r == 0)
952                        break;
953
954                offset += r;
955                total += r;
956        }
957
958        return total;
959}
960
961/*
962 * APDU exchange with terminal
963 */
964static int __kaan_apdu_xcv(ifd_reader_t * reader, const unsigned char *sbuf,
965                    size_t slen, unsigned char *rbuf, size_t rlen,
966                    time_t timeout, int activity)
967{
968        kaan_status_t *st = (kaan_status_t *) reader->driver_data;
969        long orig_timeout = 0;
970        int rc;
971
972        /* Override timeout if needed */
973        if (timeout) {
974                ifd_protocol_get_parameter(st->p,
975                                           IFD_PROTOCOL_RECV_TIMEOUT,
976                                           &orig_timeout);
977                ifd_protocol_set_parameter(st->p,
978                                           IFD_PROTOCOL_RECV_TIMEOUT,
979                                           timeout * 1000);
980        }
981
982        rc = ifd_protocol_transceive(st->p, 0x12, sbuf, slen, rbuf, rlen);
983        if (rc < 0)
984                return rc;
985        if (rc < 2) {
986                ct_error("kaan: T=1 protocol failure, rc=%d", rc);
987                rc = IFD_ERROR_COMM_ERROR;
988        }
989
990        if (timeout) {
991                ifd_protocol_set_parameter(st->p,
992                                           IFD_PROTOCOL_RECV_TIMEOUT,
993                                           orig_timeout);
994        }
995
996        if (activity) {
997                st->last_activity = time(NULL);
998                st->frozen = 0;
999        }
1000
1001        return rc;
1002}
1003
1004/*
1005 * Check status word returned by Kaan
1006 */
1007static int kaan_check_sw(const char *msg, const unsigned char *buf, int rc)
1008{
1009        unsigned short sw;
1010
1011        if (rc < 0) {
1012                ct_error("%s: %s", msg, ct_strerror(rc));
1013        } else if ((rc = kaan_get_sw(buf, rc, &sw)) >= 0) {
1014                if (sw != 0x9000) {
1015                        ct_error("%s: failure, status code %04X", msg, sw);
1016                        rc = IFD_ERROR_COMM_ERROR;
1017                }
1018        }
1019        return rc;
1020}
1021
1022static int kaan_get_sw(const unsigned char *buf, unsigned int n,
1023                                unsigned short *sw)
1024{
1025        if (n < 2) {
1026                ifd_debug(1, "response too short (%d bytes)", n);
1027                return IFD_ERROR_COMM_ERROR;
1028        }
1029
1030        n -= 2;
1031        *sw = (buf[n] << 8) | buf[n + 1];
1032        return n;
1033}
1034
1035/*
1036 * Send/receive T=1 apdu
1037 * This is just for the communication with the card reader.
1038 */
1039static int kaan_send(ifd_reader_t * reader, unsigned int dad,
1040                     const unsigned char *buffer, size_t len)
1041{
1042        return ifd_device_send(reader->device, buffer, len);
1043}
1044
1045static int kaan_recv(ifd_reader_t * reader, unsigned int dad,
1046                     unsigned char *buffer, size_t len, long timeout)
1047{
1048        return ifd_device_recv(reader->device, buffer, len, timeout);
1049}
1050
1051/*
1052 * Extract data from TLV encoded result.
1053 * The length is encoded as a single byte in the range 0 to 254.
1054 * A value of 255 means a big endian two byte length value follows.
1055 */
1056static int kaan_get_tlv(unsigned char *buf, size_t len, unsigned char tag,
1057                 unsigned char **res)
1058{
1059        unsigned char *p = buf;
1060        unsigned int n;
1061
1062        n = len;
1063        while (n >= 2) {
1064                len = p[1];
1065                if (len + 2 > n)
1066                        break;
1067                if (p[0] == tag) {
1068                        *res = p + 2;
1069                        return len;
1070                }
1071                p += len + 2;
1072                n -= len + 2;
1073        }
1074        return -1;
1075}
1076
1077/*
1078 * Driver operations
1079 */
1080static struct ifd_driver_ops kaan_driver, b1_driver;
1081
1082/*
1083 * Initialize this module
1084 */
1085void ifd_kaan_register(void)
1086{
1087        kaan_driver.open = kaan_open;
1088        kaan_driver.activate = kaan_activate;
1089        kaan_driver.deactivate = kaan_deactivate;
1090        kaan_driver.card_status = kaan_card_status;
1091        kaan_driver.card_reset = kaan_card_reset;
1092        kaan_driver.card_request = kaan_card_request;
1093        kaan_driver.output = kaan_display;
1094        kaan_driver.perform_verify = kaan_perform_verify;
1095        kaan_driver.send = kaan_send;
1096        kaan_driver.recv = kaan_recv;
1097        kaan_driver.set_protocol = kaan_set_protocol;
1098        kaan_driver.transparent = kaan_transparent;
1099        kaan_driver.sync_read = kaan_sync_read;
1100        kaan_driver.sync_write = kaan_sync_write;
1101
1102        b1_driver.open = b1_open;
1103        b1_driver.activate = kaan_activate;
1104        b1_driver.deactivate = kaan_deactivate;
1105        b1_driver.card_status = b1_card_status;
1106        b1_driver.card_reset = kaan_card_reset;
1107        b1_driver.card_request = kaan_card_request;
1108        b1_driver.output = kaan_display;
1109        b1_driver.perform_verify = kaan_perform_verify;
1110        b1_driver.send = kaan_send;
1111        b1_driver.recv = kaan_recv;
1112        b1_driver.set_protocol = kaan_set_protocol;
1113        b1_driver.transparent = kaan_transparent;
1114        b1_driver.sync_read = kaan_sync_read;
1115        b1_driver.sync_write = kaan_sync_write;
1116
1117        ifd_driver_register("kaan", &kaan_driver);
1118        ifd_driver_register("b1", &b1_driver);
1119}
Note: See TracBrowser for help on using the repository browser.