diff -ur libtasn1-3.3/lib/decoding.c libtasn1-3.3.new/lib/decoding.c
--- libtasn1-3.3/lib/decoding.c 2013-03-24 10:55:30.000000000 +0100
+++ libtasn1-3.3.new/lib/decoding.c 2014-05-29 11:03:39.837782788 +0200
@@ -33,8 +33,25 @@
#include <limits.h>
#include <intprops.h>
+#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)
@@ -149,7 +166,7 @@
/* Long form */
punt = 1;
ris = 0;
- while (punt <= der_len && der[punt] & 128)
+ while (punt < der_len && der[punt] & 128)
{
if (INT_MULTIPLY_OVERFLOW (ris, 128))
@@ -206,8 +223,7 @@
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;
}
@@ -233,12 +249,11 @@
int *ret_len, unsigned char *str, int str_size,
int *str_len)
{
- int len_len;
+ int len_len = 0;
if (der_len <= 0)
return ASN1_GENERIC_ERROR;
- /* if(str==NULL) return ASN1_SUCCESS; */
*str_len = asn1_get_length_der (der, der_len, &len_len);
if (*str_len < 0)
@@ -246,7 +261,10 @@
*ret_len = *str_len + len_len;
if (str_size >= *str_len)
- memcpy (str, der + len_len, *str_len);
+ {
+ if (*str_len > 0 && str != NULL)
+ memcpy (str, der + len_len, *str_len);
+ }
else
{
return ASN1_MEM_ERROR;
@@ -265,9 +283,11 @@
if (der_len <= 0 || str == NULL)
return ASN1_DER_ERROR;
+
str_len = asn1_get_length_der (der, der_len, &len_len);
- if (str_len < 0 || str_size < str_len)
+ if (str_len <= 0 || str_size < str_len)
return ASN1_DER_ERROR;
+
memcpy (str, der + len_len, str_len);
str[str_len] = 0;
*ret_len = str_len + len_len;
@@ -293,7 +313,7 @@
len = asn1_get_length_der (der, der_len, &len_len);
- if (len < 0 || len > der_len || len_len > der_len)
+ if (len <= 0 || len + len_len > der_len)
return ASN1_DER_ERROR;
val1 = der[len_len] / 40;
@@ -355,10 +375,11 @@
int *ret_len, unsigned char *str, int str_size,
int *bit_len)
{
- int len_len, len_byte;
+ int len_len = 0, len_byte;
if (der_len <= 0)
return ASN1_GENERIC_ERROR;
+
len_byte = asn1_get_length_der (der, der_len, &len_len) - 1;
if (len_byte < 0)
return ASN1_DER_ERROR;
@@ -366,8 +387,14 @@
*ret_len = len_byte + len_len + 1;
*bit_len = len_byte * 8 - der[len_len];
+ if (*bit_len < 0)
+ return ASN1_DER_ERROR;
+
if (str_size >= len_byte)
- memcpy (str, der + len_len + 1, len_byte);
+ {
+ if (len_byte > 0 && str)
+ memcpy (str, der + len_len + 1, len_byte);
+ }
else
{
return ASN1_MEM_ERROR;
@@ -382,6 +409,7 @@
{
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;
@@ -409,23 +437,21 @@
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)
{
@@ -462,11 +488,11 @@
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))
{
@@ -485,18 +511,16 @@
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)
{
@@ -546,6 +570,9 @@
counter += len2;
*ret_len = counter;
return ASN1_SUCCESS;
+
+cleanup:
+ return result;
}
static int
@@ -612,97 +639,108 @@
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)
+ 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;
+ len2 = 0;
}
- 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))
- 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;
}
/* copy */
if (node)
{
- unsigned char temp[DER_LEN];
+ unsigned char temp[ASN1_MAX_LENGTH_SIZE];
int ret;
len2 = sizeof (temp);
@@ -710,7 +748,7 @@
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;
@@ -718,10 +756,11 @@
}
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);
@@ -730,12 +769,16 @@
*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;
@@ -743,12 +786,11 @@
while (1)
{
- if ((*len) < counter)
- 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;
@@ -757,36 +799,44 @@
}
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;
}
+
+
/**
* asn1_der_decoding:
* @element: pointer to an ASN1 structure.
* @ider: vector that contains the DER encoding.
- * @len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1].
* @errorDescription: null-terminated string contains details when an
* error occurred.
*
@@ -802,7 +852,7 @@
* name (*@ELEMENT 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;
@@ -824,6 +874,7 @@
if (node->type & CONST_OPTION)
{
result = ASN1_GENERIC_ERROR;
+ warn();
goto cleanup;
}
@@ -841,11 +892,12 @@
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;
}
}
@@ -858,6 +910,7 @@
else if (counter > len2)
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
p2 = p2->down;
@@ -868,7 +921,7 @@
if (type_field (p2->type) != ASN1_ETYPE_CHOICE)
ris =
_asn1_extract_tag_der (p2, der + counter,
- len - counter, &len2);
+ ider_len, &len2);
else
{
p3 = p2->down;
@@ -876,7 +929,7 @@
{
ris =
_asn1_extract_tag_der (p3, der + counter,
- len - counter, &len2);
+ ider_len, &len2);
if (ris == ASN1_SUCCESS)
break;
p3 = p3->right;
@@ -894,6 +947,7 @@
if (p2 == NULL)
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -924,12 +978,9 @@
{
while (p->down)
{
- if (counter < len)
- ris =
+ ris =
_asn1_extract_tag_der (p->down, der + counter,
- len - counter, &len2);
- else
- ris = ASN1_DER_ERROR;
+ ider_len, &len2);
if (ris == ASN1_SUCCESS)
{
while (p->down->right)
@@ -942,6 +993,7 @@
else if (ris == ASN1_ERROR_TYPE_ANY)
{
result = ASN1_ERROR_TYPE_ANY;
+ warn();
goto cleanup;
}
else
@@ -956,6 +1008,7 @@
if (!(p->type & CONST_OPTION))
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -973,7 +1026,7 @@
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)
@@ -992,11 +1045,15 @@
_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)
@@ -1004,18 +1061,23 @@
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)
@@ -1027,50 +1089,68 @@
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;
@@ -1085,13 +1165,16 @@
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;
@@ -1104,18 +1187,12 @@
_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;
}
@@ -1124,6 +1201,7 @@
if (len2 != counter)
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -1132,13 +1210,17 @@
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);
@@ -1177,13 +1259,7 @@
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;
@@ -1192,7 +1268,9 @@
move = RIGHT;
continue;
}
+
_asn1_set_value (p, NULL, 0);
+ DECR_LEN(ider_len, 2);
counter += 2;
}
else
@@ -1206,10 +1284,12 @@
move = RIGHT;
continue;
}
+
_asn1_set_value (p, NULL, 0);
if (len2 != counter)
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -1217,12 +1297,15 @@
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)
{
@@ -1251,46 +1334,59 @@
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;
@@ -1298,6 +1394,7 @@
an indefinite length method. */
if (indefinite)
{
+ DECR_LEN(ider_len, 2);
if (!der[counter] && !der[counter + 1])
{
counter += 2;
@@ -1305,6 +1402,7 @@
else
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -1340,8 +1438,9 @@
_asn1_delete_not_used (*element);
- if (counter != len)
+ if (ider_len != 0)
{
+ warn();
result = ASN1_DER_ERROR;
goto cleanup;
}
@@ -1374,6 +1473,9 @@
* decoding procedure, the *@STRUCTURE is deleted and set equal to
* %NULL.
*
+ * This function is deprecated and may just be an alias to asn1_der_decoding
+ * in future versions. Use asn1_der_decoding() instead.
+ *
* Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
* if ELEMENT is %NULL or @elementName == NULL, and
* %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't
@@ -1737,15 +1839,14 @@
move = RIGHT;
break;
case ASN1_ETYPE_OCTET_STRING:
- len3 = len - counter;
if (state == FOUND)
{
- result = _asn1_get_octet_string (der + counter, p, &len3);
+ result = _asn1_get_octet_string (p, der + counter, len-counter, &len3);
if (p == nodeFound)
state = EXIT;
}
else
- result = _asn1_get_octet_string (der + counter, NULL, &len3);
+ result = _asn1_get_octet_string (NULL, der + counter, len-counter, &len3);
if (result != ASN1_SUCCESS)
goto cleanup;
@@ -1987,9 +2088,8 @@
else
indefinite = 0;
- len2 = len - counter;
result =
- _asn1_get_indefinite_length_string (der + counter, &len2);
+ _asn1_get_indefinite_length_string (der + counter, len-counter, &len2);
if (result != ASN1_SUCCESS)
goto cleanup;
@@ -2160,7 +2260,7 @@
* asn1_der_decoding_startEnd:
* @element: pointer to an ASN1 element
* @ider: vector that contains the DER encoding.
- * @len: number of bytes of *@ider: @ider[0]..@ider[len-1]
+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]
* @name_element: an element of NAME structure.
* @start: the position of the first byte of NAME_ELEMENT decoding
* (@ider[*start])
@@ -2182,14 +2282,14 @@
* 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, p3;
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;
@@ -2205,7 +2305,7 @@
if (node_to_find == node)
{
*start = 0;
- *end = len - 1;
+ *end = ider_len - 1;
return ASN1_SUCCESS;
}
@@ -2228,16 +2328,20 @@
{
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;
}
}
@@ -2248,7 +2352,10 @@
continue;
}
else if (counter > len2)
- return ASN1_DER_ERROR;
+ {
+ warn();
+ return ASN1_DER_ERROR;
+ }
p2 = p2->down;
@@ -2259,7 +2366,7 @@
if (type_field (p2->type) != ASN1_ETYPE_CHOICE)
ris =
_asn1_extract_tag_der (p2, der + counter,
- len - counter, &len2);
+ ider_len, &len2);
else
{
p3 = p2->down;
@@ -2268,7 +2375,7 @@
ris =
_asn1_extract_tag_der (p3, der + counter,
- len - counter, &len2);
+ ider_len, &len2);
}
if (ris == ASN1_SUCCESS)
{
@@ -2280,7 +2387,10 @@
p2 = p2->right;
}
if (p2 == NULL)
- return ASN1_DER_ERROR;
+ {
+ warn();
+ return ASN1_DER_ERROR;
+ }
}
if (p == node_to_find)
@@ -2290,10 +2400,13 @@
{
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;
@@ -2301,7 +2414,7 @@
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)
@@ -2315,11 +2428,15 @@
}
else
{
+ warn();
return ASN1_TAG_ERROR;
}
}
else
- counter += len2;
+ {
+ DECR_LEN(ider_len, len2);
+ counter += len2;
+ }
}
if (ris == ASN1_SUCCESS)
@@ -2327,22 +2444,36 @@
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;
@@ -2362,9 +2493,14 @@
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;
@@ -2373,10 +2509,16 @@
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
@@ -2384,8 +2526,11 @@
}
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;
@@ -2394,13 +2539,26 @@
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) ||
@@ -2411,52 +2569,79 @@
}
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;
@@ -2494,7 +2679,11 @@
p = _asn1_find_up (p);
}
+ warn();
return ASN1_ELEMENT_NOT_FOUND;
+
+cleanup:
+ return result;
}
/**