libtasn1-commit
[Top][All Lists]
Advanced

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

[SCM] GNU libtasn1 branch, master, updated. libtasn1_3_5-18-g06898d9


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU libtasn1 branch, master, updated. libtasn1_3_5-18-g06898d9
Date: Fri, 16 May 2014 17:28:45 +0000

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 "GNU libtasn1".

http://git.savannah.gnu.org/cgit/libtasn1.git/commit/?id=06898d9e086d7d30fcfc7b0b61b8405e2d6bac28

The branch, master has been updated
       via  06898d9e086d7d30fcfc7b0b61b8405e2d6bac28 (commit)
       via  af0e8cd0bacf47ecce049165d3bc1ed9e861df1c (commit)
       via  6fee6745b1bd1a82f16ae9b607855a3e3ab39fc6 (commit)
       via  609d5c1366fb424f6150c4eed358d246e61cf204 (commit)
       via  cc10a8c5443c751d920cfaca1f104089e43296be (commit)
       via  df4b741dfc41c1930fd73a5c7968479196961508 (commit)
       via  37a16434131c6ad8745b9accefec5cecb4cbb5b7 (commit)
       via  25d7f2dbb74fa5033117e52638f082b94b3ef5fa (commit)
       via  eb83e268099b92e046f4ec224c8296f7bb61f159 (commit)
       via  154909136c12cfa5c60732b7210827dfb1ec6aee (commit)
      from  a8866ebf9a62386bd24f107e8384bbbf032baa52 (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 06898d9e086d7d30fcfc7b0b61b8405e2d6bac28
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 19:27:03 2014 +0200

    doc update

commit af0e8cd0bacf47ecce049165d3bc1ed9e861df1c
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 19:25:53 2014 +0200

    use DECR_LEN() in _asn1_get_indefinite_length_string().

commit 6fee6745b1bd1a82f16ae9b607855a3e3ab39fc6
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 19:21:37 2014 +0200

    use DECR_LEN in _asn1_get_octet_string()

commit 609d5c1366fb424f6150c4eed358d246e61cf204
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 19:16:09 2014 +0200

    Fixes in _asn1_extract_der_octet() and usage of DECR_LEN().

commit cc10a8c5443c751d920cfaca1f104089e43296be
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 19:02:46 2014 +0200

    use DECR_LEN() in _asn1_extract_tag_der()

commit df4b741dfc41c1930fd73a5c7968479196961508
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 19:00:04 2014 +0200

    simplified check for indefinite.

commit 37a16434131c6ad8745b9accefec5cecb4cbb5b7
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 18:21:08 2014 +0200

    expanded usage of DECR_LEN().

commit 25d7f2dbb74fa5033117e52638f082b94b3ef5fa
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 18:07:52 2014 +0200

    simplified _asn1_get_octet_string().

commit eb83e268099b92e046f4ec224c8296f7bb61f159
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 18:05:44 2014 +0200

    simplified _asn1_get_indefinite_length_string()

commit 154909136c12cfa5c60732b7210827dfb1ec6aee
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 16 18:02:32 2014 +0200

    More precise tracking of data.

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

Summary of changes:
 NEWS           |    1 +
 lib/decoding.c |  467 +++++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 327 insertions(+), 141 deletions(-)

diff --git a/NEWS b/NEWS
index 49fb8ba..1e62c5d 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ GNU Libtasn1 NEWS                                     -*- 
outline -*-
 
 * Noteworthy changes in release 3.6 (unreleased) [stable]
 - Corrected an off-by-one error in ASN.1 DER tag decoding.
+- Several improvements and new safety checks on DER decoding.
 
 * Noteworthy changes in release 3.5 (released 2014-05-01) [stable]
 - Correctly handle decoding of recursive CHOICE options.
diff --git a/lib/decoding.c b/lib/decoding.c
index f6c495f..ef2468a 100644
--- a/lib/decoding.c
+++ b/lib/decoding.c
@@ -33,8 +33,27 @@
 #include <limits.h>
 #include <intprops.h>
 
+#define DEBUG
+
+#ifdef DEBUG
+# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__)
+#else
+# define warn()
+#endif
+
+#define HAVE_TWO(x) (x>=2?1:0)
+
+#define DECR_LEN(l, s) do { \
+         l -= s; \
+         if (l < 0) { \
+           warn(); \
+           result = ASN1_DER_ERROR; \
+           goto cleanup; \
+         } \
+       } while (0)
+
 static int
