On mar., 2012-10-23 at 13:12 +0200, Heiko Schlittermann wrote:
> Package: libassuan0
> Version: 2.0.3-1
> Severity: important
> Tags: upstream patch
> 
> I used a 4096bit key for encryption (using the GnuPG crypto-stick).
> Encryption worked, but decryption didn't work (gpg2 didn't find
> the secret key.)
> 
> gpg2 uses libassuan to talk to some daemons/agents. 
> gpg (1.x) worked, but only if there was no gnupg-agent running.
> 
> Patch:
>    http://lists.gnupg.org/pipermail/gnupg-users/2012-June/044868.html
> 
> I applied this patch and re-built libassuan0-* and gnupg2. This
> seems to fix the issue.

The patch is wrong, according to
http://lists.gnupg.org/pipermail/gnupg-devel/2009-October/025412.html

A better patch was once sent to the same mailing list the following
month:
http://lists.gnupg.org/pipermail/gnupg-devel/2009-November/025421.html
by Klaus Flittner (on CC:).

This was never applied because of the lack of copyright assignment.

Imho this is a simple bugfix which is not even copyrightable, but IANAL.
I've ported the patch to the current gnupg 2.0.19 in Wheezy and sid
(it's attached). 

I intend to (re)submit it to upstream but it won't work on 2.1 / git
HEAD right now and I lack the time to properly port it right now.

I think it'd still be nice to push it to gnupg in Debian so we can use
4096 encryption with smartcard, although it might be worth having
upstream comment on the technical part before.

Regards,
-- 
Yves-Alexis
Author: Klaus Flittner <kl...@flittner.org>
Description: Fix decryption with 4096b keys on smartcards
	It seems the Assuan protocol "MTU" is limited to 1002 which is too low when
  decrypting data with a 4096 key. One solution is to raise ASSUAN_LINELENGTH,
  the other is to split messages.
Index: gnupg2-2.0.19/agent/call-scd.c
===================================================================
--- gnupg2-2.0.19.orig/agent/call-scd.c	2012-03-27 10:00:37.000000000 +0200
+++ gnupg2-2.0.19/agent/call-scd.c	2012-11-05 11:30:07.619537775 +0100
@@ -897,19 +897,22 @@ agent_card_pkdecrypt (ctrl_t ctrl,
   if (rc)
     return rc;
 
-  /* FIXME: use secure memory where appropriate */
-  if (indatalen*2 + 50 > DIM(line))
-    return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
-
   sprintf (line, "SETDATA ");
   p = line + strlen (line);
-  for (i=0; i < indatalen ; i++, p += 2 )
-    sprintf (p, "%02X", indata[i]);
-  rc = assuan_transact (ctrl->scd_local->ctx, line,
-                        NULL, NULL, NULL, NULL, NULL, NULL);
-  if (rc)
-    return unlock_scd (ctrl, rc);
-
+  while (i < indatalen)
+    {
+      sprintf (p, "%02X", indata[i++]);
+      p += 2;
+      if ((i == indatalen) || ((i % ((DIM(line)-50)/2)) == 0))
+        {
+          rc = assuan_transact (ctrl->scd_local->ctx, line,
+                                NULL, NULL, NULL, NULL, NULL, NULL);
+          if (rc)
+            return unlock_scd (ctrl, rc);
+          sprintf (line, "SETDATA --more ");
+          p = line + strlen (line);
+        }
+    }
   init_membuf (&data, 1024);
   inqparm.ctx = ctrl->scd_local->ctx;
   inqparm.getpin_cb = getpin_cb;
Index: gnupg2-2.0.19/g10/call-agent.c
===================================================================
--- gnupg2-2.0.19.orig/g10/call-agent.c	2012-03-27 10:00:37.000000000 +0200
+++ gnupg2-2.0.19/g10/call-agent.c	2012-11-05 12:17:53.721832346 +0100
@@ -1057,21 +1057,25 @@ agent_scd_pkdecrypt (const char *serialn
   if (rc)
     return rc;
 
-  /* FIXME: use secure memory where appropriate */
-  if (indatalen*2 + 50 > DIM(line))
-    return gpg_error (GPG_ERR_GENERAL);
-
   rc = select_openpgp (serialno);
   if (rc)
     return rc;
 
   sprintf (line, "SCD SETDATA ");
   p = line + strlen (line);
-  for (i=0; i < indatalen ; i++, p += 2 )
-    sprintf (p, "%02X", indata[i]);
-  rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
-  if (rc)
-    return rc;
+  while (i < indatalen)
+    {
+      sprintf (p, "%02X", indata[i++]);
+      p += 2;
+      if ((i == indatalen) || ((i % ((DIM(line)-50)/2)) == 0))
+        {
+          rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+          if (rc)
+            return rc;
+          sprintf (line, "SCD SETDATA --more ");
+          p = line + strlen (line);
+        }
+    }
 
   init_membuf (&data, 1024);
   snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
Index: gnupg2-2.0.19/scd/command.c
===================================================================
--- gnupg2-2.0.19.orig/scd/command.c	2012-03-27 10:00:38.000000000 +0200
+++ gnupg2-2.0.19/scd/command.c	2012-11-05 12:21:22.454422302 +0100
@@ -806,13 +806,16 @@ static gpg_error_t
 cmd_setdata (assuan_context_t ctx, char *line)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
-  int n;
+  int n, offset;
+  int more_data = has_option (line, "--more");
   char *p;
   unsigned char *buf;
 
   if (locked_session && locked_session != ctrl->server_local)
     return gpg_error (GPG_ERR_LOCKED);
 
+  line = skip_options (line);
+
   /* Parse the hexstring. */
   for (p=line,n=0; hexdigitp (p); p++, n++)
     ;
@@ -823,13 +826,21 @@ cmd_setdata (assuan_context_t ctx, char
   if ((n&1))
     return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
   n /= 2;
-  buf = xtrymalloc (n);
+  if (more_data)
+    buf = xtryrealloc (ctrl->in_data.value, ctrl->in_data.valuelen + n);
+  else
+    {
+      xfree (ctrl->in_data.value);
+      ctrl->in_data.valuelen = 0;
+      buf = xtrymalloc (n);
+    }
   if (!buf)
     return out_of_core ();
 
+  offset = ctrl->in_data.valuelen;
   ctrl->in_data.value = buf;
-  ctrl->in_data.valuelen = n;
-  for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
+  ctrl->in_data.valuelen += n;
+  for (p=line, n=offset; n < ctrl->in_data.valuelen; p += 2, n++)
     buf[n] = xtoi_2 (p);
   return 0;
 }

Reply via email to