[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#824484: jessie-pu: package libksba/1.3.2-1+deb8u1



Package: release.debian.org
Severity: normal
Tags: jessie
User: release.debian.org@packages.debian.org
Usertags: pu

Hi

libksba in jessie is affected by some CVEs which do not neccessarly
seem to need a DSA. I would like to propose the attached
debdiff/update for libksba via the next jessie point release.

Would you accept that upload? I took the git commits without
modifying, thus the first patch as well updates the copyright years
notice in one file. I can drop that if you prefer.

The "Fix an OOB read access in _ksba_dn_to_str" patch is an addition
to CVE-2016-4356 required. If we do not apply that one libskba will be
affected by CVE-2016-4574.

Thanks a lot for your time and review already,

Regards,
Salvatore
diff -Nru libksba-1.3.2/debian/changelog libksba-1.3.2/debian/changelog
--- libksba-1.3.2/debian/changelog	2014-11-25 20:08:22.000000000 +0100
+++ libksba-1.3.2/debian/changelog	2016-05-16 17:18:48.000000000 +0200
@@ -1,3 +1,14 @@
+libksba (1.3.2-1+deb8u1) jessie; urgency=medium
+
+  * Non-maintainer upload.
+  * Do not abort on decoder stack overflow (CVE-2016-4353)
+  * Fix integer overflow in the BER decoder (CVE-2016-4354 CVE-2016-4355)
+  * Fix encoding of invalid utf-8 strings in dn.c (CVE-2016-4356)
+  * Fix an OOB read access in _ksba_dn_to_str
+  * Fix possible read access beyond the buffer (CVE-2016-4579)
+
+ -- Salvatore Bonaccorso <carnil@debian.org>  Mon, 16 May 2016 17:18:33 +0200
+
 libksba (1.3.2-1) unstable; urgency=high
 
   * New upstream security release, fixing a buffer overflow in ksba_oid_to_str
diff -Nru libksba-1.3.2/debian/patches/Do-not-abort-on-decoder-stack-overflow.patch libksba-1.3.2/debian/patches/Do-not-abort-on-decoder-stack-overflow.patch
--- libksba-1.3.2/debian/patches/Do-not-abort-on-decoder-stack-overflow.patch	1970-01-01 01:00:00.000000000 +0100
+++ libksba-1.3.2/debian/patches/Do-not-abort-on-decoder-stack-overflow.patch	2016-05-16 17:18:48.000000000 +0200
@@ -0,0 +1,137 @@
+From 07116a314f4dcd4d96990bbd74db95a03a9f650a Mon Sep 17 00:00:00 2001
+From: Werner Koch <wk@gnupg.org>
+Date: Thu, 9 Apr 2015 11:50:03 +0200
+Subject: [PATCH] Do not abort on decoder stack overflow.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+* src/ber-decoder.c (push_decoder_state, pop_decoder_state): Return an
+error code.
+(set_error): Prefix error message with "ksba:". Act on new return code.
+(decoder_next): Act on new return code.
+--
+
+This changes the behaviour from
+
+  gpgsm: unknown hash algorithm '1.8.48.48.48.48.48.48.48.48'
+  gpgsm: detached signature w/o data - assuming certs-only
+  ERROR: decoder stack overflow!
+  Aborted
+
+to
+
+  gpgsm: detached signature w/o data - assuming certs-only
+  ksba: ber-decoder: stack overflow!
+  gpgsm: ksba_cms_parse failed: Limit reached
+
+Use "gpgsm --verify FILE" to exhibit the problem.  FILE is
+-----BEGIN PGP ARMORED FILE-----
+
+MDAGCSqGSIb3DQEHAqCAMDACAQExDzANBgkwMDAwMDAwMDAwADCABgkwMDAwMDAw
+MDAAMDEwoIGTMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+MDAwMDAwMDAwMDAwMDAjMDA=
+=PQdP
+-----END PGP ARMORED FILE-----
+
+Reported-by: Hanno Böck
+Signed-off-by: Werner Koch <wk@gnupg.org>
+---
+ src/ber-decoder.c | 30 ++++++++++++++++++------------
+ 1 file changed, 18 insertions(+), 12 deletions(-)
+
+diff --git a/src/ber-decoder.c b/src/ber-decoder.c
+index b4689fa..9e70d92 100644
+--- a/src/ber-decoder.c
++++ b/src/ber-decoder.c
+@@ -1,5 +1,5 @@
+ /* ber-decoder.c - Basic Encoding Rules Decoder
+- *      Copyright (C) 2001, 2004, 2006, 2012 g10 Code GmbH
++ * Copyright (C) 2001, 2004, 2006, 2012, 2015 g10 Code GmbH
+  *
+  * This file is part of KSBA.
+  *
+@@ -175,26 +175,28 @@ dump_decoder_state (DECODER_STATE ds)
+ }
+ 
+ /* Push ITEM onto the stack */
+-static void
++static gpg_error_t
+ push_decoder_state (DECODER_STATE ds)
+ {
+   if (ds->idx >= ds->stacksize)
+     {
+-      fprintf (stderr, "ERROR: decoder stack overflow!\n");
+-      abort ();
++      fprintf (stderr, "ksba: ber-decoder: stack overflow!\n");
++      return gpg_error (GPG_ERR_LIMIT_REACHED);
+     }
+   ds->stack[ds->idx++] = ds->cur;
++  return 0;
+ }
+ 
+-static void
++static gpg_error_t
+ pop_decoder_state (DECODER_STATE ds)
+ {
+   if (!ds->idx)
+     {
+-      fprintf (stderr, "ERROR: decoder stack underflow!\n");
+-      abort ();
++      fprintf (stderr, "ksba: ber-decoder: stack underflow!\n");
++      return gpg_error (GPG_ERR_INTERNAL);
+     }
+   ds->cur = ds->stack[--ds->idx];
++  return 0;
+ }
+ 
+ 
+@@ -202,7 +204,7 @@ pop_decoder_state (DECODER_STATE ds)
+ static int
+ set_error (BerDecoder d, AsnNode node, const char *text)
+ {
+-  fprintf (stderr,"ber-decoder: node `%s': %s\n",
++  fprintf (stderr,"ksba: ber-decoder: node `%s': %s\n",
+            node? node->name:"?", text);
+   d->last_errdesc = text;
+   return gpg_error (GPG_ERR_BAD_BER);
+@@ -955,9 +957,9 @@ decoder_next (BerDecoder d)
+                        && (ds->cur.nread
+                            > ds->stack[ds->idx-1].length))
+                     {
+-                      fprintf (stderr, "  ERROR: object length field "
++                      fprintf (stderr, "ksba: ERROR: object length field "
+                                "%d octects too large\n",
+-                              ds->cur.nread > ds->cur.length);
++                               ds->cur.nread - ds->cur.length);
+                       ds->cur.nread = ds->cur.length;
+                     }
+                   if ( ds->idx
+@@ -967,7 +969,9 @@ decoder_next (BerDecoder d)
+                                    >= ds->stack[ds->idx-1].length))))
+                     {
+                       int n = ds->cur.nread;
+-                      pop_decoder_state (ds);
++                      err = pop_decoder_state (ds);
++                      if (err)
++                        return err;
+                       ds->cur.nread += n;
+                       ds->cur.went_up++;
+                     }
+@@ -983,7 +987,9 @@ decoder_next (BerDecoder d)
+                   /* prepare for the next level */
+                   ds->cur.length = ti.length;
+                   ds->cur.ndef_length = ti.ndef;
+-                  push_decoder_state (ds);
++                  err = push_decoder_state (ds);
++                  if (err)
++                    return err;
+                   ds->cur.length = 0;
+                   ds->cur.ndef_length = 0;
+                   ds->cur.nread = 0;
+-- 
+2.8.1
+
diff -Nru libksba-1.3.2/debian/patches/Fix-an-OOB-read-access-in-_ksba_dn_to_str.patch libksba-1.3.2/debian/patches/Fix-an-OOB-read-access-in-_ksba_dn_to_str.patch
--- libksba-1.3.2/debian/patches/Fix-an-OOB-read-access-in-_ksba_dn_to_str.patch	1970-01-01 01:00:00.000000000 +0100
+++ libksba-1.3.2/debian/patches/Fix-an-OOB-read-access-in-_ksba_dn_to_str.patch	2016-05-16 17:18:48.000000000 +0200
@@ -0,0 +1,40 @@
+From 6be61daac047d8e6aa941eb103f8e71a1d4e3c75 Mon Sep 17 00:00:00 2001
+From: Werner Koch <wk@gnupg.org>
+Date: Tue, 3 May 2016 16:01:09 +0200
+Subject: [PATCH] Fix an OOB read access in _ksba_dn_to_str.
+
+* src/dn.c (append_utf8_value): Use a straightforward check to fix an
+off-by-one.
+--
+
+The old fix for the problem from April 2015 had an off-by-one in the
+bad encoding handing.
+
+Fixes-commit: 243d12fdec66a4360fbb3e307a046b39b5b4ffc3
+GnuPG-bug-id: 2344
+Reported-by: Pascal Cuoq
+Signed-off-by: Werner Koch <wk@gnupg.org>
+---
+ src/dn.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/src/dn.c b/src/dn.c
+index d207bf0..cea18a1 100644
+--- a/src/dn.c
++++ b/src/dn.c
+@@ -332,11 +332,8 @@ append_utf8_value (const unsigned char *value, size_t length,
+         }
+       else
+         {
+-          if (n+nmore > length)
+-            nmore = length - n; /* Oops, encoding to short */
+-
+           tmp[0] = *s++; n++;
+-          for (i=1; i <= nmore; i++)
++          for (i=1; n < length && i <= nmore; i++)
+             {
+               if ( (*s & 0xc0) != 0x80)
+                 break; /* Invalid encoding - let the next cycle detect this. */
+-- 
+2.8.1
+
diff -Nru libksba-1.3.2/debian/patches/Fix-encoding-of-invalid-utf-8-strings-in-dn.c.patch libksba-1.3.2/debian/patches/Fix-encoding-of-invalid-utf-8-strings-in-dn.c.patch
--- libksba-1.3.2/debian/patches/Fix-encoding-of-invalid-utf-8-strings-in-dn.c.patch	1970-01-01 01:00:00.000000000 +0100
+++ libksba-1.3.2/debian/patches/Fix-encoding-of-invalid-utf-8-strings-in-dn.c.patch	2016-05-16 17:18:48.000000000 +0200
@@ -0,0 +1,128 @@
+From 243d12fdec66a4360fbb3e307a046b39b5b4ffc3 Mon Sep 17 00:00:00 2001
+From: Werner Koch <wk@gnupg.org>
+Date: Wed, 8 Apr 2015 18:51:21 +0200
+Subject: [PATCH] Fix encoding of invalid utf-8 strings in dn.c
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+* src/dn.c (append_quoted, append_atv): Use snprintf.
+(append_utf8_value): Fix invalid encoding handling.
+--
+
+An invalid utf-8 encoding will make the loop in append_utf8_value run
+once more with N > length which is not found by the termination
+condition and only the former assert terminates the process if the byte
+following the bad encoding has the high bit cleared.  This will lead
+to a read access out of bounds.
+
+The patch removes the assert and fixes the handling of bad encoding.
+Due to the new quoting the output of a badly encoded utf-8 string will
+be different than in previous versions.
+
+Replacing sprintf is only for cosmetic reasons.
+
+Use "gpgsm --verify FILE" to exhibit the problem.  FILE is
+-----BEGIN PGP ARMORED FILE-----
+
+MDAGCSqGSIb3DQEHAqCAMDACAQExDzANBgkwMDAwMDAwMDAwADCABgkwMDAwMDAw
+MDAAMDEwAgEwMDAwMDEwMDAGA1UEAwwB/4AwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+=NJTr
+-----END PGP ARMORED FILE-----
+
+Reported-by: Hanno Böck
+Signed-off-by: Werner Koch <wk@gnupg.org>
+---
+ src/dn.c | 44 +++++++++++++++++++++++++++-----------------
+ 1 file changed, 27 insertions(+), 17 deletions(-)
+
+diff --git a/src/dn.c b/src/dn.c
+index 4fab689..d207bf0 100644
+--- a/src/dn.c
++++ b/src/dn.c
+@@ -260,7 +260,7 @@ append_quoted (struct stringbuf *sb, const unsigned char *value, size_t length,
+       n += skip;
+       if ( *s < ' ' || *s > 126 )
+         {
+-          sprintf (tmp, "\\%02X", *s);
++          snprintf (tmp, sizeof tmp, "\\%02X", *s);
+           put_stringbuf_mem (sb, tmp, 3);
+         }
+       else
+@@ -300,7 +300,6 @@ append_utf8_value (const unsigned char *value, size_t length,
+       length--;
+     }
+ 
+-  /* FIXME: check that the invalid encoding handling is correct */
+   for (s=value, n=0;;)
+     {
+       for (value = s; n < length && !(*s & 0x80); n++, s++)
+@@ -309,8 +308,9 @@ append_utf8_value (const unsigned char *value, size_t length,
+         append_quoted (sb, value, s-value, 0);
+       if (n==length)
+         return; /* ready */
+-      assert ((*s & 0x80));
+-      if ( (*s & 0xe0) == 0xc0 )      /* 110x xxxx */
++      if (!(*s & 0x80))
++        nmore = 0; /* Not expected here: high bit not set.  */
++      else if ( (*s & 0xe0) == 0xc0 ) /* 110x xxxx */
+         nmore = 1;
+       else if ( (*s & 0xf0) == 0xe0 ) /* 1110 xxxx */
+         nmore = 2;
+@@ -320,21 +320,31 @@ append_utf8_value (const unsigned char *value, size_t length,
+         nmore = 4;
+       else if ( (*s & 0xfe) == 0xfc ) /* 1111 110x */
+         nmore = 5;
+-      else /* invalid encoding */
+-        nmore = 5;  /* we will reduce the check length anyway */
+-
+-      if (n+nmore > length)
+-        nmore = length - n; /* oops, encoding to short */
++      else /* Invalid encoding */
++        nmore = 0;
+ 
+-      tmp[0] = *s++; n++;
+-      for (i=1; i <= nmore; i++)
++      if (!nmore)
+         {
+-          if ( (*s & 0xc0) != 0x80)
+-            break; /* invalid encoding - stop */
+-          tmp[i] = *s++;
+-          n++;
++          /* Encoding error:  We quote the bad byte.  */
++          snprintf (tmp, sizeof tmp, "\\%02X", *s);
++          put_stringbuf_mem (sb, tmp, 3);
++          s++; n++;
++        }
++      else
++        {
++          if (n+nmore > length)
++            nmore = length - n; /* Oops, encoding to short */
++
++          tmp[0] = *s++; n++;
++          for (i=1; i <= nmore; i++)
++            {
++              if ( (*s & 0xc0) != 0x80)
++                break; /* Invalid encoding - let the next cycle detect this. */
++              tmp[i] = *s++;
++              n++;
++            }
++          put_stringbuf_mem (sb, tmp, i);
+         }
+-      put_stringbuf_mem (sb, tmp, i);
+     }
+ }
+ 
+@@ -618,7 +628,7 @@ append_atv (const unsigned char *image, AsnNode root, struct stringbuf *sb)
+       for (i=0; i < node->len; i++)
+         {
+           char tmp[3];
+-          sprintf (tmp, "%02X", image[node->off+node->nhdr+i]);
++          snprintf (tmp, sizeof tmp, "%02X", image[node->off+node->nhdr+i]);
+           put_stringbuf (sb, tmp);
+         }
+       break;
+-- 
+2.8.1
+
diff -Nru libksba-1.3.2/debian/patches/Fix-integer-overflow-in-the-BER-decoder.patch libksba-1.3.2/debian/patches/Fix-integer-overflow-in-the-BER-decoder.patch
--- libksba-1.3.2/debian/patches/Fix-integer-overflow-in-the-BER-decoder.patch	1970-01-01 01:00:00.000000000 +0100
+++ libksba-1.3.2/debian/patches/Fix-integer-overflow-in-the-BER-decoder.patch	2016-05-16 17:18:48.000000000 +0200
@@ -0,0 +1,244 @@
+From aea7b6032865740478ca4b706850a5217f1c3887 Mon Sep 17 00:00:00 2001
+From: Werner Koch <wk@gnupg.org>
+Date: Thu, 9 Apr 2015 11:17:28 +0200
+Subject: [PATCH] Fix integer overflow in the BER decoder.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+* src/ber-decoder.c (ber_decoder_s): Change val.length from int to
+size_t.
+(sum_a1_a2_gt_b, sum_a1_a2_ge_b): New.
+(decoder_next): Check for integer overflow.  Use new sum function for
+size check.
+(_ksba_ber_decoder_dump): Use size_t for n to match change of
+val.length.  Adjust printf fomrat.  Check for integer overflow and use
+gpg_error_from_syserror instead of GPG_ERR_ENOMEM.
+(_ksba_ber_decoder_decode): Use new sum function for size check.
+Check for integer overflow.  Use size_t for n to match change of
+val.length.
+--
+
+The actual bug described below is due to assigning an int
+(val.length) to a size_t (ti.length).  The int was too large and thus
+negative so that the condition to check for too large objects didn't
+worked.  Changing the type would have been enough but other conditions
+are possible.  Thus the introduction of sum_a1_a2_ge_b for overflow
+checking and checks when adding 100 extra bytes to malloc calls are
+added.
+
+Use "gpgsm --verify FILE" to exhibit the problem.  FILE is
+-----BEGIN PGP ARMORED FILE-----
+
+MDAGCSqGSIb3DQEHAqCAMIACAQExDzANBgkwMDAwMDAwMDAwADAwBhcwMDAwMDAw
+MDAwMDAwMDAwMDAwMDAwMAAwMTAGCTAwMDAwMDAwMDAwBgkwMDAwMDAwMDAwMAYJ
+MDAwMDAwMDAwMDAXLDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
+MDAwMDAwMDAwCoYwMP////UwMDAwMDAwMDAwMDAwMDAwMA==
+=tvju
+-----END PGP ARMORED FILE-----
+
+Without the patch this error occured:
+
+  gpgsm: unknown hash algorithm '1.8.48.48.48.48.48.48.48.48'
+  gpgsm: detached signature w/o data - assuming certs-only
+  =================================================================
+  ==14322==ERROR: AddressSanitizer: heap-buffer-overflow on address
+   0x60b00000aded at pc 0x462ca8 bp 0x7fffd5928d90 sp 0x7fffd5928d80
+  WRITE of size 1 at 0x60b00000aded thread T0
+      #0 0x462ca7 in base64_reader_cb [...]-2.1.2/sm/base64.c:363
+      #1 0x7f35e70b6365 (/usr/lib64/libksba.so.8+0x7365)
+      #2 0x7f35e70bee11 (/usr/lib64/libksba.so.8+0xfe11)
+      #3 0x7f35e70c75ed (/usr/lib64/libksba.so.8+0x185ed)
+      #4 0x7f35e70c7a9d (/usr/lib64/libksba.so.8+0x18a9d)
+      #5 0x7f35e70c356f (/usr/lib64/libksba.so.8+0x1456f)
+      #6 0x7f35e70c58bf (/usr/lib64/libksba.so.8+0x168bf)
+      #7 0x48cbee in gpgsm_verify [...]/gnupg-2.1.2/sm/verify.c:171
+      #8 0x412901 in main /data/gnupg/gnupg-2.1.2/sm/gpgsm.c:1795
+      #9 0x7f35e68d5f9f in __libc_start_main ([...]
+      #10 0x415a91 (/data/gnupg/gnupg-2.1.2/sm/gpgsm+0x415a91)
+
+  0x60b00000aded is located 0 bytes to the right of 109-byte region
+   [0x60b00000ad80,0x60b00000aded)
+  allocated by thread T0 here:
+      #0 0x7f35e782e6f7 in malloc [...]
+      #1 0x7f35e75040b0 (/usr/lib64/libgcrypt.so.20+0xc0b0)
+
+  SUMMARY: AddressSanitizer: heap-buffer-overflow [...]
+  Shadow bytes around the buggy address:
+    0x0c167fff9560: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
+    0x0c167fff9570: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
+    0x0c167fff9580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
+    0x0c167fff9590: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
+    0x0c167fff95a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
+  =>0x0c167fff95b0: 00 00 00 00 00 00 00 00 00 00 00 00 00[05]fa fa
+    0x0c167fff95c0: fa fa fa fa fa fa 00 00 00 00 00 00 00 00 00 00
+    0x0c167fff95d0: 00 00 00 fa fa fa fa fa fa fa fa fa 00 00 00 00
+
+Reported-by: Hanno Böck
+Signed-off-by: Werner Koch <wk@gnupg.org>
+---
+ src/ber-decoder.c | 71 ++++++++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 54 insertions(+), 17 deletions(-)
+
+diff --git a/src/ber-decoder.c b/src/ber-decoder.c
+index 873f810..b4689fa 100644
+--- a/src/ber-decoder.c
++++ b/src/ber-decoder.c
+@@ -100,7 +100,7 @@ struct ber_decoder_s
+   struct
+   {
+     int primitive;  /* current value is a primitive one */
+-    int length;     /* length of the primitive one */
++    size_t length;  /* length of the primitive one */
+     int nhdr;       /* length of the header */
+     int tag;
+     int is_endtag;
+@@ -109,6 +109,23 @@ struct ber_decoder_s
+ };
+ 
+ 
++
++/* Evaluate with overflow check:  A1 + A2 > B  */
++static inline int
++sum_a1_a2_gt_b (size_t a1, size_t a2, size_t b)
++{
++  size_t sum = a1 + a2;
++  return (sum < a1 || sum > b);
++}
++
++/* Evaluate with overflow check:  A1 + A2 >= B  */
++static inline int
++sum_a1_a2_ge_b (size_t a1, size_t a2, size_t b)
++{
++  size_t sum = a1 + a2;
++  return (sum < a1 || sum >= b);
++}
++
+ 
+ 
+ static DECODER_STATE
+@@ -839,14 +856,16 @@ decoder_next (BerDecoder d)
+         {
+           /* We need some extra bytes to store the stuff we read ahead
+              at the end of the module which is later pushed back. */
+-          d->image.length = ti.length + 100;
+           d->image.used = 0;
++          d->image.length = ti.length + 100;
++          if (d->image.length < ti.length)
++            return gpg_error (GPG_ERR_BAD_BER);
+           d->image.buf = xtrymalloc (d->image.length);
+           if (!d->image.buf)
+             return gpg_error (GPG_ERR_ENOMEM);
+         }
+ 
+-      if (ti.nhdr + d->image.used >= d->image.length)
++      if (sum_a1_a2_ge_b (ti.nhdr, d->image.used, d->image.length))
+         return set_error (d, NULL, "image buffer too short to store the tag");
+ 
+       memcpy (d->image.buf + d->image.used, ti.buf, ti.nhdr);
+@@ -1041,7 +1060,7 @@ _ksba_ber_decoder_dump (BerDecoder d, FILE *fp)
+   int depth = 0;
+   AsnNode node;
+   unsigned char *buf = NULL;
+-  size_t buflen = 0;;
++  size_t buflen = 0;
+ 
+   if (!d)
+     return gpg_error (GPG_ERR_INV_VALUE);
+@@ -1063,9 +1082,9 @@ _ksba_ber_decoder_dump (BerDecoder d, FILE *fp)
+       if (node)
+         depth = distance (d->root, node);
+ 
+-      fprintf (fp, "%4lu %4u:%*s",
++      fprintf (fp, "%4lu %4lu:%*s",
+                ksba_reader_tell (d->reader) - d->val.nhdr,
+-               d->val.length,
++               (unsigned long)d->val.length,
+                depth*2, "");
+       if (node)
+         _ksba_asn_node_dump (node, fp);
+@@ -1074,16 +1093,22 @@ _ksba_ber_decoder_dump (BerDecoder d, FILE *fp)
+ 
+       if (node && d->val.primitive)
+         {
+-          int i, n, c;
++          size_t n;
++          int i, c;
+           char *p;
+ 
+           if (!buf || buflen < d->val.length)
+             {
+               xfree (buf);
+               buflen = d->val.length + 100;
+-              buf = xtrymalloc (buflen);
+-              if (!buf)
+-                err = gpg_error (GPG_ERR_ENOMEM);
++              if (buflen < d->val.length)
++                err = gpg_error (GPG_ERR_BAD_BER); /* Overflow */
++              else
++                {
++                  buf = xtrymalloc (buflen);
++                  if (!buf)
++                    err = gpg_error_from_syserror ();
++                }
+             }
+ 
+           for (n=0; !err && n < d->val.length; n++)
+@@ -1171,8 +1196,6 @@ _ksba_ber_decoder_decode (BerDecoder d, const char *start_name,
+ 
+   while (!(err = decoder_next (d)))
+     {
+-      int n, c;
+-
+       node = d->val.node;
+       /* Fixme: USE_IMAGE is only not used with the ber-dump utility
+          and thus of no big use.  We should remove the other code
+@@ -1188,7 +1211,7 @@ _ksba_ber_decoder_decode (BerDecoder d, const char *start_name,
+               if (node->type == TYPE_ANY)
+                 node->actual_type = d->val.tag;
+             }
+-          if (d->image.used + d->val.length > d->image.length)
++          if (sum_a1_a2_gt_b (d->image.used, d->val.length, d->image.length))
+             err = set_error(d, NULL, "TLV length too large");
+           else if (d->val.primitive)
+             {
+@@ -1196,18 +1219,32 @@ _ksba_ber_decoder_decode (BerDecoder d, const char *start_name,
+                                d->image.buf + d->image.used, d->val.length))
+                 err = eof_or_error (d, 1);
+               else
+-                d->image.used += d->val.length;
++                {
++                  size_t sum = d->image.used + d->val.length;
++                  if (sum < d->image.used)
++                    err = gpg_error (GPG_ERR_BAD_BER);
++                  else
++                    d->image.used = sum;
++                }
+             }
+         }
+       else if (node && d->val.primitive)
+         {
++          size_t n;
++          int c;
++
+           if (!buf || buflen < d->val.length)
+             {
+               xfree (buf);
+               buflen = d->val.length + 100;
+-              buf = xtrymalloc (buflen);
+-              if (!buf)
+-                err = gpg_error (GPG_ERR_ENOMEM);
++              if (buflen < d->val.length)
++                err = gpg_error (GPG_ERR_BAD_BER);
++              else
++                {
++                  buf = xtrymalloc (buflen);
++                  if (!buf)
++                    err = gpg_error_from_syserror ();
++                }
+             }
+ 
+           for (n=0; !err && n < d->val.length; n++)
+-- 
+2.8.1
+
diff -Nru libksba-1.3.2/debian/patches/Fix-possible-read-access-beyond-the-buffer.patch libksba-1.3.2/debian/patches/Fix-possible-read-access-beyond-the-buffer.patch
--- libksba-1.3.2/debian/patches/Fix-possible-read-access-beyond-the-buffer.patch	1970-01-01 01:00:00.000000000 +0100
+++ libksba-1.3.2/debian/patches/Fix-possible-read-access-beyond-the-buffer.patch	2016-05-16 17:18:48.000000000 +0200
@@ -0,0 +1,125 @@
+From a7eed17a0b2a1c09ef986f3b4b323cd31cea2b64 Mon Sep 17 00:00:00 2001
+From: Werner Koch <wk@gnupg.org>
+Date: Tue, 3 May 2016 14:10:04 +0200
+Subject: [PATCH] Fix possible read access beyond the buffer.
+
+* src/ber-help.c (_ksba_ber_parse_tl): Add extra sanity check.
+* src/cert.c (ksba_cert_get_cert_policies): Check TLV given length
+against buffer length.
+(ksba_cert_get_ext_key_usages): Ditto.
+* src/ocsp.c (parse_asntime_into_isotime): Ditto.
+--
+
+The returned length of the object from _ksba_ber_parse_tl (ti.length)
+was not always checked against the actual buffer length, thus leading
+to a read access after the end of the buffer and thus a segv.
+
+GnuPG-bug-id: 2344
+Reported-by: Pascal Cuoq
+Signed-off-by: Werner Koch <wk@gnupg.org>
+---
+ src/ber-help.c |  6 ++++++
+ src/cert.c     | 23 ++++++++++++++++++++++-
+ src/name.c     |  2 +-
+ src/ocsp.c     |  2 ++
+ 4 files changed, 31 insertions(+), 2 deletions(-)
+
+diff --git a/src/ber-help.c b/src/ber-help.c
+index f6a6692..87109f3 100644
+--- a/src/ber-help.c
++++ b/src/ber-help.c
+@@ -285,9 +285,15 @@ _ksba_ber_parse_tl (unsigned char const **buffer, size_t *size,
+           ti->buf[ti->nhdr++] = c;
+           len |= c & 0xff;
+         }
++      /* Sanity check for the length: This is done so that we can take
++       * the value for malloc plus some additional bytes without
++       * risking an overflow.  */
++      if (len > (1 << 30))
++        return gpg_error (GPG_ERR_BAD_BER);
+       ti->length = len;
+     }
+ 
++
+   /* Without this kludge some example certs can't be parsed */
+   if (ti->class == CLASS_UNIVERSAL && !ti->tag)
+     ti->length = 0;
+diff --git a/src/cert.c b/src/cert.c
+index 7f19dc1..f3ff6a1 100644
+--- a/src/cert.c
++++ b/src/cert.c
+@@ -1335,9 +1335,15 @@ ksba_cert_get_cert_policies (ksba_cert_t cert, char **r_policies)
+                   err = gpg_error (GPG_ERR_NOT_DER_ENCODED);
+                   goto leave;
+                 }
++              if (ti.length > derlen)
++                {
++                  err = gpg_error (GPG_ERR_BAD_BER);
++                  goto leave;
++                }
+               if (!ti.length)
+                 {
+-                  err = gpg_error (GPG_ERR_INV_CERT_OBJ); /* no empty inner SEQ */
++                  /* We do not accept an empty inner SEQ */
++                  err = gpg_error (GPG_ERR_INV_CERT_OBJ);
+                   goto leave;
+                 }
+               if (ti.nhdr+ti.length > seqlen)
+@@ -1356,6 +1362,11 @@ ksba_cert_get_cert_policies (ksba_cert_t cert, char **r_policies)
+                   err = gpg_error (GPG_ERR_INV_CERT_OBJ);
+                   goto leave;
+                 }
++              if (ti.length > derlen)
++                {
++                  err = gpg_error (GPG_ERR_BAD_BER);
++                  goto leave;
++                }
+               if (ti.nhdr+ti.length > seqseqlen)
+                 {
+                   err = gpg_error (GPG_ERR_BAD_BER);
+@@ -1458,6 +1469,16 @@ ksba_cert_get_ext_key_usages (ksba_cert_t cert, char **result)
+                   err = gpg_error (GPG_ERR_INV_CERT_OBJ);
+                   goto leave;
+                 }
++              if (ti.ndef)
++                {
++                  err = gpg_error (GPG_ERR_NOT_DER_ENCODED);
++                  goto leave;
++                }
++              if (ti.length > derlen)
++                {
++                  err = gpg_error (GPG_ERR_BAD_BER);
++                  goto leave;
++                }
+ 
+               suboid = ksba_oid_to_str (der, ti.length);
+               if (!suboid)
+diff --git a/src/name.c b/src/name.c
+index c734199..371fc41 100644
+--- a/src/name.c
++++ b/src/name.c
+@@ -113,7 +113,7 @@ _ksba_name_new_from_der (ksba_name_t *r_name,
+ 
+   *r_name = NULL;
+ 
+-  /* count and check for encoding errors - we won;t do this again
++  /* Count and check for encoding errors - we won't do this again
+      during the second pass */
+   der = image;
+   derlen = imagelen;
+diff --git a/src/ocsp.c b/src/ocsp.c
+index 85679bb..c053b18 100644
+--- a/src/ocsp.c
++++ b/src/ocsp.c
+@@ -231,6 +231,8 @@ parse_asntime_into_isotime (unsigned char const **buf, size_t *len,
+               && (ti.tag == TYPE_UTC_TIME || ti.tag == TYPE_GENERALIZED_TIME)
+               && !ti.is_constructed) )
+     err = gpg_error (GPG_ERR_INV_OBJ);
++  else if (ti.length > *len)
++    err = gpg_error (GPG_ERR_INV_BER);
+   else if (!(err = _ksba_asntime_to_iso (*buf, ti.length,
+                                          ti.tag == TYPE_UTC_TIME, isotime)))
+     parse_skip (buf, len, &ti);
+-- 
+2.8.1
+
diff -Nru libksba-1.3.2/debian/patches/series libksba-1.3.2/debian/patches/series
--- libksba-1.3.2/debian/patches/series	1970-01-01 01:00:00.000000000 +0100
+++ libksba-1.3.2/debian/patches/series	2016-05-16 17:18:48.000000000 +0200
@@ -0,0 +1,5 @@
+Do-not-abort-on-decoder-stack-overflow.patch
+Fix-integer-overflow-in-the-BER-decoder.patch
+Fix-encoding-of-invalid-utf-8-strings-in-dn.c.patch
+Fix-an-OOB-read-access-in-_ksba_dn_to_str.patch
+Fix-possible-read-access-beyond-the-buffer.patch

Reply to: