source: trunk/src/ifd/reader.c @ 1137

Revision 1137, 14.7 KB checked in by alonbl, 3 years ago (diff)

Allow driver to specify events to poll

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * IFD reader
3 *
4 * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
5 */
6
7#include "internal.h"
8#include <stdlib.h>
9#include <string.h>
10#include <signal.h>
11#include <time.h>
12
13static int ifd_recv_atr(ifd_device_t *, ct_buf_t *, unsigned int, int);
14
15/*
16 * Initialize a reader and open the device
17 */
18ifd_reader_t *ifd_open(const char *driver_name, const char *device_name)
19{
20        const ifd_driver_t *driver;
21        ifd_reader_t *reader;
22
23        ifd_debug(1, "trying to open %s@%s", driver_name, device_name);
24        driver = ifd_driver_get(driver_name);
25        if (driver == NULL) {
26                ct_error("%s: driver not available", driver_name);
27                return NULL;
28        }
29
30        reader = (ifd_reader_t *) calloc(1, sizeof(*reader));
31        if (!reader) {
32                ct_error("out of memory");
33                return NULL;
34        }
35        reader->driver = driver;
36
37        if (driver->ops->open && driver->ops->open(reader, device_name) < 0) {
38                ct_error("%s: initialization failed (driver %s)",
39                         device_name, driver->name);
40                free(reader);
41                return NULL;
42        }
43
44        return reader;
45}
46
47/*
48 * Select a different protocol for this reader
49 */
50int ifd_set_protocol(ifd_reader_t * reader, unsigned int idx, int prot)
51{
52        const ifd_driver_t *drv = reader->driver;
53        ifd_slot_t *slot;
54        ifd_protocol_t *p;
55
56        if (idx > reader->nslots)
57                return -1;
58
59        if (drv && drv->ops && drv->ops->set_protocol)
60                return drv->ops->set_protocol(reader, idx, prot);
61
62        if (drv && drv->ops && prot == IFD_PROTOCOL_DEFAULT)
63                prot = drv->ops->default_protocol;
64
65        slot = &reader->slot[idx];
66        if (slot->proto && slot->proto->ops->id == prot)
67                return 0;
68
69        if (!(p = ifd_protocol_new(prot, reader, slot->dad)))
70                return -1;
71
72        if (slot->proto) {
73                ifd_protocol_free(slot->proto);
74                slot->proto = NULL;
75        }
76
77        slot->proto = p;
78        return 0;
79}
80
81#if 0
82/*
83 * Set the serial speed at which we communicate with the
84 * reader
85 */
86int ifd_set_speed(ifd_reader_t * reader, unsigned int speed)
87{
88        const ifd_driver_t *drv = reader->driver;
89        int rc = 0;
90
91        if (drv && drv->ops && drv->ops->change_speed)
92                rc = drv->ops->change_speed(reader, speed);
93        else
94                rc = IFD_ERROR_NOT_SUPPORTED;
95        return rc;
96}
97#endif
98
99/*
100 * Activate/Deactivate the reader
101 */
102int ifd_activate(ifd_reader_t * reader)
103{
104        const ifd_driver_t *drv = reader->driver;
105        int rc = 0;
106
107        if (drv && drv->ops && drv->ops->activate)
108                rc = drv->ops->activate(reader);
109        reader->flags |= IFD_READER_ACTIVE;
110        return rc;
111}
112
113int ifd_deactivate(ifd_reader_t * reader)
114{
115        const ifd_driver_t *drv = reader->driver;
116        int rc = 0;
117
118        if (drv && drv->ops && drv->ops->deactivate)
119                rc = drv->ops->deactivate(reader);
120        reader->flags &= ~IFD_READER_ACTIVE;
121        return rc;
122}
123
124/*
125 * Output to reader's display
126 */
127int ifd_output(ifd_reader_t * reader, const char *message)
128{
129        const ifd_driver_t *drv = reader->driver;
130
131        if (!drv || !drv->ops || !drv->ops->output)
132                return IFD_ERROR_NOT_SUPPORTED;
133
134        return drv->ops->output(reader, message);
135}
136
137/*
138 * Detect card status
139 */
140int ifd_card_status(ifd_reader_t * reader, unsigned int idx, int *status)
141{
142        const ifd_driver_t *drv = reader->driver;
143        int rc;
144
145        if (idx > reader->nslots) {
146                ct_error("%s: invalid slot number %u", reader->name, idx);
147                return -1;
148        }
149
150        *status = 0;
151        if (!drv || !drv->ops || !drv->ops->card_status)
152                return IFD_ERROR_NOT_SUPPORTED;
153
154        if ((rc = drv->ops->card_status(reader, idx, status)) < 0)
155                return rc;
156        if (*status & IFD_CARD_STATUS_CHANGED)
157                reader->slot[idx].atr_len = 0;
158        reader->slot[idx].status = *status;
159
160        return 0;
161}
162
163/*
164 * Reset card and obtain ATR
165 */
166int ifd_card_reset(ifd_reader_t * reader, unsigned int idx, void *atr,
167                   size_t size)
168{
169        return ifd_card_request(reader, idx, 0, NULL, atr, size);
170}
171
172/*
173 * Request ICC
174 */
175int ifd_card_request(ifd_reader_t * reader, unsigned int idx, time_t timeout,
176                     const char *message, void *atr, size_t size)
177{
178        const ifd_driver_t *drv = reader->driver;
179        ifd_device_t *dev = reader->device;
180        ifd_slot_t *slot;
181        unsigned int count;
182        int n, parity;
183
184        if (idx > reader->nslots) {
185                ct_error("%s: invalid slot number %u", reader->name, idx);
186                return IFD_ERROR_INVALID_ARG;
187        }
188
189        if (dev == NULL)
190                return IFD_ERROR_INVALID_ARG;
191
192        if (!drv || !drv->ops || !drv->ops->card_reset)
193                return IFD_ERROR_NOT_SUPPORTED;
194
195        slot = &reader->slot[idx];
196        slot->atr_len = 0;
197
198        if (slot->proto) {
199                ifd_protocol_free(slot->proto);
200                slot->proto = NULL;
201        }
202
203        /* Do the reset thing - if the driver supports
204         * request ICC, call the function if needed.
205         * Otherwise fall back to ordinary reset.
206         *
207         * For asynchronous cards, the driver's card_reset
208         * function should perform the reset, and start to
209         * read the ATR. It should either read the first byte
210         * of the ATR, and leave it to the caller to read
211         * the remaining bytes of it, or it should read the
212         * whole ATR (as done by the B1 driver, for instance).
213         *
214         * When receiving the complete ATR, we will select
215         * the default protocol as specified by the card.
216         *
217         * If the driver was unable to receive the ATR
218         * (e.g. because the command timed out) it should
219         * return IFD_ERROR_NO_ATR. This will allow us
220         * to retry with different parity.
221         *
222         * For synchronous cards, the driver can call
223         * ifd_sync_detect_icc to detect whether the card
224         * is synchronous. This will also set the slot's
225         * protocol.
226         *
227         * If the card driver does it's own handling of sync
228         * ICCs, it should call ifd_set_protocol to signal
229         * that card detection was successful.
230         */
231        if (drv->ops->card_request && (timeout || message)) {
232                n = drv->ops->card_request(reader, idx,
233                                           timeout, message, slot->atr,
234                                           sizeof(slot->atr));
235                if (n <= 0)
236                        return n;
237                count = n;
238        } else
239            if (dev->type != IFD_DEVICE_TYPE_SERIAL
240                || !drv->ops->change_parity) {
241                n = drv->ops->card_reset(reader, idx,
242                                         slot->atr, sizeof(slot->atr));
243                if (n <= 0)
244                        return n;
245                count = n;
246        } else {
247                parity = IFD_SERIAL_PARITY_EVEN;
248                if ((n = drv->ops->change_parity(reader, parity)) < 0)
249                        return n;
250
251                /* Reset the card */
252                n = drv->ops->card_reset(reader, idx,
253                                         slot->atr, sizeof(slot->atr));
254
255                /* If there was no ATR, try again with odd parity */
256                if (n == IFD_ERROR_NO_ATR) {
257                        parity = IFD_SERIAL_PARITY_TOGGLE(parity);
258                        if (drv->ops->change_parity(reader, parity) < 0)
259                                return -1;
260                        n = drv->ops->card_reset(reader, idx,
261                                                 slot->atr, sizeof(slot->atr));
262                }
263
264                /* Bail out in case of general error */
265                if (n < 0)
266                        return -1;
267
268                count = n;
269
270                /* If we got just the first byte of the (async) ATR,
271                 * get the rest now */
272                if (count == 1) {
273                        ct_buf_t rbuf;
274                        unsigned char c;
275                        unsigned int num, proto = 0;
276                        int revert_bits = 0;
277
278                        if (slot->atr[0] == 0x03) {
279                                revert_bits = 1;
280                                slot->atr[0] = 0x3F;
281                        }
282
283                        ct_buf_init(&rbuf, slot->atr, sizeof(slot->atr));
284                        rbuf.tail++;
285
286                        if (ifd_recv_atr(dev, &rbuf, 1, revert_bits) < 0)
287                                return -1;
288
289                        c = rbuf.base[1];
290                        while (1) {
291                                num = ifd_count_bits(c & 0xF0);
292                                if (ifd_recv_atr(dev, &rbuf, num, revert_bits) <
293                                    0)
294                                        return -1;
295
296                                if (!(c & 0x80))
297                                        break;
298
299                                c = rbuf.base[rbuf.tail - 1];
300                                proto = c & 0xF;
301                        }
302
303                        /* Historical bytes */
304                        c = rbuf.base[1] & 0xF;
305                        if (ifd_recv_atr(dev, &rbuf, c, revert_bits) < 0)
306                                return -1;
307
308                        /* If a protocol other than T0 was specified,
309                         * read check byte */
310                        if (proto
311                            && ifd_recv_atr(dev, &rbuf, 1, revert_bits) < 0)
312                                return -1;
313
314                        if (slot->atr[0] == 0x3F)
315                                parity = IFD_SERIAL_PARITY_TOGGLE(parity);
316                        count = rbuf.tail - rbuf.head;
317                }
318
319                ifd_debug(1, "received atr:%s", ct_hexdump(slot->atr, count));
320
321                /* Set the parity in case it was toggled */
322                if (drv->ops->change_parity(reader, parity) < 0)
323                        return -1;
324        }
325
326        slot->atr_len = count;
327
328        if (count > size)
329                size = count;
330        if (atr)
331                memcpy(atr, slot->atr, count);
332
333        /* For synchronous cards, the slot's protocol will already
334         * be set when we get here. */
335        if (slot->proto == NULL) {
336                if (!ifd_protocol_select(reader, idx, IFD_PROTOCOL_DEFAULT))
337                        ct_error("Protocol selection failed");
338        }
339
340        return count;
341}
342
343static int ifd_recv_atr(ifd_device_t * dev, ct_buf_t * bp, unsigned int count,
344                        int revert_bits)
345{
346        unsigned char *buf;
347        unsigned int n;
348
349        if (count > ct_buf_tailroom(bp)) {
350                ct_error("ATR buffer too small");
351                return -1;
352        }
353
354        buf = (unsigned char *)ct_buf_tail(bp);
355        for (n = 0; n < count; n++) {
356                if (ifd_device_recv(dev, buf + n, 1, 1000) < 0) {
357                        ct_error("failed to receive ATR");
358                        return -1;
359                }
360        }
361
362        if (revert_bits)
363                ifd_revert_bits(buf, count);
364
365        /* Advance tail pointer */
366        ct_buf_put(bp, NULL, count);
367        return count;
368}
369
370/*
371 * Check ATR for completeness
372 */
373int ifd_atr_complete(const unsigned char *atr, size_t len)
374{
375        unsigned int j = 2, c;
376        int proto = 0;
377
378        do {
379                if (j > len)
380                        return 0;
381                c = atr[j - 1];
382                if (j > 2)
383                        proto = c & 0xF;
384                j += ifd_count_bits(c & 0xF0);
385        } while (c & 0x80);
386
387        /* Historical bytes */
388        if ((j += (atr[1] & 0xF)) > len)
389                return 0;
390
391        /* If a protocol other than T0 was specified,
392         * read check byte */
393        if (proto && j + 1 > len)
394                return 0;
395
396        return 1;
397}
398
399/*
400 * Eject the card
401 */
402int ifd_card_eject(ifd_reader_t * reader, unsigned int idx, time_t timeout,
403                   const char *message)
404{
405        const ifd_driver_t *drv = reader->driver;
406
407        if (idx > reader->nslots) {
408                ct_error("%s: invalid slot number %u", reader->name, idx);
409                return -1;
410        }
411
412        if (!drv || !drv->ops || !drv->ops->card_eject)
413                return 0;
414
415        return drv->ops->card_eject(reader, idx, timeout, message);
416}
417
418/*
419 * Perform a PIN verification, using the reader's pin pad
420 */
421int ifd_card_perform_verify(ifd_reader_t * reader, unsigned int idx,
422                            time_t timeout, const char *message,
423                            const unsigned char *data, size_t data_len,
424                            unsigned char *resp, size_t resp_len)
425{
426        const ifd_driver_t *drv = reader->driver;
427
428        if (idx > reader->nslots) {
429                ct_error("%s: invalid slot number %u", reader->name, idx);
430                return -1;
431        }
432
433        if (!drv || !drv->ops || !drv->ops->perform_verify)
434                return IFD_ERROR_NOT_SUPPORTED;
435
436        return drv->ops->perform_verify(reader, idx, timeout, message,
437                                        data, data_len, resp, resp_len);
438}
439
440/*
441 * Send/receive APDU to the ICC
442 */
443int ifd_card_command(ifd_reader_t * reader, unsigned int idx, const void *sbuf,
444                     size_t slen, void *rbuf, size_t rlen)
445{
446        ifd_slot_t *slot;
447
448        if (idx > reader->nslots)
449                return -1;
450
451        /* XXX handle driver specific methods of transmitting
452         * commands */
453
454        slot = &reader->slot[idx];
455        if (slot->proto == NULL) {
456                ct_error("No communication protocol selected");
457                return -1;
458        }
459
460        /* An application is talking to the card. Prevent
461         * automatic card status updates from slowing down
462         * things */
463        slot->next_update = time(NULL) + 1;
464
465        return ifd_protocol_transceive(slot->proto, slot->dad,
466                                       sbuf, slen, rbuf, rlen);
467}
468
469/*
470 * Read/write synchronous ICCs
471 */
472int ifd_card_read_memory(ifd_reader_t * reader, unsigned int idx,
473                         unsigned short addr, unsigned char *rbuf, size_t rlen)
474{
475        ifd_slot_t *slot;
476
477        if (idx > reader->nslots)
478                return -1;
479
480        slot = &reader->slot[idx];
481        if (slot->proto == NULL) {
482                ct_error("No communication protocol selected");
483                return -1;
484        }
485
486        /* An application is talking to the card. Prevent
487         * automatic card status updates from slowing down
488         * things */
489        slot->next_update = time(NULL) + 1;
490
491        return ifd_protocol_read_memory(slot->proto, idx, addr, rbuf, rlen);
492}
493
494int ifd_card_write_memory(ifd_reader_t * reader, unsigned int idx,
495                          unsigned short addr, const unsigned char *sbuf,
496                          size_t slen)
497{
498        ifd_slot_t *slot;
499
500        if (idx > reader->nslots)
501                return -1;
502
503        slot = &reader->slot[idx];
504        if (slot->proto == NULL) {
505                ct_error("No communication protocol selected");
506                return -1;
507        }
508
509        /* An application is talking to the card. Prevent
510         * automatic card status updates from slowing down
511         * things */
512        slot->next_update = time(NULL) + 1;
513
514        return ifd_protocol_write_memory(slot->proto, idx, addr, sbuf, slen);
515}
516
517/*
518 * Transfer/receive APDU using driver specific mechanisms
519 * This functions is called from the protocol (T=0,1,...) layer
520 */
521int ifd_send_command(ifd_protocol_t * prot, const void *buffer, size_t len)
522{
523        const ifd_driver_t *drv;
524
525        if (!prot || !prot->reader || !(drv = prot->reader->driver)
526            || !drv->ops || !drv->ops->send)
527                return -1;
528
529        return drv->ops->send(prot->reader, prot->dad,
530                              (const unsigned char *)buffer, len);
531}
532
533int
534ifd_recv_response(ifd_protocol_t * prot, void *buffer, size_t len, long timeout)
535{
536        const ifd_driver_t *drv;
537
538        if (!prot || !prot->reader || !(drv = prot->reader->driver)
539            || !drv->ops || !drv->ops->recv)
540                return -1;
541
542        return drv->ops->recv(prot->reader, prot->dad, (unsigned char *)buffer,
543                              len, timeout);
544}
545
546/*
547 * Shut down reader
548 */
549void ifd_close(ifd_reader_t * reader)
550{
551        ifd_detach(reader);
552
553        if (reader->driver->ops->close)
554                reader->driver->ops->close(reader);
555
556        if (reader->device)
557                ifd_device_close(reader->device);
558
559        memset(reader, 0, sizeof(*reader));
560        free(reader);
561}
562
563/*
564 * Before command
565 */
566int ifd_before_command(ifd_reader_t *reader)
567{
568        if (reader->driver->ops->before_command)
569                return reader->driver->ops->before_command(reader);
570        else
571                return 0;
572}
573
574/*
575 * After command
576 */
577int ifd_after_command(ifd_reader_t *reader)
578{
579        if (reader->driver->ops->after_command)
580                return reader->driver->ops->after_command(reader);
581        else
582                return 0;
583}
584
585/*
586 * Get eventfd
587 */
588int ifd_get_eventfd(ifd_reader_t *reader, short *events)
589{
590        if (reader->driver->ops->get_eventfd) {
591                return reader->driver->ops->get_eventfd(reader, events);
592        }
593        else {
594                return -1;
595        }
596}
597
598static void ifd_slot_status_update(ifd_reader_t *reader, int slot, int status)
599{
600        static unsigned int card_seq = 1;
601
602        ct_info_t *info = reader->status;
603        unsigned int prev_seq, new_seq;
604
605        new_seq = prev_seq = info->ct_card[slot];
606
607        if (!(status & IFD_CARD_PRESENT)) {
608                new_seq = 0;
609        }
610        else if (!prev_seq || (status & IFD_CARD_STATUS_CHANGED)) {
611                new_seq = card_seq++;
612        }
613
614        if (prev_seq != new_seq) {
615                ifd_debug(1, "card status change slot %d: %u -> %u",
616                          slot, prev_seq, new_seq);
617                info->ct_card[slot] = new_seq;
618                ct_status_update(info);
619        }
620}
621
622void ifd_poll(ifd_reader_t *reader)
623{
624        unsigned slot;
625
626        /* Check if the card status changed */
627        for (slot = 0; slot < reader->nslots; slot++) {
628                time_t now;
629                int status;
630
631                time(&now);
632                if (now < reader->slot[slot].next_update)
633                        continue;
634
635                /* Poll card status at most once a second
636                 * XXX: make this configurable */
637                reader->slot[slot].next_update = now + 1;
638
639                if (ifd_card_status(reader, slot, &status) < 0) {
640                        /* Don't return error; let the hotplug test
641                         * pick up the detach
642                         if (rc == IFD_ERROR_DEVICE_DISCONNECTED)
643                         return rc;
644                         */
645                        continue;
646                }
647
648                ifd_slot_status_update(reader, slot, status);
649        }
650}
651
652int ifd_error(ifd_reader_t *reader)
653{
654        if (reader->driver->ops->error == NULL) {
655                return IFD_ERROR_NOT_SUPPORTED;
656        }
657
658        return reader->driver->ops->error(reader);
659}
660
661int ifd_event(ifd_reader_t *reader)
662{
663        int status[OPENCT_MAX_SLOTS];
664        unsigned slot;
665        int rc;
666
667        if (reader->driver->ops->event == NULL) {
668                return IFD_ERROR_NOT_SUPPORTED;
669        }
670
671        rc = reader->driver->ops->event(reader, status, reader->nslots);
672
673        for (slot=0;slot<reader->nslots;slot++) {
674                ifd_slot_status_update(reader, slot, status[slot]);
675        }
676
677        return rc;
678}
679
Note: See TracBrowser for help on using the repository browser.