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