scd: Fix "Conflicting usage" bug.
[gnupg.git] / scd / app.c
1 /* app.c - Application selection.
2  *      Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <npth.h>
26
27 #include "scdaemon.h"
28 #include "app-common.h"
29 #include "iso7816.h"
30 #include "apdu.h"
31 #include "tlv.h"
32
33 /* This table is used to keep track of locks on a per reader base.
34    The index into the table is the slot number of the reader.  The
35    mutex will be initialized on demand (one of the advantages of a
36    userland threading system). */
37 static struct
38 {
39   int initialized;
40   npth_mutex_t lock;
41   app_t app;        /* Application context in use or NULL. */
42   app_t last_app;   /* Last application object used as this slot or NULL. */
43 } lock_table[10];
44
45
46
47 static void deallocate_app (app_t app);
48
49
50 \f
51 static void
52 print_progress_line (void *opaque, const char *what, int pc, int cur, int tot)
53 {
54   ctrl_t ctrl = opaque;
55   char line[100];
56
57   if (ctrl)
58     {
59       snprintf (line, sizeof line, "%s %c %d %d", what, pc, cur, tot);
60       send_status_direct (ctrl, "PROGRESS", line);
61     }
62 }
63
64
65 /* Lock the reader SLOT.  This function shall be used right before
66    calling any of the actual application functions to serialize access
67    to the reader.  We do this always even if the reader is not
68    actually used.  This allows an actual connection to assume that it
69    never shares a reader (while performing one command).  Returns 0 on
70    success; only then the unlock_reader function must be called after
71    returning from the handler. */
72 static gpg_error_t
73 lock_reader (int slot, ctrl_t ctrl)
74 {
75   int res;
76
77   if (slot < 0 || slot >= DIM (lock_table))
78     return gpg_error (slot<0? GPG_ERR_INV_VALUE : GPG_ERR_RESOURCE_LIMIT);
79
80   if (!lock_table[slot].initialized)
81     {
82       res = npth_mutex_init (&lock_table[slot].lock, NULL);
83       if (res)
84         {
85           log_error ("error initializing mutex: %s\n", strerror (res));
86           return gpg_error_from_errno (res);
87         }
88       lock_table[slot].initialized = 1;
89       lock_table[slot].app = NULL;
90       lock_table[slot].last_app = NULL;
91     }
92
93   res = npth_mutex_lock (&lock_table[slot].lock);
94   if (res)
95     {
96       log_error ("failed to acquire APP lock for slot %d: %s\n",
97                  slot, strerror (res));
98       return gpg_error_from_errno (res);
99     }
100
101   apdu_set_progress_cb (slot, print_progress_line, ctrl);
102
103   return 0;
104 }
105
106 /* Release a lock on the reader.  See lock_reader(). */
107 static void
108 unlock_reader (int slot)
109 {
110   int res;
111
112   if (slot < 0 || slot >= DIM (lock_table)
113       || !lock_table[slot].initialized)
114     log_bug ("unlock_reader called for invalid slot %d\n", slot);
115
116   apdu_set_progress_cb (slot, NULL, NULL);
117
118   res = npth_mutex_unlock (&lock_table[slot].lock);
119   if (res)
120     log_error ("failed to release APP lock for slot %d: %s\n",
121                slot, strerror (res));
122 }
123
124
125 /* This function may be called to print information pertaining to the
126    current state of this module to the log. */
127 void
128 app_dump_state (void)
129 {
130   int slot;
131
132   for (slot=0; slot < DIM (lock_table); slot++)
133     if (lock_table[slot].initialized)
134       {
135         log_info ("app_dump_state: slot=%d", slot);
136         if (lock_table[slot].app)
137           {
138             log_printf (" app=%p", lock_table[slot].app);
139             if (lock_table[slot].app->apptype)
140               log_printf (" type='%s'", lock_table[slot].app->apptype);
141           }
142         if (lock_table[slot].last_app)
143           {
144             log_printf (" lastapp=%p", lock_table[slot].last_app);
145             if (lock_table[slot].last_app->apptype)
146               log_printf (" type='%s'", lock_table[slot].last_app->apptype);
147           }
148         log_printf ("\n");
149       }
150 }
151
152 /* Check wether the application NAME is allowed.  This does not mean
153    we have support for it though.  */
154 static int
155 is_app_allowed (const char *name)
156 {
157   strlist_t l;
158
159   for (l=opt.disabled_applications; l; l = l->next)
160     if (!strcmp (l->d, name))
161       return 0; /* no */
162   return 1; /* yes */
163 }
164
165
166 /* This may be called to tell this module about a removed or resetted card. */
167 void
168 application_notify_card_reset (int slot)
169 {
170   app_t app;
171
172   if (slot < 0 || slot >= DIM (lock_table))
173     return;
174
175   /* FIXME: We are ignoring any error value here.  */
176   lock_reader (slot, NULL);
177
178   /* Release the APP, as it's not reusable any more.  */
179   if (lock_table[slot].app)
180     {
181       deallocate_app (lock_table[slot].app);
182       lock_table[slot].app = NULL;
183     }
184
185   /* Deallocate a saved application for that slot, so that we won't
186      try to reuse it.  If there is no saved application, set a flag so
187      that we won't save the current state. */
188   app = lock_table[slot].last_app;
189
190   if (app)
191     {
192       lock_table[slot].last_app = NULL;
193       deallocate_app (app);
194     }
195   unlock_reader (slot);
196 }
197
198
199 /* This function is used by the serialno command to check for an
200    application conflict which may appear if the serialno command is
201    used to request a specific application and the connection has
202    already done a select_application. */
203 gpg_error_t
204 check_application_conflict (ctrl_t ctrl, int slot, const char *name)
205 {
206   app_t app;
207
208   (void)ctrl;
209
210   if (slot < 0 || slot >= DIM (lock_table))
211     return gpg_error (GPG_ERR_INV_VALUE);
212
213   app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
214   if (app && app->apptype && name)
215     if ( ascii_strcasecmp (app->apptype, name))
216       return gpg_error (GPG_ERR_CONFLICT);
217   return 0;
218 }
219
220
221 /* If called with NAME as NULL, select the best fitting application
222    and return a context; otherwise select the application with NAME
223    and return a context.  SLOT identifies the reader device. Returns
224    an error code and stores NULL at R_APP if no application was found
225    or no card is present. */
226 gpg_error_t
227 select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
228 {
229   gpg_error_t err;
230   app_t app = NULL;
231   unsigned char *result = NULL;
232   size_t resultlen;
233   int want_undefined;
234
235   (void)ctrl;
236
237   *r_app = NULL;
238
239   want_undefined = (name && !strcmp (name, "undefined"));
240
241   err = lock_reader (slot, ctrl);
242   if (err)
243     return err;
244
245   /* First check whether we already have an application to share. */
246   app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
247   if (app && name)
248     if (!app->apptype || ascii_strcasecmp (app->apptype, name))
249       {
250         unlock_reader (slot);
251         if (app->apptype)
252           log_info ("application '%s' in use by reader %d - can't switch\n",
253                     app->apptype, slot);
254         return gpg_error (GPG_ERR_CONFLICT);
255       }
256
257   /* If we don't have an app, check whether we have a saved
258      application for that slot.  This is useful so that a card does
259      not get reset even if only one session is using the card - this
260      way the PIN cache and other cached data are preserved.  */
261   if (!app && lock_table[slot].initialized && lock_table[slot].last_app)
262     {
263       app = lock_table[slot].last_app;
264       if (!name || (app->apptype && !ascii_strcasecmp (app->apptype, name)) )
265         {
266           /* Yes, we can reuse this application - either the caller
267              requested an unspecific one or the requested one matches
268              the saved one. */
269           lock_table[slot].app = app;
270           lock_table[slot].last_app = NULL;
271         }
272       else
273         {
274           /* No, this saved application can't be used - deallocate it. */
275           lock_table[slot].last_app = NULL;
276           deallocate_app (app);
277           app = NULL;
278         }
279     }
280
281   /* If we can reuse an application, bump the reference count and
282      return it.  */
283   if (app)
284     {
285       if (app->slot != slot)
286         log_bug ("slot mismatch %d/%d\n", app->slot, slot);
287       app->slot = slot;
288
289       app->ref_count++;
290       *r_app = app;
291       unlock_reader (slot);
292       return 0; /* Okay: We share that one. */
293     }
294
295   /* Need to allocate a new one.  */
296   app = xtrycalloc (1, sizeof *app);
297   if (!app)
298     {
299       err = gpg_error_from_syserror ();
300       log_info ("error allocating context: %s\n", gpg_strerror (err));
301       unlock_reader (slot);
302       return err;
303     }
304   app->slot = slot;
305
306
307   /* Fixme: We should now first check whether a card is at all
308      present. */
309
310   /* Try to read the GDO file first to get a default serial number.
311      We skip this if the undefined application has been requested. */
312   if (!want_undefined)
313     {
314       err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
315       if (!err)
316         err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
317       if (!err)
318         err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
319       if (!err)
320         {
321           size_t n;
322           const unsigned char *p;
323
324           p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
325           if (p)
326             resultlen -= (p-result);
327           if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
328             {
329               /* The object it does not fit into the buffer.  This is an
330                  invalid encoding (or the buffer is too short.  However, I
331                  have some test cards with such an invalid encoding and
332                  therefore I use this ugly workaround to return something
333                  I can further experiment with. */
334               log_info ("enabling BMI testcard workaround\n");
335               n--;
336             }
337
338           if (p && n <= resultlen)
339             {
340               /* The GDO file is pretty short, thus we simply reuse it for
341                  storing the serial number. */
342               memmove (result, p, n);
343               app->serialno = result;
344               app->serialnolen = n;
345               err = app_munge_serialno (app);
346               if (err)
347                 goto leave;
348             }
349           else
350             xfree (result);
351           result = NULL;
352         }
353     }
354
355   /* For certain error codes, there is no need to try more.  */
356   if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
357       || gpg_err_code (err) == GPG_ERR_ENODEV)
358     goto leave;
359
360   /* Figure out the application to use.  */
361   if (want_undefined)
362     {
363       /* We switch to the "undefined" application only if explicitly
364          requested.  */
365       app->apptype = "UNDEFINED";
366       err = 0;
367     }
368   else
369     err = gpg_error (GPG_ERR_NOT_FOUND);
370
371   if (err && is_app_allowed ("openpgp")
372           && (!name || !strcmp (name, "openpgp")))
373     err = app_select_openpgp (app);
374   if (err && is_app_allowed ("nks") && (!name || !strcmp (name, "nks")))
375     err = app_select_nks (app);
376   if (err && is_app_allowed ("p15") && (!name || !strcmp (name, "p15")))
377     err = app_select_p15 (app);
378   if (err && is_app_allowed ("geldkarte")
379       && (!name || !strcmp (name, "geldkarte")))
380     err = app_select_geldkarte (app);
381   if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig")))
382     err = app_select_dinsig (app);
383   if (err && is_app_allowed ("sc-hsm") && (!name || !strcmp (name, "sc-hsm")))
384     err = app_select_sc_hsm (app);
385   if (err && name && gpg_err_code (err) != GPG_ERR_OBJ_TERM_STATE)
386     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
387
388  leave:
389   if (err)
390     {
391       if (name)
392         log_info ("can't select application '%s': %s\n",
393                   name, gpg_strerror (err));
394       else
395         log_info ("no supported card application found: %s\n",
396                   gpg_strerror (err));
397       xfree (app);
398       unlock_reader (slot);
399       return err;
400     }
401
402   app->ref_count = 1;
403
404   lock_table[slot].app = app;
405   *r_app = app;
406   unlock_reader (slot);
407   return 0;
408 }
409
410
411 char *
412 get_supported_applications (void)
413 {
414   const char *list[] = {
415     "openpgp",
416     "nks",
417     "p15",
418     "geldkarte",
419     "dinsig",
420     "sc-hsm",
421     /* Note: "undefined" is not listed here because it needs special
422        treatment by the client.  */
423     NULL
424   };
425   int idx;
426   size_t nbytes;
427   char *buffer, *p;
428
429   for (nbytes=1, idx=0; list[idx]; idx++)
430     nbytes += strlen (list[idx]) + 1 + 1;
431
432   buffer = xtrymalloc (nbytes);
433   if (!buffer)
434     return NULL;
435
436   for (p=buffer, idx=0; list[idx]; idx++)
437     if (is_app_allowed (list[idx]))
438       p = stpcpy (stpcpy (p, list[idx]), ":\n");
439   *p = 0;
440
441   return buffer;
442 }
443
444
445 /* Deallocate the application. */
446 static void
447 deallocate_app (app_t app)
448 {
449   if (app->fnc.deinit)
450     {
451       app->fnc.deinit (app);
452       app->fnc.deinit = NULL;
453     }
454
455   xfree (app->serialno);
456   xfree (app);
457 }
458
459 /* Free the resources associated with the application APP.  APP is
460    allowed to be NULL in which case this is a no-op.  Note that we are
461    using reference counting to track the users of the application and
462    actually deferring the deallocation to allow for a later reuse by
463    a new connection. */
464 void
465 release_application (app_t app)
466 {
467   int slot;
468
469   if (!app)
470     return;
471
472   if (!app->ref_count)
473     log_bug ("trying to release an already released context\n");
474   if (--app->ref_count)
475     return;
476
477   /* Move the reference to the application in the lock table. */
478   slot = app->slot;
479   /* FIXME: We are ignoring any error value.  */
480   lock_reader (slot, NULL);
481   if (lock_table[slot].app != app)
482     {
483       unlock_reader (slot);
484       log_bug ("app mismatch %p/%p\n", app, lock_table[slot].app);
485       deallocate_app (app);
486       return;
487     }
488
489   if (lock_table[slot].last_app)
490     deallocate_app (lock_table[slot].last_app);
491   lock_table[slot].last_app = lock_table[slot].app;
492   lock_table[slot].app = NULL;
493   unlock_reader (slot);
494 }
495
496
497
498 /* The serial number may need some cosmetics.  Do it here.  This
499    function shall only be called once after a new serial number has
500    been put into APP->serialno.
501
502    Prefixes we use:
503
504      FF 00 00 = For serial numbers starting with an FF
505      FF 01 00 = Some german p15 cards return an empty serial number so the
506                 serial number from the EF(TokenInfo) is used instead.
507      FF 7F 00 = No serialno.
508
509      All other serial number not starting with FF are used as they are.
510 */
511 gpg_error_t
512 app_munge_serialno (app_t app)
513 {
514   if (app->serialnolen && app->serialno[0] == 0xff)
515     {
516       /* The serial number starts with our special prefix.  This
517          requires that we put our default prefix "FF0000" in front. */
518       unsigned char *p = xtrymalloc (app->serialnolen + 3);
519       if (!p)
520         return gpg_error_from_syserror ();
521       memcpy (p, "\xff\0", 3);
522       memcpy (p+3, app->serialno, app->serialnolen);
523       app->serialnolen += 3;
524       xfree (app->serialno);
525       app->serialno = p;
526     }
527   else if (!app->serialnolen)
528     {
529       unsigned char *p = xtrymalloc (3);
530       if (!p)
531         return gpg_error_from_syserror ();
532       memcpy (p, "\xff\x7f", 3);
533       app->serialnolen = 3;
534       xfree (app->serialno);
535       app->serialno = p;
536     }
537   return 0;
538 }
539
540
541
542 /* Retrieve the serial number and the time of the last update of the
543    card.  The serial number is returned as a malloced string (hex
544    encoded) in SERIAL and the time of update is returned in STAMP.  If
545    no update time is available the returned value is 0.  Caller must
546    free SERIAL unless the function returns an error.  If STAMP is not
547    of interest, NULL may be passed. */
548 gpg_error_t
549 app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp)
550 {
551   char *buf;
552
553   if (!app || !serial)
554     return gpg_error (GPG_ERR_INV_VALUE);
555
556   *serial = NULL;
557   if (stamp)
558     *stamp = 0; /* not available */
559
560   if (!app->serialnolen)
561     buf = xtrystrdup ("FF7F00");
562   else
563     buf = bin2hex (app->serialno, app->serialnolen, NULL);
564   if (!buf)
565     return gpg_error_from_syserror ();
566
567   *serial = buf;
568   return 0;
569 }
570
571
572 /* Write out the application specifig status lines for the LEARN
573    command. */
574 gpg_error_t
575 app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
576 {
577   gpg_error_t err;
578
579   if (!app)
580     return gpg_error (GPG_ERR_INV_VALUE);
581   if (!app->ref_count)
582     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
583   if (!app->fnc.learn_status)
584     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
585
586   /* We do not send APPTYPE if only keypairinfo is requested.  */
587   if (app->apptype && !(flags & 1))
588     send_status_info (ctrl, "APPTYPE",
589                       app->apptype, strlen (app->apptype), NULL, 0);
590   err = lock_reader (app->slot, ctrl);
591   if (err)
592     return err;
593   err = app->fnc.learn_status (app, ctrl, flags);
594   unlock_reader (app->slot);
595   return err;
596 }
597
598
599 /* Read the certificate with id CERTID (as returned by learn_status in
600    the CERTINFO status lines) and return it in the freshly allocated
601    buffer put into CERT and the length of the certificate put into
602    CERTLEN. */
603 gpg_error_t
604 app_readcert (app_t app, const char *certid,
605               unsigned char **cert, size_t *certlen)
606 {
607   gpg_error_t err;
608
609   if (!app)
610     return gpg_error (GPG_ERR_INV_VALUE);
611   if (!app->ref_count)
612     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
613   if (!app->fnc.readcert)
614     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
615   err = lock_reader (app->slot, NULL/* FIXME*/);
616   if (err)
617     return err;
618   err = app->fnc.readcert (app, certid, cert, certlen);
619   unlock_reader (app->slot);
620   return err;
621 }
622
623
624 /* Read the key with ID KEYID.  On success a canonical encoded
625    S-expression with the public key will get stored at PK and its
626    length (for assertions) at PKLEN; the caller must release that
627    buffer. On error NULL will be stored at PK and PKLEN and an error
628    code returned.
629
630    This function might not be supported by all applications.  */
631 gpg_error_t
632 app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
633 {
634   gpg_error_t err;
635
636   if (pk)
637     *pk = NULL;
638   if (pklen)
639     *pklen = 0;
640
641   if (!app || !keyid || !pk || !pklen)
642     return gpg_error (GPG_ERR_INV_VALUE);
643   if (!app->ref_count)
644     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
645   if (!app->fnc.readkey)
646     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
647   err = lock_reader (app->slot, NULL /*FIXME*/);
648   if (err)
649     return err;
650   err= app->fnc.readkey (app, keyid, pk, pklen);
651   unlock_reader (app->slot);
652   return err;
653 }
654
655
656 /* Perform a GETATTR operation.  */
657 gpg_error_t
658 app_getattr (app_t app, ctrl_t ctrl, const char *name)
659 {
660   gpg_error_t err;
661
662   if (!app || !name || !*name)
663     return gpg_error (GPG_ERR_INV_VALUE);
664   if (!app->ref_count)
665     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
666
667   if (app->apptype && name && !strcmp (name, "APPTYPE"))
668     {
669       send_status_info (ctrl, "APPTYPE",
670                         app->apptype, strlen (app->apptype), NULL, 0);
671       return 0;
672     }
673   if (name && !strcmp (name, "SERIALNO"))
674     {
675       char *serial;
676       time_t stamp;
677       int rc;
678
679       rc = app_get_serial_and_stamp (app, &serial, &stamp);
680       if (rc)
681         return rc;
682       send_status_info (ctrl, "SERIALNO", serial, strlen (serial), NULL, 0);
683       xfree (serial);
684       return 0;
685     }
686
687   if (!app->fnc.getattr)
688     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
689   err = lock_reader (app->slot, ctrl);
690   if (err)
691     return err;
692   err =  app->fnc.getattr (app, ctrl, name);
693   unlock_reader (app->slot);
694   return err;
695 }
696
697 /* Perform a SETATTR operation.  */
698 gpg_error_t
699 app_setattr (app_t app, const char *name,
700              gpg_error_t (*pincb)(void*, const char *, char **),
701              void *pincb_arg,
702              const unsigned char *value, size_t valuelen)
703 {
704   gpg_error_t err;
705
706   if (!app || !name || !*name || !value)
707     return gpg_error (GPG_ERR_INV_VALUE);
708   if (!app->ref_count)
709     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
710   if (!app->fnc.setattr)
711     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
712   err = lock_reader (app->slot, NULL /*FIXME*/);
713   if (err)
714     return err;
715   err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
716   unlock_reader (app->slot);
717   return err;
718 }
719
720 /* Create the signature and return the allocated result in OUTDATA.
721    If a PIN is required the PINCB will be used to ask for the PIN; it
722    should return the PIN in an allocated buffer and put it into PIN.  */
723 gpg_error_t
724 app_sign (app_t app, const char *keyidstr, int hashalgo,
725           gpg_error_t (*pincb)(void*, const char *, char **),
726           void *pincb_arg,
727           const void *indata, size_t indatalen,
728           unsigned char **outdata, size_t *outdatalen )
729 {
730   gpg_error_t err;
731
732   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
733     return gpg_error (GPG_ERR_INV_VALUE);
734   if (!app->ref_count)
735     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
736   if (!app->fnc.sign)
737     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
738   err = lock_reader (app->slot, NULL /*FIXME*/);
739   if (err)
740     return err;
741   err = app->fnc.sign (app, keyidstr, hashalgo,
742                        pincb, pincb_arg,
743                        indata, indatalen,
744                        outdata, outdatalen);
745   unlock_reader (app->slot);
746   if (opt.verbose)
747     log_info ("operation sign result: %s\n", gpg_strerror (err));
748   return err;
749 }
750
751 /* Create the signature using the INTERNAL AUTHENTICATE command and
752    return the allocated result in OUTDATA.  If a PIN is required the
753    PINCB will be used to ask for the PIN; it should return the PIN in
754    an allocated buffer and put it into PIN.  */
755 gpg_error_t
756 app_auth (app_t app, const char *keyidstr,
757           gpg_error_t (*pincb)(void*, const char *, char **),
758           void *pincb_arg,
759           const void *indata, size_t indatalen,
760           unsigned char **outdata, size_t *outdatalen )
761 {
762   gpg_error_t err;
763
764   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
765     return gpg_error (GPG_ERR_INV_VALUE);
766   if (!app->ref_count)
767     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
768   if (!app->fnc.auth)
769     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
770   err = lock_reader (app->slot, NULL /*FIXME*/);
771   if (err)
772     return err;
773   err = app->fnc.auth (app, keyidstr,
774                        pincb, pincb_arg,
775                        indata, indatalen,
776                        outdata, outdatalen);
777   unlock_reader (app->slot);
778   if (opt.verbose)
779     log_info ("operation auth result: %s\n", gpg_strerror (err));
780   return err;
781 }
782
783
784 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
785    If a PIN is required the PINCB will be used to ask for the PIN; it
786    should return the PIN in an allocated buffer and put it into PIN.  */
787 gpg_error_t
788 app_decipher (app_t app, const char *keyidstr,
789               gpg_error_t (*pincb)(void*, const char *, char **),
790               void *pincb_arg,
791               const void *indata, size_t indatalen,
792               unsigned char **outdata, size_t *outdatalen,
793               unsigned int *r_info)
794 {
795   gpg_error_t err;
796
797   *r_info = 0;
798
799   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
800     return gpg_error (GPG_ERR_INV_VALUE);
801   if (!app->ref_count)
802     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
803   if (!app->fnc.decipher)
804     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
805   err = lock_reader (app->slot, NULL /*FIXME*/);
806   if (err)
807     return err;
808   err = app->fnc.decipher (app, keyidstr,
809                            pincb, pincb_arg,
810                            indata, indatalen,
811                            outdata, outdatalen,
812                            r_info);
813   unlock_reader (app->slot);
814   if (opt.verbose)
815     log_info ("operation decipher result: %s\n", gpg_strerror (err));
816   return err;
817 }
818
819
820 /* Perform the WRITECERT operation.  */
821 gpg_error_t
822 app_writecert (app_t app, ctrl_t ctrl,
823               const char *certidstr,
824               gpg_error_t (*pincb)(void*, const char *, char **),
825               void *pincb_arg,
826               const unsigned char *data, size_t datalen)
827 {
828   gpg_error_t err;
829
830   if (!app || !certidstr || !*certidstr || !pincb)
831     return gpg_error (GPG_ERR_INV_VALUE);
832   if (!app->ref_count)
833     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
834   if (!app->fnc.writecert)
835     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
836   err = lock_reader (app->slot, ctrl);
837   if (err)
838     return err;
839   err = app->fnc.writecert (app, ctrl, certidstr,
840                             pincb, pincb_arg, data, datalen);
841   unlock_reader (app->slot);
842   if (opt.verbose)
843     log_info ("operation writecert result: %s\n", gpg_strerror (err));
844   return err;
845 }
846
847
848 /* Perform the WRITEKEY operation.  */
849 gpg_error_t
850 app_writekey (app_t app, ctrl_t ctrl,
851               const char *keyidstr, unsigned int flags,
852               gpg_error_t (*pincb)(void*, const char *, char **),
853               void *pincb_arg,
854               const unsigned char *keydata, size_t keydatalen)
855 {
856   gpg_error_t err;
857
858   if (!app || !keyidstr || !*keyidstr || !pincb)
859     return gpg_error (GPG_ERR_INV_VALUE);
860   if (!app->ref_count)
861     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
862   if (!app->fnc.writekey)
863     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
864   err = lock_reader (app->slot, ctrl);
865   if (err)
866     return err;
867   err = app->fnc.writekey (app, ctrl, keyidstr, flags,
868                            pincb, pincb_arg, keydata, keydatalen);
869   unlock_reader (app->slot);
870   if (opt.verbose)
871     log_info ("operation writekey result: %s\n", gpg_strerror (err));
872   return err;
873 }
874
875
876 /* Perform a SETATTR operation.  */
877 gpg_error_t
878 app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
879             time_t createtime,
880             gpg_error_t (*pincb)(void*, const char *, char **),
881             void *pincb_arg)
882 {
883   gpg_error_t err;
884
885   if (!app || !keynostr || !*keynostr || !pincb)
886     return gpg_error (GPG_ERR_INV_VALUE);
887   if (!app->ref_count)
888     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
889   if (!app->fnc.genkey)
890     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
891   err = lock_reader (app->slot, ctrl);
892   if (err)
893     return err;
894   err = app->fnc.genkey (app, ctrl, keynostr, flags,
895                          createtime, pincb, pincb_arg);
896   unlock_reader (app->slot);
897   if (opt.verbose)
898     log_info ("operation genkey result: %s\n", gpg_strerror (err));
899   return err;
900 }
901
902
903 /* Perform a GET CHALLENGE operation.  This function is special as it
904    directly accesses the card without any application specific
905    wrapper. */
906 gpg_error_t
907 app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer)
908 {
909   gpg_error_t err;
910
911   if (!app || !nbytes || !buffer)
912     return gpg_error (GPG_ERR_INV_VALUE);
913   if (!app->ref_count)
914     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
915   err = lock_reader (app->slot, NULL /*FIXME*/);
916   if (err)
917     return err;
918   err = iso7816_get_challenge (app->slot, nbytes, buffer);
919   unlock_reader (app->slot);
920   return err;
921 }
922
923
924
925 /* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation.  */
926 gpg_error_t
927 app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
928                 gpg_error_t (*pincb)(void*, const char *, char **),
929                 void *pincb_arg)
930 {
931   gpg_error_t err;
932
933   if (!app || !chvnostr || !*chvnostr || !pincb)
934     return gpg_error (GPG_ERR_INV_VALUE);
935   if (!app->ref_count)
936     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
937   if (!app->fnc.change_pin)
938     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
939   err = lock_reader (app->slot, ctrl);
940   if (err)
941     return err;
942   err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode,
943                              pincb, pincb_arg);
944   unlock_reader (app->slot);
945   if (opt.verbose)
946     log_info ("operation change_pin result: %s\n", gpg_strerror (err));
947   return err;
948 }
949
950
951 /* Perform a VERIFY operation without doing anything lese.  This may
952    be used to initialze a the PIN cache for long lasting other
953    operations.  Its use is highly application dependent. */
954 gpg_error_t
955 app_check_pin (app_t app, const char *keyidstr,
956                gpg_error_t (*pincb)(void*, const char *, char **),
957                void *pincb_arg)
958 {
959   gpg_error_t err;
960
961   if (!app || !keyidstr || !*keyidstr || !pincb)
962     return gpg_error (GPG_ERR_INV_VALUE);
963   if (!app->ref_count)
964     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
965   if (!app->fnc.check_pin)
966     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
967   err = lock_reader (app->slot, NULL /*FIXME*/);
968   if (err)
969     return err;
970   err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);
971   unlock_reader (app->slot);
972   if (opt.verbose)
973     log_info ("operation check_pin result: %s\n", gpg_strerror (err));
974   return err;
975 }