source: trunk/src/ifd/ifd-rutoken.c @ 1179

Revision 1179, 18.8 KB checked in by s, 2 years ago (diff)

fix: Le (APDU_CASE_2S) for get_do_info in accordance with Windows driver

Line 
1/*
2 * driver for Rutoken devices
3 *
4 * Copyright (C) 2007, Pavel Mironchik <rutoken@rutoken.ru>
5 * Copyright (C) 2007, Eugene Hermann <e_herman@rutoken.ru>
6 */
7
8#include "internal.h"
9#include <unistd.h>
10#include <string.h>
11#include <stdlib.h>
12
13#define MAX_BUF_T0_LEN  256
14#define T0_HDR_LEN      5
15
16#define USB_ICC_POWER_ON        0x62
17#define USB_ICC_POWER_OFF       0x63
18#define USB_ICC_XFR_BLOCK       0x65
19#define USB_ICC_DATA_BLOCK      0x6F
20#define USB_ICC_GET_STATUS      0xA0
21
22#define ICC_STATUS_IDLE                 0x00
23#define ICC_STATUS_READY_DATA   0x10
24#define ICC_STATUS_READY_SW             0x20
25#define ICC_STATUS_BUSY_COMMON  0x40
26#define ICC_STATUS_MUTE                 0x80
27
28#define OUR_ATR_LEN     19
29
30static int rutoken_open(ifd_reader_t * reader, const char *device_name)
31{
32        ifd_device_t *dev;
33        ifd_device_params_t params;
34
35        ifd_debug(6, "rutoken_open - %s", device_name);
36
37        reader->name = "Rutoken S driver";
38        reader->nslots = 1;
39        if (!(dev = ifd_device_open(device_name)))
40                return -1;
41
42        if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) {
43                ct_error("Rutoken: device %s is not a USB device", device_name);
44                ifd_device_close(dev);
45                return -1;
46        }
47
48        params = dev->settings;
49        params.usb.interface = 0;
50        if (ifd_device_set_parameters(dev, &params) < 0) {
51                ct_error("Rutoken: setting parameters failed", device_name);
52                ifd_device_close(dev);
53                return -1;
54        }
55
56        reader->device = dev;
57        dev->timeout = 1000;
58
59        ifd_debug(6, "rutoken_open - %s - successful", device_name);
60        return 0;
61}
62
63static int rutoken_activate(ifd_reader_t * reader)
64{
65        ifd_debug(6, "called.");
66        return 0;
67}
68
69static int rutoken_deactivate(ifd_reader_t * reader)
70{
71        ifd_debug(6, "called.");
72        return -1;
73}
74
75static int rutoken_getstatus(ifd_reader_t * reader, unsigned char *status)
76{
77        if(ifd_usb_control(reader->device, 0xc1, USB_ICC_GET_STATUS, 
78                                0, 0, status, 1, 1000) < 0 )
79                return -1;
80        if((*status & 0xF0) == ICC_STATUS_BUSY_COMMON){
81                unsigned char prev_status;
82                int i;
83                for(i = 0; i < 200; i++) { // 2 s  (200 * 10 ms)
84                        do {
85                                usleep(10000); // 10 ms
86                                prev_status = *status;
87                                if(ifd_usb_control(reader->device, 0xc1, 
88                                                        USB_ICC_GET_STATUS, 0, 0, 
89                                                        status, 1, 1000) < 0
90                                )
91                                return -1;
92                        if((*status & 0xF0) != ICC_STATUS_BUSY_COMMON)
93                                        return *status;
94                        } while((((prev_status & 0x0F) + 1) & 0x0F) == (*status & 0x0F));
95                }
96                return -1;
97        }
98        return *status;
99}
100
101static int rutoken_card_reset(ifd_reader_t * reader, int slot, void *atr,
102                size_t atr_len)
103{
104        int nLen = 0, i;
105        ifd_debug(6, "rutoken_card_reset, slot = %X", slot);
106        if(ifd_usb_control(reader->device, 0x41, USB_ICC_POWER_OFF, 0, 0, 0, 0, -1) < 0)
107        {
108                ifd_debug(6, "error poweroff");
109                return -1;
110        }
111        unsigned char status;
112        if( rutoken_getstatus(reader, &status) < 0)
113        {
114                ifd_debug(6, "error get status");
115                return -1;
116        }
117        if( status == ICC_STATUS_READY_DATA ) {
118                char buf[OUR_ATR_LEN];
119                memset(buf, 0, OUR_ATR_LEN);
120
121                nLen = ifd_usb_control(reader->device, 0xc1, USB_ICC_POWER_ON, 0, 0, 
122                                buf, OUR_ATR_LEN, 1000);
123                if( nLen < 0 )
124                {
125                        ifd_debug(6, "error poewron");
126                        return -1;
127                }
128
129                ifd_debug(6, "returned len = %d", nLen);
130                for(i = 0; i < OUR_ATR_LEN; i++) ifd_debug(6, "%c", buf[i]);
131                memcpy(atr, buf, nLen);
132                return nLen;
133        }
134
135        ifd_debug(6, "error bad status");
136        return -1;
137}
138
139static int rutoken_restart(ifd_reader_t * reader)
140{
141        char atr[256];
142        return rutoken_card_reset(reader, 0, atr, 256);
143}
144
145/*
146 * Select a protocol.
147 */
148static int rutoken_set_protocol(ifd_reader_t * reader, int nslot, int proto)
149{
150        ifd_slot_t *slot;
151        ifd_protocol_t *p;
152
153        ifd_debug(6, "proto=%d", proto);
154        if (proto != IFD_PROTOCOL_T0 && proto != IFD_PROTOCOL_TRANSPARENT) {
155                ct_error("%s: protocol %d not supported", reader->name, proto);
156                return IFD_ERROR_NOT_SUPPORTED;
157        }
158        slot = &reader->slot[nslot];
159        p = ifd_protocol_new(IFD_PROTOCOL_TRANSPARENT, reader, slot->dad);
160        if (p == NULL) {
161                ct_error("%s: internal error", reader->name);
162                return IFD_ERROR_GENERIC;
163        }
164        if (slot->proto) {
165                ifd_protocol_free(slot->proto);
166                slot->proto = NULL;
167        }
168        slot->proto = p;
169        ifd_debug(6, "success");
170        return 0;
171}
172
173static int rutoken_card_status(ifd_reader_t * reader, int slot,
174                int *status)
175{
176        *status = IFD_CARD_PRESENT;
177        return 0;
178}
179
180static int rutoken_send(ifd_reader_t * reader, unsigned int dad,
181                const unsigned char *buffer, size_t len)
182{
183        int ret;
184        unsigned char status;
185        ifd_debug(3, "usb send %s len %d", ct_hexdump(buffer, len), len);
186        ret = ifd_usb_control(reader->device, 0x41, USB_ICC_XFR_BLOCK, 0, 0, 
187                        (void *)buffer, len, -1);
188
189        if (rutoken_getstatus(reader, &status) < 0)
190        {
191                ret = -1;
192                ifd_debug(6, "error get status");
193        }
194        return ret;
195}
196
197static int rutoken_recv(ifd_reader_t * reader, unsigned int dad,
198                unsigned char *buffer, size_t len, long timeout)
199{
200        unsigned char status;
201        int ret = len;
202        // USB_ICC_DATA_BLOCK
203        if( (ret = ifd_usb_control(reader->device, 0xc1, USB_ICC_DATA_BLOCK, 0, 0, 
204                                        buffer, len, timeout)) >= 0)
205                if (rutoken_getstatus(reader, &status) < 0)
206                {
207                        ret = -1;
208                        ifd_debug(6, "error get status, %0x", status);
209                }
210        ifd_debug(3, "usd recv %s len %d", ct_hexdump(buffer, ret), ret);
211        return ret;
212}
213
214static int rutoken_recv_sw(ifd_reader_t * reader, int dad, unsigned char *sw)
215{
216        unsigned char status;
217        if(rutoken_getstatus(reader, &status) == ICC_STATUS_MUTE)
218        {  //If device not responsive
219                ifd_debug(6, "status = ICC_STATUS_MUTE");
220                return(rutoken_restart(reader));
221        }
222        if(status == ICC_STATUS_READY_SW)
223        {
224                ifd_debug(6, "status = ICC_STATUS_READY_SW;");
225                if(rutoken_recv(reader, 0, sw, 2, 10000) < 0)
226                        return -5;
227                ifd_debug(6, "Get SW %x %x", sw[0], sw[1]);
228                return 2;
229        }
230        return -1;
231}
232
233// return how mach byte send
234// sbuf - APDU bufer
235// slen
236static int rutoken_send_tpducomand(ifd_reader_t * reader, int dad, const void *sbuf, 
237                size_t slen, void *rbuf, size_t rlen, int iscase4)
238{
239        ifd_debug(6, "send tpdu command %s, len: %d", ct_hexdump(sbuf, slen), slen);
240        int rrecv = 0;
241        unsigned char status;
242        unsigned char sw[2];
243        ifd_iso_apdu_t iso;
244        if ( ifd_iso_apdu_parse(sbuf, slen, &iso) < 0)
245                return -1;
246        unsigned char hdr[T0_HDR_LEN]={iso.cla, iso.ins, iso.p1, iso.p2, 0};
247        switch(iso.cse){
248                case    IFD_APDU_CASE_1:
249                        // {cla, ins, p1, p2, 0};
250                        ifd_debug(6, "case 1");
251                        break;
252                case    IFD_APDU_CASE_2S:
253                        // {cla, ins, p1, p2, le};
254                        // Rutoken Bug!!!
255                        ifd_debug(6, "case 2");
256                        /* select file */
257                        if (iso.cla == 0 && iso.ins == 0xa4)
258                                iso.le = 0x20;
259                        /* get_do_info */
260                        else if (iso.cla == 0x80 && iso.ins == 0x30)
261                                iso.le = 0xff;
262                        hdr[4] = iso.le;
263                        break;
264                case    IFD_APDU_CASE_3S:
265                        // {cla, ins, p1, p2, lc};
266                        ifd_debug(6, "case 3");
267                        hdr[4] = iso.lc;
268                        break;
269                default:
270                        break;
271        }
272        //send TPDU header
273        if (rutoken_send(reader, 0, hdr, T0_HDR_LEN) < 0)
274                return -1;
275        // send TPDU data or get answere and sw
276        switch(iso.cse){
277                case    IFD_APDU_CASE_1:
278                        // get sw
279                        if (rutoken_recv_sw(reader, 0, sw) < 0)
280                                return -2;
281                        break;
282                case    IFD_APDU_CASE_2S:
283                        // get answere
284                        ifd_debug(6, "Get Data %d", iso.le);
285                        if(rutoken_getstatus(reader, &status) == ICC_STATUS_READY_DATA)
286                        {
287                                rrecv = rutoken_recv(reader, 0, rbuf, iso.le, 10000);
288                                if (rrecv < 0)
289                                        return -2;
290                                ifd_debug(6, "Get TPDU Anser %s", 
291                                                ct_hexdump(rbuf, iso.le));
292                        }
293                        if (rutoken_recv_sw(reader, 0, sw) < 0)
294                                return -2;
295                        if ( sw[0] == 0x67) {
296                                // Le definitely not accepted
297                                break;
298                        }
299                        if ( (sw[0] == 0x6c) ) {
300                                unsigned char sbuftmp[slen];
301                                memcpy(sbuftmp, sbuf, slen);
302                                sbuftmp[4] = sw[1];
303                                return rutoken_send_tpducomand(reader, dad, sbuftmp, 
304                                                slen, rbuf,  rlen, 0);
305                        }
306                        break;
307                case    IFD_APDU_CASE_3S:
308                        // send data
309                        ifd_debug(6, "Send Data %d", iso.lc);
310                        if(rutoken_getstatus(reader, &status) == ICC_STATUS_READY_DATA)
311                        {
312                                ifd_debug(6, "Send TPDU Data %s", 
313                                                ct_hexdump(iso.data, iso.lc));
314                                if (rutoken_send(reader, 0, iso.data, iso.lc) < 0)
315                                        return -4;
316                        } else return -3;
317                        // get sw
318                        if (rutoken_recv_sw(reader, 0, sw) < 0)
319                                return -2;
320
321                        // NOT STANDART TPDU!!! BEGIN
322                        if ( sw[0]== 0x61){
323                                unsigned char lx = sw[1];
324                                hdr[0] = 0x00;  //  iso.cla; (ruTokens specific)
325                                hdr[1] = 0xc0; // ins get response
326                                hdr[2] = 0; // p1
327                                hdr[3] = 0; // p2
328                                hdr[4] = lx ; //lx (case 2)
329                                if(iscase4)
330                                        return rutoken_send_tpducomand(reader, dad, hdr, 
331                                                        T0_HDR_LEN, rbuf, rlen, 0);
332                                else {
333                                        int recvtmp = rutoken_send_tpducomand(reader,dad,
334                                                        hdr, T0_HDR_LEN, rbuf, rlen, 0);
335                                        rrecv = 0;
336                                        memcpy(sw, (unsigned char*)rbuf+recvtmp-2, 2);
337                                        break;
338                                }
339                        }
340
341                        if ( (sw[0] == 0x90) && (sw[1] == 0x00))
342                        {
343                                hdr[0] = 0x00; //iso.cla;
344                                hdr[1] = 0xc0; // ins get response
345                                hdr[2] = 0; // p1
346                                hdr[3] = 0; // p2
347                                hdr[4] = iso.le; // le (case 2)
348                                if(iscase4)
349                                        return rutoken_send_tpducomand(reader, dad, hdr, 
350                                                        T0_HDR_LEN, rbuf, rlen, 0);
351                        }
352                        // NOT STANDART TPDU!!! END
353
354                        break;
355                default:
356                        break;
357        }
358        // Add SW to respond
359        memcpy(((char *)rbuf)+rrecv, sw, 2);
360        rrecv+=2;
361        ifd_debug(6, "Recv %d bytes", rrecv);
362        return rrecv;
363}
364
365static void swap_pair(unsigned char *buf, size_t len)
366{
367        size_t i;
368        unsigned char tmp;
369
370        for (i = 0; i + 1 < len; i += 2) {
371                tmp = buf[i];
372                buf[i] = buf[i + 1];
373                buf[i + 1] = tmp;
374        }
375}
376
377static void swap_four(unsigned char *buf, size_t len)
378{
379        size_t i;
380        unsigned char tmp;
381
382        for (i = 0; i + 3 < len; i += 4) {
383                tmp = buf[i];
384                buf[i] = buf[i + 3];
385                buf[i + 3] = tmp;
386
387                swap_pair(&buf[i + 1], 2);
388        }
389}
390
391static int read_tag(unsigned char *buf, size_t buf_len,
392                unsigned char tag_in, unsigned char *out, size_t out_len)
393{
394        unsigned char tag;
395        size_t taglen, i = 0;
396
397        while (i + 2 <= buf_len) {
398                tag = buf[i];
399                taglen = buf[i + 1];
400                i += 2;
401                if (taglen + i > buf_len)
402                        return -1;
403                if (tag == tag_in) {
404                        if (taglen != out_len)
405                                return -1;
406                        memcpy(out, buf + i, out_len);
407                        return 0;
408                }
409                i += taglen;
410        }
411        return -1;
412}
413
414static int convert_doinfo_to_rtprot(void *data, size_t data_len)
415{
416        unsigned char dohdr[32] = { 0 };
417        unsigned char secattr[40], data_a5[0xff];
418        unsigned char *p = data;
419        size_t i, data_a5_len;
420
421        if (read_tag(p, data_len, 0x80, &dohdr[0], 2) == 0) {
422                swap_pair(&dohdr[0], 2);
423                ifd_debug(6, "tag 0x80 (file size) = %02x %02x", dohdr[0], dohdr[1]);
424        }
425        data_a5_len = dohdr[1] & 0xff;
426        if (read_tag(p, data_len, 0xA5, data_a5, data_a5_len) == 0)
427                ifd_debug(6, "tag 0xA5 = %s", ct_hexdump(data_a5, data_a5_len));
428        else
429                data_a5_len = 0;
430        if (data_len < sizeof(dohdr) + data_a5_len) {
431                ifd_debug(6, "data_len = %u", data_len);
432                return -1;
433        }
434        if (read_tag(p, data_len, 0x83, &dohdr[2], 2) == 0)
435                ifd_debug(6, "tag 0x83 (Type,ID) = %02x %02x", dohdr[2], dohdr[3]);
436        if (read_tag(p, data_len, 0x85, &dohdr[4], 3) == 0)
437                ifd_debug(6, "tag 0x85 (Opt,Flags,MaxTry) = %02x %02x %02x",
438                                dohdr[4], dohdr[5], dohdr[6]);
439        if (read_tag(p, data_len, 0x86, secattr, sizeof(secattr)) == 0) {
440                i = 17;
441                memcpy(dohdr + i, secattr, 8);
442                for (i += 8, p = &secattr[8]; i < sizeof(dohdr); ++i, p += 4)
443                        dohdr[i] = *p;
444                ifd_debug(6, "tag 0x86 = %s", ct_hexdump(&dohdr[17], 15));
445        }
446        memcpy(data, dohdr, sizeof(dohdr));
447        memcpy((unsigned char*)data + sizeof(dohdr), data_a5, data_a5_len);
448        return sizeof(dohdr) + data_a5_len;
449}
450
451static int convert_fcp_to_rtprot(void *data, size_t data_len)
452{
453        unsigned char rtprot[32] = { 0 };
454        unsigned char secattr[40];
455        unsigned char *p = data;
456        size_t i;
457
458        if (data_len < sizeof(rtprot)) {
459                ifd_debug(6, "data_len = %u", data_len);
460                return -1;
461        }
462        /* 0x62 - FCP */
463        if (p[0] != 0x62  ||  (size_t)p[1] + 2 > data_len) {
464                ifd_debug(6, "Tag = %02x  len = %u", p[0], p[1]);
465                return -1;
466        }
467        p += 2;
468        data_len -= 2;
469        /* file type */
470        if (read_tag(p, data_len, 0x82, &rtprot[4], 2) != 0)
471                return -1;
472        ifd_debug(6, "tag 0x82 (file type) = %02x %02x", rtprot[4], rtprot[5]);
473        /* file id */
474        if (read_tag(p, data_len, 0x83, &rtprot[6], 2) != 0)
475                return -1;
476        swap_pair(&rtprot[6], 2);
477        ifd_debug(6, "tag 0x83 (file id) = %02x %02x", rtprot[6], rtprot[7]);
478        /* file size */
479        if (read_tag(p, data_len, 0x81, &rtprot[0], 2) == 0) {
480                swap_pair(&rtprot[0], 2);
481                ifd_debug(6, "tag 0x81 (complete file size) = %02x %02x",
482                                rtprot[0], rtprot[1]);
483        }
484        if (read_tag(p, data_len, 0x80, &rtprot[2], 2) == 0) {
485                swap_pair(&rtprot[2], 2);
486                ifd_debug(6, "tag 0x80 (file size) = %02x %02x", rtprot[2], rtprot[3]);
487        }
488        if (read_tag(p, data_len, 0x86, secattr, sizeof(secattr)) == 0) {
489                i = 17;
490                memcpy(rtprot + i, secattr, 8);
491                for (i += 8, p = &secattr[8]; i < sizeof(rtprot); ++i, p += 4)
492                        rtprot[i] = *p;
493                ifd_debug(6, "tag 0x86 = %s", ct_hexdump(&rtprot[17], 15));
494        }
495        memcpy(data, rtprot, sizeof(rtprot));
496        return sizeof(rtprot);
497}
498
499static int convert_rtprot_to_doinfo(void *data, size_t data_len)
500{
501        unsigned char doinfo[0xff] = { 0 };
502        unsigned char *pdata = data;
503        size_t i, doinfo_len = 0;
504
505        if (data_len < 32) {
506                ifd_debug(6, "data_len = %u", data_len);
507                return -1;
508        }
509        if (pdata[0] != 0 && pdata[0] < sizeof(doinfo) - 4 - 4 - 5 - 42 - 2) {
510                /* Tag 0x80 */
511                doinfo[doinfo_len++] = 0x80;
512                doinfo[doinfo_len++] = 2;
513                memcpy(doinfo + doinfo_len, pdata, 2);
514                swap_pair(doinfo + doinfo_len, 2);
515                doinfo_len += 2;
516        }
517        /* Tag 0x83 */
518        doinfo[doinfo_len++] = 0x83;
519        doinfo[doinfo_len++] = 2;
520        doinfo[doinfo_len++] = pdata[2];
521        doinfo[doinfo_len++] = pdata[3];
522
523        /* Tag 0x85 */
524        doinfo[doinfo_len++] = 0x85;
525        doinfo[doinfo_len++] = 3;
526        doinfo[doinfo_len++] = pdata[4];
527        doinfo[doinfo_len++] = pdata[5];
528        doinfo[doinfo_len++] = pdata[6];
529
530        /* Tag 0x86 */
531        doinfo[doinfo_len++] = 0x86;
532        doinfo[doinfo_len++] = 40;
533        memcpy(doinfo + doinfo_len, pdata + 17, 8);
534        doinfo_len += 8;
535        for (i = 0; i < 7 && doinfo_len + 3 < sizeof(doinfo); ++i, doinfo_len += 4)
536                doinfo[doinfo_len] = pdata[17 + 8 + i];
537        doinfo_len += 4; /* for reserved */
538        if (pdata[0] != 0 && pdata[0] + doinfo_len + 2 < sizeof(doinfo)) {
539                /* Tag 0xA5 */
540                if (data_len - 32 < pdata[0]) {
541                        ifd_debug(6, "for tag 0xA5 incorrect data_len = %u", data_len);
542                        return -1;
543                }
544                doinfo[doinfo_len++] = 0xA5;
545                doinfo[doinfo_len++] = pdata[0];
546                memcpy(doinfo + doinfo_len, pdata + 32, pdata[0]);
547                doinfo_len += pdata[0];
548        }
549        ifd_debug(6, "doinfo = %s", ct_hexdump(doinfo, doinfo_len));
550        memcpy(data, doinfo, doinfo_len);
551        return doinfo_len;
552}
553
554static int convert_rtprot_to_fcp(void *data, size_t data_len)
555{
556        unsigned char fcp[63] = {
557                0x62, sizeof(fcp) - 2,
558                0x81, 2, 0, 0,
559                0x80, 2, 0, 0,
560                0x82, 2, 0, 0,
561                0x83, 2, 0, 0,
562                0x8A, 1, 0,
563                0x86, 40
564        };
565        unsigned char *p = data;
566        size_t i;
567
568        if (data_len < sizeof(fcp)) {
569                ifd_debug(6, "data_len = %u", data_len);
570                return -1;
571        }
572        /* Tag 0x81 */
573        memcpy(fcp + 4, p, 2);
574        swap_pair(fcp + 4, 2);
575        /* Tag 0x80 */
576        memcpy(fcp + 8, p + 2, 2);
577        swap_pair(fcp + 8, 2);
578        /* Tag 0x82 */
579        memcpy(fcp + 12, p + 4, 2);
580        /* Tag 0x83 */
581        memcpy(fcp + 16, p + 6, 2);
582        swap_pair(fcp + 16, 2);
583        /* Tag 0x8A */
584        fcp[20] = p[8];
585
586        /* Tag 0x86 */
587        memcpy(fcp + 23, p + 17, 8);
588        for (i = 0; i < 7 && sizeof(fcp) > 23 + 8 + i * 4; ++i)
589                fcp[23 + 8 + i * 4] = p[17 + 8 + i];
590        ifd_debug(6, "fcp = %s", ct_hexdump(fcp, sizeof(fcp)));
591        memcpy(data, fcp, sizeof(fcp));
592        return sizeof(fcp);
593}
594
595static int rutoken_transparent( ifd_reader_t * reader, int dad,
596                const void *sbuf, size_t slen,
597                void *rbuf, size_t rlen)
598{
599        unsigned char sw[2], *send_buf_trn = NULL;
600        const void *send_buf = sbuf;
601        int len, rrecv = -1, iscase4 = 0;
602        ifd_iso_apdu_t iso;
603
604        ifd_debug(6, "buffer %s rlen = %d", ct_hexdump(sbuf, slen), rlen);
605        if ( ifd_iso_apdu_parse(sbuf, slen, &iso) < 0)
606                return -1;
607        ifd_debug(6, "iso.le = %d", iso.le);
608
609        if (iso.cla == 0 && slen > 5) {
610                send_buf_trn = malloc(slen);
611                if (!send_buf_trn) {
612                        ifd_debug(5, "out of memory (slen = %u)", slen);
613                        return IFD_ERROR_NO_MEMORY;
614                }
615                memcpy(send_buf_trn, sbuf, slen);
616                /* select file, delete file */
617                if (iso.ins == 0xa4 || iso.ins == 0xe4)
618                        swap_pair(send_buf_trn + 5, slen - 5);
619                /* create file */
620                else if (iso.ins == 0xe0) {
621                        len = convert_fcp_to_rtprot(send_buf_trn + 5, slen - 5);
622                        ifd_debug(6, "convert_fcp_to_rtprot = %i", len);
623                        if (len > 0) {
624                                slen = len + 5;
625                                send_buf_trn[4] = len; /* replace le */
626                        }
627                }
628                /* create_do, key_gen */
629                else if (iso.ins == 0xda && iso.p1 == 1
630                                && (iso.p2 == 0x65 || iso.p2 == 0x62)) {
631                        len = convert_doinfo_to_rtprot(send_buf_trn + 5, slen - 5);
632                        ifd_debug(6, "convert_doinfo_to_rtprot = %i", len);
633                        if (len > 0) {
634                                slen = len + 5;
635                                send_buf_trn[4] = len; /* replace le */
636                        }
637                }
638                ifd_debug(6, "le = %u", send_buf_trn[4]);
639                send_buf = send_buf_trn;
640        }
641        switch(iso.cse){
642                case    IFD_APDU_CASE_2S:
643                case    IFD_APDU_CASE_3S:
644                        if (iso.cla == 0 && iso.ins == 0xa4)
645                                iscase4 = 1; /* FIXME: */
646                case    IFD_APDU_CASE_1:
647                        rrecv = rutoken_send_tpducomand(reader, dad, send_buf, slen,
648                                        rbuf, rlen, iscase4);
649                        break;
650                case    IFD_APDU_CASE_4S:
651                        // make send case 4 command
652                        rrecv = rutoken_send_tpducomand(reader, dad, send_buf, slen-1,
653                                        rbuf, rlen, 1);
654                        break;
655                default:
656                        break;
657        }
658        if (send_buf_trn)
659                free(send_buf_trn);
660
661        if (rrecv > 0 && (size_t)rrecv >= sizeof(sw)) {
662                memcpy(sw, (unsigned char*)rbuf + rrecv - sizeof(sw), sizeof(sw));
663                if (sw[0] != 0x90 || sw[1] != 0)
664                        /* do nothing */;
665                /* select file */
666                else if (iso.cla == 0 && iso.ins == 0xa4
667                                && rrecv == sizeof(sw) + 32 /* size rtprot */) {
668                        len = convert_rtprot_to_fcp(rbuf, rlen);
669                        ifd_debug(6, "convert_rtprot_to_fcp = %i", len);
670                        if (len > 0) {
671                                rrecv = -1;
672                                if (rlen >= len + sizeof(sw)) {
673                                        memcpy((unsigned char*)rbuf+len, sw, sizeof(sw));
674                                        rrecv = len + sizeof(sw);
675                                }
676                        }
677                }
678                /* get_do_info */
679                else if (iso.cla == 0x80 && iso.ins == 0x30
680                                && (size_t)rrecv >= sizeof(sw) + 32 /* size rtprot */) {
681                        len = convert_rtprot_to_doinfo(rbuf, rlen);
682                        ifd_debug(6, "convert_rtprot_to_doinfo = %i", len);
683                        if (len > 0) {
684                                rrecv = -1;
685                                if (rlen >= len + sizeof(sw)) {
686                                        memcpy((unsigned char*)rbuf+len, sw, sizeof(sw));
687                                        rrecv = len + sizeof(sw);
688                                }
689                        }
690                }
691                else if (iso.cla == 0 && iso.ins == 0xca && iso.p1 == 1) {
692                        /* get_serial, get_free_mem */
693                        if (iso.p2 == 0x81 || iso.p2 == 0x8a)
694                                swap_four(rbuf, rrecv - sizeof(sw));
695                        /* get_current_ef */
696                        else if (iso.p2 == 0x11)
697                                swap_pair(rbuf, rrecv - sizeof(sw));
698                }
699        }
700        return rrecv;
701}
702
703static int rutoken_get_eventfd(ifd_reader_t * reader, short *events)
704{
705        ifd_debug(6, "called.");
706
707        return ifd_device_get_eventfd(reader->device, events);
708}
709
710static int rutoken_event(ifd_reader_t * reader, int *status, size_t status_size)
711{
712        (void)reader;
713        (void)status;
714        (void)status_size;
715
716        ifd_debug(6, "called.");
717
718        return 0;
719}
720
721static int rutoken_error(ifd_reader_t * reader)
722{
723        (void)reader;
724
725        ifd_debug(6, "called.");
726
727        return IFD_ERROR_DEVICE_DISCONNECTED;
728}
729
730static struct ifd_driver_ops rutoken_driver;
731
732void ifd_rutoken_register(void)
733{
734        rutoken_driver.open = rutoken_open;
735        rutoken_driver.activate = rutoken_activate;
736        rutoken_driver.deactivate = rutoken_deactivate;
737        rutoken_driver.card_reset = rutoken_card_reset;
738        rutoken_driver.card_status = rutoken_card_status;
739        rutoken_driver.set_protocol = rutoken_set_protocol;
740        rutoken_driver.transparent = rutoken_transparent;
741        rutoken_driver.get_eventfd = rutoken_get_eventfd;
742        rutoken_driver.event = rutoken_event;
743        rutoken_driver.error = rutoken_error;
744
745        ifd_driver_register("rutoken", &rutoken_driver);
746}
747
Note: See TracBrowser for help on using the repository browser.