Hi!

Unfortunately I realized too late that 2.0.12 still had bugs with the
new OpenPGP card[1].  Without actual hardware testing stuff is a bit
hard; I had 2 engineering samples during development and we swapped card
back and forth to squash the bugs in the card's firmware while also
hacking gnupg.  Thus some things got not tested for 2.0.12.

Find attached 2 patches against GnuPG 2.0.12 to fix the card problem as
well as an unlrealted Windows-only problem.  These patches are already
in the Gpg4win 2.0.0rc1 installer currently being copied to the servers.

GnuPG 1.4 does not yet support the v2 cards.  I plan to backport the
code from 2.0 in the next week and then it should not take too long to
get 1.4.10 out.  If you don't want to wait: gpg2 is the perfect version
for the desktop or laptop ;-)

A cautionary note: If you plan to buy a smartcard reader, please abstain
From Omnikey based readers (Cardman and some others).  They do not work
with 2048 bit smartcards.  They work on Windows, but not on a free OSes.
We need to do some protocol analysis to see how the Windows driver
achieves to send so-called extended lengths APDUs.  The vendors are not
very helpful in this regard, thus I can only suggest to resort to SCM
based readers.


Salam-Shalom,

   Werner


[1] Meanwhile we received the first batch of cards; they will be sold at
    the LinuxTag and if cards are left over by next week through the
    well known distributor.

-- 
Die Gedanken sind frei.  Auschnahme regelt ein Bundeschgesetz.
#! /bin/sh
patch -p0 -f $* < $0
exit $?

scd/
2009-06-18  Werner Koch  <[email protected]>

	* app-openpgp.c (verify_chv2): Remove special case for v2 cards.
	(get_public_key): Use extended mode.


