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