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