summaryrefslogtreecommitdiff
path: root/lib/minitasn1
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2014-05-25 21:35:55 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2014-05-29 19:01:03 +0200
commit682ada3f9cfcd54964267160fe58d1da2a9664ea (patch)
tree9d1e5611e05ac4d29975acbf6b942fa406a734a1 /lib/minitasn1
parent39adcb42eab7f743df0edcb36d726aa4f69db6ac (diff)
downloadgnutls-682ada3f9cfcd54964267160fe58d1da2a9664ea.tar.gz
updated libtasn1
Diffstat (limited to 'lib/minitasn1')
-rw-r--r--lib/minitasn1/coding.c4
-rw-r--r--lib/minitasn1/decoding.c1258
-rw-r--r--lib/minitasn1/element.c96
-rw-r--r--lib/minitasn1/gstr.h15
-rw-r--r--lib/minitasn1/libtasn1.h16
-rw-r--r--lib/minitasn1/parser_aux.c15
-rw-r--r--lib/minitasn1/parser_aux.h3
7 files changed, 449 insertions, 958 deletions
diff --git a/lib/minitasn1/coding.c b/lib/minitasn1/coding.c
index e4eb060bc8..d6b7cf4114 100644
--- a/lib/minitasn1/coding.c
+++ b/lib/minitasn1/coding.c
@@ -594,7 +594,7 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter,
{
asn1_node p;
int tag_len, is_tag_implicit;
- unsigned char class, class_implicit = 0, temp[SIZEOF_UNSIGNED_INT * 3 + 1];
+ unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)];
unsigned long tag_implicit = 0;
unsigned char tag_der[MAX_TAG_LEN];
@@ -1012,7 +1012,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
char *ErrorDescription)
{
asn1_node node, p, p2;
- unsigned char temp[SIZEOF_UNSIGNED_LONG_INT * 3 + 1];
+ unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)];
int counter, counter_old, len2, len3, tlen, move, max_len, max_len_old;
int err;
unsigned char *der = ider;
diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c
index 16f202a2c4..a9aecc254b 100644
--- a/lib/minitasn1/decoding.c
+++ b/lib/minitasn1/decoding.c
@@ -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)
@@ -206,8 +223,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;
}
@@ -233,12 +249,11 @@ asn1_get_octet_der (const unsigned char *der, int der_len,
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 @@ asn1_get_octet_der (const unsigned char *der, int der_len,
*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 @@ _asn1_get_time_der (const unsigned char *der, int der_len, int *ret_len,
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;
@@ -281,7 +301,7 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len,
{
int len_len, len, k;
int leading;
- char temp[20];
+ char temp[LTOSTR_MAX_SIZE];
unsigned long val, val1;
*ret_len = 0;
@@ -293,7 +313,7 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len,
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 @@ asn1_get_bit_der (const unsigned char *der, int der_len,
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 @@ asn1_get_bit_der (const unsigned char *der, int der_len,
*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;
@@ -383,6 +410,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 +438,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 +489,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 +512,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 +574,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,97 +668,108 @@ _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)
+ 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);
@@ -739,7 +777,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 +785,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 +798,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 +815,11 @@ _asn1_get_indefinite_length_string (const unsigned char *der, int *len)
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;
@@ -786,29 +828,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,11 +870,13 @@ static void delete_unneeded_choice_fields(asn1_node p)
}
}
+
+
/**
* 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.
*
@@ -842,7 +892,7 @@ static void delete_unneeded_choice_fields(asn1_node p)
* 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;
@@ -864,6 +914,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 +932,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 +950,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 +960,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 +973,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
if (p2 == NULL)
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -950,12 +1004,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 +1016,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 +1031,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 +1043,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 +1070,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 +1086,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 +1114,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 +1190,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 +1212,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 +1226,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
if (len2 != counter)
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -1154,13 +1235,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 +1284,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 +1293,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 +1309,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 +1322,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 +1359,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 +1419,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 +1427,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
else
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -1362,8 +1463,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;
}
@@ -1396,6 +1498,9 @@ cleanup:
* 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
@@ -1405,766 +1510,14 @@ int
asn1_der_decoding_element (asn1_node * structure, const char *elementName,
const void *ider, int len, char *errorDescription)
{
- asn1_node node, p, p2, p3, nodeFound = NULL;
- char temp[128], currentName[ASN1_MAX_NAME_SIZE * 10], *dot_p, *char_p;
- int nameLen = ASN1_MAX_NAME_SIZE * 10 - 1, state;
- int counter, len2, len3, len4, move, ris, tlen;
- unsigned char class;
- unsigned long tag;
- int indefinite, result;
- const unsigned char *der = ider;
-
- node = *structure;
-
- if (node == NULL)
- return ASN1_ELEMENT_NOT_FOUND;
-
- if (elementName == NULL)
- {
- result = ASN1_ELEMENT_NOT_FOUND;
- goto cleanup;
- }
-
- if (node->type & CONST_OPTION)
- {
- result = ASN1_GENERIC_ERROR;
- goto cleanup;
- }
-
- if ((*structure)->name[0] != 0)
- { /* Has *structure got a name? */
- nameLen -= strlen ((*structure)->name);
- if (nameLen > 0)
- strcpy (currentName, (*structure)->name);
- else
- {
- result = ASN1_MEM_ERROR;
- goto cleanup;
- }
- if (!(strcmp (currentName, elementName)))
- {
- state = FOUND;
- nodeFound = *structure;
- }
- else if (!memcmp (currentName, elementName, strlen (currentName)))
- state = SAME_BRANCH;
- else
- state = OTHER_BRANCH;
- }
- else
- { /* *structure doesn't have a name? */
- currentName[0] = 0;
- if (elementName[0] == 0)
- {
- state = FOUND;
- nodeFound = *structure;
- }
- else
- {
- state = SAME_BRANCH;
- }
- }
-
- counter = 0;
- move = DOWN;
- p = node;
- while (1)
- {
-
- ris = ASN1_SUCCESS;
-
- if (move != UP)
- {
- if (p->type & CONST_SET)
- {
- p2 = _asn1_find_up (p);
- len2 = _asn1_strtol (p2->value, NULL, 10);
- if (counter == len2)
- {
- p = p2;
- move = UP;
- continue;
- }
- else if (counter > len2)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- p2 = p2->down;
- while (p2)
- {
- if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
- {
- ris =
- extract_tag_der_recursive (p2, der + counter,
- len - counter, &len2);
- if (ris == ASN1_SUCCESS)
- {
- p2->type &= ~CONST_NOT_USED;
- p = p2;
- break;
- }
- }
- p2 = p2->right;
- }
- if (p2 == NULL)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- }
-
- if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
- {
- p2 = _asn1_find_up (p);
- len2 = _asn1_strtol (p2->value, NULL, 10);
- if (counter == len2)
- {
- if (p->right)
- {
- p2 = p->right;
- move = RIGHT;
- }
- else
- move = UP;
-
- if (p->type & CONST_OPTION)
- asn1_delete_structure (&p);
-
- p = p2;
- continue;
- }
- }
-
- if (type_field (p->type) == ASN1_ETYPE_CHOICE)
- {
- while (p->down)
- {
- if (counter < len)
- ris =
- _asn1_extract_tag_der (p->down, der + counter,
- len - counter, &len2);
- else
- ris = ASN1_DER_ERROR;
- if (ris == ASN1_SUCCESS)
- {
- delete_unneeded_choice_fields(p->down);
- break;
- }
- else if (ris == ASN1_ERROR_TYPE_ANY)
- {
- result = ASN1_ERROR_TYPE_ANY;
- goto cleanup;
- }
- else
- {
- p2 = p->down;
- asn1_delete_structure (&p2);
- }
- }
-
- if (p->down == NULL)
- {
- if (!(p->type & CONST_OPTION))
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- }
- else if (type_field (p->type) != ASN1_ETYPE_CHOICE)
- p = p->down;
- }
-
- if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
- {
- p2 = _asn1_find_up (p);
- len2 = _asn1_strtol (p2->value, NULL, 10);
- if (counter > len2)
- ris = ASN1_TAG_ERROR;
- }
-
- if (ris == ASN1_SUCCESS)
- ris =
- _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
- if (ris != ASN1_SUCCESS)
- {
- if (p->type & CONST_OPTION)
- {
- p->type |= CONST_NOT_USED;
- move = RIGHT;
- }
- else if (p->type & CONST_DEFAULT)
- {
- _asn1_set_value (p, NULL, 0);
- move = RIGHT;
- }
- else
- {
- if (errorDescription != NULL)
- _asn1_error_description_tag_error (p, errorDescription);
-
- result = ASN1_TAG_ERROR;
- goto cleanup;
- }
- }
- else
- counter += len2;
- }
-
- if (ris == ASN1_SUCCESS)
- {
- switch (type_field (p->type))
- {
- case ASN1_ETYPE_NULL:
- if (der[counter])
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
-
- if (p == nodeFound)
- state = EXIT;
-
- counter++;
- move = RIGHT;
- break;
- case ASN1_ETYPE_BOOLEAN:
- if (der[counter++] != 1)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
-
- if (state == FOUND)
- {
- if (der[counter++] == 0)
- _asn1_set_value (p, "F", 1);
- else
- _asn1_set_value (p, "T", 1);
-
- if (p == nodeFound)
- state = EXIT;
-
- }
- else
- counter++;
-
- move = RIGHT;
- break;
- case ASN1_ETYPE_INTEGER:
- case ASN1_ETYPE_ENUMERATED:
- len2 =
- asn1_get_length_der (der + counter, len - counter, &len3);
- if (len2 < 0)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
-
- if (state == FOUND)
- {
- if (len3 + len2 > len - counter)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- _asn1_set_value (p, der + counter, len3 + len2);
-
- if (p == nodeFound)
- state = EXIT;
- }
- counter += len3 + len2;
- move = RIGHT;
- break;
- case ASN1_ETYPE_OBJECT_ID:
- if (state == FOUND)
- {
- result =
- _asn1_get_objectid_der (der + counter, len - counter,
- &len2, temp, sizeof (temp));
- if (result != ASN1_SUCCESS)
- goto cleanup;
-
- tlen = strlen (temp);
-
- if (tlen > 0)
- _asn1_set_value (p, temp, tlen + 1);
-
- if (p == nodeFound)
- state = EXIT;
- }
- else
- {
- len2 =
- asn1_get_length_der (der + counter, len - counter, &len3);
- if (len2 < 0)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- len2 += len3;
- }
-
- counter += len2;
- move = RIGHT;
- break;
- case ASN1_ETYPE_GENERALIZED_TIME:
- case ASN1_ETYPE_UTC_TIME:
- if (state == FOUND)
- {
- result =
- _asn1_get_time_der (der + counter, len - counter, &len2,
- temp, sizeof (temp) - 1);
- if (result != ASN1_SUCCESS)
- goto cleanup;
-
- tlen = strlen (temp);
- if (tlen > 0)
- _asn1_set_value (p, temp, tlen + 1);
-
- if (p == nodeFound)
- state = EXIT;
- }
- else
- {
- len2 =
- asn1_get_length_der (der + counter, len - counter, &len3);
- if (len2 < 0)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- len2 += len3;
- }
-
- counter += len2;
- move = RIGHT;
- break;
- case ASN1_ETYPE_OCTET_STRING:
- len3 = len - counter;
- if (state == FOUND)
- {
- result = _asn1_get_octet_string (der + counter, p, &len3);
- if (p == nodeFound)
- state = EXIT;
- }
- else
- result = _asn1_get_octet_string (der + counter, NULL, &len3);
-
- if (result != ASN1_SUCCESS)
- goto cleanup;
-
- counter += len3;
- move = RIGHT;
- break;
- case ASN1_ETYPE_GENERALSTRING:
- case ASN1_ETYPE_NUMERIC_STRING:
- case ASN1_ETYPE_IA5_STRING:
- case ASN1_ETYPE_TELETEX_STRING:
- case ASN1_ETYPE_PRINTABLE_STRING:
- case ASN1_ETYPE_UNIVERSAL_STRING:
- case ASN1_ETYPE_BMP_STRING:
- case ASN1_ETYPE_UTF8_STRING:
- case ASN1_ETYPE_VISIBLE_STRING:
- case ASN1_ETYPE_BIT_STRING:
- len2 =
- asn1_get_length_der (der + counter, len - counter, &len3);
- if (len2 < 0)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
-
- if (state == FOUND)
- {
- if (len3 + len2 > len - counter)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- _asn1_set_value (p, der + counter, len3 + len2);
-
- if (p == nodeFound)
- state = EXIT;
- }
- counter += len3 + len2;
- move = RIGHT;
- break;
- case ASN1_ETYPE_SEQUENCE:
- case ASN1_ETYPE_SET:
- if (move == UP)
- {
- len2 = _asn1_strtol (p->value, NULL, 10);
- _asn1_set_value (p, NULL, 0);
- if (len2 == -1)
- { /* indefinite length method */
- if ((der[counter]) || der[counter + 1])
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- counter += 2;
- }
- else
- { /* definite length method */
- if (len2 != counter)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- }
- if (p == nodeFound)
- state = EXIT;
- move = RIGHT;
- }
- else
- { /* move==DOWN || move==RIGHT */
- if (state == OTHER_BRANCH)
- {
- len3 =
- asn1_get_length_der (der + counter, len - counter,
- &len2);
- if (len3 < 0)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- counter += len2 + len3;
- move = RIGHT;
- }
- else
- { /* state==SAME_BRANCH or state==FOUND */
- len3 =
- asn1_get_length_der (der + counter, len - counter,
- &len2);
- if (len3 < 0)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- counter += len2;
- if (len3 > 0)
- {
- _asn1_ltostr (counter + len3, temp);
- tlen = strlen (temp);
-
- if (tlen > 0)
- _asn1_set_value (p, temp, tlen + 1);
- move = DOWN;
- }
- else if (len3 == 0)
- {
- p2 = p->down;
- while (p2)
- {
- if (type_field (p2->type) != ASN1_ETYPE_TAG)
- {
- p3 = p2->right;
- asn1_delete_structure (&p2);
- p2 = p3;
- }
- else
- p2 = p2->right;
- }
- move = RIGHT;
- }
- else
- { /* indefinite length method */
- _asn1_set_value (p, "-1", 3);
- move = DOWN;
- }
- }
- }
- break;
- case ASN1_ETYPE_SEQUENCE_OF:
- case ASN1_ETYPE_SET_OF:
- if (move == UP)
- {
- len2 = _asn1_strtol (p->value, NULL, 10);
- if (len2 > counter)
- {
- _asn1_append_sequence_set (p);
- p = p->down;
- while (p->right)
- p = p->right;
- move = RIGHT;
- continue;
- }
- _asn1_set_value (p, NULL, 0);
- if (len2 != counter)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
-
- if (p == nodeFound)
- state = EXIT;
- }
- else
- { /* move==DOWN || move==RIGHT */
- if (state == OTHER_BRANCH)
- {
- len3 =
- asn1_get_length_der (der + counter, len - counter,
- &len2);
- if (len3 < 0)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- counter += len2 + len3;
- move = RIGHT;
- }
- else
- { /* state==FOUND or state==SAME_BRANCH */
- len3 =
- asn1_get_length_der (der + counter, len - counter,
- &len2);
- if (len3 < 0)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- counter += len2;
- if (len3)
- {
- _asn1_ltostr (counter + len3, temp);
- tlen = strlen (temp);
-
- if (tlen > 0)
- _asn1_set_value (p, temp, tlen + 1);
- p2 = p->down;
- while ((type_field (p2->type) == ASN1_ETYPE_TAG)
- || (type_field (p2->type) ==
- ASN1_ETYPE_SIZE))
- p2 = p2->right;
- if (p2->right == NULL)
- _asn1_append_sequence_set (p);
- p = p2;
- state = FOUND;
- }
- }
- }
-
- break;
- case ASN1_ETYPE_ANY:
- if (asn1_get_tag_der
- (der + counter, len - counter, &class, &len2,
- &tag) != ASN1_SUCCESS)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
-
- if (counter + len2 > len)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
-
- len4 =
- asn1_get_length_der (der + counter + len2,
- len - counter - len2, &len3);
- if (len4 < -1)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
-
- if (len4 != -1)
- {
- len2 += len4;
- if (state == FOUND)
- {
- _asn1_set_value_lv (p, der + counter, len2 + len3);
-
- if (p == nodeFound)
- state = EXIT;
- }
- counter += len2 + len3;
- }
- else
- { /* indefinite length */
- /* 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);
- if (result != ASN1_SUCCESS)
- goto cleanup;
-
- if (state == FOUND)
- {
- _asn1_set_value_lv (p, der + counter, len2);
-
- if (p == nodeFound)
- state = EXIT;
- }
-
- counter += len2;
-
- /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
- an indefinite length method. */
- if (indefinite)
- {
- if (!der[counter] && !der[counter + 1])
- {
- counter += 2;
- }
- else
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
- }
- }
- move = RIGHT;
- break;
-
- default:
- move = (move == UP) ? RIGHT : DOWN;
- break;
- }
- }
-
- if ((p == node && move != DOWN) || (state == EXIT))
- break;
-
- if (move == DOWN)
- {
- if (p->down)
- {
- p = p->down;
-
- if (state != FOUND)
- {
- nameLen -= strlen (p->name) + 1;
- if (nameLen > 0)
- {
- if (currentName[0])
- strcat (currentName, ".");
- strcat (currentName, p->name);
- }
- else
- {
- result = ASN1_MEM_ERROR;
- goto cleanup;
- }
- if (!(strcmp (currentName, elementName)))
- {
- state = FOUND;
- nodeFound = p;
- }
- else
- if (!memcmp
- (currentName, elementName, strlen (currentName)))
- state = SAME_BRANCH;
- else
- state = OTHER_BRANCH;
- }
- }
- else
- move = RIGHT;
- }
-
- if ((move == RIGHT) && !(p->type & CONST_SET))
- {
- if (p->right)
- {
- p = p->right;
-
- if (state != FOUND)
- {
- dot_p = char_p = currentName;
- while ((char_p = strchr (char_p, '.')))
- {
- dot_p = char_p++;
- dot_p++;
- }
-
- nameLen += strlen (currentName) - (dot_p - currentName);
- *dot_p = 0;
-
- nameLen -= strlen (p->name);
- if (nameLen > 0)
- strcat (currentName, p->name);
- else
- {
- result = ASN1_MEM_ERROR;
- goto cleanup;
- }
-
- if (!(strcmp (currentName, elementName)))
- {
- state = FOUND;
- nodeFound = p;
- }
- else
- if (!memcmp
- (currentName, elementName, strlen (currentName)))
- state = SAME_BRANCH;
- else
- state = OTHER_BRANCH;
- }
- }
- else
- move = UP;
- }
-
- if (move == UP)
- {
- p = _asn1_find_up (p);
-
- if (state != FOUND)
- {
- dot_p = char_p = currentName;
- while ((char_p = strchr (char_p, '.')))
- {
- dot_p = char_p++;
- dot_p++;
- }
-
- nameLen += strlen (currentName) - (dot_p - currentName);
- *dot_p = 0;
-
- if (!(strcmp (currentName, elementName)))
- {
- state = FOUND;
- nodeFound = p;
- }
- else
- if (!memcmp (currentName, elementName, strlen (currentName)))
- state = SAME_BRANCH;
- else
- state = OTHER_BRANCH;
- }
- }
- }
-
- _asn1_delete_not_used (*structure);
-
- if (counter > len)
- {
- result = ASN1_DER_ERROR;
- goto cleanup;
- }
-
- return ASN1_SUCCESS;
-
-cleanup:
- asn1_delete_structure (structure);
- return result;
+ return asn1_der_decoding(structure, ider, len, errorDescription);
}
/**
* 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])
@@ -2186,14 +1539,14 @@ cleanup:
* 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;
@@ -2209,7 +1562,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;
}
@@ -2232,16 +1585,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;
}
}
@@ -2252,7 +1609,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;
@@ -2262,7 +1622,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;
@@ -2273,7 +1633,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)
@@ -2283,10 +1646,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;
@@ -2294,7 +1660,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)
@@ -2308,11 +1674,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)
@@ -2320,22 +1690,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;
@@ -2355,9 +1739,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;
@@ -2366,10 +1755,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
@@ -2377,8 +1772,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;
@@ -2387,13 +1785,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) ||
@@ -2404,52 +1815,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;
@@ -2487,7 +1925,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;
}
/**
diff --git a/lib/minitasn1/element.c b/lib/minitasn1/element.c
index 1fd988a88d..ac30e46610 100644
--- a/lib/minitasn1/element.c
+++ b/lib/minitasn1/element.c
@@ -112,8 +112,11 @@ _asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
/* VALUE_OUT is too short to contain the value conversion */
return ASN1_MEM_ERROR;
- for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
- value_out[k2 - k] = val[k2];
+ if (value_out != NULL)
+ {
+ for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
+ value_out[k2 - k] = val[k2];
+ }
#if 0
printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len);
@@ -130,7 +133,7 @@ int
_asn1_append_sequence_set (asn1_node node)
{
asn1_node p, p2;
- char temp[10];
+ char temp[LTOSTR_MAX_SIZE];
long n;
if (!node || !(node->down))
@@ -621,7 +624,7 @@ asn1_write_value (asn1_node node_root, const char *name,
if (ptr_size < data_size) { \
return ASN1_MEM_ERROR; \
} else { \
- if (ptr) \
+ if (ptr && data_size > 0) \
memcpy (ptr, data, data_size); \
}
@@ -631,8 +634,9 @@ asn1_write_value (asn1_node node_root, const char *name,
return ASN1_MEM_ERROR; \
} else { \
/* this strcpy is checked */ \
- if (ptr) \
+ if (ptr) { \
_asn1_strcpy (ptr, data); \
+ } \
}
#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
@@ -642,37 +646,41 @@ asn1_write_value (asn1_node node_root, const char *name,
} else { \
/* this strcpy is checked */ \
if (ptr) { \
- memcpy (ptr, data, data_size); \
+ if (data_size > 0) \
+ memcpy (ptr, data, data_size); \
ptr[data_size] = 0; \
} \
}
#define ADD_STR_VALUE( ptr, ptr_size, data) \
- *len = (int) _asn1_strlen (data) + 1; \
- if (ptr_size < (int) _asn1_strlen (ptr) + (*len)) { \
- return ASN1_MEM_ERROR; \
- } else { \
- /* this strcat is checked */ \
- if (ptr) _asn1_strcat (ptr, data); \
- }
+ *len += _asn1_strlen(data); \
+ if (ptr_size < (int) *len) { \
+ (*len)++; \
+ return ASN1_MEM_ERROR; \
+ } else { \
+ /* this strcat is checked */ \
+ if (ptr) _asn1_strcat (ptr, data); \
+ }
/**
* asn1_read_value:
* @root: pointer to a structure.
* @name: the name of the element inside a structure that you want to read.
* @ivalue: vector that will contain the element's content, must be a
- * pointer to memory cells already allocated.
+ * pointer to memory cells already allocated (may be %NULL).
* @len: number of bytes of *value: value[0]..value[len-1]. Initialy
* holds the sizeof value.
*
- * Returns the value of one element inside a structure.
- *
- * If an element is OPTIONAL and the function "read_value" returns
+ * Returns the value of one element inside a structure.
+ * If an element is OPTIONAL and this returns
* %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
* in the der encoding that created the structure. The first element
* of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
* so on.
*
+ * Note that there can be valid values with length zero. In these case
+ * this function will succeed and @len will be zero.
+ *
* INTEGER: VALUE will contain a two's complement form integer.
*
* integer=-1 -> value[0]=0xFF , len=1.
@@ -728,19 +736,22 @@ asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len)
* @root: pointer to a structure.
* @name: the name of the element inside a structure that you want to read.
* @ivalue: vector that will contain the element's content, must be a
- * pointer to memory cells already allocated.
+ * pointer to memory cells already allocated (may be %NULL).
* @len: number of bytes of *value: value[0]..value[len-1]. Initialy
* holds the sizeof value.
* @etype: The type of the value read (ASN1_ETYPE)
*
- * Returns the value of one element inside a structure.
- *
- * If an element is OPTIONAL and the function "read_value" returns
+ * Returns the value of one element inside a structure.
+ * If an element is OPTIONAL and this returns
* %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
* in the der encoding that created the structure. The first element
* of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
* so on.
*
+ * Note that there can be valid values with length zero. In these case
+ * this function will succeed and @len will be zero.
+ *
+ *
* INTEGER: VALUE will contain a two's complement form integer.
*
* integer=-1 -> value[0]=0xFF , len=1.
@@ -790,7 +801,7 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
int *len, unsigned int *etype)
{
asn1_node node, p, p2;
- int len2, len3;
+ int len2, len3, result;
int value_size = *len;
unsigned char *value = ivalue;
unsigned type;
@@ -848,9 +859,10 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
if ((isdigit (p->value[0])) || (p->value[0] == '-')
|| (p->value[0] == '+'))
{
- if (_asn1_convert_integer
- (p->value, value, value_size, len) != ASN1_SUCCESS)
- return ASN1_MEM_ERROR;
+ result = _asn1_convert_integer
+ (p->value, value, value_size, len);
+ if (result != ASN1_SUCCESS)
+ return result;
}
else
{ /* is an identifier like v1 */
@@ -861,10 +873,11 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
{
if (!_asn1_strcmp (p2->name, p->value))
{
- if (_asn1_convert_integer
+ result = _asn1_convert_integer
(p2->value, value, value_size,
- len) != ASN1_SUCCESS)
- return ASN1_MEM_ERROR;
+ len);
+ if (result != ASN1_SUCCESS)
+ return result;
break;
}
}
@@ -875,16 +888,19 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
else
{
len2 = -1;
- if (asn1_get_octet_der
+ result = asn1_get_octet_der
(node->value, node->value_len, &len2, value, value_size,
- len) != ASN1_SUCCESS)
- return ASN1_MEM_ERROR;
+ len);
+ if (result != ASN1_SUCCESS)
+ return result;
}
break;
case ASN1_ETYPE_OBJECT_ID:
if (node->type & CONST_ASSIGN)
{
- value[0] = 0;
+ *len = 0;
+ if (value)
+ value[0] = 0;
p = node->down;
while (p)
{
@@ -898,7 +914,7 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
}
p = p->right;
}
- *len = _asn1_strlen (value) + 1;
+ (*len)++;
}
else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
{
@@ -927,17 +943,19 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
case ASN1_ETYPE_UTF8_STRING:
case ASN1_ETYPE_VISIBLE_STRING:
len2 = -1;
- if (asn1_get_octet_der
+ result = asn1_get_octet_der
(node->value, node->value_len, &len2, value, value_size,
- len) != ASN1_SUCCESS)
- return ASN1_MEM_ERROR;
+ len);
+ if (result != ASN1_SUCCESS)
+ return result;
break;
case ASN1_ETYPE_BIT_STRING:
len2 = -1;
- if (asn1_get_bit_der
+ result = asn1_get_bit_der
(node->value, node->value_len, &len2, value, value_size,
- len) != ASN1_SUCCESS)
- return ASN1_MEM_ERROR;
+ len);
+ if (result != ASN1_SUCCESS)
+ return result;
break;
case ASN1_ETYPE_CHOICE:
PUT_STR_VALUE (value, value_size, node->down->name);
diff --git a/lib/minitasn1/gstr.h b/lib/minitasn1/gstr.h
index 51db059489..00c335ca93 100644
--- a/lib/minitasn1/gstr.h
+++ b/lib/minitasn1/gstr.h
@@ -25,3 +25,18 @@ void _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src);
#define Estrcpy(x,y) _asn1_str_cpy(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
#define Estrcat(x,y) _asn1_str_cat(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
+
+inline static
+void safe_memset(void *data, int c, size_t size)
+{
+ volatile unsigned volatile_zero = 0;
+ volatile char *vdata = (volatile char*)data;
+
+ /* This is based on a nice trick for safe memset,
+ * sent by David Jacobson in the openssl-dev mailing list.
+ */
+
+ if (size > 0) do {
+ memset(data, c, size);
+ } while(vdata[volatile_zero] != c);
+}
diff --git a/lib/minitasn1/libtasn1.h b/lib/minitasn1/libtasn1.h
index 92ae54eb4e..a4570682e0 100644
--- a/lib/minitasn1/libtasn1.h
+++ b/lib/minitasn1/libtasn1.h
@@ -44,7 +44,18 @@ extern "C"
{
#endif
-#define ASN1_VERSION "3.5"
+#define ASN1_VERSION "3.6"
+
+#if defined(__GNUC__) && !defined(ASN1_INTERNAL_BUILD)
+# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+# if _ASN1_GCC_VERSION >= 30100
+# define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
+# endif
+#endif
+
+#ifndef _ASN1_GCC_ATTR_DEPRECATED
+#define _ASN1_GCC_ATTR_DEPRECATED
+#endif
/*****************************************/
/* Errors returned by libtasn1 functions */
@@ -251,11 +262,12 @@ extern "C"
asn1_der_decoding (asn1_node * element, const void *ider,
int len, char *errorDescription);
+ /* Do not use. Use asn1_der_decoding() instead. */
extern ASN1_API int
asn1_der_decoding_element (asn1_node * structure,
const char *elementName,
const void *ider, int len,
- char *errorDescription);
+ char *errorDescription) _ASN1_GCC_ATTR_DEPRECATED;
extern ASN1_API int
asn1_der_decoding_startEnd (asn1_node element,
diff --git a/lib/minitasn1/parser_aux.c b/lib/minitasn1/parser_aux.c
index b5f665db4c..effedb2366 100644
--- a/lib/minitasn1/parser_aux.c
+++ b/lib/minitasn1/parser_aux.c
@@ -458,11 +458,16 @@ _asn1_remove_node (asn1_node node, unsigned int flags)
if (node == NULL)
return;
- if (flags & ASN1_DELETE_FLAG_ZEROIZE)
- memset(node->value, 0, node->value_len);
+ if (node->value != NULL)
+ {
+ if (flags & ASN1_DELETE_FLAG_ZEROIZE)
+ {
+ safe_memset(node->value, 0, node->value_len);
+ }
- if (node->value != NULL && node->value != node->small_value)
- free (node->value);
+ if (node->value != node->small_value)
+ free (node->value);
+ }
free (node);
}
@@ -531,7 +536,7 @@ char *
_asn1_ltostr (long v, char *str)
{
long d, r;
- char temp[20];
+ char temp[LTOSTR_MAX_SIZE];
int count, k, start;
if (v < 0)
diff --git a/lib/minitasn1/parser_aux.h b/lib/minitasn1/parser_aux.h
index bf378527fe..1f1aec2637 100644
--- a/lib/minitasn1/parser_aux.h
+++ b/lib/minitasn1/parser_aux.h
@@ -22,8 +22,6 @@
#ifndef _PARSER_AUX_H
#define _PARSER_AUX_H
-#define DER_LEN 16
-
/***************************************/
/* Functions used by ASN.1 parser */
/***************************************/
@@ -54,6 +52,7 @@ void _asn1_delete_list (void);
void _asn1_delete_list_and_nodes (void);
+#define LTOSTR_MAX_SIZE 20
char *_asn1_ltostr (long v, char *str);
asn1_node _asn1_find_up (asn1_node node);