[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [SCM] GNU libtasn1 branch, master, updated. libtasn1_3_5-18-g06898d9,
Nikos Mavrogiannopoulos <=