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