Port to npth.
[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 "apdu.h"
30 #include "iso7816.h"
31 #include "tlv.h"
32
33 /* This table is used to keep track of locks on a per reader base.
34    The index into the table is the slot number of the reader.  The
35    mutex will be initialized on demand (one of the advantages of a
36    userland threading system). */
37 static struct
38 {
39   int initialized;
40   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 && name)
391     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
392
393  leave:
394   if (err)
395     {
396       if (name)
397         log_info ("can't select application `%s': %s\n",
398                   name, gpg_strerror (err));
399       else
400         log_info ("no supported card application found: %s\n",
401                   gpg_strerror (err));
402       xfree (app);
403       unlock_reader (slot);
404       return err;
405     }
406
407   app->ref_count = 1;
408
409   lock_table[slot].app = app;
410   *r_app = app;
411   unlock_reader (slot);
412   return 0;
413 }
414
415
416 char *
417 get_supported_applications (void)
418 {
419   const char *list[] = {
420     "openpgp",
421     "nks",
422     "p15",
423     "geldkarte",
424     "dinsig",
425     /* Note: "undefined" is not listed here because it needs special
426        treatment by the client.  */
427     NULL
428   };
429   int idx;
430   size_t nbytes;
431   char *buffer, *p;
432
433   for (nbytes=1, idx=0; list[idx]; idx++)
434     nbytes += strlen (list[idx]) + 1 + 1;
435
436   buffer = xtrymalloc (nbytes);
437   if (!buffer)
438     return NULL;
439
440   for (p=buffer, idx=0; list[idx]; idx++)
441     if (is_app_allowed (list[idx]))
442       p = stpcpy (stpcpy (p, list[idx]), ":\n");
443   *p = 0;
444
445   return buffer;
446 }
447
448
449 /* Deallocate the application. */
450 static void
451 deallocate_app (app_t app)
452 {
453   if (app->fnc.deinit)
454     {
455       app->fnc.deinit (app);
456       app->fnc.deinit = NULL;
457     }
458
459   xfree (app->serialno);
460   xfree (app);
461 }
462
463 /* Free the resources associated with the application APP.  APP is
464    allowed to be NULL in which case this is a no-op.  Note that we are
465    using reference counting to track the users of the application and
466    actually deferring the deallocation to allow for a later reuse by
467    a new connection. */
468 void
469 release_application (app_t app)
470 {
471   int slot;
472
473   if (!app)
474     return;
475
476   if (!app->ref_count)
477     log_bug ("trying to release an already released context\n");
478   if (--app->ref_count)
479     return;
480
481   /* Move the reference to the application in the lock table. */
482   slot = app->slot;
483   /* FIXME: We are ignoring any error value.  */
484   lock_reader (slot, NULL);
485   if (lock_table[slot].app != app)
486     {
487       unlock_reader (slot);
488       log_bug ("app mismatch %p/%p\n", app, lock_table[slot].app);
489       deallocate_app (app);
490       return;
491     }
492
493   if (lock_table[slot].last_app)
494     deallocate_app (lock_table[slot].last_app);
495   if (app->no_reuse)
496     {
497       /* If we shall not re-use the application we can't save it for
498          later use. */
499       deallocate_app (app);
500       lock_table[slot].last_app = NULL;
501     }
502   else
503     lock_table[slot].last_app = lock_table[slot].app;
504   lock_table[slot].app = NULL;
505   unlock_reader (slot);
506 }
507
508
509
510 /* The serial number may need some cosmetics.  Do it here.  This
511    function shall only be called once after a new serial number has
512    been put into APP->serialno.
513
514    Prefixes we use:
515
516      FF 00 00 = For serial numbers starting with an FF
517      FF 01 00 = Some german p15 cards return an empty serial number so the
518                 serial number from the EF(TokenInfo) is used instead.
519      FF 7F 00 = No serialno.
520
521      All other serial number not starting with FF are used as they are.
522 */
523 gpg_error_t
524 app_munge_serialno (app_t app)
525 {
526   if (app->serialnolen && app->serialno[0] == 0xff)
527     {
528       /* The serial number starts with our special prefix.  This
529          requires that we put our default prefix "FF0000" in front. */
530       unsigned char *p = xtrymalloc (app->serialnolen + 3);
531       if (!p)
532         return gpg_error_from_syserror ();
533       memcpy (p, "\xff\0", 3);
534       memcpy (p+3, app->serialno, app->serialnolen);
535       app->serialnolen += 3;
536       xfree (app->serialno);
537       app->serialno = p;
538     }
539   else if (!app->serialnolen)
540     {
541       unsigned char *p = xtrymalloc (3);
542       if (!p)
543         return gpg_error_from_syserror ();
544       memcpy (p, "\xff\x7f", 3);
545       app->serialnolen = 3;
546       xfree (app->serialno);
547       app->serialno = p;
548     }
549   return 0;
550 }
551
552
553
554 /* Retrieve the serial number and the time of the last update of the
555    card.  The serial number is returned as a malloced string (hex
556    encoded) in SERIAL and the time of update is returned in STAMP.  If
557    no update time is available the returned value is 0.  Caller must
558    free SERIAL unless the function returns an error.  If STAMP is not
559    of interest, NULL may be passed. */
560 gpg_error_t
561 app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp)
562 {
563   char *buf;
564
565   if (!app || !serial)
566     return gpg_error (GPG_ERR_INV_VALUE);
567
568   *serial = NULL;
569   if (stamp)
570     *stamp = 0; /* not available */
571
572   if (!app->serialnolen)
573     buf = xtrystrdup ("FF7F00");
574   else
575     buf = bin2hex (app->serialno, app->serialnolen, NULL);
576   if (!buf)
577     return gpg_error_from_syserror ();
578
579   *serial = buf;
580   return 0;
581 }
582
583
584 /* Write out the application specifig status lines for the LEARN
585    command. */
586 gpg_error_t
587 app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
588 {
589   gpg_error_t err;
590
591   if (!app)
592     return gpg_error (GPG_ERR_INV_VALUE);
593   if (!app->ref_count)
594     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
595   if (!app->fnc.learn_status)
596     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
597
598   /* We do not send APPTYPE if only keypairinfo is requested.  */
599   if (app->apptype && !(flags & 1))
600     send_status_info (ctrl, "APPTYPE",
601                       app->apptype, strlen (app->apptype), NULL, 0);
602   err = lock_reader (app->slot, ctrl);
603   if (err)
604     return err;
605   err = app->fnc.learn_status (app, ctrl, flags);
606   unlock_reader (app->slot);
607   return err;
608 }
609
610
611 /* Read the certificate with id CERTID (as returned by learn_status in
612    the CERTINFO status lines) and return it in the freshly allocated
613    buffer put into CERT and the length of the certificate put into
614    CERTLEN. */
615 gpg_error_t
616 app_readcert (app_t app, const char *certid,
617               unsigned char **cert, size_t *certlen)
618 {
619   gpg_error_t err;
620
621   if (!app)
622     return gpg_error (GPG_ERR_INV_VALUE);
623   if (!app->ref_count)
624     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
625   if (!app->fnc.readcert)
626     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
627   err = lock_reader (app->slot, NULL/* FIXME*/);
628   if (err)
629     return err;
630   err = app->fnc.readcert (app, certid, cert, certlen);
631   unlock_reader (app->slot);
632   return err;
633 }
634
635
636 /* Read the key with ID KEYID.  On success a canonical encoded
637    S-expression with the public key will get stored at PK and its
638    length (for assertions) at PKLEN; the caller must release that
639    buffer. On error NULL will be stored at PK and PKLEN and an error
640    code returned.
641
642    This function might not be supported by all applications.  */
643 gpg_error_t
644 app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
645 {
646   gpg_error_t err;
647
648   if (pk)
649     *pk = NULL;
650   if (pklen)
651     *pklen = 0;
652
653   if (!app || !keyid || !pk || !pklen)
654     return gpg_error (GPG_ERR_INV_VALUE);
655   if (!app->ref_count)
656     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
657   if (!app->fnc.readkey)
658     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
659   err = lock_reader (app->slot, NULL /*FIXME*/);
660   if (err)
661     return err;
662   err= app->fnc.readkey (app, keyid, pk, pklen);
663   unlock_reader (app->slot);
664   return err;
665 }
666
667
668 /* Perform a GETATTR operation.  */
669 gpg_error_t
670 app_getattr (app_t app, ctrl_t ctrl, const char *name)
671 {
672   gpg_error_t err;
673
674   if (!app || !name || !*name)
675     return gpg_error (GPG_ERR_INV_VALUE);
676   if (!app->ref_count)
677     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
678
679   if (app->apptype && name && !strcmp (name, "APPTYPE"))
680     {
681       send_status_info (ctrl, "APPTYPE",
682                         app->apptype, strlen (app->apptype), NULL, 0);
683       return 0;
684     }
685   if (name && !strcmp (name, "SERIALNO"))
686     {
687       char *serial;
688       time_t stamp;
689       int rc;
690
691       rc = app_get_serial_and_stamp (app, &serial, &stamp);
692       if (rc)
693         return rc;
694       send_status_info (ctrl, "SERIALNO", serial, strlen (serial), NULL, 0);
695       xfree (serial);
696       return 0;
697     }
698
699   if (!app->fnc.getattr)
700     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
701   err = lock_reader (app->slot, ctrl);
702   if (err)
703     return err;
704   err =  app->fnc.getattr (app, ctrl, name);
705   unlock_reader (app->slot);
706   return err;
707 }
708
709 /* Perform a SETATTR operation.  */
710 gpg_error_t
711 app_setattr (app_t app, const char *name,
712              gpg_error_t (*pincb)(void*, const char *, char **),
713              void *pincb_arg,
714              const unsigned char *value, size_t valuelen)
715 {
716   gpg_error_t err;
717
718   if (!app || !name || !*name || !value)
719     return gpg_error (GPG_ERR_INV_VALUE);
720   if (!app->ref_count)
721     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
722   if (!app->fnc.setattr)
723     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
724   err = lock_reader (app->slot, NULL /*FIXME*/);
725   if (err)
726     return err;
727   err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
728   unlock_reader (app->slot);
729   return err;
730 }
731
732 /* Create the signature and return the allocated result in OUTDATA.
733    If a PIN is required the PINCB will be used to ask for the PIN; it
734    should return the PIN in an allocated buffer and put it into PIN.  */
735 gpg_error_t
736 app_sign (app_t app, const char *keyidstr, int hashalgo,
737           gpg_error_t (*pincb)(void*, const char *, char **),
738           void *pincb_arg,
739           const void *indata, size_t indatalen,
740           unsigned char **outdata, size_t *outdatalen )
741 {
742   gpg_error_t err;
743
744   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
745     return gpg_error (GPG_ERR_INV_VALUE);
746   if (!app->ref_count)
747     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
748   if (!app->fnc.sign)
749     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
750   err = lock_reader (app->slot, NULL /*FIXME*/);
751   if (err)
752     return err;
753   err = app->fnc.sign (app, keyidstr, hashalgo,
754                        pincb, pincb_arg,
755                        indata, indatalen,
756                        outdata, outdatalen);
757   unlock_reader (app->slot);
758   if (opt.verbose)
759     log_info ("operation sign result: %s\n", gpg_strerror (err));
760   return err;
761 }
762
763 /* Create the signature using the INTERNAL AUTHENTICATE command and
764    return the allocated result in OUTDATA.  If a PIN is required the
765    PINCB will be used to ask for the PIN; it should return the PIN in
766    an allocated buffer and put it into PIN.  */
767 gpg_error_t
768 app_auth (app_t app, const char *keyidstr,
769           gpg_error_t (*pincb)(void*, const char *, char **),
770           void *pincb_arg,
771           const void *indata, size_t indatalen,
772           unsigned char **outdata, size_t *outdatalen )
773 {
774   gpg_error_t err;
775
776   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
777     return gpg_error (GPG_ERR_INV_VALUE);
778   if (!app->ref_count)
779     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
780   if (!app->fnc.auth)
781     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
782   err = lock_reader (app->slot, NULL /*FIXME*/);
783   if (err)
784     return err;
785   err = app->fnc.auth (app, keyidstr,
786                        pincb, pincb_arg,
787                        indata, indatalen,
788                        outdata, outdatalen);
789   unlock_reader (app->slot);
790   if (opt.verbose)
791     log_info ("operation auth result: %s\n", gpg_strerror (err));
792   return err;
793 }
794
795
796 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
797    If a PIN is required the PINCB will be used to ask for the PIN; it
798    should return the PIN in an allocated buffer and put it into PIN.  */
799 gpg_error_t
800 app_decipher (app_t app, const char *keyidstr,
801               gpg_error_t (*pincb)(void*, const char *, char **),
802               void *pincb_arg,
803               const void *indata, size_t indatalen,
804               unsigned char **outdata, size_t *outdatalen )
805 {
806   gpg_error_t err;
807
808   if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
809     return gpg_error (GPG_ERR_INV_VALUE);
810   if (!app->ref_count)
811     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
812   if (!app->fnc.decipher)
813     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
814   err = lock_reader (app->slot, NULL /*FIXME*/);
815   if (err)
816     return err;
817   err = app->fnc.decipher (app, keyidstr,
818                            pincb, pincb_arg,
819                            indata, indatalen,
820                            outdata, outdatalen);
821   unlock_reader (app->slot);
822   if (opt.verbose)
823     log_info ("operation decipher result: %s\n", gpg_strerror (err));
824   return err;
825 }
826
827
828 /* Perform the WRITECERT operation.  */
829 gpg_error_t
830 app_writecert (app_t app, ctrl_t ctrl,
831               const char *certidstr,
832               gpg_error_t (*pincb)(void*, const char *, char **),
833               void *pincb_arg,
834               const unsigned char *data, size_t datalen)
835 {
836   gpg_error_t err;
837
838   if (!app || !certidstr || !*certidstr || !pincb)
839     return gpg_error (GPG_ERR_INV_VALUE);
840   if (!app->ref_count)
841     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
842   if (!app->fnc.writecert)
843     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
844   err = lock_reader (app->slot, ctrl);
845   if (err)
846     return err;
847   err = app->fnc.writecert (app, ctrl, certidstr,
848                             pincb, pincb_arg, data, datalen);
849   unlock_reader (app->slot);
850   if (opt.verbose)
851     log_info ("operation writecert result: %s\n", gpg_strerror (err));
852   return err;
853 }
854
855
856 /* Perform the WRITEKEY operation.  */
857 gpg_error_t
858 app_writekey (app_t app, ctrl_t ctrl,
859               const char *keyidstr, unsigned int flags,
860               gpg_error_t (*pincb)(void*, const char *, char **),
861               void *pincb_arg,
862               const unsigned char *keydata, size_t keydatalen)
863 {
864   gpg_error_t err;
865
866   if (!app || !keyidstr || !*keyidstr || !pincb)
867     return gpg_error (GPG_ERR_INV_VALUE);
868   if (!app->ref_count)
869     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
870   if (!app->fnc.writekey)
871     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
872   err = lock_reader (app->slot, ctrl);
873   if (err)
874     return err;
875   err = app->fnc.writekey (app, ctrl, keyidstr, flags,
876                            pincb, pincb_arg, keydata, keydatalen);
877   unlock_reader (app->slot);
878   if (opt.verbose)
879     log_info ("operation writekey result: %s\n", gpg_strerror (err));
880   return err;
881 }
882
883
884 /* Perform a SETATTR operation.  */
885 gpg_error_t
886 app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
887             time_t createtime,
888             gpg_error_t (*pincb)(void*, const char *, char **),
889             void *pincb_arg)
890 {
891   gpg_error_t err;
892
893   if (!app || !keynostr || !*keynostr || !pincb)
894     return gpg_error (GPG_ERR_INV_VALUE);
895   if (!app->ref_count)
896     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
897   if (!app->fnc.genkey)
898     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
899   err = lock_reader (app->slot, ctrl);
900   if (err)
901     return err;
902   err = app->fnc.genkey (app, ctrl, keynostr, flags,
903                          createtime, pincb, pincb_arg);
904   unlock_reader (app->slot);
905   if (opt.verbose)
906     log_info ("operation genkey result: %s\n", gpg_strerror (err));
907   return err;
908 }
909
910
911 /* Perform a GET CHALLENGE operation.  This fucntion is special as it
912    directly accesses the card without any application specific
913    wrapper. */
914 gpg_error_t
915 app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer)
916 {
917   gpg_error_t err;
918
919   if (!app || !nbytes || !buffer)
920     return gpg_error (GPG_ERR_INV_VALUE);
921   if (!app->ref_count)
922     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
923   err = lock_reader (app->slot, NULL /*FIXME*/);
924   if (err)
925     return err;
926   err = iso7816_get_challenge (app->slot, nbytes, buffer);
927   unlock_reader (app->slot);
928   return err;
929 }
930
931
932
933 /* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation.  */
934 gpg_error_t
935 app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
936                 gpg_error_t (*pincb)(void*, const char *, char **),
937                 void *pincb_arg)
938 {
939   gpg_error_t err;
940
941   if (!app || !chvnostr || !*chvnostr || !pincb)
942     return gpg_error (GPG_ERR_INV_VALUE);
943   if (!app->ref_count)
944     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
945   if (!app->fnc.change_pin)
946     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
947   err = lock_reader (app->slot, ctrl);
948   if (err)
949     return err;
950   err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode,
951                              pincb, pincb_arg);
952   unlock_reader (app->slot);
953   if (opt.verbose)
954     log_info ("operation change_pin result: %s\n", gpg_strerror (err));
955   return err;
956 }
957
958
959 /* Perform a VERIFY operation without doing anything lese.  This may
960    be used to initialze a the PIN cache for long lasting other
961    operations.  Its use is highly application dependent. */
962 gpg_error_t
963 app_check_pin (app_t app, const char *keyidstr,
964                gpg_error_t (*pincb)(void*, const char *, char **),
965                void *pincb_arg)
966 {
967   gpg_error_t err;
968
969   if (!app || !keyidstr || !*keyidstr || !pincb)
970     return gpg_error (GPG_ERR_INV_VALUE);
971   if (!app->ref_count)
972     return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
973   if (!app->fnc.check_pin)
974     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
975   err = lock_reader (app->slot, NULL /*FIXME*/);
976   if (err)
977     return err;
978   err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);
979   unlock_reader (app->slot);
980   if (opt.verbose)
981     log_info ("operation check_pin result: %s\n", gpg_strerror (err));
982   return err;
983 }