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

Generated by: LCOV version 1.11