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