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