agent/
[gnupg.git] / scd / app.c
bloba23c4a54631e7d17d3d4c045cccdb5a4840a7391
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 3 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, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <pth.h>
27 #include "scdaemon.h"
28 #include "app-common.h"
29 #include "apdu.h"
30 #include "iso7816.h"
31 #include "tlv.h"
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
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];
47 static void deallocate_app (app_t app);
51 static void
52 print_progress_line (void *opaque, const char *what, int pc, int cur, int tot)
54 ctrl_t ctrl = opaque;
55 char line[100];
57 if (ctrl)
59 snprintf (line, sizeof line, "%s %c %d %d", what, pc, cur, tot);
60 send_status_direct (ctrl, "PROGRESS", line);
65 /* Lock the reader SLOT. This function shall be used right before
66 calling any of the actual application functions to serialize access
67 to the reader. We do this always even if the reader is not
68 actually used. This allows an actual connection to assume that it
69 never shares a reader (while performing one command). Returns 0 on
70 success; only then the unlock_reader function must be called after
71 returning from the handler. */
72 static gpg_error_t
73 lock_reader (int slot, ctrl_t ctrl)
75 gpg_error_t err;
77 if (slot < 0 || slot >= DIM (lock_table))
78 return gpg_error (slot<0? GPG_ERR_INV_VALUE : GPG_ERR_RESOURCE_LIMIT);
80 if (!lock_table[slot].initialized)
82 if (!pth_mutex_init (&lock_table[slot].lock))
84 err = gpg_error_from_syserror ();
85 log_error ("error initializing mutex: %s\n", strerror (errno));
86 return err;
88 lock_table[slot].initialized = 1;
89 lock_table[slot].app = NULL;
90 lock_table[slot].last_app = NULL;
93 if (!pth_mutex_acquire (&lock_table[slot].lock, 0, NULL))
95 err = gpg_error_from_syserror ();
96 log_error ("failed to acquire APP lock for slot %d: %s\n",
97 slot, strerror (errno));
98 return err;
101 apdu_set_progress_cb (slot, print_progress_line, ctrl);
103 return 0;
106 /* Release a lock on the reader. See lock_reader(). */
107 static void
108 unlock_reader (int slot)
110 if (slot < 0 || slot >= DIM (lock_table)
111 || !lock_table[slot].initialized)
112 log_bug ("unlock_reader called for invalid slot %d\n", slot);
114 apdu_set_progress_cb (slot, NULL, NULL);
116 if (!pth_mutex_release (&lock_table[slot].lock))
117 log_error ("failed to release APP lock for slot %d: %s\n",
118 slot, strerror (errno));
122 static void
123 dump_mutex_state (pth_mutex_t *m)
125 #ifdef _W32_PTH_H
126 (void)m;
127 log_printf ("unknown under W32");
128 #else
129 if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
130 log_printf ("not_initialized");
131 else if (!(m->mx_state & PTH_MUTEX_LOCKED))
132 log_printf ("not_locked");
133 else
134 log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
135 #endif
139 /* This function may be called to print information pertaining to the
140 current state of this module to the log. */
141 void
142 app_dump_state (void)
144 int slot;
146 for (slot=0; slot < DIM (lock_table); slot++)
147 if (lock_table[slot].initialized)
149 log_info ("app_dump_state: slot=%d lock=", slot);
150 dump_mutex_state (&lock_table[slot].lock);
151 if (lock_table[slot].app)
153 log_printf (" app=%p", lock_table[slot].app);
154 if (lock_table[slot].app->apptype)
155 log_printf (" type=`%s'", lock_table[slot].app->apptype);
157 if (lock_table[slot].last_app)
159 log_printf (" lastapp=%p", lock_table[slot].last_app);
160 if (lock_table[slot].last_app->apptype)
161 log_printf (" type=`%s'", lock_table[slot].last_app->apptype);
163 log_printf ("\n");
167 /* Check wether the application NAME is allowed. This does not mean
168 we have support for it though. */
169 static int
170 is_app_allowed (const char *name)
172 strlist_t l;
174 for (l=opt.disabled_applications; l; l = l->next)
175 if (!strcmp (l->d, name))
176 return 0; /* no */
177 return 1; /* yes */
181 /* This may be called to tell this module about a removed or resetted card. */
182 void
183 application_notify_card_reset (int slot)
185 app_t app;
187 if (slot < 0 || slot >= DIM (lock_table))
188 return;
190 /* FIXME: We are ignoring any error value here. */
191 lock_reader (slot, NULL);
193 /* Mark application as non-reusable. */
194 if (lock_table[slot].app)
195 lock_table[slot].app->no_reuse = 1;
197 /* Deallocate a saved application for that slot, so that we won't
198 try to reuse it. If there is no saved application, set a flag so
199 that we won't save the current state. */
200 app = lock_table[slot].last_app;
202 if (app)
204 lock_table[slot].last_app = NULL;
205 deallocate_app (app);
207 unlock_reader (slot);
211 /* This function is used by the serialno command to check for an
212 application conflict which may appear if the serialno command is
213 used to request a specific application and the connection has
214 already done a select_application. */
215 gpg_error_t
216 check_application_conflict (ctrl_t ctrl, const char *name)
218 int slot = ctrl->reader_slot;
219 app_t app;
221 if (slot < 0 || slot >= DIM (lock_table))
222 return gpg_error (GPG_ERR_INV_VALUE);
224 app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
225 if (app && app->apptype && name)
226 if ( ascii_strcasecmp (app->apptype, name))
227 return gpg_error (GPG_ERR_CONFLICT);
228 return 0;
232 /* If called with NAME as NULL, select the best fitting application
233 and return a context; otherwise select the application with NAME
234 and return a context. SLOT identifies the reader device. Returns
235 an error code and stores NULL at R_APP if no application was found
236 or no card is present. */
237 gpg_error_t
238 select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
240 gpg_error_t err;
241 app_t app = NULL;
242 unsigned char *result = NULL;
243 size_t resultlen;
245 (void)ctrl;
247 *r_app = NULL;
249 err = lock_reader (slot, ctrl);
250 if (err)
251 return err;
253 /* First check whether we already have an application to share. */
254 app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
255 if (app && name)
256 if (!app->apptype || ascii_strcasecmp (app->apptype, name))
258 unlock_reader (slot);
259 if (app->apptype)
260 log_info ("application `%s' in use by reader %d - can't switch\n",
261 app->apptype, slot);
262 return gpg_error (GPG_ERR_CONFLICT);
265 /* Don't use a non-reusable marked application. */
266 if (app && app->no_reuse)
268 unlock_reader (slot);
269 log_info ("lingering application `%s' in use by reader %d"
270 " - can't switch\n",
271 app->apptype? app->apptype:"?", slot);
272 return gpg_error (GPG_ERR_CONFLICT);
275 /* If we don't have an app, check whether we have a saved
276 application for that slot. This is useful so that a card does
277 not get reset even if only one session is using the card - this
278 way the PIN cache and other cached data are preserved. */
279 if (!app && lock_table[slot].initialized && lock_table[slot].last_app)
281 app = lock_table[slot].last_app;
282 if (!name || (app->apptype && !ascii_strcasecmp (app->apptype, name)) )
284 /* Yes, we can reuse this application - either the caller
285 requested an unspecific one or the requested one matches
286 the saved one. */
287 lock_table[slot].app = app;
288 lock_table[slot].last_app = NULL;
290 else
292 /* No, this saved application can't be used - deallocate it. */
293 lock_table[slot].last_app = NULL;
294 deallocate_app (app);
295 app = NULL;
299 /* If we can reuse an application, bump the reference count and
300 return it. */
301 if (app)
303 if (app->slot != slot)
304 log_bug ("slot mismatch %d/%d\n", app->slot, slot);
305 app->slot = slot;
307 app->ref_count++;
308 *r_app = app;
309 unlock_reader (slot);
310 return 0; /* Okay: We share that one. */
313 /* Need to allocate a new one. */
314 app = xtrycalloc (1, sizeof *app);
315 if (!app)
317 err = gpg_error_from_syserror ();
318 log_info ("error allocating context: %s\n", gpg_strerror (err));
319 unlock_reader (slot);
320 return err;
322 app->slot = slot;
325 /* Fixme: We should now first check whether a card is at all
326 present. */
328 /* Try to read the GDO file first to get a default serial number. */
329 err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
330 if (!err)
331 err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
332 if (!err)
333 err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
334 if (!err)
336 size_t n;
337 const unsigned char *p;
339 p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
340 if (p)
341 resultlen -= (p-result);
342 if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
344 /* The object it does not fit into the buffer. This is an
345 invalid encoding (or the buffer is too short. However, I
346 have some test cards with such an invalid encoding and
347 therefore I use this ugly workaround to return something
348 I can further experiment with. */
349 log_info ("enabling BMI testcard workaround\n");
350 n--;
353 if (p && n <= resultlen)
355 /* The GDO file is pretty short, thus we simply reuse it for
356 storing the serial number. */
357 memmove (result, p, n);
358 app->serialno = result;
359 app->serialnolen = n;
360 err = app_munge_serialno (app);
361 if (err)
362 goto leave;
364 else
365 xfree (result);
366 result = NULL;
369 /* For certain error codes, there is no need to try more. */
370 if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
371 || gpg_err_code (err) == GPG_ERR_ENODEV)
372 goto leave;
374 /* Figure out the application to use. */
375 err = gpg_error (GPG_ERR_NOT_FOUND);
377 if (err && is_app_allowed ("openpgp")
378 && (!name || !strcmp (name, "openpgp")))
379 err = app_select_openpgp (app);
380 if (err && is_app_allowed ("nks") && (!name || !strcmp (name, "nks")))
381 err = app_select_nks (app);
382 if (err && is_app_allowed ("p15") && (!name || !strcmp (name, "p15")))
383 err = app_select_p15 (app);
384 if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig")))
385 err = app_select_dinsig (app);
386 if (err && is_app_allowed ("geldkarte")
387 && (!name || !strcmp (name, "geldkarte")))
388 err = app_select_geldkarte (app);
389 if (err && name)
390 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
392 leave:
393 if (err)
395 if (name)
396 log_info ("can't select application `%s': %s\n",
397 name, gpg_strerror (err));
398 else
399 log_info ("no supported card application found: %s\n",
400 gpg_strerror (err));
401 xfree (app);
402 unlock_reader (slot);
403 return err;
406 app->ref_count = 1;
408 lock_table[slot].app = app;
409 *r_app = app;
410 unlock_reader (slot);
411 return 0;
415 char *
416 get_supported_applications (void)
418 const char *list[] = {
419 "openpgp",
420 "nks",
421 "p15",
422 "dinsig",
423 "geldkarte",
424 NULL
426 int idx;
427 size_t nbytes;
428 char *buffer, *p;
430 for (nbytes=1, idx=0; list[idx]; idx++)
431 nbytes += strlen (list[idx]) + 1 + 1;
433 buffer = xtrymalloc (nbytes);
434 if (!buffer)
435 return NULL;
437 for (p=buffer, idx=0; list[idx]; idx++)
438 if (is_app_allowed (list[idx]))
439 p = stpcpy (stpcpy (p, list[idx]), ":\n");
440 *p = 0;
442 return buffer;
446 /* Deallocate the application. */
447 static void
448 deallocate_app (app_t app)
450 if (app->fnc.deinit)
452 app->fnc.deinit (app);
453 app->fnc.deinit = NULL;
456 xfree (app->serialno);
457 xfree (app);
460 /* Free the resources associated with the application APP. APP is
461 allowed to be NULL in which case this is a no-op. Note that we are
462 using reference counting to track the users of the application and
463 actually deferring the deallocation to allow for a later reuse by
464 a new connection. */
465 void
466 release_application (app_t app)
468 int slot;
470 if (!app)
471 return;
473 if (!app->ref_count)
474 log_bug ("trying to release an already released context\n");
475 if (--app->ref_count)
476 return;
478 /* Move the reference to the application in the lock table. */
479 slot = app->slot;
480 /* FIXME: We are ignoring any error value. */
481 lock_reader (slot, NULL);
482 if (lock_table[slot].app != app)
484 unlock_reader (slot);
485 log_bug ("app mismatch %p/%p\n", app, lock_table[slot].app);
486 deallocate_app (app);
487 return;
490 if (lock_table[slot].last_app)
491 deallocate_app (lock_table[slot].last_app);
492 if (app->no_reuse)
494 /* If we shall not re-use the application we can't save it for
495 later use. */
496 deallocate_app (app);
497 lock_table[slot].last_app = NULL;
499 else
500 lock_table[slot].last_app = lock_table[slot].app;
501 lock_table[slot].app = NULL;
502 unlock_reader (slot);
507 /* The serial number may need some cosmetics. Do it here. This
508 function shall only be called once after a new serial number has
509 been put into APP->serialno.
511 Prefixes we use:
513 FF 00 00 = For serial numbers starting with an FF
514 FF 01 00 = Some german p15 cards return an empty serial number so the
515 serial number from the EF(TokenInfo) is used instead.
516 FF 7F 00 = No serialno.
518 All other serial number not starting with FF are used as they are.
520 gpg_error_t
521 app_munge_serialno (app_t app)
523 if (app->serialnolen && app->serialno[0] == 0xff)
525 /* The serial number starts with our special prefix. This
526 requires that we put our default prefix "FF0000" in front. */
527 unsigned char *p = xtrymalloc (app->serialnolen + 3);
528 if (!p)
529 return gpg_error_from_syserror ();
530 memcpy (p, "\xff\0", 3);
531 memcpy (p+3, app->serialno, app->serialnolen);
532 app->serialnolen += 3;
533 xfree (app->serialno);
534 app->serialno = p;
536 else if (!app->serialnolen)
538 unsigned char *p = xtrymalloc (3);
539 if (!p)
540 return gpg_error_from_syserror ();
541 memcpy (p, "\xff\x7f", 3);
542 app->serialnolen = 3;
543 xfree (app->serialno);
544 app->serialno = p;
546 return 0;
551 /* Retrieve the serial number and the time of the last update of the
552 card. The serial number is returned as a malloced string (hex
553 encoded) in SERIAL and the time of update is returned in STAMP. If
554 no update time is available the returned value is 0. Caller must
555 free SERIAL unless the function returns an error. If STAMP is not
556 of interest, NULL may be passed. */
557 gpg_error_t
558 app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp)
560 char *buf;
562 if (!app || !serial)
563 return gpg_error (GPG_ERR_INV_VALUE);
565 *serial = NULL;
566 if (stamp)
567 *stamp = 0; /* not available */
569 if (!app->serialnolen)
570 buf = xtrystrdup ("FF7F00");
571 else
572 buf = bin2hex (app->serialno, app->serialnolen, NULL);
573 if (!buf)
574 return gpg_error_from_syserror ();
576 *serial = buf;
577 return 0;
581 /* Write out the application specifig status lines for the LEARN
582 command. */
583 gpg_error_t
584 app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
586 gpg_error_t err;
588 if (!app)
589 return gpg_error (GPG_ERR_INV_VALUE);
590 if (!app->ref_count)
591 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
592 if (!app->fnc.learn_status)
593 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
595 /* We do not send APPTYPE if only keypairinfo is requested. */
596 if (app->apptype && !(flags & 1))
597 send_status_info (ctrl, "APPTYPE",
598 app->apptype, strlen (app->apptype), NULL, 0);
599 err = lock_reader (app->slot, ctrl);
600 if (err)
601 return err;
602 err = app->fnc.learn_status (app, ctrl, flags);
603 unlock_reader (app->slot);
604 return err;
608 /* Read the certificate with id CERTID (as returned by learn_status in
609 the CERTINFO status lines) and return it in the freshly allocated
610 buffer put into CERT and the length of the certificate put into
611 CERTLEN. */
612 gpg_error_t
613 app_readcert (app_t app, const char *certid,
614 unsigned char **cert, size_t *certlen)
616 gpg_error_t err;
618 if (!app)
619 return gpg_error (GPG_ERR_INV_VALUE);
620 if (!app->ref_count)
621 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
622 if (!app->fnc.readcert)
623 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
624 err = lock_reader (app->slot, NULL/* FIXME*/);
625 if (err)
626 return err;
627 err = app->fnc.readcert (app, certid, cert, certlen);
628 unlock_reader (app->slot);
629 return err;
633 /* Read the key with ID KEYID. On success a canonical encoded
634 S-expression with the public key will get stored at PK and its
635 length (for assertions) at PKLEN; the caller must release that
636 buffer. On error NULL will be stored at PK and PKLEN and an error
637 code returned.
639 This function might not be supported by all applications. */
640 gpg_error_t
641 app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
643 gpg_error_t err;
645 if (pk)
646 *pk = NULL;
647 if (pklen)
648 *pklen = 0;
650 if (!app || !keyid || !pk || !pklen)
651 return gpg_error (GPG_ERR_INV_VALUE);
652 if (!app->ref_count)
653 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
654 if (!app->fnc.readkey)
655 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
656 err = lock_reader (app->slot, NULL /*FIXME*/);
657 if (err)
658 return err;
659 err= app->fnc.readkey (app, keyid, pk, pklen);
660 unlock_reader (app->slot);
661 return err;
665 /* Perform a GETATTR operation. */
666 gpg_error_t
667 app_getattr (app_t app, ctrl_t ctrl, const char *name)
669 gpg_error_t err;
671 if (!app || !name || !*name)
672 return gpg_error (GPG_ERR_INV_VALUE);
673 if (!app->ref_count)
674 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
676 if (app->apptype && name && !strcmp (name, "APPTYPE"))
678 send_status_info (ctrl, "APPTYPE",
679 app->apptype, strlen (app->apptype), NULL, 0);
680 return 0;
682 if (name && !strcmp (name, "SERIALNO"))
684 char *serial;
685 time_t stamp;
686 int rc;
688 rc = app_get_serial_and_stamp (app, &serial, &stamp);
689 if (rc)
690 return rc;
691 send_status_info (ctrl, "SERIALNO", serial, strlen (serial), NULL, 0);
692 xfree (serial);
693 return 0;
696 if (!app->fnc.getattr)
697 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
698 err = lock_reader (app->slot, ctrl);
699 if (err)
700 return err;
701 err = app->fnc.getattr (app, ctrl, name);
702 unlock_reader (app->slot);
703 return err;
706 /* Perform a SETATTR operation. */
707 gpg_error_t
708 app_setattr (app_t app, const char *name,
709 gpg_error_t (*pincb)(void*, const char *, char **),
710 void *pincb_arg,
711 const unsigned char *value, size_t valuelen)
713 gpg_error_t err;
715 if (!app || !name || !*name || !value)
716 return gpg_error (GPG_ERR_INV_VALUE);
717 if (!app->ref_count)
718 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
719 if (!app->fnc.setattr)
720 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
721 err = lock_reader (app->slot, NULL /*FIXME*/);
722 if (err)
723 return err;
724 err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
725 unlock_reader (app->slot);
726 return err;
729 /* Create the signature and return the allocated result in OUTDATA.
730 If a PIN is required the PINCB will be used to ask for the PIN; it
731 should return the PIN in an allocated buffer and put it into PIN. */
732 gpg_error_t
733 app_sign (app_t app, const char *keyidstr, int hashalgo,
734 gpg_error_t (*pincb)(void*, const char *, char **),
735 void *pincb_arg,
736 const void *indata, size_t indatalen,
737 unsigned char **outdata, size_t *outdatalen )
739 gpg_error_t err;
741 if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
742 return gpg_error (GPG_ERR_INV_VALUE);
743 if (!app->ref_count)
744 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
745 if (!app->fnc.sign)
746 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
747 err = lock_reader (app->slot, NULL /*FIXME*/);
748 if (err)
749 return err;
750 err = app->fnc.sign (app, keyidstr, hashalgo,
751 pincb, pincb_arg,
752 indata, indatalen,
753 outdata, outdatalen);
754 unlock_reader (app->slot);
755 if (opt.verbose)
756 log_info ("operation sign result: %s\n", gpg_strerror (err));
757 return err;
760 /* Create the signature using the INTERNAL AUTHENTICATE command and
761 return the allocated result in OUTDATA. If a PIN is required the
762 PINCB will be used to ask for the PIN; it should return the PIN in
763 an allocated buffer and put it into PIN. */
764 gpg_error_t
765 app_auth (app_t app, const char *keyidstr,
766 gpg_error_t (*pincb)(void*, const char *, char **),
767 void *pincb_arg,
768 const void *indata, size_t indatalen,
769 unsigned char **outdata, size_t *outdatalen )
771 gpg_error_t err;
773 if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
774 return gpg_error (GPG_ERR_INV_VALUE);
775 if (!app->ref_count)
776 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
777 if (!app->fnc.auth)
778 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
779 err = lock_reader (app->slot, NULL /*FIXME*/);
780 if (err)
781 return err;
782 err = app->fnc.auth (app, keyidstr,
783 pincb, pincb_arg,
784 indata, indatalen,
785 outdata, outdatalen);
786 unlock_reader (app->slot);
787 if (opt.verbose)
788 log_info ("operation auth result: %s\n", gpg_strerror (err));
789 return err;
793 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
794 If a PIN is required the PINCB will be used to ask for the PIN; it
795 should return the PIN in an allocated buffer and put it into PIN. */
796 gpg_error_t
797 app_decipher (app_t app, const char *keyidstr,
798 gpg_error_t (*pincb)(void*, const char *, char **),
799 void *pincb_arg,
800 const void *indata, size_t indatalen,
801 unsigned char **outdata, size_t *outdatalen )
803 gpg_error_t err;
805 if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
806 return gpg_error (GPG_ERR_INV_VALUE);
807 if (!app->ref_count)
808 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
809 if (!app->fnc.decipher)
810 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
811 err = lock_reader (app->slot, NULL /*FIXME*/);
812 if (err)
813 return err;
814 err = app->fnc.decipher (app, keyidstr,
815 pincb, pincb_arg,
816 indata, indatalen,
817 outdata, outdatalen);
818 unlock_reader (app->slot);
819 if (opt.verbose)
820 log_info ("operation decipher result: %s\n", gpg_strerror (err));
821 return err;
825 /* Perform the WRITECERT operation. */
826 gpg_error_t
827 app_writecert (app_t app, ctrl_t ctrl,
828 const char *certidstr,
829 gpg_error_t (*pincb)(void*, const char *, char **),
830 void *pincb_arg,
831 const unsigned char *data, size_t datalen)
833 gpg_error_t err;
835 if (!app || !certidstr || !*certidstr || !pincb)
836 return gpg_error (GPG_ERR_INV_VALUE);
837 if (!app->ref_count)
838 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
839 if (!app->fnc.writecert)
840 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
841 err = lock_reader (app->slot, ctrl);
842 if (err)
843 return err;
844 err = app->fnc.writecert (app, ctrl, certidstr,
845 pincb, pincb_arg, data, datalen);
846 unlock_reader (app->slot);
847 if (opt.verbose)
848 log_info ("operation writecert result: %s\n", gpg_strerror (err));
849 return err;
853 /* Perform the WRITEKEY operation. */
854 gpg_error_t
855 app_writekey (app_t app, ctrl_t ctrl,
856 const char *keyidstr, unsigned int flags,
857 gpg_error_t (*pincb)(void*, const char *, char **),
858 void *pincb_arg,
859 const unsigned char *keydata, size_t keydatalen)
861 gpg_error_t err;
863 if (!app || !keyidstr || !*keyidstr || !pincb)
864 return gpg_error (GPG_ERR_INV_VALUE);
865 if (!app->ref_count)
866 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
867 if (!app->fnc.writekey)
868 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
869 err = lock_reader (app->slot, ctrl);
870 if (err)
871 return err;
872 err = app->fnc.writekey (app, ctrl, keyidstr, flags,
873 pincb, pincb_arg, keydata, keydatalen);
874 unlock_reader (app->slot);
875 if (opt.verbose)
876 log_info ("operation writekey result: %s\n", gpg_strerror (err));
877 return err;
881 /* Perform a SETATTR operation. */
882 gpg_error_t
883 app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
884 time_t createtime,
885 gpg_error_t (*pincb)(void*, const char *, char **),
886 void *pincb_arg)
888 gpg_error_t err;
890 if (!app || !keynostr || !*keynostr || !pincb)
891 return gpg_error (GPG_ERR_INV_VALUE);
892 if (!app->ref_count)
893 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
894 if (!app->fnc.genkey)
895 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
896 err = lock_reader (app->slot, ctrl);
897 if (err)
898 return err;
899 err = app->fnc.genkey (app, ctrl, keynostr, flags,
900 createtime, pincb, pincb_arg);
901 unlock_reader (app->slot);
902 if (opt.verbose)
903 log_info ("operation genkey result: %s\n", gpg_strerror (err));
904 return err;
908 /* Perform a GET CHALLENGE operation. This fucntion is special as it
909 directly accesses the card without any application specific
910 wrapper. */
911 gpg_error_t
912 app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer)
914 gpg_error_t err;
916 if (!app || !nbytes || !buffer)
917 return gpg_error (GPG_ERR_INV_VALUE);
918 if (!app->ref_count)
919 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
920 err = lock_reader (app->slot, NULL /*FIXME*/);
921 if (err)
922 return err;
923 err = iso7816_get_challenge (app->slot, nbytes, buffer);
924 unlock_reader (app->slot);
925 return err;
930 /* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation. */
931 gpg_error_t
932 app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
933 gpg_error_t (*pincb)(void*, const char *, char **),
934 void *pincb_arg)
936 gpg_error_t err;
938 if (!app || !chvnostr || !*chvnostr || !pincb)
939 return gpg_error (GPG_ERR_INV_VALUE);
940 if (!app->ref_count)
941 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
942 if (!app->fnc.change_pin)
943 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
944 err = lock_reader (app->slot, ctrl);
945 if (err)
946 return err;
947 err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode,
948 pincb, pincb_arg);
949 unlock_reader (app->slot);
950 if (opt.verbose)
951 log_info ("operation change_pin result: %s\n", gpg_strerror (err));
952 return err;
956 /* Perform a VERIFY operation without doing anything lese. This may
957 be used to initialze a the PIN cache for long lasting other
958 operations. Its use is highly application dependent. */
959 gpg_error_t
960 app_check_pin (app_t app, const char *keyidstr,
961 gpg_error_t (*pincb)(void*, const char *, char **),
962 void *pincb_arg)
964 gpg_error_t err;
966 if (!app || !keyidstr || !*keyidstr || !pincb)
967 return gpg_error (GPG_ERR_INV_VALUE);
968 if (!app->ref_count)
969 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
970 if (!app->fnc.check_pin)
971 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
972 err = lock_reader (app->slot, NULL /*FIXME*/);
973 if (err)
974 return err;
975 err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);
976 unlock_reader (app->slot);
977 if (opt.verbose)
978 log_info ("operation check_pin result: %s\n", gpg_strerror (err));
979 return err;