Index: scd/app-openpgp.c
===================================================================
--- scd/app-openpgp.c	(revision 5047)
+++ scd/app-openpgp.c	(working copy)
@@ -1118,11 +1118,25 @@
 
   if (app->card_version > 0x0100)
     {
+      int exmode, le_value;
+
       /* We may simply read the public key out of these cards.  */
+      if (app->app_local->cardcap.ext_lc_le)
+        {
+          exmode = 1;    /* Use extended length.  */
+          le_value = app->app_local->extcap.max_rsp_data;
+        }
+      else
+        {
+          exmode = 0;
+          le_value = 256; /* Use legacy value. */
+        }
+
       err = iso7816_read_public_key 
-        (app->slot, 0, (const unsigned char*)(keyno == 0? "\xB6" :
-                                              keyno == 1? "\xB8" : "\xA4"), 2,  
-         0,
+        (app->slot, exmode,
+         (const unsigned char*)(keyno == 0? "\xB6" :
+                                keyno == 1? "\xB8" : "\xA4"), 2,  
+         le_value,
          &buffer, &buflen);
       if (err)
         {
@@ -1579,43 +1593,31 @@
   char *pinvalue;
 
   if (app->did_chv2) 
-    return 0;  /* We already verified CHV2 (PW1 for v2 cards).  */
+    return 0;  /* We already verified CHV2.  */
 
-  if (app->app_local->extcap.is_v2)
+  rc = verify_a_chv (app, pincb, pincb_arg, 2, 0, &pinvalue);
+  if (rc)
+    return rc;
+  app->did_chv2 = 1;
+  
+  if (!app->did_chv1 && !app->force_chv1 && pinvalue)
     {
-      /* Version two cards don't have a CHV2 anymore.  We need to
-         verify CHV1 (now called PW1) instead.  */
-      rc = verify_a_chv (app, pincb, pincb_arg, 1, 0, &pinvalue);
+      /* For convenience we verify CHV1 here too.  We do this only if
+         the card is not configured to require a verification before
+         each CHV1 controlled operation (force_chv1) and if we are not
+         using the keypad (PINVALUE == NULL). */
+      rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
+      if (gpg_err_code (rc) == GPG_ERR_BAD_PIN)
+        rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
       if (rc)
-        return rc;
-      app->did_chv2 = 1;
-    }
-  else
-    {
-      /* Version 1 cards only.  */
-      rc = verify_a_chv (app, pincb, pincb_arg, 2, 0, &pinvalue);
-      if (rc)
-        return rc;
-      app->did_chv2 = 1;
-  
-      if (!app->did_chv1 && !app->force_chv1 && pinvalue)
         {
-          /* For convenience we verify CHV1 here too.  We do this only
-             if the card is not configured to require a verification
-             before each CHV1 controlled operation (force_chv1) and if
-             we are not using the keypad (PINVALUE == NULL). */
-          rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
-          if (gpg_err_code (rc) == GPG_ERR_BAD_PIN)
-            rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
-          if (rc)
-            {
-              log_error (_("verify CHV%d failed: %s\n"), 1, gpg_strerror (rc));
-              flush_cache_after_error (app);
-            }
-          else
-            app->did_chv1 = 1;
+          log_error (_("verify CHV%d failed: %s\n"), 1, gpg_strerror (rc));
+          flush_cache_after_error (app);
         }
+      else
+        app->did_chv1 = 1;
     }
+
   xfree (pinvalue);
 
   return rc;


#! /bin/sh
patch -p0 -f $* < $0
exit $?

2009-06-22  Werner Koch  <[email protected]>

	* estream.c (es_pth_read, es_pth_write) [W32]: New.
	(ESTREAM_SYS_READ, ESTREAM_SYS_WRITE) [HAVE_PTH]: Use them.


Index: common/estream.c
===================================================================
--- common/estream.c	(revision 5047)
+++ common/estream.c	(working copy)
@@ -138,8 +138,8 @@
 /* Primitive system I/O.  */
 
 #ifdef HAVE_PTH
-# define ESTREAM_SYS_READ  pth_read
-# define ESTREAM_SYS_WRITE pth_write
+# define ESTREAM_SYS_READ  es_pth_read
+# define ESTREAM_SYS_WRITE es_pth_write
 #else
 # define ESTREAM_SYS_READ  read
 # define ESTREAM_SYS_WRITE write
@@ -325,8 +325,47 @@
   return ret;
 }
 
+

+/*
+ * I/O Helper
+ *
+ * Unfortunately our Pth emulation for Windows expects system handles
+ * for pth_read and pth_write.  We use a simple approach to fix this:
+ * If the function returns an error we fall back to a vanilla read or
+ * write, assuming that we do I/O on a plain file where the operation
+ * can't block.
+ */
+#ifdef HAVE_PTH
+static int
+es_pth_read (int fd, void *buffer, size_t size)
+{
+# ifdef HAVE_W32_SYSTEM
+  int rc = pth_read (fd, buffer, size);
+  if (rc == -1 && errno == EINVAL)
+    rc = read (fd, buffer, size);
+  return rc;
+# else /*!HAVE_W32_SYSTEM*/
+  return pth_read (fd, buffer, size);
+# endif /* !HAVE_W32_SYSTEM*/
+}
 
+static int
+es_pth_write (int fd, const void *buffer, size_t size)
+{
+# ifdef HAVE_W32_SYSTEM
+  int rc = pth_write (fd, buffer, size);
+  if (rc == -1 && errno == EINVAL)
+    rc = write (fd, buffer, size);
+  return rc;
+# else /*!HAVE_W32_SYSTEM*/
+  return pth_write (fd, buffer, size);
+# endif /* !HAVE_W32_SYSTEM*/
+}
+#endif /*HAVE_PTH*/
+
+
+
 /*
  * Initialization.
  */

Attachment: pgpsxp9iWTdX3.pgp
Description: PGP signature

_______________________________________________
Gnupg-users mailing list
[email protected]
http://lists.gnupg.org/mailman/listinfo/gnupg-users

Reply via email to