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