summaryrefslogtreecommitdiff
path: root/lib/minitasn1
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-06-26 14:25:40 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-06-26 14:25:40 +0200
commit6079b0d6761619169f4462c6892d49f82d64fc75 (patch)
treea08d265baa8b7f7efdf15c2312d3671e72d5a9e8 /lib/minitasn1
parent0010600abd68d1fcd6273d6073c5c0b35ed6de11 (diff)
downloadgnutls-6079b0d6761619169f4462c6892d49f82d64fc75.tar.gz
minitasn1: updated to version 4.0
Diffstat (limited to 'lib/minitasn1')
-rw-r--r--lib/minitasn1/coding.c29
-rw-r--r--lib/minitasn1/decoding.c532
-rw-r--r--lib/minitasn1/element.c41
-rw-r--r--lib/minitasn1/element.h2
-rw-r--r--lib/minitasn1/int.h6
-rw-r--r--lib/minitasn1/libtasn1.h12
-rw-r--r--lib/minitasn1/parser_aux.c36
-rw-r--r--lib/minitasn1/parser_aux.h13
-rw-r--r--lib/minitasn1/structure.c50
9 files changed, 244 insertions, 477 deletions
diff --git a/lib/minitasn1/coding.c b/lib/minitasn1/coding.c
index d6b7cf4114..2dd80ba419 100644
--- a/lib/minitasn1/coding.c
+++ b/lib/minitasn1/coding.c
@@ -493,6 +493,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der,
{
len2 = strtol (p->name, NULL, 10);
_asn1_set_name (p, NULL);
+
asn1_length_der (*counter - len2, temp, &len3);
if (len3 <= (*max_len))
{
@@ -1013,7 +1014,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
{
asn1_node node, p, p2;
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 counter, counter_old, len2, len3, move, max_len, max_len_old;
int err;
unsigned char *der = ider;
@@ -1034,6 +1035,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
counter = 0;
move = DOWN;
p = node;
+
while (1)
{
@@ -1041,6 +1043,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
max_len_old = max_len;
if (move != UP)
{
+ p->start = counter;
err = _asn1_insert_tag_der (p, der, &counter, &max_len);
if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
goto error;
@@ -1187,10 +1190,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
case ASN1_ETYPE_SET:
if (move != UP)
{
- _asn1_ltostr (counter, (char *) temp);
- tlen = _asn1_strlen (temp);
- if (tlen > 0)
- _asn1_set_value (p, temp, tlen + 1);
+ p->tmp_ival = counter;
if (p->down == NULL)
{
move = UP;
@@ -1213,8 +1213,8 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
}
else
{ /* move==UP */
- len2 = _asn1_strtol (p->value, NULL, 10);
- _asn1_set_value (p, NULL, 0);
+ len2 = p->tmp_ival;
+ p->tmp_ival = 0;
if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0))
{
err = _asn1_ordering_set (der + len2, counter - len2, p);
@@ -1236,11 +1236,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
case ASN1_ETYPE_SET_OF:
if (move != UP)
{
- _asn1_ltostr (counter, (char *) temp);
- tlen = _asn1_strlen (temp);
-
- if (tlen > 0)
- _asn1_set_value (p, temp, tlen + 1);
+ p->tmp_ival = counter;
p = p->down;
while ((type_field (p->type) == ASN1_ETYPE_TAG)
|| (type_field (p->type) == ASN1_ETYPE_SIZE))
@@ -1252,13 +1248,13 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
continue;
}
else
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
move = UP;
}
if (move == UP)
{
- len2 = _asn1_strtol (p->value, NULL, 10);
- _asn1_set_value (p, NULL, 0);
+ len2 = p->tmp_ival;
+ p->tmp_ival = 0;
if ((type_field (p->type) == ASN1_ETYPE_SET_OF)
&& (counter - len2 > 0) && (max_len >= 0))
{
@@ -1303,6 +1299,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
if ((move != DOWN) && (counter != counter_old))
{
+ p->end = counter - 1;
err = _asn1_complete_explicit_tag (p, der, &counter, &max_len);
if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
goto error;
@@ -1326,7 +1323,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
move = UP;
}
if (move == UP)
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
}
*len = counter;
diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c
index a9aecc254b..b7e49b4af3 100644
--- a/lib/minitasn1/decoding.c
+++ b/lib/minitasn1/decoding.c
@@ -622,7 +622,7 @@ _asn1_delete_not_used (asn1_node node)
{
p2 = _asn1_find_left (p);
if (!p2)
- p2 = _asn1_find_up (p);
+ p2 = _asn1_get_up (p);
}
asn1_delete_structure (&p);
p = p2;
@@ -645,7 +645,7 @@ _asn1_delete_not_used (asn1_node node)
{
while (1)
{
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
if (p == node)
{
p = NULL;
@@ -871,20 +871,23 @@ static void delete_unneeded_choice_fields(asn1_node p)
}
-
/**
- * asn1_der_decoding:
+ * asn1_der_decoding2
* @element: pointer to an ASN1 structure.
* @ider: vector that contains the DER encoding.
- * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+ * @max_ider_len: pointer to an integer giving the information about the
+ * maximal number of bytes occupied by *@ider. The real size of the DER
+ * encoding is returned through this pointer.
+ * @flags: flags controlling the behaviour of the function.
* @errorDescription: null-terminated string contains details when an
* error occurred.
*
- * Fill the structure *@ELEMENT with values of a DER encoding
- * string. The structure must just be created with function
- * asn1_create_element(). If an error occurs during the decoding
- * procedure, the *@ELEMENT is deleted and set equal to
- * %NULL.
+ * Fill the structure *@element with values of a DER encoding string. The
+ * structure must just be created with function asn1_create_element().
+ *
+ * If %ASN1_DECODE_FLAG_ALLOW_PADDING flag is set then the function will ignore
+ * padding after the decoded DER data. Upon a successful return the value of
+ * *@max_ider_len will be set to the number of bytes decoded.
*
* Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
* if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or
@@ -892,15 +895,16 @@ static void delete_unneeded_choice_fields(asn1_node p)
* name (*@ELEMENT deleted).
**/
int
-asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
- char *errorDescription)
+asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
+ unsigned int flags, char *errorDescription)
{
asn1_node node, p, p2, p3;
char temp[128];
int counter, len2, len3, len4, move, ris, tlen;
+ asn1_node ptail = NULL;
unsigned char class;
unsigned long tag;
- int indefinite, result;
+ int indefinite, result, total_len = *max_ider_len, ider_len = *max_ider_len;
const unsigned char *der = ider;
node = *element;
@@ -928,8 +932,8 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
{
if (p->type & CONST_SET)
{
- p2 = _asn1_find_up (p);
- len2 = _asn1_strtol (p2->value, NULL, 10);
+ p2 = _asn1_get_up (p);
+ len2 = p2->tmp_ival;
if (len2 == -1)
{
if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
@@ -978,10 +982,14 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
}
}
+ /* the position in the DER structure this starts */
+ p->start = counter;
+ p->end = total_len - 1;
+
if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
{
- p2 = _asn1_find_up (p);
- len2 = _asn1_strtol (p2->value, NULL, 10);
+ p2 = _asn1_get_up (p);
+ len2 = p2->tmp_ival;
if (counter == len2)
{
if (p->right)
@@ -1037,12 +1045,14 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
}
else if (type_field (p->type) != ASN1_ETYPE_CHOICE)
p = p->down;
+
+ p->start = counter;
}
if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
{
- p2 = _asn1_find_up (p);
- len2 = _asn1_strtol (p2->value, NULL, 10);
+ p2 = _asn1_get_up (p);
+ len2 = p2->tmp_ival;
if ((len2 != -1) && (counter > len2))
ris = ASN1_TAG_ERROR;
@@ -1208,8 +1218,8 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
case ASN1_ETYPE_SET:
if (move == UP)
{
- len2 = _asn1_strtol (p->value, NULL, 10);
- _asn1_set_value (p, NULL, 0);
+ len2 = p->tmp_ival;
+ p->tmp_ival = 0;
if (len2 == -1)
{ /* indefinite length method */
DECR_LEN(ider_len, 2);
@@ -1248,10 +1258,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
if (len3 > 0)
{
- _asn1_ltostr (counter + len3, temp);
- tlen = strlen (temp);
- if (tlen > 0)
- _asn1_set_value (p, temp, tlen + 1);
+ p->tmp_ival = counter + len3;
move = DOWN;
}
else if (len3 == 0)
@@ -1272,7 +1279,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
}
else
{ /* indefinite length method */
- _asn1_set_value (p, "-1", 3);
+ p->tmp_ival = -1;
move = DOWN;
}
}
@@ -1281,20 +1288,19 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
case ASN1_ETYPE_SET_OF:
if (move == UP)
{
- len2 = _asn1_strtol (p->value, NULL, 10);
+ len2 = p->tmp_ival;
if (len2 == -1)
{ /* indefinite length method */
if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1]))
{
- _asn1_append_sequence_set (p);
- p = p->down;
- while (p->right)
- p = p->right;
+ _asn1_append_sequence_set (p, &ptail);
+ p = ptail;
move = RIGHT;
continue;
}
- _asn1_set_value (p, NULL, 0);
+ p->tmp_ival = 0;
+ ptail = NULL; /* finished decoding this structure */
DECR_LEN(ider_len, 2);
counter += 2;
}
@@ -1302,15 +1308,15 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
{ /* definite length method */
if (len2 > counter)
{
- _asn1_append_sequence_set (p);
- p = p->down;
- while (p->right)
- p = p->right;
+ _asn1_append_sequence_set (p, &ptail);
+ p = ptail;
move = RIGHT;
continue;
}
- _asn1_set_value (p, NULL, 0);
+ p->tmp_ival = 0;
+ ptail = NULL; /* finished decoding this structure */
+
if (len2 != counter)
{
result = ASN1_DER_ERROR;
@@ -1336,22 +1342,18 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
{
if (len3 > 0)
{ /* definite length method */
- _asn1_ltostr (counter + len3, temp);
- tlen = strlen (temp);
-
- if (tlen > 0)
- _asn1_set_value (p, temp, tlen + 1);
+ p->tmp_ival = counter + len3;
}
else
{ /* indefinite length method */
- _asn1_set_value (p, "-1", 3);
+ p->tmp_ival = -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);
+ _asn1_append_sequence_set (p, &ptail);
p = p2;
}
}
@@ -1440,6 +1442,11 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
}
}
+ if (p)
+ {
+ p->end = counter - 1;
+ }
+
if (p == node && move != DOWN)
break;
@@ -1458,18 +1465,21 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
move = UP;
}
if (move == UP)
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
}
_asn1_delete_not_used (*element);
- if (ider_len != 0)
+ if ((ider_len < 0) ||
+ (!(flags & ASN1_DECODE_FLAG_ALLOW_PADDING) && (ider_len != 0)))
{
warn();
result = ASN1_DER_ERROR;
goto cleanup;
}
+ *max_ider_len = total_len - ider_len;
+
return ASN1_SUCCESS;
cleanup:
@@ -1477,6 +1487,34 @@ cleanup:
return result;
}
+
+/**
+ * asn1_der_decoding:
+ * @element: pointer to an ASN1 structure.
+ * @ider: vector that contains the DER encoding.
+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+ * @errorDescription: null-terminated string contains details when an
+ * error occurred.
+ *
+ * Fill the structure *@element with values of a DER encoding
+ * string. The structure must just be created with function
+ * asn1_create_element().
+ *
+ * Note that the *@element variable is provided as a pointer for
+ * historical reasons.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+ * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or
+ * %ASN1_DER_ERROR if the der encoding doesn't match the structure
+ * name (*@ELEMENT deleted).
+ **/
+int
+asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
+ char *errorDescription)
+{
+ return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription);
+}
+
#define FOUND 1
#define SAME_BRANCH 2
#define OTHER_BRANCH 3
@@ -1533,6 +1571,9 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName,
* One example is the sequence "tbsCertificate" inside an X509
* certificate.
*
+ * Note that since libtasn1 3.7 the @ider and @ider_len parameters
+ * can be omitted, if the element is already decoded using asn1_der_decoding().
+ *
* Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
* if ELEMENT is %asn1_node EMPTY or @name_element is not a valid
* element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding
@@ -1542,12 +1583,8 @@ int
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, result = ASN1_DER_ERROR;
- const unsigned char *der = ider;
+ asn1_node node, node_to_find;
+ int result = ASN1_DER_ERROR;
node = element;
@@ -1559,377 +1596,34 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len,
if (node_to_find == NULL)
return ASN1_ELEMENT_NOT_FOUND;
- if (node_to_find == node)
- {
- *start = 0;
- *end = ider_len - 1;
- return ASN1_SUCCESS;
- }
-
- if (node->type & CONST_OPTION)
- return ASN1_GENERIC_ERROR;
+ *start = node_to_find->start;
+ *end = node_to_find->end;
- counter = 0;
- move = DOWN;
- p = node;
- while (1)
+ if (*start == 0 && *end == 0)
{
- if (p == NULL)
- return ASN1_DER_ERROR;
-
- ris = ASN1_SUCCESS;
-
- if (move != UP)
- {
- if (p->type & CONST_SET)
- {
- p2 = _asn1_find_up (p);
- if (p2 == NULL)
- {
- warn();
- return ASN1_DER_ERROR;
- }
-
- len2 = _asn1_strtol (p2->value, NULL, 10);
- if (len2 == -1)
- {
- if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
- {
- p = p2;
- move = UP;
- counter += 2;
- DECR_LEN(ider_len, 2);
- continue;
- }
- }
- else if (counter == len2)
- {
- p = p2;
- move = UP;
- continue;
- }
- else if (counter > len2)
- {
- warn();
- return ASN1_DER_ERROR;
- }
-
- p2 = p2->down;
-
- while (p2)
- {
- if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
- { /* CONTROLLARE */
- ris =
- extract_tag_der_recursive (p2, der + counter,
- ider_len, &len2);
- if (ris == ASN1_SUCCESS)
- {
- p2->type &= ~CONST_NOT_USED;
- p = p2;
- break;
- }
- }
- p2 = p2->right;
- }
- if (p2 == NULL)
- {
- warn();
- return ASN1_DER_ERROR;
- }
- }
-
- if (p == node_to_find)
- *start = counter;
-
- if (type_field (p->type) == ASN1_ETYPE_CHOICE)
- {
- p = p->down;
- if (p == NULL)
- {
- warn();
- return ASN1_DER_ERROR;
- }
-
- ris =
- _asn1_extract_tag_der (p, der + counter, ider_len,
- &len2);
- if (p == node_to_find)
- *start = counter;
- }
-
- if (ris == ASN1_SUCCESS)
- ris =
- _asn1_extract_tag_der (p, der + counter, ider_len, &len2);
- if (ris != ASN1_SUCCESS)
- {
- if (p->type & CONST_OPTION)
- {
- p->type |= CONST_NOT_USED;
- move = RIGHT;
- }
- else if (p->type & CONST_DEFAULT)
- {
- move = RIGHT;
- }
- else
- {
- warn();
- return ASN1_TAG_ERROR;
- }
- }
- else
- {
- DECR_LEN(ider_len, len2);
- counter += len2;
- }
- }
-
- if (ris == ASN1_SUCCESS)
- {
- switch (type_field (p->type))
- {
- case ASN1_ETYPE_NULL:
- DECR_LEN(ider_len, 1);
-
- if (der[counter])
- {
- warn();
- return ASN1_DER_ERROR;
- }
- counter++;
- move = RIGHT;
- break;
- case ASN1_ETYPE_BOOLEAN:
- DECR_LEN(ider_len, 2);
-
- if (der[counter] != 1)
- {
- warn();
- return ASN1_DER_ERROR;
- }
-
- counter += 2;
- move = RIGHT;
- break;
- case ASN1_ETYPE_OCTET_STRING:
- ris = _asn1_get_octet_string (NULL, der + counter, ider_len, &len3);
- if (ris != ASN1_SUCCESS)
- {
- warn();
- return ris;
- }
- DECR_LEN(ider_len, len3);
- counter += len3;
- move = RIGHT;
- break;
- case ASN1_ETYPE_UTC_TIME:
- case ASN1_ETYPE_GENERALIZED_TIME:
- case ASN1_ETYPE_OBJECT_ID:
- case ASN1_ETYPE_INTEGER:
- case ASN1_ETYPE_ENUMERATED:
- 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, ider_len, &len3);
- if (len2 < 0)
- {
- warn();
- return ASN1_DER_ERROR;
- }
-
- DECR_LEN(ider_len, len3 + len2);
- counter += len3 + len2;
- move = RIGHT;
- break;
- case ASN1_ETYPE_SEQUENCE:
- case ASN1_ETYPE_SET:
- if (move != UP)
- {
- len3 =
- asn1_get_length_der (der + counter, ider_len, &len2);
- if (len3 < -1)
- {
- warn();
- return ASN1_DER_ERROR;
- }
-
- DECR_LEN(ider_len, len2);
- counter += len2;
-
- if (len3 == 0)
- move = RIGHT;
- else
- move = DOWN;
- }
- else
- {
- if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) /* indefinite length method */
- {
- counter += 2;
- DECR_LEN(ider_len, 2);
- }
- move = RIGHT;
- }
- break;
- case ASN1_ETYPE_SEQUENCE_OF:
- case ASN1_ETYPE_SET_OF:
- if (move != UP)
- {
- len3 =
- asn1_get_length_der (der + counter, ider_len, &len2);
- if (len3 < -1)
- {
- warn();
- return ASN1_DER_ERROR;
- }
-
- DECR_LEN(ider_len, len2);
- counter += len2;
-
- 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) ||
- (type_field (p2->type) == ASN1_ETYPE_SIZE))
- p2 = p2->right;
- p = p2;
- }
- }
- else
- {
- 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, ider_len, &class, &len2,
- &tag) != ASN1_SUCCESS)
- {
- warn();
- return ASN1_DER_ERROR;
- }
-
- DECR_LEN(ider_len, len2);
+ if (ider == NULL || ider_len == 0)
+ return ASN1_GENERIC_ERROR;
- len4 =
- asn1_get_length_der (der + counter + len2,
- ider_len, &len3);
- if (len4 < -1)
- {
- warn();
- return ASN1_DER_ERROR;
- }
-
- if (len4 != -1)
- {
- 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;
-
- ris =
- _asn1_get_indefinite_length_string (der + counter, ider_len, &len2);
- if (ris != ASN1_SUCCESS)
- {
- 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
- {
- warn();
- return ASN1_DER_ERROR;
- }
- }
- }
- move = RIGHT;
- break;
- default:
- move = (move == UP) ? RIGHT : DOWN;
- break;
- }
- }
-
- if ((p == node_to_find) && (move == RIGHT))
- {
- *end = counter - 1;
- return ASN1_SUCCESS;
- }
+ /* it seems asn1_der_decoding() wasn't called before. Do it now */
+ result = asn1_der_decoding (&node, ider, ider_len, NULL);
+ if (result != ASN1_SUCCESS)
+ {
+ warn();
+ return result;
+ }
- if (p == node && move != DOWN)
- break;
+ node_to_find = asn1_find_node (node, name_element);
+ if (node_to_find == NULL)
+ return ASN1_ELEMENT_NOT_FOUND;
- if (move == DOWN)
- {
- if (p->down)
- p = p->down;
- else
- move = RIGHT;
- }
- if ((move == RIGHT) && !(p->type & CONST_SET))
- {
- if (p->right)
- p = p->right;
- else
- move = UP;
- }
- if (move == UP)
- p = _asn1_find_up (p);
+ *start = node_to_find->start;
+ *end = node_to_find->end;
}
- warn();
- return ASN1_ELEMENT_NOT_FOUND;
+ if (*end < *start)
+ return ASN1_GENERIC_ERROR;
-cleanup:
- return result;
+ return ASN1_SUCCESS;
}
/**
@@ -1984,7 +1678,7 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
break;
}
- p3 = _asn1_find_up (p);
+ p3 = _asn1_get_up (p);
if (!p3)
{
@@ -2004,8 +1698,8 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
(p3->value == NULL))
{
- p3 = _asn1_find_up (p);
- p3 = _asn1_find_up (p3);
+ p3 = _asn1_get_up (p);
+ p3 = _asn1_get_up (p3);
if (!p3)
{
@@ -2140,7 +1834,7 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
{
while (1)
{
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
if (p == *element)
{
p = NULL;
diff --git a/lib/minitasn1/element.c b/lib/minitasn1/element.c
index ac30e46610..321302af06 100644
--- a/lib/minitasn1/element.c
+++ b/lib/minitasn1/element.c
@@ -52,7 +52,7 @@ _asn1_hierarchical_name (asn1_node node, char *name, int name_size)
_asn1_str_cat (name, name_size, ".");
_asn1_str_cat (name, name_size, tmp_name);
}
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
}
if (name[0] == 0)
@@ -128,9 +128,18 @@ _asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
return ASN1_SUCCESS;
}
-
+/* Appends a new element into the sequent (or set) defined by this
+ * node. The new element will have a name of '?number', where number
+ * is a monotonically increased serial number.
+ *
+ * The last element in the list may be provided in @ptail, to avoid
+ * traversing the list, an expensive operation in long lists.
+ *
+ * On success it returns in @ptail the added element (which is the
+ * tail in the list of added elements).
+ */
int
-_asn1_append_sequence_set (asn1_node node)
+_asn1_append_sequence_set (asn1_node node, asn1_node *ptail)
{
asn1_node p, p2;
char temp[LTOSTR_MAX_SIZE];
@@ -144,9 +153,19 @@ _asn1_append_sequence_set (asn1_node node)
|| (type_field (p->type) == ASN1_ETYPE_SIZE))
p = p->right;
p2 = _asn1_copy_structure3 (p);
- while (p->right)
- p = p->right;
+
+ if (ptail == NULL || *ptail == NULL || (*ptail)->up != p->up)
+ while (p->right) {
+ p = p->right;
+ }
+ else
+ {
+ p = *ptail;
+ }
+
_asn1_set_right (p, p2);
+ if (ptail)
+ *ptail = p2;
if (p->name[0] == 0)
_asn1_str_cpy (temp, sizeof (temp), "?1");
@@ -608,7 +627,7 @@ asn1_write_value (asn1_node node_root, const char *name,
case ASN1_ETYPE_SET_OF:
if (_asn1_strcmp (value, "NEW"))
return ASN1_VALUE_NOT_VALID;
- _asn1_append_sequence_set (node);
+ _asn1_append_sequence_set (node, NULL);
break;
default:
return ASN1_ELEMENT_NOT_FOUND;
@@ -676,7 +695,9 @@ asn1_write_value (asn1_node node_root, const char *name,
* %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.
+ * so on. If the @root provided is a node to specific sequence element,
+ * then the keyword "?CURRENT" is also acceptable and indicates the
+ * current sequence element of this node.
*
* Note that there can be valid values with length zero. In these case
* this function will succeed and @len will be zero.
@@ -741,12 +762,14 @@ asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len)
* holds the sizeof value.
* @etype: The type of the value read (ASN1_ETYPE)
*
- * Returns the value of one element inside a structure.
+ * Returns the type and 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.
+ * so on. If the @root provided is a node to specific sequence element,
+ * then the keyword "?CURRENT" is also acceptable and indicates the
+ * current sequence element of this node.
*
* Note that there can be valid values with length zero. In these case
* this function will succeed and @len will be zero.
diff --git a/lib/minitasn1/element.h b/lib/minitasn1/element.h
index fdecafb611..65a4845699 100644
--- a/lib/minitasn1/element.h
+++ b/lib/minitasn1/element.h
@@ -23,7 +23,7 @@
#define _ELEMENT_H
-int _asn1_append_sequence_set (asn1_node node);
+int _asn1_append_sequence_set (asn1_node node, asn1_node *pcached);
int _asn1_convert_integer (const unsigned char *value,
unsigned char *value_out,
diff --git a/lib/minitasn1/int.h b/lib/minitasn1/int.h
index 3701e5f645..8cc79cca2e 100644
--- a/lib/minitasn1/int.h
+++ b/lib/minitasn1/int.h
@@ -51,11 +51,17 @@ struct asn1_node_st
unsigned int type; /* Node type */
unsigned char *value; /* Node value */
int value_len;
+ asn1_node up; /* Pointer to the parent node */
asn1_node down; /* Pointer to the son node */
asn1_node right; /* Pointer to the brother node */
asn1_node left; /* Pointer to the next list element */
/* private fields: */
unsigned char small_value[ASN1_SMALL_VALUE_SIZE]; /* For small values */
+
+ /* values used during decoding/coding */
+ int tmp_ival;
+ unsigned start; /* the start of the DER sequence - if decoded */
+ unsigned end; /* the end of the DER sequence - if decoded */
};
typedef struct tag_and_class_st
diff --git a/lib/minitasn1/libtasn1.h b/lib/minitasn1/libtasn1.h
index a4570682e0..8f7ff0b262 100644
--- a/lib/minitasn1/libtasn1.h
+++ b/lib/minitasn1/libtasn1.h
@@ -44,7 +44,7 @@ extern "C"
{
#endif
-#define ASN1_VERSION "3.6"
+#define ASN1_VERSION "4.0"
#if defined(__GNUC__) && !defined(ASN1_INTERNAL_BUILD)
# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
@@ -184,6 +184,9 @@ extern "C"
/* makes sure the values are zeroized prior to deinitialization */
#define ASN1_DELETE_FLAG_ZEROIZE 1
+/* Flags used by asn1_der_decoding2(). */
+#define ASN1_DECODE_FLAG_ALLOW_PADDING 1
+
struct asn1_data_node_st
{
@@ -259,6 +262,11 @@ extern "C"
void *ider, int *len, char *ErrorDescription);
extern ASN1_API int
+ asn1_der_decoding2 (asn1_node *element, const void *ider,
+ int *max_ider_len, unsigned int flags,
+ char *errorDescription);
+
+ extern ASN1_API int
asn1_der_decoding (asn1_node * element, const void *ider,
int len, char *errorDescription);
@@ -329,6 +337,8 @@ extern "C"
extern ASN1_API int
asn1_copy_node (asn1_node dst, const char *dst_name,
asn1_node src, const char *src_name);
+ extern ASN1_API asn1_node
+ asn1_dup_node (asn1_node src, const char *src_name);
/* Internal and low-level DER utility functions. */
diff --git a/lib/minitasn1/parser_aux.c b/lib/minitasn1/parser_aux.c
index effedb2366..4b150009aa 100644
--- a/lib/minitasn1/parser_aux.c
+++ b/lib/minitasn1/parser_aux.c
@@ -108,7 +108,13 @@ asn1_find_node (asn1_node pointer, const char *name)
p = pointer;
n_start = name;
- if (p->name[0] != 0)
+ if (name[0] == '?' && name[1] == 'C' && p->name[0] == '?')
+ { /* ?CURRENT */
+ n_start = strchr(n_start, '.');
+ if (n_start)
+ n_start++;
+ }
+ else if (p->name[0] != 0)
{ /* has *pointer got a name ? */
n_end = strchr (n_start, '.'); /* search the first dot */
if (n_end)
@@ -170,13 +176,13 @@ asn1_find_node (asn1_node pointer, const char *name)
return NULL;
p = p->down;
+ if (p == NULL)
+ return NULL;
/* The identifier "?LAST" indicates the last element
in the right chain. */
- if (!strcmp (n, "?LAST"))
+ if (n[0] == '?' && n[1] == 'L') /* ?LAST */
{
- if (p == NULL)
- return NULL;
while (p->right)
p = p->right;
}
@@ -189,9 +195,9 @@ asn1_find_node (asn1_node pointer, const char *name)
else
p = p->right;
}
- if (p == NULL)
- return NULL;
}
+ if (p == NULL)
+ return NULL;
} /* while */
return p;
@@ -419,7 +425,11 @@ _asn1_set_right (asn1_node node, asn1_node right)
return node;
node->right = right;
if (right)
- right->left = node;
+ {
+ right->left = node;
+ if (right->up == NULL)
+ right->up = node->up;
+ }
return node;
}
@@ -615,7 +625,7 @@ _asn1_change_integer_value (asn1_node node)
{
while (1)
{
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
if (p == node)
{
p = NULL;
@@ -740,7 +750,7 @@ _asn1_expand_object_id (asn1_node node)
move = UP;
}
if (move == UP)
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
}
@@ -812,7 +822,7 @@ _asn1_expand_object_id (asn1_node node)
move = UP;
}
if (move == UP)
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
}
return ASN1_SUCCESS;
@@ -882,7 +892,7 @@ _asn1_type_set_config (asn1_node node)
move = UP;
}
if (move == UP)
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
}
return ASN1_SUCCESS;
@@ -979,7 +989,7 @@ _asn1_check_identifier (asn1_node node)
{
while (1)
{
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
if (p == node)
{
p = NULL;
@@ -1039,7 +1049,7 @@ _asn1_set_default_tag (asn1_node node)
{
while (1)
{
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
if (p == node)
{
p = NULL;
diff --git a/lib/minitasn1/parser_aux.h b/lib/minitasn1/parser_aux.h
index 1f1aec2637..55d9061917 100644
--- a/lib/minitasn1/parser_aux.h
+++ b/lib/minitasn1/parser_aux.h
@@ -57,6 +57,14 @@ char *_asn1_ltostr (long v, char *str);
asn1_node _asn1_find_up (asn1_node node);
+inline static asn1_node _asn1_get_up(asn1_node node)
+{
+ if (node && node->up)
+ return node->up;
+ else
+ return _asn1_find_up(node);
+}
+
int _asn1_change_integer_value (asn1_node node);
int _asn1_expand_object_id (asn1_node node);
@@ -99,7 +107,10 @@ _asn1_set_down (asn1_node node, asn1_node down)
return node;
node->down = down;
if (down)
- down->left = node;
+ {
+ down->left = node;
+ down->up = node;
+ }
return node;
}
diff --git a/lib/minitasn1/structure.c b/lib/minitasn1/structure.c
index 27fbfe3a22..ffb6aa5092 100644
--- a/lib/minitasn1/structure.c
+++ b/lib/minitasn1/structure.c
@@ -134,7 +134,7 @@ _asn1_create_static_structure (asn1_node pointer, char *output_file_name,
{
while (1)
{
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
if (p == pointer)
{
p = NULL;
@@ -221,7 +221,7 @@ asn1_array2tree (const asn1_static_node * array, asn1_node * definitions,
if (p_last == *definitions)
break;
- p_last = _asn1_find_up (p_last);
+ p_last = _asn1_get_up (p_last);
if (p_last == NULL)
break;
@@ -321,7 +321,7 @@ asn1_delete_structure2 (asn1_node * structure, unsigned int flags)
p2 = p->right;
if (p != *structure)
{
- p3 = _asn1_find_up (p);
+ p3 = _asn1_get_up (p);
_asn1_set_down (p3, p2);
_asn1_remove_node (p, flags);
p = p3;
@@ -331,7 +331,7 @@ asn1_delete_structure2 (asn1_node * structure, unsigned int flags)
p3 = _asn1_find_left (p);
if (!p3)
{
- p3 = _asn1_find_up (p);
+ p3 = _asn1_get_up (p);
if (p3)
_asn1_set_down (p3, p2);
else
@@ -379,7 +379,7 @@ asn1_delete_element (asn1_node structure, const char *element_name)
p3 = _asn1_find_left (source_node);
if (!p3)
{
- p3 = _asn1_find_up (source_node);
+ p3 = _asn1_get_up (source_node);
if (p3)
_asn1_set_down (p3, p2);
else if (source_node->right)
@@ -423,6 +423,8 @@ _asn1_copy_structure3 (asn1_node source_node)
_asn1_set_down (p_d_prev, p_d);
continue;
}
+ p_d->start = p_s->start;
+ p_d->end = p_s->end;
}
if (p_s == source_node)
@@ -439,8 +441,8 @@ _asn1_copy_structure3 (asn1_node source_node)
else
{
move = UP;
- p_s = _asn1_find_up (p_s);
- p_d = _asn1_find_up (p_d);
+ p_s = _asn1_get_up (p_s);
+ p_d = _asn1_get_up (p_d);
}
}
while (p_s != source_node);
@@ -540,7 +542,7 @@ _asn1_type_choice_config (asn1_node node)
move = UP;
}
if (move == UP)
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
}
return ASN1_SUCCESS;
@@ -591,7 +593,7 @@ _asn1_expand_identifier (asn1_node * node, asn1_node root)
_asn1_set_right (p3, p2);
else
{
- p3 = _asn1_find_up (p);
+ p3 = _asn1_get_up (p);
if (p3)
_asn1_set_down (p3, p2);
else
@@ -647,7 +649,7 @@ _asn1_expand_identifier (asn1_node * node, asn1_node root)
move = UP;
}
if (move == UP)
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
}
return ASN1_SUCCESS;
@@ -1015,7 +1017,7 @@ asn1_print_structure (FILE * out, asn1_node structure, const char *name,
{
while (1)
{
- p = _asn1_find_up (p);
+ p = _asn1_get_up (p);
if (p == root)
{
p = NULL;
@@ -1128,12 +1130,13 @@ asn1_find_structure_from_oid (asn1_node definitions, const char *oidValue)
/**
* asn1_copy_node:
- * @dst: Destination asn1_node node.
+ * @dst: Destination asn1 node.
* @dst_name: Field name in destination node.
- * @src: Source asn1_node node.
+ * @src: Source asn1 node.
* @src_name: Field name in source node.
*
- * Create a deep copy of a asn1_node variable.
+ * Create a deep copy of a asn1_node variable. That
+ * function requires @dst to be expanded using asn1_create_element().
*
* Returns: Return %ASN1_SUCCESS on success.
**/
@@ -1141,9 +1144,6 @@ int
asn1_copy_node (asn1_node dst, const char *dst_name,
asn1_node src, const char *src_name)
{
-/* FIXME: rewrite using copy_structure().
- * It seems quite hard to do.
- */
int result;
asn1_node dst_node;
void *data = NULL;
@@ -1177,3 +1177,19 @@ asn1_copy_node (asn1_node dst, const char *dst_name,
return result;
}
+
+/**
+ * asn1_dup_node:
+ * @src: Source asn1 node.
+ * @src_name: Field name in source node.
+ *
+ * Create a deep copy of a asn1_node variable. This function
+ * will return an exact copy of the provided structure.
+ *
+ * Returns: Return %NULL on failure.
+ **/
+asn1_node
+asn1_dup_node (asn1_node src, const char *src_name)
+{
+ return _asn1_copy_structure2(src, src_name);
+}