gnupg: Make SPRx332 work under Windows.
authorWerner Koch <wk@gnupg.org>
Wed, 21 Aug 2013 15:05:32 +0000 (17:05 +0200)
committerWerner Koch <wk@gnupg.org>
Wed, 21 Aug 2013 15:05:32 +0000 (17:05 +0200)
* patches/gnupg2-2.0.21/01-scd-varlen.patch: New.
* patches/gnupg2-2.0.21/02-scd-spr532.patch: New.
* Makefile.am (EXTRA_DIST): Add patches.

Makefile.am
patches/gnupg2-2.0.21/01-scd-varlen.patch [new file with mode: 0755]
patches/gnupg2-2.0.21/02-scd-spr532.patch [new file with mode: 0755]

index d152b75..45a4e00 100644 (file)
@@ -23,6 +23,7 @@ DISTCHECK_CONFIGURE_FLAGS = --host=i686-w64-mingw32
 SUBDIRS = po packages doc src
 
 EXTRA_DIST = autogen.sh README.GIT ONEWS \
+       doc/license-page doc/GPLv3 \
         build-aux/git-log-footer build-aux/git-log-fix \
         patches/pthreads-w32-2-8-0-release/01-make.patch \
  patches/pthreads-w32-2-8-0-release/02-mingw_w64_timespec_compatibility.patch \
@@ -35,6 +36,8 @@ EXTRA_DIST = autogen.sh README.GIT ONEWS \
         patches/libxml2-2.7.8/01-cve-2012-5134 \
        patches/gnupg2/01-version.patch.in \
        patches/gnupg2-2.0.20/02-allow-mark-trusted.patch \
+        patches/gnupg2-2.0.21/01-scd-varlen.patch \
+        patches/gnupg2-2.0.21/02-scd-spr532.patch \
        patches/dirmngr-1.1.0/01-mmap.patch \
         patches/gpgol-1.1.3/01-w64-ming64.patch  \
         patches/gpgol-1.1.3/02-off_t.postcfg-build \
@@ -56,8 +59,7 @@ EXTRA_DIST = autogen.sh README.GIT ONEWS \
         patches/gpa-0.9.4/03-homedir-via-gpgconf.patch \
         patches/gpa-0.9.4/04-utf-clip-crash.patch \
         patches/gpa-0.9.4/05-event-done.patch \
-       patches/gpgme-1.4.3/01-card-edit.patch \
-       doc/license-page doc/GPLv3
+       patches/gpgme-1.4.3/01-card-edit.patch
 
 copy-news:
        cp NEWS doc/website/NEWS.last
