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