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