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