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