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