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