LCOV - code coverage report
Current view: top level - scd - app.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 439 0.0 %
Date: 2016-09-12 12:29:17 Functions: 0 28 0.0 %

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

Generated by: LCOV version 1.11