1 /***************************************************************************
2     begin       : Mon Mar 01 2004
3     copyright   : (C) 2004-2010 by Martin Preuss
4     email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *          Please see toplevel file COPYING for license details           *
8  ***************************************************************************/
9 
10 
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14 
15 #define LC_CARD_EXTEND_CLIENT
16 
17 
18 #include "card_p.h"
19 #include "client_l.h"
20 #include <gwenhywfar/debug.h>
21 #include <gwenhywfar/inherit.h>
22 #include <gwenhywfar/misc.h>
23 #include <gwenhywfar/text.h>
24 #include <gwenhywfar/gwentime.h>
25 #include <chipcard/chipcard.h>
26 
27 #ifdef OS_WIN32
28 # define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)
29 
30 # define FEATURE_VERIFY_PIN_START  0x01 /* OMNIKEY Proposal */
31 # define FEATURE_VERIFY_PIN_FINISH 0x02 /* OMNIKEY Proposal */
32 # define FEATURE_MODIFY_PIN_START  0x03 /* OMNIKEY Proposal */
33 # define FEATURE_MODIFY_PIN_FINISH 0x04 /* OMNIKEY Proposal */
34 # define FEATURE_GET_KEY_PRESSED   0x05 /* OMNIKEY Proposal */
35 # define FEATURE_VERIFY_PIN_DIRECT 0x06 /* USB CCID PIN Verify */
36 # define FEATURE_MODIFY_PIN_DIRECT 0x07 /* USB CCID PIN Modify */
37 # define FEATURE_MCT_READERDIRECT  0x08 /* KOBIL Proposal */
38 # define FEATURE_MCT_UNIVERSAL     0x09 /* KOBIL Proposal */
39 # define FEATURE_IFD_PIN_PROP      0x0A /* Gemplus Proposal */
40 # define FEATURE_ABORT             0x0B /* SCM Proposal */
41 
42 /* Set structure elements aligment on bytes
43  * http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */
44 #pragma pack(push, 1)
45 
46 /* the structure must be 6-bytes long */
47 typedef struct {
48   uint8_t tag;
49   uint8_t length;
50   uint32_t value;
51 } PCSC_TLV_STRUCTURE;
52 
53 #pragma pack(pop)
54 
55 
56 #elif defined (OS_DARWIN)
57 # define SCARD_CTL_CODE(code) (0x42000000 + (code))
58 # define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)
59 
60 # define FEATURE_VERIFY_PIN_START  0x01 /* OMNIKEY Proposal */
61 # define FEATURE_VERIFY_PIN_FINISH 0x02 /* OMNIKEY Proposal */
62 # define FEATURE_MODIFY_PIN_START  0x03 /* OMNIKEY Proposal */
63 # define FEATURE_MODIFY_PIN_FINISH 0x04 /* OMNIKEY Proposal */
64 # define FEATURE_GET_KEY_PRESSED   0x05 /* OMNIKEY Proposal */
65 # define FEATURE_VERIFY_PIN_DIRECT 0x06 /* USB CCID PIN Verify */
66 # define FEATURE_MODIFY_PIN_DIRECT 0x07 /* USB CCID PIN Modify */
67 # define FEATURE_MCT_READERDIRECT  0x08 /* KOBIL Proposal */
68 # define FEATURE_MCT_UNIVERSAL     0x09 /* KOBIL Proposal */
69 # define FEATURE_IFD_PIN_PROP      0x0A /* Gemplus Proposal */
70 # define FEATURE_ABORT             0x0B /* SCM Proposal */
71 
72 /* Set structure elements aligment on bytes
73  * http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */
74 #ifdef __APPLE__
75 #pragma pack(1)
76 #else
77 #pragma pack(push, 1)
78 #endif
79 
80 /* the structure must be 6-bytes long */
81 typedef struct {
82   uint8_t tag;
83   uint8_t length;
84   uint32_t value;
85 } PCSC_TLV_STRUCTURE;
86 
87 #ifdef __APPLE__
88 #pragma pack()
89 #else
90 #pragma pack(pop)
91 #endif
92 
93 #else
94 # include <PCSC/reader.h>
95 #endif
96 
97 
98 #include <stdlib.h>
99 #include <assert.h>
100 #include <string.h>
101 
102 
GWEN_LIST_FUNCTIONS(LC_CARD,LC_Card)103 GWEN_LIST_FUNCTIONS(LC_CARD, LC_Card)
104 GWEN_INHERIT_FUNCTIONS(LC_CARD)
105 GWEN_LIST2_FUNCTIONS(LC_CARD, LC_Card)
106 
107 
108 LC_CARD *LC_Card_new(LC_CLIENT *cl,
109 		     SCARDHANDLE scardHandle,
110 		     const char *readerName,
111 		     DWORD protocol,
112 		     const char *cardType,
113                      uint32_t rflags,
114                      const unsigned char *atrBuf,
115                      unsigned int atrLen) {
116   LC_CARD *cd;
117 
118   assert(cl);
119   assert(cardType);
120 
121   GWEN_NEW_OBJECT(LC_CARD, cd);
122   GWEN_LIST_INIT(LC_CARD, cd);
123   GWEN_INHERIT_INIT(LC_CARD, cd);
124   cd->client=cl;
125   cd->cardType=strdup(cardType);
126   cd->readerFlags=rflags;
127   cd->cardTypes=GWEN_StringList_new();
128   cd->dbCommandCache=GWEN_DB_Group_new("commandCache");
129   cd->usage=1;
130   if (atrBuf && atrLen) {
131     cd->atr=GWEN_Buffer_new(0, atrLen, 0, 1);
132     GWEN_Buffer_AppendBytes(cd->atr, (const char*)atrBuf, atrLen);
133   }
134 
135   cd->openFn=LC_Card__Open;
136   cd->closeFn=LC_Card__Close;
137 
138   /* determine card types by comparing the ATR to known ATRs */
139   if (cd->atr) {
140     int rv;
141 
142     rv=LC_Client_AddCardTypesByAtr(cl, cd);
143     if (rv) {
144       if (rv==1) {
145         DBG_WARN(LC_LOGDOMAIN, "Unknown card type (no matching ATR)");
146       }
147       else {
148         DBG_ERROR(LC_LOGDOMAIN, "Error determining card types");
149       }
150     }
151   }
152 
153   cd->readerName=strdup(readerName);
154   cd->scardHandle=scardHandle;
155   cd->protocol=protocol;
156 
157   return cd;
158 }
159 
160 
161 
LC_Card_free(LC_CARD * cd)162 void LC_Card_free(LC_CARD *cd){
163   if (cd) {
164     assert(cd->usage>0);
165     cd->usage--;
166     if (cd->usage==0) {
167       GWEN_INHERIT_FINI(LC_CARD, cd);
168       if (cd->connected) {
169         DBG_WARN(LC_LOGDOMAIN,
170                  "Card to be deleted is still connected");
171       }
172       free(cd->cardType);
173       free(cd->lastResult);
174       free(cd->lastText);
175       GWEN_StringList_free(cd->cardTypes);
176       GWEN_Buffer_free(cd->atr);
177       GWEN_DB_Group_free(cd->dbCommandCache);
178       GWEN_LIST_FINI(LC_CARD, cd);
179       GWEN_FREE_OBJECT(cd);
180     }
181   }
182 }
183 
184 
185 
LC_Card_List2_freeAll(LC_CARD_LIST2 * l)186 void LC_Card_List2_freeAll(LC_CARD_LIST2 *l){
187   if (l) {
188     LC_CARD_LIST2_ITERATOR *cit;
189 
190     cit=LC_Card_List2_First(l);
191     if (cit) {
192       LC_CARD *card;
193 
194       card=LC_Card_List2Iterator_Data(cit);
195       while(card) {
196         LC_CARD *next;
197 
198         next=LC_Card_List2Iterator_Next(cit);
199         LC_Card_free(card);
200         card=next;
201       } /* while */
202       LC_Card_List2Iterator_free(cit);
203     }
204     LC_Card_List2_free(l);
205   }
206 }
207 
208 
209 
LC_Card_GetSCardHandle(const LC_CARD * card)210 SCARDHANDLE LC_Card_GetSCardHandle(const LC_CARD *card) {
211   assert(card);
212   return card->scardHandle;
213 }
214 
215 
216 
LC_Card_IsConnected(const LC_CARD * card)217 int LC_Card_IsConnected(const LC_CARD *card) {
218   assert(card);
219   return card->connected;
220 }
221 
222 
223 
LC_Card_SetConnected(LC_CARD * card,int b)224 void LC_Card_SetConnected(LC_CARD *card, int b) {
225   assert(card);
226   card->connected=b;
227 }
228 
229 
230 
LC_Card_GetReaderType(const LC_CARD * cd)231 const char *LC_Card_GetReaderType(const LC_CARD *cd) {
232   assert(cd);
233   return cd->readerType;
234 }
235 
236 
237 
LC_Card_SetReaderType(LC_CARD * cd,const char * s)238 void LC_Card_SetReaderType(LC_CARD *cd, const char *s) {
239   assert(cd);
240   free(cd->readerType);
241   if (s)
242     cd->readerType=strdup(s);
243   else
244     cd->readerType=0;
245 }
246 
247 
248 
LC_Card_GetDriverType(const LC_CARD * cd)249 const char *LC_Card_GetDriverType(const LC_CARD *cd) {
250   assert(cd);
251   return cd->driverType;
252 }
253 
254 
255 
LC_Card_SetDriverType(LC_CARD * cd,const char * s)256 void LC_Card_SetDriverType(LC_CARD *cd, const char *s) {
257   assert(cd);
258   free(cd->driverType);
259   if (s)
260     cd->driverType=strdup(s);
261   else
262     cd->driverType=0;
263 }
264 
265 
266 
LC_Card_GetCardTypes(const LC_CARD * cd)267 const GWEN_STRINGLIST *LC_Card_GetCardTypes(const LC_CARD *cd){
268   assert(cd);
269   return cd->cardTypes;
270 }
271 
272 
273 
LC_Card_AddCardType(LC_CARD * cd,const char * s)274 int LC_Card_AddCardType(LC_CARD *cd, const char *s) {
275   assert(cd);
276   return GWEN_StringList_AppendString(cd->cardTypes, s, 0, 1);
277 }
278 
279 
280 
LC_Card_SetLastResult(LC_CARD * cd,const char * result,const char * text,int sw1,int sw2)281 void LC_Card_SetLastResult(LC_CARD *cd,
282                            const char *result,
283                            const char *text,
284                            int sw1, int sw2){
285   assert(cd);
286   free(cd->lastResult);
287   free(cd->lastText);
288   if (result)
289     cd->lastResult=strdup(result);
290   else
291     cd->lastResult=0;
292   if (text)
293     cd->lastText=strdup(text);
294   else
295     cd->lastText=0;
296   cd->lastSW1=sw1;
297   cd->lastSW2=sw2;
298 }
299 
300 
LC_Card_GetLastSW1(const LC_CARD * cd)301 int LC_Card_GetLastSW1(const LC_CARD *cd){
302   assert(cd);
303   return cd->lastSW1;
304 }
305 
306 
307 
LC_Card_GetLastSW2(const LC_CARD * cd)308 int LC_Card_GetLastSW2(const LC_CARD *cd){
309   assert(cd);
310   return cd->lastSW2;
311 }
312 
313 
314 
LC_Card_GetLastResult(const LC_CARD * cd)315 const char *LC_Card_GetLastResult(const LC_CARD *cd){
316   assert(cd);
317   return cd->lastResult;
318 }
319 
320 
321 
LC_Card_GetLastText(const LC_CARD * cd)322 const char *LC_Card_GetLastText(const LC_CARD *cd){
323   assert(cd);
324   return cd->lastText;
325 }
326 
327 
328 
LC_Card_GetClient(const LC_CARD * cd)329 LC_CLIENT *LC_Card_GetClient(const LC_CARD *cd){
330   assert(cd);
331   return cd->client;
332 }
333 
334 
335 
LC_Card_GetReaderFlags(const LC_CARD * cd)336 uint32_t LC_Card_GetReaderFlags(const LC_CARD *cd){
337   assert(cd);
338   return cd->readerFlags;
339 }
340 
341 
342 
LC_Card_GetCardType(const LC_CARD * cd)343 const char *LC_Card_GetCardType(const LC_CARD *cd){
344   assert(cd);
345   return cd->cardType;
346 }
347 
348 
349 
LC_Card_SetCardType(LC_CARD * cd,const char * ct)350 void LC_Card_SetCardType(LC_CARD *cd, const char *ct){
351   assert(cd);
352   assert(ct);
353 
354   free(cd->cardType);
355   cd->cardType=strdup(ct);
356 }
357 
358 
359 
LC_Card_GetAtr(const LC_CARD * cd,const unsigned char ** pbuf)360 unsigned int LC_Card_GetAtr(const LC_CARD *cd, const unsigned char **pbuf){
361   assert(cd);
362   if (cd->atr) {
363     unsigned int len;
364 
365     len=GWEN_Buffer_GetUsedBytes(cd->atr);
366     if (len) {
367       *pbuf=(const unsigned char*)GWEN_Buffer_GetStart(cd->atr);
368       return len;
369     }
370   }
371   return 0;
372 }
373 
374 
375 
LC_Card_GetFeatureCode(const LC_CARD * cd,int idx)376 uint32_t LC_Card_GetFeatureCode(const LC_CARD *cd, int idx) {
377   assert(cd);
378   assert(idx<LC_PCSC_MAX_FEATURES);
379   return cd->featureCode[idx];
380 }
381 
382 
383 
LC_Card_GetReaderName(const LC_CARD * card)384 const char *LC_Card_GetReaderName(const LC_CARD *card) {
385   assert(card);
386   return card->readerName;
387 }
388 
389 
390 
LC_Card_GetProtocol(const LC_CARD * card)391 DWORD LC_Card_GetProtocol(const LC_CARD *card) {
392   assert(card);
393   return card->protocol;
394 }
395 
396 
397 
LC_Card_Dump(const LC_CARD * cd,int insert)398 void LC_Card_Dump(const LC_CARD *cd, int insert) {
399   int k;
400   GWEN_STRINGLISTENTRY *se;
401   GWEN_DB_NODE *dbT;
402 
403   assert(cd);
404   for (k=0; k<insert; k++)
405     fprintf(stderr, " ");
406   fprintf(stderr, "Card\n");
407   for (k=0; k<insert; k++)
408     fprintf(stderr, " ");
409   fprintf(stderr,
410           "==================="
411           "==================="
412           "==================="
413           "==================\n");
414   for (k=0; k<insert; k++)
415     fprintf(stderr, " ");
416   fprintf(stderr, "Card type     : %s\n", cd->cardType);
417   for (k=0; k<insert; k++)
418     fprintf(stderr, " ");
419   fprintf(stderr, "Driver type   : %s\n", cd->driverType);
420   for (k=0; k<insert; k++)
421     fprintf(stderr, " ");
422   fprintf(stderr, "Reader type   : %s\n", cd->readerType);
423   for (k=0; k<insert; k++)
424     fprintf(stderr, " ");
425   fprintf(stderr, "Card types    :");
426   se=GWEN_StringList_FirstEntry(cd->cardTypes);
427   while(se) {
428     const char *s;
429 
430     s=GWEN_StringListEntry_Data(se);
431     assert(s);
432     fprintf(stderr, " %s", s);
433     se=GWEN_StringListEntry_Next(se);
434   } /* while */
435   fprintf(stderr, "\n");
436   for (k=0; k<insert; k++)
437     fprintf(stderr, " ");
438   fprintf(stderr, "Reader flags  : ");
439 
440   dbT=GWEN_DB_Group_new("flags");
441   LC_ReaderFlags_toDb(dbT, "flags", cd->readerFlags);
442   for (k=0; k<32; k++) {
443     const char *s;
444 
445     s=GWEN_DB_GetCharValue(dbT, "flags", k, 0);
446     if (!s)
447       break;
448     if (k)
449       fprintf(stderr, ", ");
450     fprintf(stderr, "%s", s);
451   }
452   fprintf(stderr, "\n");
453   GWEN_DB_Group_free(dbT);
454 
455   if (cd->atr) {
456     for (k=0; k<insert; k++)
457       fprintf(stderr, " ");
458     fprintf(stderr, "ATR\n");
459     for (k=0; k<insert; k++)
460       fprintf(stderr, " ");
461     fprintf(stderr,
462             "-------------------"
463             "-------------------"
464             "-------------------"
465             "------------------\n");
466     GWEN_Text_DumpString(GWEN_Buffer_GetStart(cd->atr),
467                          GWEN_Buffer_GetUsedBytes(cd->atr),
468                          insert+2);
469   }
470   for (k=0; k<insert; k++)
471     fprintf(stderr, " ");
472   fprintf(stderr,
473           "==================="
474           "==================="
475           "==================="
476           "==================\n");
477 }
478 
479 
480 
LC_Card_ReadFeatures(LC_CARD * card)481 LC_CLIENT_RESULT LC_Card_ReadFeatures(LC_CARD *card) {
482   LONG rv;
483   unsigned char rbuffer[300];
484   DWORD rblen;
485 
486   assert(card);
487 
488   /* get control codes */
489   DBG_INFO(LC_LOGDOMAIN, "Reading control codes for CCID features");
490   rv=SCardControl(card->scardHandle,
491 		  CM_IOCTL_GET_FEATURE_REQUEST,
492                   NULL,
493                   0,
494                   rbuffer,
495                   sizeof(rbuffer),
496                   &rblen);
497   if (rv!=SCARD_S_SUCCESS) {
498     DBG_INFO(LC_LOGDOMAIN,
499 	     "SCardControl: %04lx", (long unsigned int) rv);
500   }
501   else {
502     int cnt;
503     PCSC_TLV_STRUCTURE *tlv;
504     int i;
505 
506     /* clear keypad flag; if there is TLV indicating the reader has a keypad and
507      * the driver supports it we set the flag upon encounter of the tlv */
508     card->readerFlags&=~LC_READER_FLAGS_KEYPAD;
509     cnt=rblen/sizeof(PCSC_TLV_STRUCTURE);
510     tlv=(PCSC_TLV_STRUCTURE*)rbuffer;
511     for (i=0; i<cnt; i++) {
512       uint32_t v;
513 
514       v=tlv[i].value;
515 #ifdef LC_ENDIAN_LITTLE
516       v=((v & 0xff000000)>>24) |
517         ((v & 0x00ff0000)>>8) |
518         ((v & 0x0000ff00)<<8) |
519         ((v & 0x000000ff)<<24);
520 #endif
521       DBG_INFO(LC_LOGDOMAIN, "Feature %d: %08x", tlv[i].tag, v);
522       if (tlv[i].tag==FEATURE_VERIFY_PIN_DIRECT)
523 	card->readerFlags|=LC_READER_FLAGS_KEYPAD;
524       if (tlv[i].tag<LC_PCSC_MAX_FEATURES) {
525 	card->featureCode[tlv[i].tag]=v;
526       }
527     }
528   }
529 
530   /* done */
531   return LC_Client_ResultOk;
532 }
533 
534 
535 
LC_Card_Open(LC_CARD * card)536 LC_CLIENT_RESULT LC_Card_Open(LC_CARD *card) {
537   LONG rv;
538 
539   assert(card);
540 
541   rv=LC_Card_ReadFeatures(card);
542   if (rv!=LC_Client_ResultOk) {
543     DBG_INFO(LC_LOGDOMAIN, "here (%d)", (int) rv);
544   }
545 
546   LC_Card_SetLastResult(card, 0, 0, -1, -1);
547   if (!card->openFn) {
548     DBG_DEBUG(LC_LOGDOMAIN, "No OpenFn set");
549     return LC_Client_ResultOk;
550   }
551   return card->openFn(card);
552 }
553 
554 
555 
LC_Card_Close(LC_CARD * card)556 LC_CLIENT_RESULT LC_Card_Close(LC_CARD *card) {
557   LC_CLIENT_RESULT res;
558 
559   assert(card);
560   LC_Card_SetLastResult(card, 0, 0, -1, -1);
561   if (!card->closeFn) {
562     DBG_DEBUG(LC_LOGDOMAIN, "No CloseFn set");
563     res=LC_Client_ResultOk;
564   }
565   else
566     res=card->closeFn(card);
567   return res;
568 }
569 
570 
571 
LC_Card__Open(LC_CARD * card)572 LC_CLIENT_RESULT CHIPCARD_CB LC_Card__Open(LC_CARD *card) {
573   return LC_Client_ResultOk;
574 }
575 
576 
577 
LC_Card__Close(LC_CARD * card)578 LC_CLIENT_RESULT CHIPCARD_CB LC_Card__Close(LC_CARD *card) {
579   return LC_Client_ResultOk;
580 }
581 
582 
583 
LC_Card_ExecApdu(LC_CARD * card,const char * apdu,unsigned int len,GWEN_BUFFER * rbuf,LC_CLIENT_CMDTARGET t)584 LC_CLIENT_RESULT LC_Card_ExecApdu(LC_CARD *card,
585                                   const char *apdu,
586                                   unsigned int len,
587                                   GWEN_BUFFER *rbuf,
588                                   LC_CLIENT_CMDTARGET t) {
589   assert(card);
590   assert(card->client);
591   LC_Card_SetLastResult(card, 0, 0, -1, -1);
592   return LC_Client_ExecApdu(card->client,
593                             card,
594                             apdu,
595                             len,
596                             rbuf,
597                             t);
598 }
599 
600 
601 
LC_Card_ExecCommand(LC_CARD * card,const char * commandName,GWEN_DB_NODE * cmdData,GWEN_DB_NODE * rspData)602 LC_CLIENT_RESULT LC_Card_ExecCommand(LC_CARD *card,
603                                      const char *commandName,
604                                      GWEN_DB_NODE *cmdData,
605                                      GWEN_DB_NODE *rspData) {
606   LC_CLIENT_RESULT res;
607 
608   assert(card);
609   assert(card->client);
610   LC_Card_SetLastResult(card, 0, 0, -1, -1);
611   res=LC_Client_ExecCommand(card->client,
612                             card,
613                             commandName,
614                             cmdData,
615                             rspData);
616   return res;
617 }
618 
619 
620 
LC_Card_FindCommand(LC_CARD * card,const char * commandName)621 GWEN_XMLNODE *LC_Card_FindCommand(LC_CARD *card,
622                                   const char *commandName) {
623   GWEN_DB_NODE *db;
624   GWEN_XMLNODE *node;
625 
626   assert(card);
627   assert(commandName);
628 
629   db=card->dbCommandCache;
630   if (card->driverType) {
631     db=GWEN_DB_GetGroup(db, GWEN_DB_FLAGS_DEFAULT, card->driverType);
632     assert(db);
633   }
634   if (card->readerType) {
635     db=GWEN_DB_GetGroup(db, GWEN_DB_FLAGS_DEFAULT, card->readerType);
636     assert(db);
637   }
638 
639   node=(GWEN_XMLNODE*)GWEN_DB_GetPtrValue(db, commandName, 0, 0);
640   if (node==0) {
641     node=LC_Client_FindCardCommand(card->client, card, commandName);
642     if (node)
643       GWEN_DB_SetPtrValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
644                           commandName,
645                           (void*) node);
646   }
647   else {
648     DBG_INFO(LC_LOGDOMAIN, "Found command \"%s\" in cache", commandName);
649   }
650 
651   return node;
652 }
653 
654 
655 
LC_Card_BuildApdu(LC_CARD * card,const char * command,GWEN_DB_NODE * cmdData,GWEN_BUFFER * gbuf)656 LC_CLIENT_RESULT LC_Card_BuildApdu(LC_CARD *card,
657                                    const char *command,
658                                    GWEN_DB_NODE *cmdData,
659                                    GWEN_BUFFER *gbuf) {
660   assert(card);
661   assert(card->client);
662   return LC_Client_BuildApdu(card->client,
663                              card,
664                              command,
665                              cmdData,
666                              gbuf);
667 
668 }
669 
670 
671 
LC_Card_SelectApp(LC_CARD * card,const char * appName)672 LC_CLIENT_RESULT LC_Card_SelectApp(LC_CARD *card, const char *appName) {
673   GWEN_XMLNODE *node;
674 
675   node=LC_Client_GetAppNode(card->client, appName);
676   if (node==0) {
677     DBG_INFO(LC_LOGDOMAIN, "App not found");
678     return LC_Client_ResultNotFound;
679   }
680   card->appNode=node;
681   card->dfNode=0;
682   card->efNode=0;
683   return LC_Client_ResultOk;
684 }
685 
686 
687 
LC_Card_GetAppNode(const LC_CARD * card)688 GWEN_XMLNODE *LC_Card_GetAppNode(const LC_CARD *card) {
689   assert(card);
690   return card->appNode;
691 }
692 
693 
694 
LC_Card_SelectCard(LC_CARD * card,const char * s)695 LC_CLIENT_RESULT LC_Card_SelectCard(LC_CARD *card, const char *s) {
696   assert(card);
697   if (s==0)
698     card->cardNode=0;
699   else {
700     GWEN_XMLNODE *node;
701 
702     node=LC_Client_GetCardNode(card->client, s);
703     if (node==0) {
704       DBG_INFO(LC_LOGDOMAIN, "Card type not found");
705       return LC_Client_ResultNotFound;
706     }
707     card->cardNode=node;
708     DBG_INFO(LC_LOGDOMAIN, "Clearing command cache");
709     GWEN_DB_ClearGroup(card->dbCommandCache, NULL);
710   }
711   return LC_Client_ResultOk;
712 }
713 
714 
715 
LC_Card_GetCardNode(const LC_CARD * card)716 GWEN_XMLNODE *LC_Card_GetCardNode(const LC_CARD *card) {
717   assert(card);
718   return card->cardNode;
719 }
720 
721 
722 
723 
LC_Card_FindFile(LC_CARD * card,const char * type,const char * fname)724 GWEN_XMLNODE *LC_Card_FindFile(LC_CARD *card,
725                                const char *type,
726                                const char *fname) {
727   GWEN_XMLNODE *n;
728   GWEN_XMLNODE *currDF;
729   int isSameLevel;
730 
731   currDF=card->dfNode;
732   if (!currDF)
733     currDF=card->appNode;
734 
735   isSameLevel=1;
736   while(currDF) {
737     n=GWEN_XMLNode_FindNode(currDF, GWEN_XMLNodeTypeTag, "files");
738     if (n) {
739       n=GWEN_XMLNode_FindFirstTag(n, type, "name", fname);
740       if (n) {
741         if (isSameLevel) {
742           return n;
743         }
744         if (atoi(GWEN_XMLNode_GetProperty(n, "inAnyDF", "0"))!=0) {
745           DBG_DEBUG(LC_LOGDOMAIN, "Returning file from level above");
746           return n;
747         }
748       }
749     }
750     currDF=GWEN_XMLNode_GetParent(currDF);
751     isSameLevel=0;
752   }
753   DBG_DEBUG(LC_LOGDOMAIN, "%s \"%s\" not found", type, fname);
754   return 0;
755 }
756 
757 
758 
LC_Card_SelectMf(LC_CARD * card)759 LC_CLIENT_RESULT LC_Card_SelectMf(LC_CARD *card) {
760   GWEN_DB_NODE *dbReq;
761   GWEN_DB_NODE *dbRsp;
762   LC_CLIENT_RESULT res;
763 
764   dbReq=GWEN_DB_Group_new("request");
765   dbRsp=GWEN_DB_Group_new("response");
766   res=LC_Card_ExecCommand(card, "SelectMF", dbReq, dbRsp);
767   GWEN_DB_Group_free(dbRsp);
768   GWEN_DB_Group_free(dbReq);
769   if (res!=LC_Client_ResultOk) {
770     DBG_INFO(LC_LOGDOMAIN, "here (%d)", res);
771     return res;
772   }
773   card->dfNode=0;
774 
775   return LC_Client_ResultOk;
776 }
777 
778 
779 
LC_Card_SelectDf(LC_CARD * card,const char * fname)780 LC_CLIENT_RESULT LC_Card_SelectDf(LC_CARD *card, const char *fname) {
781   GWEN_XMLNODE *n;
782   GWEN_DB_NODE *dbReq;
783   GWEN_DB_NODE *dbRsp;
784   const char *cmd;
785   int fid;
786   LC_CLIENT_RESULT res;
787 
788   n=LC_Card_FindFile(card, "DF", fname);
789   if (!n) {
790     DBG_ERROR(LC_LOGDOMAIN, "DF \"%s\" not found", fname);
791     return LC_Client_ResultCmdError;
792   }
793 
794   if (1!=sscanf(GWEN_XMLNode_GetProperty(n, "sid", "-1"), "%i", &fid)){
795     DBG_ERROR(LC_LOGDOMAIN, "Bad id for DF \"%s\"", fname);
796     return LC_Client_ResultCmdError;
797   }
798 
799   dbReq=GWEN_DB_Group_new("request");
800   if (fid==-1) {
801     GWEN_BUFFER *buf;
802     const char *lid;
803 
804     buf=GWEN_Buffer_new(0, 64, 0, 1);
805     lid=GWEN_XMLNode_GetProperty(n, "lid", 0);
806     if (!lid) {
807       DBG_ERROR(LC_LOGDOMAIN, "No long id given in XML file");
808       GWEN_Buffer_free(buf);
809       GWEN_DB_Group_free(dbReq);
810       return LC_Client_ResultDataError;
811     }
812     if (GWEN_Text_FromHexBuffer(lid, buf)) {
813       DBG_ERROR(LC_LOGDOMAIN, "Bad long id given in XML file");
814       GWEN_Buffer_free(buf);
815       GWEN_DB_Group_free(dbReq);
816       return LC_Client_ResultDataError;
817     }
818 
819     GWEN_DB_SetBinValue(dbReq, GWEN_DB_FLAGS_OVERWRITE_VARS,
820                         "fileId",
821                         GWEN_Buffer_GetStart(buf),
822                         GWEN_Buffer_GetUsedBytes(buf));
823     cmd="SelectDFL";
824 
825   }
826   else {
827     GWEN_DB_SetIntValue(dbReq, GWEN_DB_FLAGS_OVERWRITE_VARS,
828                         "fileId", fid);
829     cmd="SelectDFS";
830   }
831 
832   dbRsp=GWEN_DB_Group_new("response");
833   res=LC_Card_ExecCommand(card, cmd, dbReq, dbRsp);
834   GWEN_DB_Group_free(dbRsp);
835   GWEN_DB_Group_free(dbReq);
836   if (res!=LC_Client_ResultOk) {
837     DBG_INFO(LC_LOGDOMAIN, "here (%d)", res);
838     return res;
839   }
840   card->dfNode=n;
841   card->efNode=0;
842 
843   return LC_Client_ResultOk;
844 }
845 
846 
847 
LC_Card_GetDfNode(const LC_CARD * card)848 GWEN_XMLNODE *LC_Card_GetDfNode(const LC_CARD *card) {
849   assert(card);
850   return card->dfNode;
851 }
852 
853 
854 
LC_Card_SelectEf(LC_CARD * card,const char * fname)855 LC_CLIENT_RESULT LC_Card_SelectEf(LC_CARD *card, const char *fname) {
856   GWEN_XMLNODE *n;
857   GWEN_DB_NODE *dbReq;
858   GWEN_DB_NODE *dbRsp;
859   const char *cmd;
860   int fid;
861   LC_CLIENT_RESULT res;
862 
863   n=LC_Card_FindFile(card, "EF", fname);
864   if (!n) {
865     DBG_ERROR(LC_LOGDOMAIN, "EF \"%s\" not found", fname);
866     return LC_Client_ResultCmdError;
867   }
868 
869   if (1!=sscanf(GWEN_XMLNode_GetProperty(n, "sid", "-1"), "%i", &fid)){
870     DBG_ERROR(LC_LOGDOMAIN, "Bad id for DF \"%s\"", fname);
871     return LC_Client_ResultCmdError;
872   }
873 
874   dbReq=GWEN_DB_Group_new("request");
875   if (fid==-1) {
876     GWEN_BUFFER *buf;
877     const char *lid;
878 
879     buf=GWEN_Buffer_new(0, 64, 0, 1);
880     lid=GWEN_XMLNode_GetProperty(n, "lid", 0);
881     if (!lid) {
882       DBG_ERROR(LC_LOGDOMAIN, "No long id given in XML file");
883       GWEN_Buffer_free(buf);
884       GWEN_DB_Group_free(dbReq);
885       return LC_Client_ResultDataError;
886     }
887     if (GWEN_Text_FromHexBuffer(lid, buf)) {
888       DBG_ERROR(LC_LOGDOMAIN, "Bad long id given in XML file");
889       GWEN_Buffer_free(buf);
890       GWEN_DB_Group_free(dbReq);
891       return LC_Client_ResultDataError;
892     }
893 
894     GWEN_DB_SetBinValue(dbReq, GWEN_DB_FLAGS_OVERWRITE_VARS,
895                         "fileId",
896                         GWEN_Buffer_GetStart(buf),
897                         GWEN_Buffer_GetUsedBytes(buf));
898     cmd="SelectEFL";
899 
900   }
901   else {
902     GWEN_DB_SetIntValue(dbReq, GWEN_DB_FLAGS_OVERWRITE_VARS,
903                         "fileId", fid);
904     cmd="SelectEFS";
905   }
906 
907   dbRsp=GWEN_DB_Group_new("response");
908   res=LC_Card_ExecCommand(card, cmd, dbReq, dbRsp);
909   GWEN_DB_Group_free(dbRsp);
910   GWEN_DB_Group_free(dbReq);
911   if (res!=LC_Client_ResultOk) {
912     DBG_INFO(LC_LOGDOMAIN, "here (%d)", res);
913     return res;
914   }
915   card->efNode=n;
916 
917   return LC_Client_ResultOk;
918 }
919 
920 
921 
LC_Card_GetEfNode(const LC_CARD * card)922 GWEN_XMLNODE *LC_Card_GetEfNode(const LC_CARD *card) {
923   assert(card);
924   return card->efNode;
925 }
926 
927 
928 
LC_Card_GetPinInfoById(LC_CARD * card,uint32_t pid)929 LC_PININFO *LC_Card_GetPinInfoById(LC_CARD *card, uint32_t pid) {
930   GWEN_XMLNODE *n;
931 
932   n=card->efNode;
933   if (!n)
934     n=card->dfNode;
935   if (!n)
936     n=card->appNode;
937   if (!n) {
938     DBG_INFO(LC_LOGDOMAIN, "No XML node");
939     return 0;
940   }
941 
942   while(n) {
943     GWEN_XMLNODE *nn;
944 
945     nn=GWEN_XMLNode_FindFirstTag(n, "pins", 0, 0);
946     while (nn) {
947       GWEN_XMLNODE *nnn;
948 
949       nnn=GWEN_XMLNode_FindFirstTag(nn, "pin", 0, 0);
950       while(nnn) {
951         const char *s;
952 
953         s=GWEN_XMLNode_GetProperty(nnn, "id", 0);
954         if (s) {
955           int i;
956 
957           if (sscanf(s, "%i", &i)==1) {
958             if (i==(int)pid) {
959               LC_PININFO *pi;
960 
961               pi=LC_PinInfo_new();
962               LC_PinInfo_SetId(pi, pid);
963               s=GWEN_XMLNode_GetProperty(nnn, "name", 0);
964               LC_PinInfo_SetName(pi, s);
965               if (1==sscanf(GWEN_XMLNode_GetProperty(nnn, "minLen", "0"),
966                             "%i", &i))
967                 LC_PinInfo_SetMinLength(pi, i);
968               if (1==sscanf(GWEN_XMLNode_GetProperty(nnn, "maxLen", "0"),
969                             "%i", &i))
970                 LC_PinInfo_SetMaxLength(pi, i);
971               if (1==sscanf(GWEN_XMLNode_GetProperty(nnn, "allowChange", "0"),
972                             "%i", &i))
973                 LC_PinInfo_SetAllowChange(pi, i);
974               if (1==sscanf(GWEN_XMLNode_GetProperty(nnn, "filler", "0"),
975                             "%i", &i))
976                 LC_PinInfo_SetFiller(pi, i);
977               s=GWEN_XMLNode_GetProperty(nnn, "encoding", 0);
978               if (s)
979                 LC_PinInfo_SetEncoding(pi, GWEN_Crypt_PinEncoding_fromString(s));
980               return pi;
981             }
982           }
983         }
984         nnn=GWEN_XMLNode_FindNextTag(nnn, "pin", 0, 0);
985       }
986 
987       nn=GWEN_XMLNode_FindNextTag(nn, "pins", 0, 0);
988     }
989 
990     n=GWEN_XMLNode_GetParent(n);
991   }
992 
993   return 0;
994 }
995 
996 
997 
LC_Card_GetPinInfoByName(LC_CARD * card,const char * name)998 LC_PININFO *LC_Card_GetPinInfoByName(LC_CARD *card, const char *name) {
999   GWEN_XMLNODE *n;
1000 
1001   assert(card);
1002   assert(card->usage);
1003 
1004   n=card->efNode;
1005   if (!n) {
1006     DBG_DEBUG(LC_LOGDOMAIN, "No EF node");
1007     n=card->dfNode;
1008   }
1009   if (!n) {
1010     DBG_DEBUG(LC_LOGDOMAIN, "No DF node");
1011     n=card->appNode;
1012   }
1013   if (!n) {
1014     DBG_INFO(LC_LOGDOMAIN, "No XML node");
1015     return 0;
1016   }
1017 
1018   while(n) {
1019     GWEN_XMLNODE *nn;
1020 
1021     DBG_DEBUG(LC_LOGDOMAIN, "Searching in \"%s\" (%s)",
1022               GWEN_XMLNode_GetProperty(n, "name", "(none)"),
1023               GWEN_XMLNode_GetData(n));
1024 
1025     nn=GWEN_XMLNode_FindFirstTag(n, "pins", 0, 0);
1026     while (nn) {
1027       GWEN_XMLNODE *nnn;
1028 
1029       nnn=GWEN_XMLNode_FindFirstTag(nn, "pin", 0, 0);
1030       while(nnn) {
1031         const char *s;
1032         int i;
1033 
1034         s=GWEN_XMLNode_GetProperty(nnn, "id", 0);
1035         if (s && sscanf(s, "%i", &i)==1) {
1036           s=GWEN_XMLNode_GetProperty(nnn, "name", 0);
1037           if (s && strcasecmp(s, name)==0) {
1038             LC_PININFO *pi;
1039 
1040             pi=LC_PinInfo_new();
1041             LC_PinInfo_SetId(pi, (uint32_t)i);
1042             s=GWEN_XMLNode_GetProperty(nnn, "name", 0);
1043             LC_PinInfo_SetName(pi, s);
1044             if (1==sscanf(GWEN_XMLNode_GetProperty(nnn, "minLen", "0"),
1045                           "%i", &i))
1046               LC_PinInfo_SetMinLength(pi, i);
1047             if (1==sscanf(GWEN_XMLNode_GetProperty(nnn, "maxLen", "0"),
1048                           "%i", &i))
1049               LC_PinInfo_SetMaxLength(pi, i);
1050             if (1==sscanf(GWEN_XMLNode_GetProperty(nnn, "allowChange", "0"),
1051                           "%i", &i))
1052               LC_PinInfo_SetAllowChange(pi, i);
1053             if (1==sscanf(GWEN_XMLNode_GetProperty(nnn, "filler", "0"),
1054                           "%i", &i))
1055               LC_PinInfo_SetFiller(pi, i);
1056             s=GWEN_XMLNode_GetProperty(nnn, "encoding", 0);
1057             if (s)
1058               LC_PinInfo_SetEncoding(pi, GWEN_Crypt_PinEncoding_fromString(s));
1059             return pi;
1060           }
1061         }
1062         nnn=GWEN_XMLNode_FindNextTag(nnn, "pin", 0, 0);
1063       }
1064 
1065       nn=GWEN_XMLNode_FindNextTag(nn, "pins", 0, 0);
1066     }
1067 
1068     n=GWEN_XMLNode_GetParent(n);
1069   }
1070 
1071   return 0;
1072 }
1073 
1074 
1075 
LC_Card_ParseData(LC_CARD * card,const char * format,GWEN_BUFFER * buf,GWEN_DB_NODE * dbData)1076 LC_CLIENT_RESULT LC_Card_ParseData(LC_CARD *card,
1077                                    const char *format,
1078                                    GWEN_BUFFER *buf,
1079                                    GWEN_DB_NODE *dbData) {
1080   GWEN_XMLNODE *dataNode;
1081   GWEN_MSGENGINE *e;
1082 
1083   /* find format node */
1084   assert(card->appNode);
1085   e=LC_Client_GetMsgEngine(card->client);
1086   assert(e);
1087   if (!GWEN_Buffer_GetBytesLeft(buf)) {
1088     DBG_ERROR(LC_LOGDOMAIN, "End of buffer reached");
1089     return LC_Client_ResultNoData;
1090   }
1091   dataNode=GWEN_XMLNode_FindFirstTag(card->appNode, "formats", 0, 0);
1092   if (dataNode==0) {
1093     DBG_ERROR(LC_LOGDOMAIN, "No formats for this card application");
1094     return LC_Client_ResultNotFound;
1095   }
1096 
1097   dataNode=GWEN_XMLNode_FindFirstTag(dataNode, "format", "name", format);
1098   if (!dataNode) {
1099     DBG_ERROR(LC_LOGDOMAIN, "Format \"%s\" not found", format);
1100     return LC_Client_ResultNotFound;
1101   }
1102 
1103   /* node found, parse data */
1104   DBG_DEBUG(LC_LOGDOMAIN, "Parsing data");
1105   if (GWEN_MsgEngine_ParseMessage(e,
1106                                   dataNode,
1107                                   buf,
1108                                   dbData,
1109                                   GWEN_MSGENGINE_READ_FLAGS_DEFAULT)){
1110     DBG_ERROR(LC_LOGDOMAIN, "Error parsing data in format \"%s\"", format);
1111     return LC_Client_ResultDataError;
1112   }
1113 
1114   return LC_Client_ResultOk;
1115 }
1116 
1117 
1118 
LC_Card_CreateData(LC_CARD * card,const char * format,GWEN_BUFFER * buf,GWEN_DB_NODE * dbData)1119 LC_CLIENT_RESULT LC_Card_CreateData(LC_CARD *card,
1120                                     const char *format,
1121                                     GWEN_BUFFER *buf,
1122                                     GWEN_DB_NODE *dbData){
1123   GWEN_XMLNODE *dataNode;
1124   GWEN_MSGENGINE *e;
1125 
1126   /* find record node */
1127   assert(card->appNode);
1128   e=LC_Client_GetMsgEngine(card->client);
1129   assert(e);
1130 
1131   dataNode=GWEN_XMLNode_FindFirstTag(card->appNode, "formats", 0, 0);
1132   if (dataNode==0) {
1133     DBG_ERROR(LC_LOGDOMAIN, "No formats for this card application");
1134     return LC_Client_ResultNoData;
1135   }
1136 
1137   dataNode=GWEN_XMLNode_FindFirstTag(dataNode, "format", "name", format);
1138   if (!dataNode) {
1139     DBG_ERROR(LC_LOGDOMAIN, "Format \"%s\" not found", format);
1140     return LC_Client_ResultNoData;
1141   }
1142 
1143   /* node found, parse data */
1144   DBG_DEBUG(LC_LOGDOMAIN, "Creating data");
1145   if (GWEN_MsgEngine_CreateMessageFromNode(e,
1146                                            dataNode,
1147                                            buf,
1148                                            dbData)) {
1149     DBG_ERROR(LC_LOGDOMAIN, "Error creating data for format \"%s\"", format);
1150     return LC_Client_ResultDataError;
1151   }
1152 
1153   return LC_Client_ResultOk;
1154 }
1155 
1156 
1157 
LC_Card_ParseRecord(LC_CARD * card,int recNum,GWEN_BUFFER * buf,GWEN_DB_NODE * dbRecord)1158 LC_CLIENT_RESULT LC_Card_ParseRecord(LC_CARD *card,
1159                                      int recNum,
1160                                      GWEN_BUFFER *buf,
1161                                      GWEN_DB_NODE *dbRecord){
1162   GWEN_XMLNODE *recordNode;
1163   GWEN_MSGENGINE *e;
1164 
1165   /* find record node */
1166   assert(card->efNode);
1167   e=LC_Client_GetMsgEngine(card->client);
1168   assert(e);
1169   if (!GWEN_Buffer_GetBytesLeft(buf)) {
1170     DBG_ERROR(LC_LOGDOMAIN, "End of buffer reached");
1171     return LC_Client_ResultNoData;
1172   }
1173   recordNode=GWEN_XMLNode_FindFirstTag(card->efNode, "record", 0, 0);
1174   while(recordNode) {
1175     int lrecNum;
1176 
1177     if (1==sscanf(GWEN_XMLNode_GetProperty(recordNode,
1178                                            "recnum", "-1"),
1179                   "%i", &lrecNum)) {
1180       if (lrecNum!=-1 && recNum==lrecNum)
1181         break;
1182     }
1183     recordNode=GWEN_XMLNode_FindNextTag(recordNode, "record", 0, 0);
1184   } /* while */
1185   if (!recordNode)
1186     recordNode=GWEN_XMLNode_FindFirstTag(card->efNode,"record", 0, 0);
1187 
1188   if (recordNode) {
1189     /* node found, parse data */
1190     DBG_DEBUG(LC_LOGDOMAIN, "Parsing record data");
1191     if (GWEN_MsgEngine_ParseMessage(e,
1192                                     recordNode,
1193                                     buf,
1194                                     dbRecord,
1195                                     GWEN_MSGENGINE_READ_FLAGS_DEFAULT)){
1196       DBG_ERROR(LC_LOGDOMAIN, "Error parsing response");
1197       return LC_Client_ResultDataError;
1198     }
1199   } /* if record found */
1200   else {
1201     DBG_ERROR(LC_LOGDOMAIN, "Record not found");
1202     return LC_Client_ResultNotFound;
1203   }
1204   return LC_Client_ResultOk;
1205 }
1206 
1207 
1208 
LC_Card_CreateRecord(LC_CARD * card,int recNum,GWEN_BUFFER * buf,GWEN_DB_NODE * dbRecord)1209 LC_CLIENT_RESULT LC_Card_CreateRecord(LC_CARD *card,
1210                                       int recNum,
1211                                       GWEN_BUFFER *buf,
1212                                       GWEN_DB_NODE *dbRecord){
1213   GWEN_XMLNODE *recordNode;
1214   GWEN_MSGENGINE *e;
1215 
1216   /* find record node */
1217   assert(card->efNode);
1218   e=LC_Client_GetMsgEngine(card->client);
1219   assert(e);
1220   recordNode=GWEN_XMLNode_FindFirstTag(card->efNode, "record", 0, 0);
1221   while(recordNode) {
1222     int lrecNum;
1223 
1224     if (1==sscanf(GWEN_XMLNode_GetProperty(recordNode,
1225                                            "recnum", "-1"),
1226                   "%i", &lrecNum)) {
1227       if (lrecNum!=-1 && recNum==lrecNum)
1228         break;
1229     }
1230     recordNode=GWEN_XMLNode_FindNextTag(recordNode, "record", 0, 0);
1231   } /* while */
1232   if (!recordNode)
1233     recordNode=GWEN_XMLNode_FindFirstTag(card->efNode,"record", 0, 0);
1234 
1235   if (recordNode) {
1236     /* node found, parse data */
1237     DBG_DEBUG(LC_LOGDOMAIN, "Creating record data");
1238     if (GWEN_MsgEngine_CreateMessageFromNode(e,
1239                                              recordNode,
1240                                              buf,
1241                                              dbRecord)) {
1242       DBG_ERROR(LC_LOGDOMAIN, "Error creating record");
1243       return LC_Client_ResultDataError;
1244     }
1245   } /* if record found */
1246   else {
1247     DBG_ERROR(LC_LOGDOMAIN, "Record not found");
1248     return LC_Client_ResultNotFound;
1249   }
1250   return LC_Client_ResultOk;
1251 }
1252 
1253 
1254 
LC_Card_GetPinStatus(LC_CARD * card,unsigned int pid,int * maxErrors,int * currentErrors)1255 LC_CLIENT_RESULT LC_Card_GetPinStatus(LC_CARD *card,
1256                                       unsigned int pid,
1257                                       int *maxErrors,
1258                                       int *currentErrors) {
1259   assert(card);
1260   if (card->getPinStatusFn) {
1261     return card->getPinStatusFn(card, pid, maxErrors, currentErrors);
1262   }
1263   else {
1264     DBG_INFO(LC_LOGDOMAIN,
1265              "no getInitialPin function set");
1266     return LC_Client_ResultNotSupported;
1267   }
1268 }
1269 
1270 
1271 
LC_Card_GetInitialPin(LC_CARD * card,int id,unsigned char * buffer,unsigned int maxLen,unsigned int * pinLength)1272 LC_CLIENT_RESULT LC_Card_GetInitialPin(LC_CARD *card,
1273                                        int id,
1274                                        unsigned char *buffer,
1275                                        unsigned int maxLen,
1276                                        unsigned int *pinLength) {
1277   assert(card);
1278   if (card->getInitialPinFn) {
1279     return card->getInitialPinFn(card, id, buffer, maxLen, pinLength);
1280   }
1281   else {
1282     DBG_ERROR(LC_LOGDOMAIN,
1283               "no getInitialPin function set");
1284     return LC_Client_ResultNotSupported;
1285   }
1286 }
1287 
1288 
1289 
LC_Card_GetOpenFn(const LC_CARD * card)1290 LC_CARD_OPEN_FN LC_Card_GetOpenFn(const LC_CARD *card){
1291   assert(card);
1292   return card->openFn;
1293 }
1294 
1295 
1296 
LC_Card_SetOpenFn(LC_CARD * card,LC_CARD_OPEN_FN fn)1297 void LC_Card_SetOpenFn(LC_CARD *card, LC_CARD_OPEN_FN fn){
1298   assert(card);
1299   card->openFn=fn;
1300 }
1301 
1302 
1303 
LC_Card_GetCloseFn(const LC_CARD * card)1304 LC_CARD_CLOSE_FN LC_Card_GetCloseFn(const LC_CARD *card){
1305   assert(card);
1306   return card->closeFn;
1307 }
1308 
1309 
1310 
LC_Card_SetCloseFn(LC_CARD * card,LC_CARD_CLOSE_FN fn)1311 void LC_Card_SetCloseFn(LC_CARD *card, LC_CARD_CLOSE_FN fn){
1312   assert(card);
1313   card->closeFn=fn;
1314 }
1315 
1316 
1317 
LC_Card_SetGetPinStatusFn(LC_CARD * card,LC_CARD_GETPINSTATUS_FN fn)1318 void LC_Card_SetGetPinStatusFn(LC_CARD *card, LC_CARD_GETPINSTATUS_FN fn) {
1319   assert(card);
1320   card->getPinStatusFn=fn;
1321 }
1322 
1323 
1324 
LC_Card_SetGetInitialPinFn(LC_CARD * card,LC_CARD_GETINITIALPIN_FN fn)1325 void LC_Card_SetGetInitialPinFn(LC_CARD *card, LC_CARD_GETINITIALPIN_FN fn){
1326   assert(card);
1327   card->getInitialPinFn=fn;
1328 }
1329 
1330 
1331 
LC_Card_CreateResultString(const LC_CARD * card,const char * lastCommand,LC_CLIENT_RESULT res,GWEN_BUFFER * buf)1332 void LC_Card_CreateResultString(const LC_CARD *card,
1333                                 const char *lastCommand,
1334                                 LC_CLIENT_RESULT res,
1335                                 GWEN_BUFFER *buf) {
1336   const char *s;
1337 
1338   switch(res) {
1339   case LC_Client_ResultOk:
1340     s="Ok.";
1341     break;
1342   case LC_Client_ResultWait:
1343     s="Timeout.";
1344     break;
1345   case LC_Client_ResultIpcError:
1346     s="IPC error.";
1347     break;
1348   case LC_Client_ResultCmdError:
1349     s="Command error.";
1350     break;
1351   case LC_Client_ResultDataError:
1352     s="Data error.";
1353     break;
1354   case LC_Client_ResultAborted:
1355     s="Aborted.";
1356     break;
1357   case LC_Client_ResultInvalid:
1358     s="Invalid argument to command.";
1359     break;
1360   case LC_Client_ResultInternal:
1361     s="Internal error.";
1362     break;
1363   case LC_Client_ResultGeneric:
1364     s="Generic error.";
1365     break;
1366   default:
1367     s="Unknown error.";
1368     break;
1369   }
1370 
1371   GWEN_Buffer_AppendString(buf, "Result of \"");
1372   GWEN_Buffer_AppendString(buf, lastCommand);
1373   GWEN_Buffer_AppendString(buf, "\": ");
1374   GWEN_Buffer_AppendString(buf, s);
1375 
1376   if (res==LC_Client_ResultCmdError && card) {
1377     int sw1;
1378     int sw2;
1379     char numbuf[32];
1380 
1381     sw1=LC_Card_GetLastSW1(card);
1382     sw2=LC_Card_GetLastSW2(card);
1383     GWEN_Buffer_AppendString(buf, " (");
1384     if (sw1!=-1 && sw2!=-1) {
1385       GWEN_Buffer_AppendString(buf, " SW1=");
1386       snprintf(numbuf, sizeof(numbuf), "%02x", sw1);
1387       GWEN_Buffer_AppendString(buf, numbuf);
1388       GWEN_Buffer_AppendString(buf, " SW2=");
1389       snprintf(numbuf, sizeof(numbuf), "%02x", sw2);
1390       GWEN_Buffer_AppendString(buf, numbuf);
1391     }
1392     s=LC_Card_GetLastResult(card);
1393     if (s) {
1394       GWEN_Buffer_AppendString(buf, " result=");
1395       GWEN_Buffer_AppendString(buf, s);
1396     }
1397     s=LC_Card_GetLastText(card);
1398     if (s) {
1399       GWEN_Buffer_AppendString(buf, " text=");
1400       GWEN_Buffer_AppendString(buf, s);
1401     }
1402     GWEN_Buffer_AppendString(buf, " )");
1403   }
1404 }
1405 
1406 
1407 
LC_Card_ReadBinary(LC_CARD * card,int offset,int size,GWEN_BUFFER * buf)1408 LC_CLIENT_RESULT LC_Card_ReadBinary(LC_CARD *card,
1409 				    int offset,
1410 				    int size,
1411 				    GWEN_BUFFER *buf){
1412   int t;
1413   int bytesRead=0;
1414   LC_CLIENT_RESULT res;
1415 
1416   while(size>0) {
1417     int sw1;
1418     int sw2;
1419 
1420     if (size>252)
1421       t=252;
1422     else
1423       t=size;
1424     res=LC_Card_IsoReadBinary(card, 0,
1425                               offset, t, buf);
1426     if (res!=LC_Client_ResultOk) {
1427       if (res==LC_Client_ResultNoData && bytesRead)
1428         return LC_Client_ResultOk;
1429       return res;
1430     }
1431 
1432     size-=t;
1433     offset+=t;
1434     bytesRead+=t;
1435 
1436     /* check for EOF */
1437     sw1=LC_Card_GetLastSW1(card);
1438     sw2=LC_Card_GetLastSW2(card);
1439     if (sw1==0x62 && sw2==0x82) {
1440       DBG_DEBUG(LC_LOGDOMAIN, "EOF met after %d bytes (asked for %d bytes more)", bytesRead, size);
1441       break;
1442     }
1443   } /* while still data to read */
1444 
1445   return LC_Client_ResultOk;
1446 }
1447 
1448 
1449 
1450 #include "card_iso.c"
1451 
1452 
1453 
1454 
1455 
1456 
1457 
1458 
1459