* Makefile.am (DISTCHECK_CONFIGURE_FLAGS): New.
[gnupg.git] / g10 / app-openpgp.c
index e4c1477..d6cbe88 100644 (file)
@@ -16,6 +16,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id$
  */
 
 #include <config.h>
 #include "errors.h"
 #include "memory.h"
 #include "util.h"
-#include "i18n.h"
 #include "cardglue.h"
 #else /* GNUPG_MAJOR_VERSION != 1 */
 #include "scdaemon.h"
 #endif /* GNUPG_MAJOR_VERSION != 1 */
 
+#include "i18n.h"
 #include "iso7816.h"
 #include "app-common.h"
 #include "tlv.h"
@@ -52,27 +54,33 @@ static struct {
   int binary;
   int dont_cache;
   int flush_on_error;
+  int get_immediate_in_v11; /* Enable a hack to bypass the cache of
+                               this data object if it is used in 1.1
+                               and later versions of the card.  This
+                               does not work with composite DO and is
+                               currently only useful for the CHV
+                               status bytes. */
   char *desc;
 } data_objects[] = {
-  { 0x005E, 0,    0, 1, 0, 0, "Login Data" },
-  { 0x5F50, 0,    0, 0, 0, 0, "URL" },
-  { 0x0065, 1,    0, 1, 0, 0, "Cardholder Related Data"},
-  { 0x005B, 0, 0x65, 0, 0, 0, "Name" },
-  { 0x5F2D, 0, 0x65, 0, 0, 0, "Language preferences" },
-  { 0x5F35, 0, 0x65, 0, 0, 0, "Sex" },
-  { 0x006E, 1,    0, 1, 0, 0, "Application Related Data" },
-  { 0x004F, 0, 0x6E, 1, 0, 0, "AID" },
-  { 0x0073, 1,    0, 1, 0, 0, "Discretionary Data Objects" },
-  { 0x0047, 0, 0x6E, 1, 1, 0, "Card Capabilities" },
-  { 0x00C0, 0, 0x6E, 1, 1, 0, "Extended Card Capabilities" },
-  { 0x00C1, 0, 0x6E, 1, 1, 0, "Algorithm Attributes Signature" },
-  { 0x00C2, 0, 0x6E, 1, 1, 0, "Algorithm Attributes Decryption" },
-  { 0x00C3, 0, 0x6E, 1, 1, 0, "Algorithm Attributes Authentication" },
-  { 0x00C4, 0, 0x6E, 1, 0, 1, "CHV Status Bytes" },
-  { 0x00C5, 0, 0x6E, 1, 0, 0, "Fingerprints" },
-  { 0x00C6, 0, 0x6E, 1, 0, 0, "CA Fingerprints" },
-  { 0x007A, 1,    0, 1, 0, 0, "Security Support Template" },
-  { 0x0093, 0, 0x7A, 1, 1, 0, "Digital Signature Counter" },
+  { 0x005E, 0,    0, 1, 0, 0, 0, "Login Data" },
+  { 0x5F50, 0,    0, 0, 0, 0, 0, "URL" },
+  { 0x0065, 1,    0, 1, 0, 0, 0, "Cardholder Related Data"},
+  { 0x005B, 0, 0x65, 0, 0, 0, 0, "Name" },
+  { 0x5F2D, 0, 0x65, 0, 0, 0, 0, "Language preferences" },
+  { 0x5F35, 0, 0x65, 0, 0, 0, 0, "Sex" },
+  { 0x006E, 1,    0, 1, 0, 0, 0, "Application Related Data" },
+  { 0x004F, 0, 0x6E, 1, 0, 0, 0, "AID" },
+  { 0x0073, 1,    0, 1, 0, 0, 0, "Discretionary Data Objects" },
+  { 0x0047, 0, 0x6E, 1, 1, 0, 0, "Card Capabilities" },
+  { 0x00C0, 0, 0x6E, 1, 1, 0, 0, "Extended Card Capabilities" },
+  { 0x00C1, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Signature" },
+  { 0x00C2, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Decryption" },
+  { 0x00C3, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Authentication" },
+  { 0x00C4, 0, 0x6E, 1, 0, 1, 1, "CHV Status Bytes" },
+  { 0x00C5, 0, 0x6E, 1, 0, 0, 0, "Fingerprints" },
+  { 0x00C6, 0, 0x6E, 1, 0, 0, 0, "CA Fingerprints" },
+  { 0x007A, 1,    0, 1, 0, 0, 0, "Security Support Template" },
+  { 0x0093, 0, 0x7A, 1, 1, 0, 0, "Digital Signature Counter" },
   { 0 }
 };
 
@@ -93,6 +101,11 @@ struct app_local_s {
     unsigned int change_force_chv:1;
     unsigned int private_dos:1;
   } extcap;
+  struct
+  {
+    unsigned int no_sync:1;   /* Do not sync CHV1 and CHV2 */
+    unsigned int def_chv2:1;  /* Use 123456 for CHV2.  */
+  } flags;
 };
 
 
@@ -205,7 +218,9 @@ flush_cache_item (app_t app, int tag)
         xfree (c);
 
         for (c=app->app_local->cache; c ; c = c->next)
-          assert (c->tag != tag); /* Oops: duplicated entry. */
+          {
+            assert (c->tag != tag); /* Oops: duplicated entry. */
+          }
         return;
       }
 
@@ -265,6 +280,15 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes)
   for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++)
     ;
 
