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