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