+  if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11)
+    {
+      if( iso7816_get_data (app->slot, tag, &buffer, &buflen))
+        return NULL;
+      *result = buffer;
+      *nbytes = buflen;
+      return buffer;
+    }
+
   value = NULL;
   rc = -1;
   if (data_objects[i].tag && data_objects[i].get_from)
@@ -392,6 +416,75 @@ count_bits (const unsigned char *a, size_t len)
   return n;
 }
 
+/* GnuPG makes special use of the login-data DO, this fucntion parses
+   the login data to store the flags for later use.  It may be called
+   at any time and should be called after changing the login-data DO.
+
+   Everything up to a LF is considered a mailbox or account name.  If
+   the first LF is follewed by DC4 (0x14) control sequence are
+   expected up to the next LF.  Control sequences are separated by FS
+   (0x28) and consist of key=value pairs.  There is one key defined:
+
+    F=<flags>
+
+    Were FLAGS is a plain hexadecimal number representing flag values.
+    The lsb is here the rightmost bit.  Defined flags bits are:
+
+      Bit 0 = CHV1 and CHV2 are not syncronized
+      Bit 1 = CHV2 has been been set to the default PIN of "123456"
+              (this implies that bit 0 is also set).
+
+*/
+static void
+parse_login_data (app_t app)
+{
+  unsigned char *buffer, *p;
+  size_t buflen, len;
+  void *relptr;
+
+  /* Set defaults.  */
+  app->app_local->flags.no_sync = 0;
+  app->app_local->flags.def_chv2 = 0;
+
+  /* Read the DO.  */
+  relptr = get_one_do (app, 0x005E, &buffer, &buflen);
+  if (!relptr)
+    return; /* Ooops. */
+  for (; buflen; buflen--, buffer++)
+    if (*buffer == '\n')
+      break;
+  if (buflen < 2 || buffer[1] != '\x14')
+    return; /* No control sequences.  */
+  buflen--;
+  buffer++;
+  do
+    {
+      buflen--;
+      buffer++;
+      if (buflen > 1 && *buffer == 'F' && buffer[1] == '=')
+        {
+          /* Flags control sequence found.  */
+          int lastdig = 0;
+
+          /* For now we are only interested in the last digit, so skip
+             any leading digits but bail out on invalid characters. */
+          for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--)
+            lastdig = xtoi_1 (p);
+          if (len && !(*p == '\n' || *p == '\x18'))
+            goto next;  /* Invalid characters in field.  */
+          app->app_local->flags.no_sync = !!(lastdig & 1);
+          app->app_local->flags.def_chv2 = (lastdig & 3) == 3;
+        }
+    next:
+      for (; buflen && *buffer != '\x18'; buflen--, buffer++)
+        if (*buffer == '\n')
+          buflen = 1; 
+    }
+  while (buflen);
+
+  xfree (relptr);
+}
+
 /* Note, that FPR must be at least 20 bytes. */
 static int 
 store_fpr (int slot, int keynumber, u32 timestamp,
@@ -438,14 +531,29 @@ store_fpr (int slot, int keynumber, u32 timestamp,
   rc = iso7816_put_data (slot, (card_version > 0x0007? 0xC7 : 0xC6)
                                + keynumber, fpr, 20);
   if (rc)
-    log_error ("failed to store the fingerprint: %s\n",gpg_strerror (rc));
+    log_error (_("failed to store the fingerprint: %s\n"),gpg_strerror (rc));
+
+  if (!rc && card_version > 0x0100)
+    {
+      unsigned char buf[4];
+
+      buf[0] = timestamp >> 24;
+      buf[1] = timestamp >> 16;
+      buf[2] = timestamp >>  8;
+      buf[3] = timestamp;
+
+      rc = iso7816_put_data (slot, 0xCE + keynumber, buf, 4);
+      if (rc)
+        log_error (_("failed to store the creation date: %s\n"),
+                   gpg_strerror (rc));
+    }
 
   return rc;
 }
 
        
 static void
-send_fpr_if_not_null (CTRL ctrl, const char *keyword,
+send_fpr_if_not_null (ctrl_t ctrl, const char *keyword,
                       int number, const unsigned char *fpr)
 {                      
   int i;
@@ -468,7 +576,7 @@ send_fpr_if_not_null (CTRL ctrl, const char *keyword,
 }
 
 static void
-send_key_data (CTRL ctrl, const char *name, 
+send_key_data (ctrl_t ctrl, const char *name, 
                const unsigned char *a, size_t alen)
 {
   char *p, *buf = xmalloc (alen*2+1);
@@ -486,7 +594,7 @@ send_key_data (CTRL ctrl, const char *name,
 /* Implement the GETATTR command.  This is similar to the LEARN
    command but returns just one value via the status interface. */
 static int 
-do_getattr (APP app, CTRL ctrl, const char *name)
+do_getattr (app_t app, ctrl_t ctrl, const char *name)
 {
   static struct {
     const char *name;
@@ -588,7 +696,7 @@ do_getattr (APP app, CTRL ctrl, const char *name)
 
 
 static int
-do_learn_status (APP app, CTRL ctrl)
+do_learn_status (app_t app, ctrl_t ctrl)
 {
   do_getattr (app, ctrl, "EXTCAP");
   do_getattr (app, ctrl, "DISP-NAME");
@@ -621,13 +729,14 @@ verify_chv2 (app_t app,
       rc = pincb (pincb_arg, "PIN", &pinvalue); 
       if (rc)
         {
-          log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
+          log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc));
           return rc;
         }
 
       if (strlen (pinvalue) < 6)
         {
-          log_error ("prassphrase (CHV2) is too short; minimum length is 6\n");
+          log_error (_("PIN for CHV%d is too short;"
+                       " minimum length is %d\n"), 2, 6);
           xfree (pinvalue);
           return gpg_error (GPG_ERR_BAD_PIN);
         }
@@ -635,7 +744,7 @@ verify_chv2 (app_t app,
       rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));
       if (rc)
         {
-          log_error ("verify CHV2 failed: %s\n", gpg_strerror (rc));
+          log_error (_("verify CHV%d failed: %s\n"), 2, gpg_strerror (rc));
           xfree (pinvalue);
           flush_cache_after_error (app);
           return rc;
@@ -649,7 +758,7 @@ verify_chv2 (app_t app,
             rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
           if (rc)
             {
-              log_error ("verify CHV1 failed: %s\n", gpg_strerror (rc));
+              log_error (_("verify CHV%d failed: %s\n"), 1, gpg_strerror (rc));
               xfree (pinvalue);
               flush_cache_after_error (app);
               return rc;
@@ -663,32 +772,60 @@ verify_chv2 (app_t app,
 
 /* Verify CHV3 if required. */
 static int
-verify_chv3 (APP app,
+verify_chv3 (app_t app,
              int (*pincb)(void*, const char *, char **),
              void *pincb_arg)
 {
   int rc = 0;
 
+#if GNUPG_MAJOR_VERSION != 1
   if (!opt.allow_admin)
     {
-      log_info ("access to admin commands is not configured\n");
+      log_info (_("access to admin commands is not configured\n"));
       return gpg_error (GPG_ERR_EACCES);
     }
+#endif
       
   if (!app->did_chv3) 
     {
       char *pinvalue;
+      void *relptr;
+      unsigned char *value;
+      size_t valuelen;
+      int reread_chv_status;
+      
+
+      relptr = get_one_do (app, 0x00C4, &value, &valuelen);
+      if (!relptr || valuelen < 7)
+        {
+          log_error (_("error retrieving CHV status from card\n"));
+          xfree (relptr);
+          return gpg_error (GPG_ERR_CARD);
+        }
+      if (value[6] == 0)
+        {
+          log_info (_("card is permanently locked!\n"));
+          xfree (relptr);
+          return gpg_error (GPG_ERR_BAD_PIN);
+        }
+
+      reread_chv_status = (value[6] < 3);
 
-      rc = pincb (pincb_arg, "Admin PIN", &pinvalue); 
+      log_info(_("%d Admin PIN attempts remaining before card"
+                 " is permanently locked\n"), value[6]);
+      xfree (relptr);
+
+      rc = pincb (pincb_arg, _("Admin PIN"), &pinvalue); 
       if (rc)
         {
-          log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
+          log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc));
           return rc;
         }
 
       if (strlen (pinvalue) < 6)
         {
-          log_error ("prassphrase (CHV3) is too short; minimum length is 6\n");
+          log_error (_("prassphrase (CHV%d) is too short;"
+                       " minimum length is %d\n"), 3, 6);
           xfree (pinvalue);
           return gpg_error (GPG_ERR_BAD_PIN);
         }
@@ -697,11 +834,18 @@ verify_chv3 (APP app,
       xfree (pinvalue);
       if (rc)
         {
-          log_error ("verify CHV3 failed: %s\n", gpg_strerror (rc));
+          log_error (_("verify CHV%d failed: %s\n"), 3, gpg_strerror (rc));
           flush_cache_after_error (app);
           return rc;
         }
       app->did_chv3 = 1;
+      /* If the PIN has been entered wrongly before, we need to flush
+         the cached value so that the next read correctly reflects the
+         resetted retry counter.  Note that version 1.1 of the specs
+         allow direct reading of that DO, so that we could actually
+         flush it in all cases. */
+      if (reread_chv_status)
+        flush_cache_item (app, 0x00C4);
     }
   return rc;
 }
@@ -710,7 +854,7 @@ verify_chv3 (APP app,
 /* Handle the SETATTR operation. All arguments are already basically
    checked. */
 static int 
-do_setattr (APP app, const char *name,
+do_setattr (app_t app, const char *name,
             int (*pincb)(void*, const char *, char **),
             void *pincb_arg,
             const unsigned char *value, size_t valuelen)
@@ -723,7 +867,7 @@ do_setattr (APP app, const char *name,
     int special;
   } table[] = {
     { "DISP-NAME",    0x005B },
-    { "LOGIN-DATA",   0x005E },
+    { "LOGIN-DATA",   0x005E, 2 },
     { "DISP-LANG",    0x5F2D },
     { "DISP-SEX",     0x5F35 },
     { "PUBKEY-URL",   0x5F50 },
@@ -754,6 +898,8 @@ do_setattr (APP app, const char *name,
 
   if (table[idx].special == 1)
     app->force_chv1 = (valuelen && *value == 0);
+  else if (table[idx].special == 2)
+    parse_login_data (app);
 
   return rc;
 }
@@ -761,7 +907,7 @@ do_setattr (APP app, const char *name,
 
 /* Handle the PASSWD command. */
 static int 
-do_change_pin (APP app, CTRL ctrl,  const char *chvnostr, int reset_mode,
+do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr, int reset_mode,
                int (*pincb)(void*, const char *, char **),
                void *pincb_arg)
 {
@@ -848,7 +994,7 @@ do_change_pin (APP app, CTRL ctrl,  const char *chvnostr, int reset_mode,
 
 /* Handle the GENKEY command. */
 static int 
-do_genkey (APP app, CTRL ctrl,  const char *keynostr, unsigned int flags,
+do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
           int (*pincb)(void*, const char *, char **),
           void *pincb_arg)
 {
@@ -990,7 +1136,7 @@ convert_sig_counter_value (const unsigned char *value, size_t valuelen)
 }
 
 static unsigned long
-get_sig_counter (APP app)
+get_sig_counter (app_t app)
 {
   void *relptr;
   unsigned char *value;
@@ -1006,7 +1152,7 @@ get_sig_counter (APP app)
 }
 
 static int
-compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr)
+compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr)
 {
   const unsigned char *fpr;
   unsigned char *buffer;
@@ -1046,7 +1192,7 @@ compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr)
      known to gpg was not updated.  If there is no fingerprint we
      assume that this is okay. */
 static int
-check_against_given_fingerprint (APP app, const char *fpr, int keyno)
+check_against_given_fingerprint (app_t app, const char *fpr, int keyno)
 {
   unsigned char tmp[20];
   const char *s;
@@ -1077,7 +1223,7 @@ check_against_given_fingerprint (APP app, const char *fpr, int keyno)
    not match the one required for the requested action (e.g. the
    serial number does not match). */
 static int 
-do_sign (APP app, const char *keyidstr, int hashalgo,
+do_sign (app_t app, const char *keyidstr, int hashalgo,
          int (*pincb)(void*, const char *, char **),
          void *pincb_arg,
          const void *indata, size_t indatalen,
@@ -1152,20 +1298,21 @@ do_sign (APP app, const char *keyidstr, int hashalgo,
 
       {
         char *prompt;
-        if (asprintf (&prompt, "PIN [sigs done: %lu]", sigcount) < 0)
+        if (asprintf (&prompt, _("PIN [sigs done: %lu]"), sigcount) < 0)
           return gpg_error_from_errno (errno);
         rc = pincb (pincb_arg, prompt, &pinvalue); 
         free (prompt);
       }
       if (rc)
         {
-          log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
+          log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc));
           return rc;
         }
 
       if (strlen (pinvalue) < 6)
         {
-          log_error ("prassphrase (CHV1) is too short; minimum length is 6\n");
+          log_error (_("PIN for CHV%d is too short;"
+                       " minimum length is %d\n"), 1, 6);
           xfree (pinvalue);
           return gpg_error (GPG_ERR_BAD_PIN);
         }
@@ -1173,7 +1320,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo,
       rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
       if (rc)
         {
-          log_error ("verify CHV1 failed\n");
+          log_error (_("verify CHV%d failed: %s\n"), 1, gpg_strerror (rc));
           xfree (pinvalue);
           flush_cache_after_error (app);
           return rc;
@@ -1187,7 +1334,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo,
             rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
           if (rc)
             {
-              log_error ("verify CHV2 failed\n");
+              log_error (_("verify CHV%d failed: %s\n"), 2, gpg_strerror (rc));
               xfree (pinvalue);
               flush_cache_after_error (app);
               return rc;
@@ -1211,7 +1358,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo,
    not match the one required for the requested action (e.g. the
    serial number does not match). */
 static int 
-do_auth (APP app, const char *keyidstr,
+do_auth (app_t app, const char *keyidstr,
          int (*pincb)(void*, const char *, char **),
          void *pincb_arg,
          const void *indata, size_t indatalen,
@@ -1270,7 +1417,7 @@ do_auth (APP app, const char *keyidstr,
 
 
 static int 
-do_decipher (APP app, const char *keyidstr,
+do_decipher (app_t app, const char *keyidstr,
              int (pincb)(void*, const char *, char **),
              void *pincb_arg,
              const void *indata, size_t indatalen,
@@ -1332,7 +1479,7 @@ do_decipher (APP app, const char *keyidstr,
    dangerous CHV3.  KEYIDSTR is the usual card's serial number; an
    optional fingerprint part will be ignored. */
 static int 
-do_check_pin (APP app, const char *keyidstr,
+do_check_pin (app_t app, const char *keyidstr,
               int (pincb)(void*, const char *, char **),
               void *pincb_arg)
 {
@@ -1379,7 +1526,7 @@ do_check_pin (APP app, const char *keyidstr,
 /* Select the OpenPGP application on the card in SLOT.  This function
    must be used before any other OpenPGP application functions. */
 int
-app_select_openpgp (APP app)
+app_select_openpgp (app_t app)
 {
   static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 };
   int slot = app->slot;
@@ -1410,7 +1557,7 @@ app_select_openpgp (APP app)
         goto leave;
       if (opt.verbose)
         {
-          log_info ("got AID: ");
+          log_info ("AID: ");
           log_printhex ("", buffer, buflen);
         }
 
@@ -1432,7 +1579,8 @@ app_select_openpgp (APP app)
       relptr = get_one_do (app, 0x00C4, &buffer, &buflen);
       if (!relptr)
         {
-          log_error ("can't access CHV Status Bytes - invalid OpenPGP card?\n");
+          log_error (_("can't access %s - invalid OpenPGP card?\n"),
+                     "CHV Status Bytes");
           goto leave;
         }
       app->force_chv1 = (buflen && *buffer == 0);
@@ -1441,8 +1589,8 @@ app_select_openpgp (APP app)
       relptr = get_one_do (app, 0x00C0, &buffer, &buflen);
       if (!relptr)
         {
-          log_error ("can't access Extended Capability Flags - "
-                     "invalid OpenPGP card?\n");
+          log_error (_("can't access %s - invalid OpenPGP card?\n"),
+                     "Extended Capability Flags" );
           goto leave;
         }
       if (buflen)
@@ -1459,6 +1607,7 @@ app_select_openpgp (APP app)
       if (app->card_version <= 0x0100 && manufacturer == 1)
         app->app_local->extcap.change_force_chv = 1;
 
+      parse_login_data (app);
 
       if (opt.verbose > 1)
         dump_all_do (slot);
@@ -1490,7 +1639,7 @@ leave:
    buffers or NULL if the data object is not available.  All returned
    values are sanitized. */
 int
-app_openpgp_cardinfo (APP app,
+app_openpgp_cardinfo (app_t app,
                       char **serialno,
                       char **disp_name,
                       char **pubkey_url,
@@ -1511,7 +1660,8 @@ app_openpgp_cardinfo (APP app,
       rc = app_get_serial_and_stamp (app, serialno, &dummy);
       if (rc)
         {
-          log_error ("error getting serial number: %s\n", gpg_strerror (rc));
+          log_error (_("error getting serial number: %s\n"),
+                     gpg_strerror (rc));
           return rc;
         }
     }
@@ -1571,7 +1721,7 @@ app_openpgp_cardinfo (APP app,
 
 
 /* This function is currently only used by the sc-copykeys program to
-   store a key on the smartcard.  APP ist the application handle,
+   store a key on the smartcard.  app_t ist the application handle,
    KEYNO is the number of the key and PINCB, PINCB_ARG are used to ask
    for the SO PIN.  TEMPLATE and TEMPLATE_LEN describe a buffer with
    the key template to store. CREATED_AT is the timestamp used to
@@ -1579,7 +1729,7 @@ app_openpgp_cardinfo (APP app,
    RSA public exponent. This function silently overwrites an existing
    key.*/
 int 
-app_openpgp_storekey (APP app, int keyno,
+app_openpgp_storekey (app_t app, int keyno,
                       unsigned char *template, size_t template_len,
                       time_t created_at,
                       const unsigned char *m, size_t mlen,
@@ -1605,7 +1755,7 @@ app_openpgp_storekey (APP app, int keyno,
                          template, template_len);
   if (rc)
     {
-      log_error ("failed to store the key: rc=%s\n", gpg_strerror (rc));
+      log_error (_("failed to store the key: %s\n"), gpg_strerror (rc));
       rc = gpg_error (GPG_ERR_CARD);
       goto leave;
     }
@@ -1624,7 +1774,7 @@ app_openpgp_storekey (APP app, int keyno,
 /* Utility function for external tools: Read the public RSA key at
    KEYNO and return modulus and exponent in (M,MLEN) and (E,ELEN). */
 int 
-app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen,
+app_openpgp_readkey (app_t app, int keyno, unsigned char **m, size_t *mlen,
                      unsigned char **e, size_t *elen)
 {
   int rc;
@@ -1647,14 +1797,14 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen,
   if (rc)
     {
       rc = gpg_error (GPG_ERR_CARD);
-      log_error ("reading key failed\n");
+      log_error (_("reading the key failed\n"));
       goto leave;
     }
 
   keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen);
   if (!keydata)
     {
-      log_error ("response does not contain the public key data\n");
+      log_error (_("response does not contain the public key data\n"));
       rc = gpg_error (GPG_ERR_CARD);
       goto leave;
     }
@@ -1662,7 +1812,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen,
   a = find_tlv (keydata, keydatalen, 0x0081, &alen);
   if (!a)
     {
-      log_error ("response does not contain the RSA modulus\n");
+      log_error (_("response does not contain the RSA modulus\n"));
       rc = gpg_error (GPG_ERR_CARD);
       goto leave;
     }
@@ -1673,7 +1823,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen,
   a = find_tlv (keydata, keydatalen, 0x0082, &alen);
   if (!a)
     {
-      log_error ("response does not contain the RSA public exponent\n");
+      log_error (_("response does not contain the RSA public exponent\n"));
       rc = gpg_error (GPG_ERR_CARD);
       goto leave;
     }