-_asn1_get_indefinite_length_string (const unsigned char *der, int *len);
+_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int 
*len);
 
 static void
 _asn1_error_description_tag_error (asn1_node node, char *ErrorDescription)
@@ -206,8 +225,7 @@ asn1_get_length_ber (const unsigned char *ber, int ber_len, 
int *len)
   ret = asn1_get_length_der (ber, ber_len, len);
   if (ret == -1)
     {                          /* indefinite length method */
-      ret = ber_len;
-      err = _asn1_get_indefinite_length_string (ber + 1, &ret);
+      err = _asn1_get_indefinite_length_string (ber + 1, ber_len, &ret);
       if (err != ASN1_SUCCESS)
        return -3;
     }
@@ -383,6 +401,7 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char 
*der, int der_len,
 {
   asn1_node p;
   int counter, len2, len3, is_tag_implicit;
+  int result;
   unsigned long tag, tag_implicit = 0;
   unsigned char class, class2, class_implicit = 0;
 
@@ -410,23 +429,21 @@ _asn1_extract_tag_der (asn1_node node, const unsigned 
char *der, int der_len,
              if (p->type & CONST_EXPLICIT)
                {
                  if (asn1_get_tag_der
-                     (der + counter, der_len - counter, &class, &len2,
+                     (der + counter, der_len, &class, &len2,
                       &tag) != ASN1_SUCCESS)
                    return ASN1_DER_ERROR;
 
-                 if (counter + len2 > der_len)
-                   return ASN1_DER_ERROR;
+                  DECR_LEN(der_len, len2);
                  counter += len2;
 
                  len3 =
-                   asn1_get_length_ber (der + counter, der_len - counter,
+                   asn1_get_length_ber (der + counter, der_len,
                                         &len2);
                  if (len3 < 0)
                    return ASN1_DER_ERROR;
 
+                  DECR_LEN(der_len, len2);
                  counter += len2;
-                 if (counter > der_len)
-                   return ASN1_DER_ERROR;
 
                  if (!is_tag_implicit)
                    {
@@ -463,11 +480,11 @@ _asn1_extract_tag_der (asn1_node node, const unsigned 
char *der, int der_len,
   if (is_tag_implicit)
     {
       if (asn1_get_tag_der
-         (der + counter, der_len - counter, &class, &len2,
+         (der + counter, der_len, &class, &len2,
           &tag) != ASN1_SUCCESS)
        return ASN1_DER_ERROR;
-      if (counter + len2 > der_len)
-       return ASN1_DER_ERROR;
+
+      DECR_LEN(der_len, len2);
 
       if ((class != class_implicit) || (tag != tag_implicit))
        {
@@ -486,18 +503,16 @@ _asn1_extract_tag_der (asn1_node node, const unsigned 
char *der, int der_len,
       unsigned type = type_field (node->type);
       if (type == ASN1_ETYPE_TAG)
        {
-         counter = 0;
-         *ret_len = counter;
+         *ret_len = 0;
          return ASN1_SUCCESS;
        }
 
       if (asn1_get_tag_der
-         (der + counter, der_len - counter, &class, &len2,
+         (der + counter, der_len, &class, &len2,
           &tag) != ASN1_SUCCESS)
        return ASN1_DER_ERROR;
 
-      if (counter + len2 > der_len)
-       return ASN1_DER_ERROR;
+      DECR_LEN(der_len, len2);
 
       switch (type)
        {
@@ -550,6 +565,9 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char 
*der, int der_len,
   counter += len2;
   *ret_len = counter;
   return ASN1_SUCCESS;
+
+cleanup:
+  return result;
 }
 
 static int
@@ -641,90 +659,104 @@ _asn1_extract_der_octet (asn1_node node, const unsigned 
char *der,
                         int der_len)
 {
   int len2, len3;
-  int counter2, counter_end;
+  int counter, counter_end;
+  int result;
 
   len2 = asn1_get_length_der (der, der_len, &len3);
   if (len2 < -1)
     return ASN1_DER_ERROR;
 
-  counter2 = len3 + 1;
+  counter = len3 + 1;
 
   if (len2 == -1)
     counter_end = der_len - 2;
   else
     counter_end = der_len;
 
-  while (counter2 < counter_end)
+  while (counter < counter_end)
     {
-      len2 = asn1_get_length_der (der + counter2, der_len - counter2, &len3);
+      len2 = asn1_get_length_der (der + counter, der_len, &len3);
 
       if (len2 < -1)
        return ASN1_DER_ERROR;
 
       if (len2 > 0)
        {
-         _asn1_append_value (node, der + counter2 + len3, len2);
+         DECR_LEN(der_len, len2+len3);
+         _asn1_append_value (node, der + counter + len3, len2);
        }
       else
        {                       /* indefinite */
-
-         len2 =
-           _asn1_extract_der_octet (node, der + counter2 + len3,
-                                    der_len - counter2 - len3);
-         if (len2 < 0)
-           return len2;
+         DECR_LEN(der_len, len3);
+         result =
+           _asn1_extract_der_octet (node, der + counter + len3,
+                                    der_len);
+         if (result != ASN1_SUCCESS)
+           return result;
+         DECR_LEN(der_len, len2);
        }
 
-      counter2 += len2 + len3 + 1;
+      DECR_LEN(der_len, 1);
+      counter += len2 + len3 + 1;
     }
 
   return ASN1_SUCCESS;
+
+cleanup:
+  return result;
 }
 
 static int
-_asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len)
+_asn1_get_octet_string (asn1_node node, const unsigned char *der, int der_len, 
int *len)
 {
   int len2, len3, counter, tot_len, indefinite;
+  int result;
 
   counter = 0;
 
   if (*(der - 1) & ASN1_CLASS_STRUCTURED)
     {
       tot_len = 0;
-      indefinite = asn1_get_length_der (der, *len, &len3);
+      indefinite = asn1_get_length_der (der, der_len, &len3);
       if (indefinite < -1)
        return ASN1_DER_ERROR;
 
       counter += len3;
+      DECR_LEN(der_len, len3);
+
       if (indefinite >= 0)
        indefinite += len3;
 
       while (1)
        {
-         if (counter > (*len))
+         if (counter > der_len)
            return ASN1_DER_ERROR;
 
          if (indefinite == -1)
            {
-             if ((der[counter] == 0) && (der[counter + 1] == 0))
+             if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] 
== 0))
                {
                  counter += 2;
+                 DECR_LEN(der_len, 2);
                  break;
                }
            }
          else if (counter >= indefinite)
            break;
 
+          DECR_LEN(der_len, 1);
          if (der[counter] != ASN1_TAG_OCTET_STRING)
            return ASN1_DER_ERROR;
 
          counter++;
 
-         len2 = asn1_get_length_der (der + counter, *len - counter, &len3);
+         len2 = asn1_get_length_der (der + counter, der_len, &len3);
          if (len2 <= 0)
            return ASN1_DER_ERROR;
 
+          DECR_LEN(der_len, len3 + len2);
          counter += len3 + len2;
+
          tot_len += len2;
        }
 
@@ -739,7 +771,7 @@ _asn1_get_octet_string (const unsigned char *der, asn1_node 
node, int *len)
          asn1_length_der (tot_len, temp, &len2);
          _asn1_set_value (node, temp, len2);
 
-         ret = _asn1_extract_der_octet (node, der, *len);
+         ret = _asn1_extract_der_octet (node, der, der_len);
          if (ret != ASN1_SUCCESS)
            return ret;
 
@@ -747,10 +779,11 @@ _asn1_get_octet_string (const unsigned char *der, 
asn1_node node, int *len)
     }
   else
     {                          /* NOT STRUCTURED */
-      len2 = asn1_get_length_der (der, *len, &len3);
+      len2 = asn1_get_length_der (der, der_len, &len3);
       if (len2 < 0)
        return ASN1_DER_ERROR;
 
+      DECR_LEN(der_len, len3+len2);
       counter = len3 + len2;
       if (node)
        _asn1_set_value (node, der, counter);
@@ -759,12 +792,16 @@ _asn1_get_octet_string (const unsigned char *der, 
asn1_node node, int *len)
   *len = counter;
   return ASN1_SUCCESS;
 
+cleanup:
+  return result;
 }
 
 static int
-_asn1_get_indefinite_length_string (const unsigned char *der, int *len)
+_asn1_get_indefinite_length_string (const unsigned char *der,
+                                   int der_len, int *len)
 {
   int len2, len3, counter, indefinite;
+  int result;
   unsigned long tag;
   unsigned char class;
 
@@ -772,12 +809,11 @@ _asn1_get_indefinite_length_string (const unsigned char 
*der, int *len)
 
   while (1)
     {
-      if (counter+1 >= *len)
-       return ASN1_DER_ERROR;
-
-      if ((der[counter] == 0) && (der[counter + 1] == 0))
+      if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0))
        {
          counter += 2;
+         DECR_LEN(der_len, 2);
+
          indefinite--;
          if (indefinite <= 0)
            break;
@@ -786,29 +822,35 @@ _asn1_get_indefinite_length_string (const unsigned char 
*der, int *len)
        }
 
       if (asn1_get_tag_der
-         (der + counter, *len - counter, &class, &len2,
+         (der + counter, der_len, &class, &len2,
           &tag) != ASN1_SUCCESS)
        return ASN1_DER_ERROR;
-      if (counter + len2 > *len)
-       return ASN1_DER_ERROR;
+
+      DECR_LEN(der_len, len2);
       counter += len2;
-      len2 = asn1_get_length_der (der + counter, *len - counter, &len3);
+
+      len2 = asn1_get_length_der (der + counter, der_len, &len3);
       if (len2 < -1)
        return ASN1_DER_ERROR;
+
       if (len2 == -1)
        {
          indefinite++;
          counter += 1;
+          DECR_LEN(der_len, 1);
        }
       else
        {
          counter += len2 + len3;
+          DECR_LEN(der_len, len2+len3);
        }
     }
 
   *len = counter;
   return ASN1_SUCCESS;
 
+cleanup:
+  return result;
 }
 
 static void delete_unneeded_choice_fields(asn1_node p)
@@ -822,6 +864,8 @@ static void delete_unneeded_choice_fields(asn1_node p)
     }
 }
 
+
+
 /**
  * asn1_der_decoding:
  * @element: pointer to an ASN1 structure.
@@ -842,7 +886,7 @@ static void delete_unneeded_choice_fields(asn1_node p)
  *   name (address@hidden deleted).
  **/
 int
-asn1_der_decoding (asn1_node * element, const void *ider, int len,
+asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                   char *errorDescription)
 {
   asn1_node node, p, p2, p3;
@@ -864,6 +908,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
   if (node->type & CONST_OPTION)
     {
       result = ASN1_GENERIC_ERROR;
+      warn();
       goto cleanup;
     }
 
@@ -881,11 +926,12 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
              len2 = _asn1_strtol (p2->value, NULL, 10);
              if (len2 == -1)
                {
-                 if (!der[counter] && !der[counter + 1])
+                 if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
                    {
                      p = p2;
                      move = UP;
                      counter += 2;
+                     DECR_LEN(ider_len, 2);
                      continue;
                    }
                }
@@ -898,6 +944,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
              else if (counter > len2)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
              p2 = p2->down;
@@ -907,7 +954,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
                    {
                      ris =
                          extract_tag_der_recursive (p2, der + counter,
-                                                len - counter, &len2);
+                                                    ider_len, &len2);
                      if (ris == ASN1_SUCCESS)
                        {
                          p2->type &= ~CONST_NOT_USED;
@@ -920,6 +967,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
              if (p2 == NULL)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
            }
@@ -950,12 +998,10 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
            {
              while (p->down)
                {
-                 if (counter < len)
-                   ris =
+                 ris =
                      extract_tag_der_recursive (p->down, der + counter,
-                                            len - counter, &len2);
-                 else
-                   ris = ASN1_DER_ERROR;
+                                                ider_len, &len2);
+
                  if (ris == ASN1_SUCCESS)
                    {
                      delete_unneeded_choice_fields(p->down);
@@ -964,6 +1010,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
                  else if (ris == ASN1_ERROR_TYPE_ANY)
                    {
                      result = ASN1_ERROR_TYPE_ANY;
+                      warn();
                      goto cleanup;
                    }
                  else
@@ -978,6 +1025,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
                  if (!(p->type & CONST_OPTION))
                    {
                      result = ASN1_DER_ERROR;
+                      warn();
                      goto cleanup;
                    }
                }
@@ -989,13 +1037,15 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
            {
              p2 = _asn1_find_up (p);
              len2 = _asn1_strtol (p2->value, NULL, 10);
+
              if ((len2 != -1) && (counter > len2))
                ris = ASN1_TAG_ERROR;
            }
 
          if (ris == ASN1_SUCCESS)
            ris =
-             extract_tag_der_recursive (p, der + counter, len - counter, 
&len2);
+             extract_tag_der_recursive (p, der + counter, ider_len, &len2);
+
          if (ris != ASN1_SUCCESS)
            {
              if (p->type & CONST_OPTION)
@@ -1014,11 +1064,15 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
                    _asn1_error_description_tag_error (p, errorDescription);
 
                  result = ASN1_TAG_ERROR;
+                  warn();
                  goto cleanup;
                }
            }
          else
-           counter += len2;
+           {
+             DECR_LEN(ider_len, len2);
+             counter += len2;
+           }
        }
 
       if (ris == ASN1_SUCCESS)
@@ -1026,18 +1080,23 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
          switch (type_field (p->type))
            {
            case ASN1_ETYPE_NULL:
+             DECR_LEN(ider_len, 1);
              if (der[counter])
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
              counter++;
              move = RIGHT;
              break;
            case ASN1_ETYPE_BOOLEAN:
+             DECR_LEN(ider_len, 2);
+
              if (der[counter++] != 1)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
              if (der[counter++] == 0)
@@ -1049,50 +1108,68 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
            case ASN1_ETYPE_INTEGER:
            case ASN1_ETYPE_ENUMERATED:
              len2 =
-               asn1_get_length_der (der + counter, len - counter, &len3);
+               asn1_get_length_der (der + counter, ider_len, &len3);
              if (len2 < 0)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
 
+             DECR_LEN(ider_len, len3+len2);
+
              _asn1_set_value (p, der + counter, len3 + len2);
              counter += len3 + len2;
              move = RIGHT;
              break;
            case ASN1_ETYPE_OBJECT_ID:
              result =
-               _asn1_get_objectid_der (der + counter, len - counter, &len2,
+               _asn1_get_objectid_der (der + counter, ider_len, &len2,
                                        temp, sizeof (temp));
              if (result != ASN1_SUCCESS)
-               goto cleanup;
+               {
+                  warn();
+                 goto cleanup;
+               }
+
+             DECR_LEN(ider_len, len2);
 
              tlen = strlen (temp);
              if (tlen > 0)
                _asn1_set_value (p, temp, tlen + 1);
+
              counter += len2;
              move = RIGHT;
              break;
            case ASN1_ETYPE_GENERALIZED_TIME:
            case ASN1_ETYPE_UTC_TIME:
              result =
-               _asn1_get_time_der (der + counter, len - counter, &len2, temp,
+               _asn1_get_time_der (der + counter, ider_len, &len2, temp,
                                    sizeof (temp) - 1);
              if (result != ASN1_SUCCESS)
-               goto cleanup;
+               {
+                  warn();
+                 goto cleanup;
+               }
+
+             DECR_LEN(ider_len, len2);
 
              tlen = strlen (temp);
              if (tlen > 0)
                _asn1_set_value (p, temp, tlen);
+
              counter += len2;
              move = RIGHT;
              break;
            case ASN1_ETYPE_OCTET_STRING:
-             len3 = len - counter;
-             result = _asn1_get_octet_string (der + counter, p, &len3);
+             result = _asn1_get_octet_string (p, der + counter, ider_len, 
&len3);
              if (result != ASN1_SUCCESS)
-               goto cleanup;
+               {
+                  warn();
+                 goto cleanup;
+               }
 
+             DECR_LEN(ider_len, len3);
              counter += len3;
              move = RIGHT;
              break;
@@ -1107,13 +1184,16 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
            case ASN1_ETYPE_VISIBLE_STRING:
            case ASN1_ETYPE_BIT_STRING:
              len2 =
-               asn1_get_length_der (der + counter, len - counter, &len3);
+               asn1_get_length_der (der + counter, ider_len, &len3);
              if (len2 < 0)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
 
+             DECR_LEN(ider_len, len3+len2);
+
              _asn1_set_value (p, der + counter, len3 + len2);
              counter += len3 + len2;
              move = RIGHT;
@@ -1126,18 +1206,12 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
                  _asn1_set_value (p, NULL, 0);
                  if (len2 == -1)
                    {           /* indefinite length method */
-                     if (len - counter + 1 > 0)
-                       {
-                         if ((der[counter]) || der[counter + 1])
-                           {
-                             result = ASN1_DER_ERROR;
-                             goto cleanup;
-                           }
-                       }
-                     else
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
+                     DECR_LEN(ider_len, 2);
+                     if ((der[counter]) || der[counter + 1])
+                       {
+                         result = ASN1_DER_ERROR;
+                          warn();
+                         goto cleanup;
                        }
                      counter += 2;
                    }
@@ -1146,6 +1220,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
                      if (len2 != counter)
                        {
                          result = ASN1_DER_ERROR;
+                          warn();
                          goto cleanup;
                        }
                    }
@@ -1154,13 +1229,17 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
              else
                {               /* move==DOWN || move==RIGHT */
                  len3 =
-                   asn1_get_length_der (der + counter, len - counter, &len2);
+                   asn1_get_length_der (der + counter, ider_len, &len2);
                  if (len3 < -1)
                    {
                      result = ASN1_DER_ERROR;
+                      warn();
                      goto cleanup;
                    }
+
+                 DECR_LEN(ider_len, len2);
                  counter += len2;
+
                  if (len3 > 0)
                    {
                      _asn1_ltostr (counter + len3, temp);
@@ -1199,13 +1278,7 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
                  len2 = _asn1_strtol (p->value, NULL, 10);
                  if (len2 == -1)
                    {           /* indefinite length method */
-                     if ((counter + 2) > len)
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
-                       }
-
-                     if ((der[counter]) || der[counter + 1])
+                     if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter 
+ 1]))
                        {
                          _asn1_append_sequence_set (p);
                          p = p->down;
@@ -1214,7 +1287,9 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
                          move = RIGHT;
                          continue;
                        }
+
                      _asn1_set_value (p, NULL, 0);
+                     DECR_LEN(ider_len, 2);
                      counter += 2;
                    }
                  else
@@ -1228,10 +1303,12 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
                          move = RIGHT;
                          continue;
                        }
+
                      _asn1_set_value (p, NULL, 0);
                      if (len2 != counter)
                        {
                          result = ASN1_DER_ERROR;
+                          warn();
                          goto cleanup;
                        }
                    }
@@ -1239,12 +1316,15 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
              else
                {               /* move==DOWN || move==RIGHT */
                  len3 =
-                   asn1_get_length_der (der + counter, len - counter, &len2);
+                   asn1_get_length_der (der + counter, ider_len, &len2);
                  if (len3 < -1)
                    {
                      result = ASN1_DER_ERROR;
+                      warn();
                      goto cleanup;
                    }
+
+                 DECR_LEN(ider_len, len2);
                  counter += len2;
                  if (len3)
                    {
@@ -1273,46 +1353,59 @@ asn1_der_decoding (asn1_node * element, const void 
*ider, int len,
              break;
            case ASN1_ETYPE_ANY:
              if (asn1_get_tag_der
-                 (der + counter, len - counter, &class, &len2,
+                 (der + counter, ider_len, &class, &len2,
                   &tag) != ASN1_SUCCESS)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
 
-             if (counter + len2 > len)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
+             DECR_LEN(ider_len, len2);
+
              len4 =
                asn1_get_length_der (der + counter + len2,
-                                    len - counter - len2, &len3);
+                                    ider_len, &len3);
              if (len4 < -1)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
-             if (len4 != -1)
+             if (len4 != -1) /* definite */
                {
                  len2 += len4;
+
+                 DECR_LEN(ider_len, len4+len3);
                  _asn1_set_value_lv (p, der + counter, len2 + len3);
                  counter += len2 + len3;
                }
-             else
+             else /* == -1 */
                {               /* indefinite length */
+                 ider_len += len2; /* undo DECR_LEN */
+
+                 if (counter == 0)
+                   {
+                     result = ASN1_DER_ERROR;
+                      warn();
+                     goto cleanup;
+                   }
+
                  /* Check indefinite lenth method in an EXPLICIT TAG */
                  if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
                    indefinite = 1;
                  else
                    indefinite = 0;
 
-                 len2 = len - counter;
                  result =
-                   _asn1_get_indefinite_length_string (der + counter, &len2);
+                   _asn1_get_indefinite_length_string (der + counter, 
ider_len, &len2);
                  if (result != ASN1_SUCCESS)
-                   goto cleanup;
+                   {
+                      warn();
+                     goto cleanup;
+                   }
 
+                 DECR_LEN(ider_len, len2);
                  _asn1_set_value_lv (p, der + counter, len2);
                  counter += len2;
 
@@ -1320,6 +1413,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
                     an indefinite length method. */
                  if (indefinite)
                    {
+                     DECR_LEN(ider_len, 2);
                      if (!der[counter] && !der[counter + 1])
                        {
                          counter += 2;
@@ -1327,6 +1421,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
                      else
                        {
                          result = ASN1_DER_ERROR;
+                          warn();
                          goto cleanup;
                        }
                    }
@@ -1362,8 +1457,9 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int len,
 
   _asn1_delete_not_used (*element);
 
-  if (counter != len)
+  if (ider_len != 0)
     {
+      warn();
       result = ASN1_DER_ERROR;
       goto cleanup;
     }
@@ -1431,14 +1527,14 @@ asn1_der_decoding_element (asn1_node * structure, const 
char *elementName,
  *   doesn't match the structure ELEMENT.
  **/
 int
-asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
+asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len,
                            const char *name_element, int *start, int *end)
 {
   asn1_node node, node_to_find, p, p2;
   int counter, len2, len3, len4, move, ris;
   unsigned char class;
   unsigned long tag;
-  int indefinite;
+  int indefinite, result = ASN1_DER_ERROR;
   const unsigned char *der = ider;
 
   node = element;
@@ -1454,7 +1550,7 @@ asn1_der_decoding_startEnd (asn1_node element, const void 
*ider, int len,
   if (node_to_find == node)
     {
       *start = 0;
-      *end = len - 1;
+      *end = ider_len - 1;
       return ASN1_SUCCESS;
     }
 
@@ -1477,16 +1573,20 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
            {
              p2 = _asn1_find_up (p);
              if (p2 == NULL)
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
 
              len2 = _asn1_strtol (p2->value, NULL, 10);
              if (len2 == -1)
                {
-                 if (!der[counter] && !der[counter + 1])
+                 if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
                    {
                      p = p2;
                      move = UP;
                      counter += 2;
+                     DECR_LEN(ider_len, 2);
                      continue;
                    }
                }
@@ -1497,7 +1597,10 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
                  continue;
                }
              else if (counter > len2)
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
 
              p2 = p2->down;
 
@@ -1507,7 +1610,7 @@ asn1_der_decoding_startEnd (asn1_node element, const void 
*ider, int len,
                    {           /* CONTROLLARE */
                      ris =
                          extract_tag_der_recursive (p2, der + counter,
-                                                len - counter, &len2);
+                                                ider_len, &len2);
                      if (ris == ASN1_SUCCESS)
                        {
                          p2->type &= ~CONST_NOT_USED;
@@ -1518,7 +1621,10 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
                  p2 = p2->right;
                }
              if (p2 == NULL)
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
            }
 
          if (p == node_to_find)
@@ -1528,10 +1634,13 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
            {
              p = p->down;
              if (p == NULL)
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
 
              ris =
-               _asn1_extract_tag_der (p, der + counter, len - counter,
+               _asn1_extract_tag_der (p, der + counter, ider_len,
                                       &len2);
              if (p == node_to_find)
                *start = counter;
@@ -1539,7 +1648,7 @@ asn1_der_decoding_startEnd (asn1_node element, const void 
*ider, int len,
 
          if (ris == ASN1_SUCCESS)
            ris =
-             _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
+             _asn1_extract_tag_der (p, der + counter, ider_len, &len2);
          if (ris != ASN1_SUCCESS)
            {
              if (p->type & CONST_OPTION)
@@ -1553,11 +1662,15 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
                }
              else
                {
+                 warn();
                  return ASN1_TAG_ERROR;
                }
            }
          else
-           counter += len2;
+           {
+             DECR_LEN(ider_len, len2);
+             counter += len2;
+           }
        }
 
       if (ris == ASN1_SUCCESS)
@@ -1565,22 +1678,36 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
          switch (type_field (p->type))
            {
            case ASN1_ETYPE_NULL:
+              DECR_LEN(ider_len, 1);
+
              if (der[counter])
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
              counter++;
              move = RIGHT;
              break;
            case ASN1_ETYPE_BOOLEAN:
-             if (der[counter++] != 1)
-               return ASN1_DER_ERROR;
-             counter++;
+              DECR_LEN(ider_len, 2);
+
+             if (der[counter] != 1)
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
+
+             counter += 2;
              move = RIGHT;
              break;
            case ASN1_ETYPE_OCTET_STRING:
-             len3 = len - counter;
-             ris = _asn1_get_octet_string (der + counter, NULL, &len3);
+             ris = _asn1_get_octet_string (NULL, der + counter, ider_len, 
&len3);
              if (ris != ASN1_SUCCESS)
-               return ris;
+               {
+                 warn();
+                 return ris;
+               }
+              DECR_LEN(ider_len, len3);
              counter += len3;
              move = RIGHT;
              break;
@@ -1600,9 +1727,14 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
            case ASN1_ETYPE_VISIBLE_STRING:
            case ASN1_ETYPE_BIT_STRING:
              len2 =
-               asn1_get_length_der (der + counter, len - counter, &len3);
+               asn1_get_length_der (der + counter, ider_len, &len3);
              if (len2 < 0)
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
+
+              DECR_LEN(ider_len, len3 + len2);
              counter += len3 + len2;
              move = RIGHT;
              break;
@@ -1611,10 +1743,16 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
              if (move != UP)
                {
                  len3 =
-                   asn1_get_length_der (der + counter, len - counter, &len2);
+                   asn1_get_length_der (der + counter, ider_len, &len2);
                  if (len3 < -1)
-                   return ASN1_DER_ERROR;
+                   {
+                     warn();
+                     return ASN1_DER_ERROR;
+                   }
+
+                  DECR_LEN(ider_len, len2);
                  counter += len2;
+
                  if (len3 == 0)
                    move = RIGHT;
                  else
@@ -1622,8 +1760,11 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
                }
              else
                {
-                 if (!der[counter] && !der[counter + 1])       /* indefinite 
length method */
-                   counter += 2;
+                 if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) 
/* indefinite length method */
+                   {
+                     counter += 2;
+                     DECR_LEN(ider_len, 2);
+                   }
                  move = RIGHT;
                }
              break;
@@ -1632,13 +1773,26 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
              if (move != UP)
                {
                  len3 =
-                   asn1_get_length_der (der + counter, len - counter, &len2);
+                   asn1_get_length_der (der + counter, ider_len, &len2);
                  if (len3 < -1)
-                   return ASN1_DER_ERROR;
+                   {
+                     warn();
+                     return ASN1_DER_ERROR;
+                   }
+
+                  DECR_LEN(ider_len, len2);
                  counter += len2;
-                 if ((len3 == -1) && !der[counter] && !der[counter + 1])
-                   counter += 2;
-                 else if (len3)
+
+                 if (len3 == -1)
+                   {
+                      if (HAVE_TWO(ider_len) && !der[counter] && !der[counter 
+ 1])
+                        {
+                          DECR_LEN(ider_len, 2);
+                          counter += 2;
+                        }
+                   }
+
+                 if (len3)
                    {
                      p2 = p->down;
                      while ((type_field (p2->type) == ASN1_ETYPE_TAG) ||
@@ -1649,52 +1803,79 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
                }
              else
                {
-                 if (!der[counter] && !der[counter + 1])       /* indefinite 
length method */
-                   counter += 2;
+                 if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) 
/* indefinite length method */
+                   {
+                     DECR_LEN(ider_len, 2);
+                     counter += 2;
+                   }
                }
              move = RIGHT;
              break;
            case ASN1_ETYPE_ANY:
              if (asn1_get_tag_der
-                 (der + counter, len - counter, &class, &len2,
+                 (der + counter, ider_len, &class, &len2,
                   &tag) != ASN1_SUCCESS)
-               return ASN1_DER_ERROR;
-             if (counter + len2 > len)
-               return ASN1_DER_ERROR;
+                {
+                   warn();
+                   return ASN1_DER_ERROR;
+                }
+
+             DECR_LEN(ider_len, len2);
 
              len4 =
                asn1_get_length_der (der + counter + len2,
-                                    len - counter - len2, &len3);
+                                    ider_len, &len3);
              if (len4 < -1)
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
 
              if (len4 != -1)
                {
-                 counter += len2 + len4 + len3;
+                 DECR_LEN(ider_len, len3 + len4);
+                 counter += len2 + len3 + len4;
                }
              else
                {               /* indefinite length */
                  /* Check indefinite lenth method in an EXPLICIT TAG */
+                 ider_len += len2; /* undo DECR_LEN */
+
+                 if (counter == 0)
+                   {
+                     result = ASN1_DER_ERROR;
+                      warn();
+                     goto cleanup;
+                   }
+
                  if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
                    indefinite = 1;
                  else
                    indefinite = 0;
 
-                 len2 = len - counter;
                  ris =
-                   _asn1_get_indefinite_length_string (der + counter, &len2);
+                   _asn1_get_indefinite_length_string (der + counter, 
ider_len, &len2);
                  if (ris != ASN1_SUCCESS)
-                   return ris;
+                   {
+                     warn();
+                     return ris;
+                   }
                  counter += len2;
+                 DECR_LEN(ider_len, len2);
 
                  /* Check if a couple of 0x00 are present due to an EXPLICIT 
TAG with
                     an indefinite length method. */
                  if (indefinite)
                    {
+                     DECR_LEN(ider_len, 2);
+
                      if (!der[counter] && !der[counter + 1])
                        counter += 2;
                      else
-                       return ASN1_DER_ERROR;
+                       {
+                         warn();
+                         return ASN1_DER_ERROR;
+                       }
                    }
                }
              move = RIGHT;
@@ -1732,7 +1913,11 @@ asn1_der_decoding_startEnd (asn1_node element, const 
void *ider, int len,
        p = _asn1_find_up (p);
     }
 
+  warn();
   return ASN1_ELEMENT_NOT_FOUND;
+
+cleanup:
+  return result;
 }
 
 /**


hooks/post-receive
-- 
GNU libtasn1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]