* card-util.c (card_edit): Take admin only status from the table.
authorWerner Koch <wk@gnupg.org>
Mon, 27 Sep 2004 12:56:05 +0000 (12:56 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 27 Sep 2004 12:56:05 +0000 (12:56 +0000)
* app-openpgp.c: Made all strings translatable.
(verify_chv3) [GNUPG_MAJOR_VERSION]: Make opt.allow_admin
available for use in gnupg 2.
(verify_chv3): Reimplemented countdown showing to use only
functions from this module.  Flush the CVH status cache on a
successful read.
(get_one_do): Hack to bypass the cache for cards versions > 1.0.
(store_fpr): Store the creation date for card version > 1.0.

g10/ChangeLog
g10/app-openpgp.c
g10/card-util.c

index f3b1e79..e51bb46 100644 (file)
@@ -1,10 +1,15 @@
 2004-09-27  Werner Koch  <wk@g10code.com>
 
+       * card-util.c (card_edit): Take admin only status from the table.
+
        * app-openpgp.c: Made all strings translatable.
        (verify_chv3) [GNUPG_MAJOR_VERSION]: Make opt.allow_admin
        available for use in gnupg 2. 
        (verify_chv3): Reimplemented countdown showing to use only
-       functions from this module. 
+       functions from this module.  Flush the CVH status cache on a
+       successful read.
+       (get_one_do): Hack to bypass the cache for cards versions > 1.0.
+       (store_fpr): Store the creation date for card version > 1.0.
 
 2004-09-25  David Shaw  <dshaw@jabberwocky.com>
 
index cec1353..94a6269 100644 (file)
@@ -52,27 +52,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 }
 };
 
@@ -267,6 +273,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)
@@ -442,6 +457,21 @@ store_fpr (int slot, int keynumber, u32 timestamp,
   if (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;
 }
 
@@ -686,6 +716,8 @@ verify_chv3 (APP app,
       void *relptr;
       unsigned char *value;
       size_t valuelen;
+      int reread_chv_status;
+      
 
       relptr = get_one_do (app, 0x00C4, &value, &valuelen);
       if (!relptr || valuelen < 7)
@@ -701,6 +733,8 @@ verify_chv3 (APP app,
           return gpg_error (GPG_ERR_BAD_PIN);
         }
 
+      reread_chv_status = (value[6] < 3);
+
       log_info(_("%d Admin PIN attempts remaining before card"
                  " is permanently locked\n"), value[6]);
       xfree (relptr);
@@ -729,6 +763,13 @@ verify_chv3 (APP 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;
 }
index a58dda0..0ded216 100644 (file)
@@ -1166,6 +1166,7 @@ card_edit (STRLIST commands)
       const char *arg_string = "";
       char *p;
       int i;
+      int cmd_admin_only;
       
       tty_printf("\n");
       if (redisplay )
@@ -1208,46 +1209,39 @@ card_edit (STRLIST commands)
            }
            trim_spaces(answer);
        }
-      while( *answer == '#' );
+      while ( *answer == '#' );
 
       arg_number = 0; /* Yes, here is the init which egcc complains about */
+      cmd_admin_only = 0;
       if (!*answer)
         cmd = cmdLIST; /* Default to the list command */
       else if (*answer == CONTROL_D)
         cmd = cmdQUIT;
-      else {
-        if ((p=strchr (answer,' ')))
-          {
-            *p++ = 0;
-            trim_spaces (answer);
-            trim_spaces (p);
-            arg_number = atoi(p);
-            arg_string = p;
-          }
-
-        for (i=0; cmds[i].name; i++ )
-          if (!ascii_strcasecmp (answer, cmds[i].name ))
-            break;
-
-        cmd = cmds[i].id;
-      }
+      else 
+        {
+          if ((p=strchr (answer,' ')))
+            {
+              *p++ = 0;
+              trim_spaces (answer);
+              trim_spaces (p);
+              arg_number = atoi(p);
+              arg_string = p;
+            }
+          
+          for (i=0; cmds[i].name; i++ )
+            if (!ascii_strcasecmp (answer, cmds[i].name ))
+              break;
 
-      if(!allow_admin)
-       switch(cmd)
-         {
-         case cmdNAME:
-         case cmdURL:
-         case cmdLOGIN:
-         case cmdLANG:
-         case cmdCAFPR:
-         case cmdFORCESIG:
-         case cmdGENERATE:
-           tty_printf ("\n");
-           tty_printf (_("Admin-only command\n"));
-           continue;
-         default:
-           break;
-         }
+          cmd = cmds[i].id;
+          cmd_admin_only = cmds[i].admin_only;
+        }
+
+      if (!allow_admin && cmd_admin_only)
+       {
+          tty_printf ("\n");
+          tty_printf (_("Admin-only command\n"));
+          continue;
+        }
 
       switch (cmd)
         {