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