w32: Add icons and version information.
[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   /* Mark application as non-reusable.  */
194   if (lock_table[slot].app)
195     lock_table[slot].app->no_reuse = 1;
196
197   /* Deallocate a saved application for that slot, so that we won't
198      try to reuse it.  If there is no saved application, set a flag so
199      that we won't save the current state. */
200   app = lock_table[slot].last_app;
201
202   if (app)
203     {
204       lock_table[slot].last_app = NULL;
205       deallocate_app (app);
206     }
207   unlock_reader (slot); 
208 }
209
210  
211 /* This function is used by the serialno command to check for an
212    application conflict which may appear if the serialno command is
213    used to request a specific application and the connection has
214    already done a select_application. */
215 gpg_error_t
216 check_application_conflict (ctrl_t ctrl, const char *name)
217 {
218   int slot = ctrl->reader_slot;
219   app_t app;
220
221   if (slot < 0 || slot >= DIM (lock_table))
222     return gpg_error (GPG_ERR_INV_VALUE);
223
224   app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
225   if (app && app->apptype && name)
226     if ( ascii_strcasecmp (app->apptype, name))
227         return gpg_error (GPG_ERR_CONFLICT);
228   return 0;
229 }
230
231
232 /* If called with NAME as NULL, select the best fitting application
233    and return a context; otherwise select the application with NAME
234    and return a context.  SLOT identifies the reader device. Returns
235    an error code and stores NULL at R_APP if no application was found
236    or no card is present. */
237 gpg_error_t
238 select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
239 {
240   gpg_error_t err;
241   app_t app = NULL;
242   unsigned char *result = NULL;
243   size_t resultlen;
244
245   (void)ctrl;
246
247   *r_app = NULL;
248
249   err = lock_reader (slot, ctrl);
250   if (err)
251     return err;
252
253   /* First check whether we already have an application to share. */
254   app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
255   if (app && name)
256     if (!app->apptype || ascii_strcasecmp (app->apptype, name))
257       {
258         unlock_reader (slot);
259         if (app->apptype)
260           log_info ("application `%s' in use by reader %d - can't switch\n",
261                     app->apptype, slot);
262         return gpg_error (GPG_ERR_CONFLICT);
263       }
264
265   /* Don't use a non-reusable marked application.  */
266   if (app && app->no_reuse)
267     {
268       unlock_reader (slot);
269       log_info ("lingering application `%s' in use by reader %d"
270                 " - can't switch\n",
271                 app->apptype? app->apptype:"?", slot);
272       return gpg_error (GPG_ERR_CONFLICT);
273     }
274
275   /* If we don't have an app, check whether we have a saved
276      application for that slot.  This is useful so that a card does
277      not get reset even if only one session is using the card - this
278      way the PIN cache and other cached data are preserved.  */
279   if (!app && lock_table[slot].initialized && lock_table[slot].last_app)
280     {
281       app = lock_table[slot].last_app;
282       if (!name || (app->apptype && !ascii_strcasecmp (app->apptype, name)) )
283         {
284           /* Yes, we can reuse this application - either the caller
285              requested an unspecific one or the requested one matches
286              the saved one. */
287           lock_table[slot].app = app;
288           lock_table[slot].last_app = NULL;
289         }
290       else 
291         {
292           /* No, this saved application can't be used - deallocate it. */
293           lock_table[slot].last_app = NULL;
294           deallocate_app (app);
295           app = NULL;
296         }
297     }
298
299   /* If we can reuse an application, bump the reference count and
300      return it.  */
301   if (app)
302     {
303       if (app->slot != slot)
304         log_bug ("slot mismatch %d/%d\n", app->slot, slot);
305       app->slot = slot;
306
307       app->ref_count++;
308       *r_app = app;
309       unlock_reader (slot);
310       return 0; /* Okay: We share that one. */
311     }
312   
313   /* Need to allocate a new one.  */
314   app = xtrycalloc (1, sizeof *app);
315   if (!app)
316     {
317       err = gpg_error_from_syserror ();
318       log_info ("error allocating context: %s\n", gpg_strerror (err));
319       unlock_reader (slot);
320       return err;
321     }
322   app->slot = slot;
323
324
325   /* Fixme: We should now first check whether a card is at all
326      present. */
327
328   /* Try to read the GDO file first to get a default serial number. */
329   err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
330   if (!err)
331     err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
332   if (!err)
333      err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
334   if (!err)
335     {
336       size_t n;
337       const unsigned char *p;
338
339       p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
340       if (p)
341         resultlen -= (p-result);
342       if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
343         {
344           /* The object it does not fit into the buffer.  This is an
345              invalid encoding (or the buffer is too short.  However, I
346              have some test cards with such an invalid encoding and
347              therefore I use this ugly workaround to return something
348              I can further experiment with. */
349           log_info ("enabling BMI testcard workaround\n");
350           n--;
351         }
352
353       if (p && n <= resultlen)
354         {
355           /* The GDO file is pretty short, thus we simply reuse it for
356              storing the serial number. */
357           memmove (result, p, n);
358           app->serialno = result;
359           app->serialnolen = n;
360           err = app_munge_serialno (app);
361           if (err)
362             goto leave;
363         }
364       else
365         xfree (result);
366       result = NULL;
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   err = gpg_error (GPG_ERR_NOT_FOUND);
376
377   if (err && is_app_allowed ("openpgp")
378           && (!name || !strcmp (name, "openpgp")))
379     err = app_select_openpgp (app);
380   if (err && is_app_allowed ("nks") && (!name || !strcmp (name, "nks")))
381     err = app_select_nks (app);
382   if (err && is_app_allowed ("p15") && (!name || !strcmp (name, "p15")))
383     err = app_select_p15 (app);
384   if (err && is_app_allowed ("geldkarte")
385       && (!name || !strcmp (name, "geldkarte")))
386     err = app_select_geldkarte (app);
387   if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig")))
388     err = app_select_dinsig (app);
389   if (err && name)
390     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
391
392  leave:
393   if (err)
394     {
395       if (name)
396         log_info ("can't select application `%s': %s\n",
397                   name, gpg_strerror (err));
398       else
399         log_info ("no supported card application found: %s\n",
400                   gpg_strerror (err));
401       xfree (app);
402       unlock_reader (slot);
403       return err;
404     }
405
406   app->ref_count = 1;
407
408   lock_table[slot].app = app;
409   *r_app = app;
410   unlock_reader (slot);
411   return 0;
412 }
413
414
415 char *
416 get_supported_applications (void)
417 {
418   const char *list[] = {
419     "openpgp",
420     "nks",
421     "p15",
422     "geldkarte",
423     "dinsig",
424     /* Note: "undefined" is not listed here because it needs special
425        treatment by the client.  */
426     NULL
427   };
428   int idx;
429   size_t nbytes;
430   char *buffer, *p;
431   
432   for (nbytes=1, idx=0; list[idx]; idx++)
433     nbytes += strlen (list[idx]) + 1 + 1;
434   
435   buffer = xtrymalloc (nbytes);
436   if (!buffer)
437     return NULL;
438
439   for (p=buffer, idx=0; list[idx]; idx++)
440     if (is_app_allowed (list[idx]))
441       p = stpcpy (stpcpy (p, list[idx]), ":\n");
442   *p = 0;
443
444   return buffer;
445 }
446
447
448 /* Deallocate the application. */
449 static void
450 deallocate_app (app_t app)
451 {
452   if (app->fnc.deinit)
453     {
454       app->fnc.deinit (app);
455       app->fnc.deinit = NULL;
456     }
457
458   xfree (app->serialno);
459   xfree (app);
460 }
461
462 /* Free the resources associated with the application APP.  APP is
463    allowed to be NULL in which case this is a no-op.  Note that we are
464    using reference counting to track the users of the application and
465    actually deferring the deallocation to allow for a later reuse by
466    a new connection. */
467 void
468 release_application (app_t app)
469 {
470   int slot;
471
472   if (!app)
473     return;
474
475   if (!app->ref_count)
476     log_bug ("trying to release an already released context\n");
477   if (--app->ref_count)
478     return;
479
480   /* Move the reference to the application in the lock table. */
481   slot = app->slot;
482   /* FIXME: We are ignoring any error value.  */
483   lock_reader (slot, NULL);
484   if (lock_table[slot].app != app)
485     {
486       unlock_reader (slot);
487       log_bug ("app mismatch %p/%p\n", app, lock_table[slot].app);
488       deallocate_app (app);
489       return;
490     }
491
492   if (lock_table[slot].last_app)
493     deallocate_app (lock_table[slot].last_app);
494   if (app->no_reuse)
495     {
496       /* If we shall not re-use the application we can't save it for
497          later use. */
498       deallocate_app (app);
499       lock_table[slot].last_app = NULL;
500     }
501   else
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