[git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.27-14-g05f32c7

by NIIBE Yutaka cvs at cvs.gnupg.org
Wed Apr 15 09:10:12 CEST 2015


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, STABLE-BRANCH-2-0 has been updated
       via  05f32c702eaf6dc7fd5c0c8c01b4c731ed9a6011 (commit)
       via  93910b5b8d20c089b2578d757cf06509d7617978 (commit)
       via  de7f7b98dfeb30675369d0bedc6d639314193e96 (commit)
       via  a838e8f806693e9403541f482b58b66c606e376b (commit)
       via  b4ec909186d0150c835942754283ecc2bdf6e3e0 (commit)
      from  067b6360be6733f6faf7a6438f61393fdb7a5fb3 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 05f32c702eaf6dc7fd5c0c8c01b4c731ed9a6011
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Tue Apr 14 14:17:03 2015 +0900

    scd: better handling of extended APDU.
    
    * scd/apdu.c (send_le): Bug fix for not append Z when lc<0&&le<0.
    * scd/app-common.h (struct app_ctx_s): Use bit fields for flags.
    * scd/ccid-driver.c (CCID_MAX_BUF): New.  Only for OpenPGPcard.
    (struct ccid_driver_s): New field of max_ccid_msglen.
     Remove ifsd field.
    (parse_ccid_descriptor): Initialize max_ccid_msglen.
    (ccid_transceive_apdu_level): Implement sending extended APDU in
    chain of CCID message.
    
    --
    
    With this patch, we won't need PC/SC library/service any more.
    GnuPG-bug-id: 1947
    (backported from 2.1 commit 971d558e862db878a7310e06ed7116dbe36886ab)

diff --git a/scd/apdu.c b/scd/apdu.c
index 5fa66a8..6fc1148 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -3678,9 +3678,9 @@ send_le (int slot, int class, int ins, int p0, int p1,
           apdu[apdulen++] = ins;
           apdu[apdulen++] = p0;
           apdu[apdulen++] = p1;
-          apdu[apdulen++] = 0;  /* Z byte: Extended length marker.  */
-          if (lc >= 0)
+          if (lc > 0)
             {
+              apdu[apdulen++] = 0;  /* Z byte: Extended length marker.  */
               apdu[apdulen++] = ((lc >> 8) & 0xff);
               apdu[apdulen++] = (lc & 0xff);
               memcpy (apdu+apdulen, data, lc);
@@ -3689,6 +3689,8 @@ send_le (int slot, int class, int ins, int p0, int p1,
             }
           if (le != -1)
             {
+              if (lc <= 0)
+                apdu[apdulen++] = 0;  /* Z byte: Extended length marker.  */
               apdu[apdulen++] = ((le >> 8) & 0xff);
               apdu[apdulen++] = (le & 0xff);
             }
diff --git a/scd/app-common.h b/scd/app-common.h
index 4b2e13e..e48db3c 100644
--- a/scd/app-common.h
+++ b/scd/app-common.h
@@ -64,10 +64,10 @@ struct app_ctx_s {
   size_t serialnolen;      /* Length in octets of serialnumber. */
   const char *apptype;
   unsigned int card_version;
-  int did_chv1;
-  int force_chv1;   /* True if the card does not cache CHV1. */
-  int did_chv2;
-  int did_chv3;
+  unsigned int did_chv1:1;
+  unsigned int force_chv1:1;   /* True if the card does not cache CHV1. */
+  unsigned int did_chv2:1;
+  unsigned int did_chv3:1;
   struct app_local_s *app_local;  /* Local to the application. */
   struct {
     void (*deinit) (app_t app);
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index a179aa8..490569f 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -98,6 +98,16 @@
 
 #define DRVNAME "ccid-driver: "
 
+/* Max length of buffer with out CCID message header of 10-byte
+   Sending: 547 for RSA-4096 key import
+        APDU size = 540 (24+4+256+256)
+        commnd + lc + le = 4 + 3 + 0
+   Sending: write data object of cardholder certificate
+        APDU size = 2048
+        commnd + lc + le = 4 + 3 + 0
+   Receiving: 2048 for cardholder certificate
+*/
+#define CCID_MAX_BUF (2048+7+10)
 
 /* Depending on how this source is used we either define our error
    output to go to stderr or to the jnlib based logging functions.  We
@@ -270,7 +280,7 @@ struct ccid_driver_s
   unsigned char t1_nr;
   unsigned char nonnull_nad;
   int max_ifsd;
-  int ifsd;
+  int max_ccid_msglen;
   int ifsc;
   unsigned char apdu_level:2;     /* Reader supports short APDU level
                                      exchange.  With a value of 2 short
@@ -749,7 +759,7 @@ prepare_special_transport (ccid_driver_t handle)
   handle->nonnull_nad = 0;
   handle->auto_ifsd = 0;
   handle->max_ifsd = 32;
-  handle->ifsd = 0;
+  handle->max_ccid_msglen = CCID_MAX_BUF;
   handle->has_pinpad = 0;
   handle->apdu_level = 0;
   switch (handle->id_product)
@@ -781,7 +791,6 @@ parse_ccid_descriptor (ccid_driver_t handle,
   handle->nonnull_nad = 0;
   handle->auto_ifsd = 0;
   handle->max_ifsd = 32;
-  handle->ifsd = 0;
   handle->has_pinpad = 0;
   handle->apdu_level = 0;
   handle->auto_voltage = 0;
@@ -922,6 +931,7 @@ parse_ccid_descriptor (ccid_driver_t handle,
 
   us = convert_le_u32(buf+44);
   DEBUGOUT_1 ("  dwMaxCCIDMsgLen     %5u\n", us);
+  handle->max_ccid_msglen = us;
 
   DEBUGOUT (  "  bClassGetResponse    ");
   if (buf[48] == 0xff)
@@ -2831,109 +2841,101 @@ is_exlen_apdu (const unsigned char *apdu, size_t apdulen)
 /* Helper for ccid_transceive used for APDU level exchanges.  */
 static int
 ccid_transceive_apdu_level (ccid_driver_t handle,
-                            const unsigned char *apdu_buf, size_t apdu_buflen,
+                            const unsigned char *apdu_buf, size_t apdu_len,
                             unsigned char *resp, size_t maxresplen,
                             size_t *nresp)
 {
   int rc;
-  unsigned char send_buffer[10+261+300], recv_buffer[10+261+300];
-  const unsigned char *apdu;
-  size_t apdulen;
-  unsigned char *msg;
+  unsigned char msg[CCID_MAX_BUF];
+  const unsigned char *apdu_p;
+  size_t apdu_part_len;
   size_t msglen;
   unsigned char seqno;
   int bwi = 4;
+  unsigned char chain = 0;
 
-  msg = send_buffer;
+  if (apdu_len == 0 || apdu_len > sizeof (msg) - 10)
+    return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */
 
-  apdu = apdu_buf;
-  apdulen = apdu_buflen;
-  assert (apdulen);
+  apdu_p = apdu_buf;
+  while (1)
+    {
+      apdu_part_len = apdu_len;
+      if (apdu_part_len > handle->max_ccid_msglen - 10)
+        {
+          apdu_part_len = handle->max_ccid_msglen - 10;
+          chain |= 0x01;
+        }
 
-  /* The maximum length for a short APDU T=1 block is 261.  For an
-     extended APDU T=1 block the maximum length 65544; however
-     extended APDU exchange level is not fully supported yet.  */
-  if (apdulen > sizeof (send_buffer) - 10)
-    return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */
+      msg[0] = PC_to_RDR_XfrBlock;
+      msg[5] = 0; /* slot */
+      msg[6] = seqno = handle->seqno++;
+      msg[7] = bwi;
+      msg[8] = chain;
+      msg[9] = 0;
+      memcpy (msg+10, apdu_p, apdu_part_len);
+      set_msg_len (msg, apdu_part_len);
+      msglen = 10 + apdu_part_len;
 
-  msg[0] = PC_to_RDR_XfrBlock;
-  msg[5] = 0; /* slot */
-  msg[6] = seqno = handle->seqno++;
-  msg[7] = bwi; /* bBWI */
-  msg[8] = 0; /* RFU */
-  msg[9] = 0; /* RFU */
-  memcpy (msg+10, apdu, apdulen);
-  set_msg_len (msg, apdulen);
-  msglen = 10 + apdulen;
+      rc = bulk_out (handle, msg, msglen, 0);
+      if (rc)
+        return rc;
 
-  rc = bulk_out (handle, msg, msglen, 0);
-  if (rc)
-    return rc;
+      apdu_p += apdu_part_len;
+      apdu_len -= apdu_part_len;
 
-  msg = recv_buffer;
-  rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
-                RDR_to_PC_DataBlock, seqno, 5000, 0);
-  if (rc)
-    return rc;
+      rc = bulk_in (handle, msg, sizeof msg, &msglen,
+                    RDR_to_PC_DataBlock, seqno, 5000, 0);
+      if (rc)
+        return rc;
+
+      if (!(chain & 0x01))
+        break;
 
-  if (msg[9] == 1)
+      chain = 0x02;
+    }
+
+  apdu_len = 0;
+  while (1)
     {
-      size_t total_msglen = msglen;
+      apdu_part_len = msglen - 10;
+      if (resp && apdu_len + apdu_part_len <= maxresplen)
+        memcpy (resp + apdu_len, msg+10, apdu_part_len);
+      apdu_len += apdu_part_len;
 
-      while (1)
-        {
-          unsigned char status;
+      if (!(msg[9] & 0x01))
+        break;
 
-          msg = recv_buffer + total_msglen;
+      msg[0] = PC_to_RDR_XfrBlock;
+      msg[5] = 0; /* slot */
+      msg[6] = seqno = handle->seqno++;
+      msg[7] = bwi;
+      msg[8] = 0x10;                /* Request next data block */
+      msg[9] = 0;
+      set_msg_len (msg, 0);
+      msglen = 10;
 
-          msg[0] = PC_to_RDR_XfrBlock;
-          msg[5] = 0; /* slot */
-          msg[6] = seqno = handle->seqno++;
-          msg[7] = bwi; /* bBWI */
-          msg[8] = 0x10;                /* Request next data block */
-          msg[9] = 0;
-          set_msg_len (msg, 0);
-          msglen = 10;
-
-          rc = bulk_out (handle, msg, msglen, 0);
-          if (rc)
-            return rc;
-
-          rc = bulk_in (handle, msg, sizeof recv_buffer - total_msglen, &msglen,
-                        RDR_to_PC_DataBlock, seqno, 5000, 0);
-          if (rc)
-            return rc;
-          status = msg[9];
-          memmove (msg, msg+10, msglen - 10);
-          total_msglen += msglen - 10;
-          if (total_msglen >= sizeof recv_buffer)
-            return CCID_DRIVER_ERR_OUT_OF_CORE;
-
-          if (status == 0x02)
-            break;
-        }
+      rc = bulk_out (handle, msg, msglen, 0);
+      if (rc)
+        return rc;
 
-      apdu = recv_buffer + 10;
-      apdulen = total_msglen - 10;
-    }
-  else
-    {
-      apdu = msg + 10;
-      apdulen = msglen - 10;
+      rc = bulk_in (handle, msg, sizeof msg, &msglen,
+                    RDR_to_PC_DataBlock, seqno, 5000, 0);
+      if (rc)
+        return rc;
     }
 
   if (resp)
     {
-      if (apdulen > maxresplen)
+      if (apdu_len > maxresplen)
         {
           DEBUGOUT_2 ("provided buffer too short for received data "
                       "(%u/%u)\n",
-                      (unsigned int)apdulen, (unsigned int)maxresplen);
+                      (unsigned int)apdu_len, (unsigned int)maxresplen);
           return CCID_DRIVER_ERR_INV_VALUE;
         }
 
-      memcpy (resp, apdu, apdulen);
-      *nresp = apdulen;
+      *nresp = apdu_len;
     }
 
   return 0;

commit 93910b5b8d20c089b2578d757cf06509d7617978
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Apr 10 08:34:35 2015 +0200

    gpgparsemail: Fix last commit (3f2bdac)
    
    * tools/rfc822parse.c (parse_field): Replace break by goto.
    --
    
    Brown paper bag bug: Changing an IF to a WHILE inside another loop
    requires to fix the inner break.
    
    Reported-by: Hanno Böck
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (backported from 2.1 commit 9433661419043431a6cfc7d84c8450e0b2f6c353)

diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c
index 7b86ea9..7895e0b 100644
--- a/tools/rfc822parse.c
+++ b/tools/rfc822parse.c
@@ -829,7 +829,7 @@ parse_field (HDR_LINE hdr)
 	      while (!*s)
 		{
 		  if (!hdr->next || !hdr->next->cont)
-		    break;
+		    goto oparen_out;
                   /* Next item is a header continuation line.  */
 		  hdr = hdr->next;
 		  s = hdr->line;
@@ -852,6 +852,7 @@ parse_field (HDR_LINE hdr)
 	      else if (*s == '\"')
 		in_quote = 1;
 	    }
+        oparen_out:
 	  if (!*s)
 	    ; /* Actually this is an error, but we don't care about it. */
 	  else

commit de7f7b98dfeb30675369d0bedc6d639314193e96
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Apr 9 19:06:33 2015 +0200

    gpgparsemail: Fix case of zero length continuation lines.
    
    * tools/rfc822parse.c (parse_field): Loop after continuation line.
    --
    
    Using header lines like
    
      Name:[lf]
      [space][lf]
      [lf]
    
    resulted in running into the "(s2 = strchr (delimiters2, *s)" branch
    and inserting a new token for the empty continuation line.  This also
    led to one byte read after the string which is what Hanno figured.
    The new code should handle empty continuation lines correct.
    
    Reported-by: Hanno Böck
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (backported from 2.1 commit 3fbeba64a8bfb2b673230c124a3d616b6568fd2f)

diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c
index 8fbe3c2..7b86ea9 100644
--- a/tools/rfc822parse.c
+++ b/tools/rfc822parse.c
@@ -808,10 +808,12 @@ parse_field (HDR_LINE hdr)
   s++; /* Move over the colon. */
   for (;;)
     {
-      if (!*s)
+      while (!*s)
 	{
 	  if (!hdr->next || !hdr->next->cont)
-	    break;
+            return tok; /* Ready.  */
+
+          /* Next item is a header continuation line.  */
 	  hdr = hdr->next;
 	  s = hdr->line;
 	}
@@ -824,10 +826,11 @@ parse_field (HDR_LINE hdr)
 	  invalid = 0;
 	  for (s++;; s++)
 	    {
-	      if (!*s)
+	      while (!*s)
 		{
 		  if (!hdr->next || !hdr->next->cont)
 		    break;
+                  /* Next item is a header continuation line.  */
 		  hdr = hdr->next;
 		  s = hdr->line;
 		}
@@ -880,6 +883,7 @@ parse_field (HDR_LINE hdr)
                    
 	      if (*s2 || !hdr->next || !hdr->next->cont)
 		break;
+              /* Next item is a header continuation line.  */
 	      hdr = hdr->next;
 	      s = hdr->line;
 	    }
@@ -931,8 +935,7 @@ parse_field (HDR_LINE hdr)
 	  s++;
 	}
     }
-
-  return tok;
+  /*NOTREACHED*/
 
  failure:
   {

commit a838e8f806693e9403541f482b58b66c606e376b
Author: Werner Koch <wk at gnupg.org>
Date:   Sun Mar 15 13:04:48 2015 +0100

    agent: Fix length test in sshcontrol parser.
    
    * agent/command-ssh.c (ssh_search_control_file): Check S before
    upcasing it.
    --
    
    In contradiction to the comment we did not check the length of HEXGRIP
    and thus the GPG_ERR_INV_LENGTH was never triggered.
    
    Detected by Stack 0.3:
    
      bug: anti-simplify
      model: |
        %cmp8 = icmp ne i32 %i.0, 40, !dbg !986
        -->  false
      stack:
        - /home/wk/s/gnupg/agent/command-ssh.c:1226:0
      ncore: 2
      core:
        - /home/wk/s/gnupg/agent/command-ssh.c:1225:0
          - buffer overflow
        - /home/wk/s/gnupg/agent/command-ssh.c:1225:0
          - buffer overflow
    
    (backported from 2.1 commit 3529dd8bb5bafc4e02915648d5f409bd27a9cc37)

diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 3583ea0..ea6080a 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -1113,7 +1113,7 @@ ssh_search_control_file (ssh_control_file_t cf,
   /* We need to make sure that HEXGRIP is all uppercase.  The easiest
      way to do this and also check its length is by copying to a
      second buffer. */
-  for (i=0, s=hexgrip; i < 40; s++, i++)
+  for (i=0, s=hexgrip; i < 40 && *s; s++, i++)
     uphexgrip[i] = *s >= 'a'? (*s & 0xdf): *s;
   uphexgrip[i] = 0;
   if (i != 40)

commit b4ec909186d0150c835942754283ecc2bdf6e3e0
Author: Werner Koch <wk at gnupg.org>
Date:   Sun Mar 15 12:15:55 2015 +0100

    scd: Fix possible NULL deref in apdu.c
    
    * scd/apdu.c (control_pcsc_direct): Take care of BUFLEN being NULL.
    (control_pcsc_wrapped): Ditto.
    --
    
    pcsc_vendor_specific_init calls the above with BUFFER and BUFLEN as
    NULL.
    
    Reported by Stack 0.3:
    
      bug: anti-dce
      model: |
        control_pcsc.exit77:
        %retval.0.i.i76 = phi i32 [ %rc.0.i.i.i73, \
                %pcsc_error_to_sw.exit.i.i74 ], [ 0, %if.end.i.i75 ]
        %tobool198 = icmp ne i32 %retval.0.i.i76, 0, !dbg !728
        br i1 %tobool198, label %if.then199, label %if.end200, !dbg !728
      stack:
        - /home/wk/s/gnupg/scd/apdu.c:1882:0
      ncore: 1
      core:
        - /home/wk/s/gnupg/scd/apdu.c:1309:0
          - buffer overflow
    
    (backported from 2.1 commit ef0a3abf7305133d071bf1a94a7f461082f9a9aa)

diff --git a/scd/apdu.c b/scd/apdu.c
index 5ce7f94..5fa66a8 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -1269,7 +1269,7 @@ control_pcsc_direct (int slot, pcsc_dword_t ioctl_code,
   long err;
 
   err = pcsc_control (reader_table[slot].pcsc.card, ioctl_code,
-                      cntlbuf, len, buffer, *buflen, buflen);
+                      cntlbuf, len, buffer, buflen? *buflen:0, buflen);
   if (err)
     {
       log_error ("pcsc_control failed: %s (0x%lx)\n",
@@ -1337,14 +1337,18 @@ control_pcsc_wrapped (int slot, pcsc_dword_t ioctl_code,
 
   full_len = len;
 
-  n = *buflen < len ? *buflen : len;
+  if (buflen)
+    n = *buflen < len ? *buflen : len;
+  else
+    n = 0;
   if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n)
     {
       log_error ("error receiving PC/SC CONTROL response: %s\n",
                  i? strerror (errno) : "premature EOF");
       goto command_failed;
     }
-  *buflen = n;
+  if (buflen)
+    *buflen = n;
 
   full_len -= len;
   if (full_len)

-----------------------------------------------------------------------

Summary of changes:
 agent/command-ssh.c |   2 +-
 scd/apdu.c          |  16 ++++--
 scd/app-common.h    |   8 +--
 scd/ccid-driver.c   | 156 ++++++++++++++++++++++++++--------------------------
 tools/rfc822parse.c |  16 ++++--
 5 files changed, 105 insertions(+), 93 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list