diff --git a/patches/gnupg2-2.0.21/01-scd-varlen.patch b/patches/gnupg2-2.0.21/01-scd-varlen.patch
new file mode 100755 (executable)
index 0000000..bc4b772
--- /dev/null
@@ -0,0 +1,76 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+From 43e85d7bee4644ca84ef0ab0c3b08b2d02e4a699 Mon Sep 17 00:00:00 2001
+From: Werner Koch <wk@gnupg.org>
+Date: Wed, 21 Aug 2013 15:44:52 +0200
+Subject: [PATCH 1/2] scd: Improve --enable-pinpad-varlen.
+
+* tools/gpgconf-comp.c (gc_options_scdaemon): Add
+enable-pinpad-varlen.
+* scd/apdu.c (check_pcsc_pinpad): Detect SPRx32 reader.
+
+Signed-off-by: Werner Koch <wk@gnupg.org>
+(cherry picked from commit 7bde2bf3b0ddb5d3515a44879e1a7ddb581a5c0b)
+---
+ doc/scdaemon.texi    |    8 ++++----
+ scd/apdu.c           |    8 +++++++-
+ tools/gpgconf-comp.c |    4 ++++
+ 3 files changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi
+index ed2cc51..f454f14 100644
+--- a/doc/scdaemon.texi
++++ b/doc/scdaemon.texi
+@@ -290,10 +290,10 @@ than 0.
+ @item --enable-pinpad-varlen
+ @opindex enable-pinpad-varlen
+ Please specify this option when the card reader supports variable
+-length input for pinpad (default is no).  For known readers listed in
+-ccid-driver, this option is not needed.  Note that if your card reader
+-doesn't supports variable length input but you want to use it, you
+-need to specify your pinpad request on your card.
++length input for pinpad (default is no).  For known readers (listed in
++ccid-driver.c and apdu.c), this option is not needed.  Note that if
++your card reader doesn't supports variable length input but you want
++to use it, you need to specify your pinpad request on your card.
+
+
+ @item --disable-pinpad
+diff --git a/scd/apdu.c b/scd/apdu.c
+index 372932a..4b3509e 100644
+--- a/scd/apdu.c
++++ b/scd/apdu.c
+@@ -2032,7 +2032,13 @@ check_pcsc_pinpad (int slot, int command, pininfo_t *pininfo)
+   pcsc_dword_t len = 256;
+   int sw;
+
+-  (void)pininfo;      /* XXX: Identify reader and set pininfo->fixedlen.  */
++  /* Hack to identify the SCM SPR532 and SPR332 readers which support
++     variable length PIN input.
++     FIXME: Figure out whether there is a feature attribute for this.
++     Alternatively use the USB ids to detect known readers.  */
++  if (reader_table[slot].rdrname
++      && strstr (reader_table[slot].rdrname, "SPRx32"))
++    pininfo->fixedlen = 0;
+
+  check_again:
+   if (command == ISO7816_VERIFY)
+diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
+index 078dcea..c43e87a 100644
+--- a/tools/gpgconf-comp.c
++++ b/tools/gpgconf-comp.c
+@@ -612,6 +612,10 @@ static gc_option_t gc_options_scdaemon[] =
+    { "disable-pinpad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
+      "gnupg", "do not use a reader's pinpad",
+      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
++   { "enable-pinpad-varlen",
++     GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
++     "gnupg", "use variable length input for pinpad",
++     GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
+    { "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
+      "gnupg", "|N|disconnect the card after N seconds of inactivity",
+      GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON },
+--
+1.7.7.1
diff --git a/patches/gnupg2-2.0.21/02-scd-spr532.patch b/patches/gnupg2-2.0.21/02-scd-spr532.patch
new file mode 100755 (executable)
index 0000000..9a71168
--- /dev/null
@@ -0,0 +1,152 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+From b63717031d8ee3f9ded44a182516158f8a349bd1 Mon Sep 17 00:00:00 2001
+From: Werner Koch <wk@gnupg.org>
+Date: Wed, 21 Aug 2013 16:45:48 +0200
+Subject: [PATCH 2/2] scd: Make SPRx32 pinpad work with PC/SC on Windows.
+
+* scd/apdu.c (CM_IOCTL_GET_FEATURE_REQUEST): Use SCARD_CTL_CODE.
+(SCARD_CTL_CODE): Define if not defined.
+(reader_table_s): Add is_spr532.
+(new_reader_slot): Clear it.
+(check_pcsc_pinpad): Set it.
+(pcsc_pinpad_verify, pcsc_pinpad_modify): Add fix for SPR532.
+
+Signed-off-by: Werner Koch <wk@gnupg.org>
+(cherry picked from commit 5c5e52df4b92e23045ac87abac09357de58920d4)
+---
+ scd/apdu.c |   34 +++++++++++++++++++++++++++-------
+ 1 files changed, 27 insertions(+), 7 deletions(-)
+
+diff --git a/scd/apdu.c b/scd/apdu.c
+index 4b3509e..ecb3e82 100644
+--- a/scd/apdu.c
++++ b/scd/apdu.c
+@@ -133,6 +133,7 @@ struct reader_table_s {
+   int last_status;
+   int status;
+   int is_t0;         /* True if we know that we are running T=0. */
++  int is_spr532;     /* True if we know that the reader is a SPR532.  */
+   unsigned char atr[33];
+   size_t atrlen;           /* A zero length indicates that the ATR has
+                               not yet been read; i.e. the card is not
+@@ -219,7 +220,12 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn);
+ #define PCSC_E_NO_SERVICE              0x8010001D
+ #define PCSC_W_REMOVED_CARD            0x80100069
+
+-#define CM_IOCTL_GET_FEATURE_REQUEST (0x42000000 + 3400)
++/* Fix pcsc-lite ABI incompatibilty.  */
++#ifndef SCARD_CTL_CODE
++# define SCARD_CTL_CODE(code) (0x42000000 + (code))
++#endif
++
++#define CM_IOCTL_GET_FEATURE_REQUEST     SCARD_CTL_CODE(3400)
+ #define FEATURE_VERIFY_PIN_DIRECT        0x06
+ #define FEATURE_MODIFY_PIN_DIRECT        0x07
+
+@@ -417,6 +423,7 @@ new_reader_slot (void)
+   reader_table[reader].any_status = 0;
+   reader_table[reader].last_status = 0;
+   reader_table[reader].is_t0 = 1;
++  reader_table[reader].is_spr532 = 0;
+ #ifdef NEED_PCSC_WRAPPER
+   reader_table[reader].pcsc.req_fd = -1;
+   reader_table[reader].pcsc.rsp_fd = -1;
+@@ -2038,7 +2045,10 @@ check_pcsc_pinpad (int slot, int command, pininfo_t *pininfo)
+      Alternatively use the USB ids to detect known readers.  */
+   if (reader_table[slot].rdrname
+       && strstr (reader_table[slot].rdrname, "SPRx32"))
+-    pininfo->fixedlen = 0;
++    {
++      reader_table[slot].is_spr532 = 1;
++      pininfo->fixedlen = 0;
++    }
+
+  check_again:
+   if (command == ISO7816_VERIFY)
+@@ -2097,6 +2107,7 @@ pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
+   int len = PIN_VERIFY_STRUCTURE_SIZE + pininfo->fixedlen;
+   unsigned char result[2];
+   pcsc_dword_t resultlen = 2;
++  int no_lc;
+
+   if (!reader_table[slot].atrlen
+       && (sw = reset_pcsc_reader (slot)))
+@@ -2120,6 +2131,8 @@ pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
+   if (!pin_verify)
+     return SW_HOST_OUT_OF_CORE;
+
++  no_lc = (!pininfo->fixedlen && reader_table[slot].is_spr532);
++
+   pin_verify[0] = 0x00; /* bTimerOut */
+   pin_verify[1] = 0x00; /* bTimerOut2 */
+   pin_verify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
+@@ -2136,8 +2149,8 @@ pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
+   pin_verify[11] = 0x00; /* bMsgIndex */
+   pin_verify[12] = 0x00; /* bTeoPrologue[0] */
+   pin_verify[13] = 0x00; /* bTeoPrologue[1] */
+-  pin_verify[14] = pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
+-  pin_verify[15] = pininfo->fixedlen + 0x05; /* ulDataLength */
++  pin_verify[14] = pininfo->fixedlen + 0x05 - no_lc; /* bTeoPrologue[2] */
++  pin_verify[15] = pininfo->fixedlen + 0x05 - no_lc; /* ulDataLength */
+   pin_verify[16] = 0x00; /* ulDataLength */
+   pin_verify[17] = 0x00; /* ulDataLength */
+   pin_verify[18] = 0x00; /* ulDataLength */
+@@ -2148,6 +2161,8 @@ pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
+   pin_verify[23] = pininfo->fixedlen; /* abData[4] */
+   if (pininfo->fixedlen)
+     memset (&pin_verify[24], 0xff, pininfo->fixedlen);
++  else if (no_lc)
++    len--;
+
+   if (DBG_CARD_IO)
+     log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n",
+@@ -2178,6 +2193,7 @@ pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
+   int len = PIN_MODIFY_STRUCTURE_SIZE + 2 * pininfo->fixedlen;
+   unsigned char result[2];
+   pcsc_dword_t resultlen = 2;
++  int no_lc;
+
+   if (!reader_table[slot].atrlen
+       && (sw = reset_pcsc_reader (slot)))
+@@ -2201,6 +2217,8 @@ pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
+   if (!pin_modify)
+     return SW_HOST_OUT_OF_CORE;
+
++  no_lc = (!pininfo->fixedlen && reader_table[slot].is_spr532);
++
+   pin_modify[0] = 0x00; /* bTimerOut */
+   pin_modify[1] = 0x00; /* bTimerOut2 */
+   pin_modify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
+@@ -2221,15 +2239,15 @@ pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
+   if (pininfo->minlen && pininfo->maxlen && pininfo->minlen == pininfo->maxlen)
+     pin_modify[10] |= 0x01; /* Max size reached.  */
+   pin_modify[11] = 0xff; /* bNumberMessage: Default */
+-  pin_modify[12] =  0x09; /* wLangId: 0x0409: US English */
++  pin_modify[12] = 0x09; /* wLangId: 0x0409: US English */
+   pin_modify[13] = 0x04; /* wLangId: 0x0409: US English */
+   pin_modify[14] = 0x00; /* bMsgIndex1 */
+   pin_modify[15] = 0x00; /* bMsgIndex2 */
+   pin_modify[16] = 0x00; /* bMsgIndex3 */
+   pin_modify[17] = 0x00; /* bTeoPrologue[0] */
+   pin_modify[18] = 0x00; /* bTeoPrologue[1] */
+-  pin_modify[19] = 2 * pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
+-  pin_modify[20] = 2 * pininfo->fixedlen + 0x05; /* ulDataLength */
++  pin_modify[19] = 2 * pininfo->fixedlen + 0x05 - no_lc; /* bTeoPrologue[2] */
++  pin_modify[20] = 2 * pininfo->fixedlen + 0x05 - no_lc; /* ulDataLength */
+   pin_modify[21] = 0x00; /* ulDataLength */
+   pin_modify[22] = 0x00; /* ulDataLength */
+   pin_modify[23] = 0x00; /* ulDataLength */
+@@ -2240,6 +2258,8 @@ pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
+   pin_modify[28] = 2 * pininfo->fixedlen; /* abData[4] */
+   if (pininfo->fixedlen)
+     memset (&pin_modify[29], 0xff, 2 * pininfo->fixedlen);
++  else if (no_lc)
++    len--;
+
+   if (DBG_CARD_IO)
+     log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n",
+--
+1.7.7.1