summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2014-05-25 21:37:19 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2014-05-29 19:02:34 +0200
commit492ddda46fe985b0001128a287193e611079fd17 (patch)
tree54ad8162fca1f1e1b86a01ff46ccc69580da6afc
parente933e7d8bb32d7d0936510eba3120f94e15d9b97 (diff)
downloadgnutls-492ddda46fe985b0001128a287193e611079fd17.tar.gz
updated libtasn1
-rw-r--r--lib/minitasn1/coding.c265
-rw-r--r--lib/minitasn1/decoding.c1520
-rw-r--r--lib/minitasn1/element.c204
-rw-r--r--lib/minitasn1/element.h6
-rw-r--r--lib/minitasn1/errors.c6
-rw-r--r--lib/minitasn1/gstr.c5
-rw-r--r--lib/minitasn1/gstr.h20
-rw-r--r--lib/minitasn1/int.h23
-rw-r--r--lib/minitasn1/libtasn1.h83
-rw-r--r--lib/minitasn1/parser_aux.c68
-rw-r--r--lib/minitasn1/parser_aux.h7
-rw-r--r--lib/minitasn1/structure.c72
-rw-r--r--lib/minitasn1/structure.h5
-rw-r--r--lib/minitasn1/version.c2
14 files changed, 953 insertions, 1333 deletions
diff --git a/lib/minitasn1/coding.c b/lib/minitasn1/coding.c
index 5361b3f068..d6b7cf4114 100644
--- a/lib/minitasn1/coding.c
+++ b/lib/minitasn1/coding.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -30,6 +30,7 @@
#include "parser_aux.h"
#include <gstr.h>
#include "element.h"
+#include "minmax.h"
#include <structure.h>
#define MAX_TAG_LEN 16
@@ -61,13 +62,13 @@ _asn1_error_description_value_not_found (asn1_node node,
/**
* asn1_length_der:
* @len: value to convert.
- * @der: the encoding (may be %NULL).
+ * @der: buffer to hold the returned encoding (may be %NULL).
* @der_len: number of meaningful bytes of ANS (der[0]..der[der_len-1]).
*
* Creates the DER encoding of the provided length value.
* The @der buffer must have enough room for the output. The maximum
* length this function will encode is %ASN1_MAX_LENGTH_SIZE.
- *
+ *
* To know the size of the DER encoding use a %NULL value for @der.
**/
void
@@ -140,9 +141,9 @@ _asn1_tag_der (unsigned char class, unsigned int tag_value,
{
temp[k++] = tag_value & 0x7F;
tag_value >>= 7;
-
- if (k > ASN1_MAX_TAG_SIZE-1)
- break; /* will not encode larger tags */
+
+ if (k > ASN1_MAX_TAG_SIZE - 1)
+ break; /* will not encode larger tags */
}
*ans_len = k + 1;
while (k--)
@@ -192,52 +193,52 @@ asn1_octet_der (const unsigned char *str, int str_len,
* @tl_len: the bytes of the @tl field
*
* Creates the DER encoding for various simple ASN.1 types like strings etc.
- * It stores the tag and length in @tl, which should have space for at least
+ * It stores the tag and length in @tl, which should have space for at least
* %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl.
*
* The complete DER encoding should consist of the value in @tl appended
* with the provided @str.
*
- * Returns: %ASN1_SUCCESS if successful or an error value.
+ * Returns: %ASN1_SUCCESS if successful or an error value.
**/
int
-asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned int str_len,
- unsigned char *tl, unsigned int *tl_len)
+asn1_encode_simple_der (unsigned int etype, const unsigned char *str,
+ unsigned int str_len, unsigned char *tl,
+ unsigned int *tl_len)
{
int tag_len, len_len;
unsigned tlen;
unsigned char der_tag[ASN1_MAX_TAG_SIZE];
unsigned char der_length[ASN1_MAX_LENGTH_SIZE];
- unsigned char* p;
+ unsigned char *p;
if (str == NULL)
return ASN1_VALUE_NOT_VALID;
- if (ETYPE_OK(etype) == 0)
+ if (ETYPE_OK (etype) == 0)
return ASN1_VALUE_NOT_VALID;
/* doesn't handle constructed classes */
- if (ETYPE_CLASS(etype) != ASN1_CLASS_UNIVERSAL)
+ if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL)
return ASN1_VALUE_NOT_VALID;
- _asn1_tag_der (ETYPE_CLASS(etype), ETYPE_TAG(etype),
- der_tag, &tag_len);
+ _asn1_tag_der (ETYPE_CLASS (etype), ETYPE_TAG (etype), der_tag, &tag_len);
- asn1_length_der(str_len, der_length, &len_len);
+ asn1_length_der (str_len, der_length, &len_len);
if (tag_len <= 0 || len_len <= 0)
return ASN1_VALUE_NOT_VALID;
-
+
tlen = tag_len + len_len;
if (*tl_len < tlen)
return ASN1_MEM_ERROR;
p = tl;
- memcpy(p, der_tag, tag_len);
- p+=tag_len;
- memcpy(p, der_length, len_len);
-
+ memcpy (p, der_tag, tag_len);
+ p += tag_len;
+ memcpy (p, der_length, len_len);
+
*tl_len = tlen;
return ASN1_SUCCESS;
@@ -258,7 +259,8 @@ asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned i
/* ASN1_SUCCESS otherwise */
/******************************************************/
static int
-_asn1_time_der (unsigned char *str, int str_len, unsigned char *der, int *der_len)
+_asn1_time_der (unsigned char *str, int str_len, unsigned char *der,
+ int *der_len)
{
int len_len;
int max_len;
@@ -326,7 +328,8 @@ _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str)
/* must store the length of DER. */
/* Return: */
/* ASN1_MEM_ERROR when DER isn't big enough */
-/* ASN1_SUCCESS otherwise */
+/* ASN1_SUCCESS if succesful */
+/* or an error value. */
/******************************************************/
static int
_asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len)
@@ -473,6 +476,8 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der,
if (node->type & CONST_TAG)
{
p = node->down;
+ if (p == NULL)
+ return ASN1_DER_ERROR;
/* When there are nested tags we must complete them reverse to
the order they were created. This is because completing a tag
modifies all data within it, including the incomplete tags
@@ -517,33 +522,56 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der,
return ASN1_SUCCESS;
}
-const tag_and_class_st _asn1_tags[] =
-{
- [ASN1_ETYPE_GENERALSTRING] = {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"},
- [ASN1_ETYPE_NUMERIC_STRING] = {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"},
- [ASN1_ETYPE_IA5_STRING] = {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"},
- [ASN1_ETYPE_TELETEX_STRING] = {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"},
- [ASN1_ETYPE_PRINTABLE_STRING] = {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"},
- [ASN1_ETYPE_UNIVERSAL_STRING] = {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"},
- [ASN1_ETYPE_BMP_STRING] = {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"},
- [ASN1_ETYPE_UTF8_STRING] = {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"},
- [ASN1_ETYPE_VISIBLE_STRING] = {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"},
- [ASN1_ETYPE_OCTET_STRING] = {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"},
- [ASN1_ETYPE_BIT_STRING] = {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"},
- [ASN1_ETYPE_OBJECT_ID] = {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"},
- [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"},
- [ASN1_ETYPE_BOOLEAN] = {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"},
- [ASN1_ETYPE_INTEGER] = {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"},
- [ASN1_ETYPE_ENUMERATED] = {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"},
- [ASN1_ETYPE_SEQUENCE] = {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SEQUENCE"},
- [ASN1_ETYPE_SEQUENCE_OF] ={ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SEQ_OF"},
- [ASN1_ETYPE_SET] = {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"},
- [ASN1_ETYPE_SET_OF] = {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET_OF"},
- [ASN1_ETYPE_GENERALIZED_TIME] = {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"},
- [ASN1_ETYPE_UTC_TIME] = {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"},
+const tag_and_class_st _asn1_tags[] = {
+ [ASN1_ETYPE_GENERALSTRING] =
+ {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"},
+ [ASN1_ETYPE_NUMERIC_STRING] =
+ {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"},
+ [ASN1_ETYPE_IA5_STRING] =
+ {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"},
+ [ASN1_ETYPE_TELETEX_STRING] =
+ {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"},
+ [ASN1_ETYPE_PRINTABLE_STRING] =
+ {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"},
+ [ASN1_ETYPE_UNIVERSAL_STRING] =
+ {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"},
+ [ASN1_ETYPE_BMP_STRING] =
+ {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"},
+ [ASN1_ETYPE_UTF8_STRING] =
+ {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"},
+ [ASN1_ETYPE_VISIBLE_STRING] =
+ {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"},
+ [ASN1_ETYPE_OCTET_STRING] =
+ {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"},
+ [ASN1_ETYPE_BIT_STRING] =
+ {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"},
+ [ASN1_ETYPE_OBJECT_ID] =
+ {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"},
+ [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"},
+ [ASN1_ETYPE_BOOLEAN] =
+ {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"},
+ [ASN1_ETYPE_INTEGER] =
+ {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"},
+ [ASN1_ETYPE_ENUMERATED] =
+ {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"},
+ [ASN1_ETYPE_SEQUENCE] =
+ {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+ "type:SEQUENCE"},
+ [ASN1_ETYPE_SEQUENCE_OF] =
+ {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+ "type:SEQ_OF"},
+ [ASN1_ETYPE_SET] =
+ {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"},
+ [ASN1_ETYPE_SET_OF] =
+ {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+ "type:SET_OF"},
+ [ASN1_ETYPE_GENERALIZED_TIME] =
+ {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"},
+ [ASN1_ETYPE_UTC_TIME] =
+ {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"},
};
-unsigned int _asn1_tags_size = sizeof(_asn1_tags)/sizeof(_asn1_tags[0]);
+unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]);
/******************************************************/
/* Function : _asn1_insert_tag_der */
@@ -566,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];
@@ -613,9 +641,9 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter,
if (!is_tag_implicit)
{
if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) ||
- (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) ||
- (type_field (node->type) == ASN1_ETYPE_SET) ||
- (type_field (node->type) == ASN1_ETYPE_SET_OF))
+ (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF)
+ || (type_field (node->type) == ASN1_ETYPE_SET)
+ || (type_field (node->type) == ASN1_ETYPE_SET_OF))
class |= ASN1_CLASS_STRUCTURED;
class_implicit = class;
tag_implicit = _asn1_strtoul (p->value, NULL, 10);
@@ -636,7 +664,7 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter,
unsigned type = type_field (node->type);
switch (type)
{
- CASE_HANDLED_ETYPES:
+ CASE_HANDLED_ETYPES:
_asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag,
tag_der, &tag_len);
break;
@@ -669,8 +697,10 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter,
/* der: string with the DER coding. */
/* node: pointer to the SET element. */
/* Return: */
+/* ASN1_SUCCESS if successful */
+/* or an error value. */
/******************************************************/
-static void
+static int
_asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
{
struct vet
@@ -684,27 +714,31 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
struct vet *first, *last, *p_vet, *p2_vet;
asn1_node p;
unsigned char class, *temp;
- unsigned long tag;
+ unsigned long tag, t;
+ int err;
counter = 0;
if (type_field (node->type) != ASN1_ETYPE_SET)
- return;
+ return ASN1_VALUE_NOT_VALID;
p = node->down;
- while ((type_field (p->type) == ASN1_ETYPE_TAG)
- || (type_field (p->type) == ASN1_ETYPE_SIZE))
+ while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) ||
+ (type_field (p->type) == ASN1_ETYPE_SIZE)))
p = p->right;
if ((p == NULL) || (p->right == NULL))
- return;
+ return ASN1_SUCCESS;
first = last = NULL;
while (p)
{
p_vet = malloc (sizeof (struct vet));
if (p_vet == NULL)
- return;
+ {
+ err = ASN1_MEM_ALLOC_ERROR;
+ goto error;
+ }
p_vet->next = NULL;
p_vet->prev = last;
@@ -715,17 +749,22 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
last = p_vet;
/* tag value calculation */
- if (asn1_get_tag_der
- (der + counter, der_len - counter, &class, &len2,
- &tag) != ASN1_SUCCESS)
- return;
- p_vet->value = (class << 24) | tag;
+ err = asn1_get_tag_der (der + counter, der_len - counter, &class, &len2,
+ &tag);
+ if (err != ASN1_SUCCESS)
+ goto error;
+
+ t = class << 24;
+ p_vet->value = t | tag;
counter += len2;
/* extraction and length */
len2 = asn1_get_length_der (der + counter, der_len - counter, &len);
if (len2 < 0)
- return;
+ {
+ err = ASN1_DER_ERROR;
+ goto error;
+ }
counter += len + len2;
p_vet->end = counter;
@@ -745,7 +784,10 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
/* change position */
temp = malloc (p_vet->end - counter);
if (temp == NULL)
- return;
+ {
+ err = ASN1_MEM_ALLOC_ERROR;
+ goto error;
+ }
memcpy (temp, der + counter, p_vet->end - counter);
memcpy (der + counter, der + p_vet->end,
@@ -773,6 +815,16 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
free (p_vet);
p_vet = first;
}
+ return ASN1_SUCCESS;
+
+error:
+ while (first != NULL)
+ {
+ p_vet = first;
+ first = first->next;
+ free(p_vet);
+ }
+ return err;
}
/******************************************************/
@@ -783,8 +835,10 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
/* der: string with the DER coding. */
/* node: pointer to the SET OF element. */
/* Return: */
+/* ASN1_SUCCESS if successful */
+/* or an error value. */
/******************************************************/
-static void
+static int
_asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
{
struct vet
@@ -797,28 +851,34 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
struct vet *first, *last, *p_vet, *p2_vet;
asn1_node p;
unsigned char *temp, class;
- unsigned long k, max;
+ unsigned long k, length;
+ int err;
counter = 0;
if (type_field (node->type) != ASN1_ETYPE_SET_OF)
- return;
+ return ASN1_VALUE_NOT_VALID;
p = node->down;
- while ((type_field (p->type) == ASN1_ETYPE_TAG)
- || (type_field (p->type) == ASN1_ETYPE_SIZE))
+ while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) ||
+ (type_field (p->type) == ASN1_ETYPE_SIZE)))
p = p->right;
+ if (p == NULL)
+ return ASN1_VALUE_NOT_VALID;
p = p->right;
if ((p == NULL) || (p->right == NULL))
- return;
+ return ASN1_SUCCESS;
first = last = NULL;
while (p)
{
p_vet = malloc (sizeof (struct vet));
if (p_vet == NULL)
- return;
+ {
+ err = ASN1_MEM_ALLOC_ERROR;
+ goto error;
+ }
p_vet->next = NULL;
p_vet->prev = last;
@@ -832,17 +892,25 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
if (der_len - counter > 0)
{
- if (asn1_get_tag_der
- (der + counter, der_len - counter, &class, &len,
- NULL) != ASN1_SUCCESS)
- return;
+ err = asn1_get_tag_der (der + counter, der_len - counter, &class,
+ &len, NULL);
+ if (err != ASN1_SUCCESS)
+ goto error;
counter += len;
len2 = asn1_get_length_der (der + counter, der_len - counter, &len);
if (len2 < 0)
- return;
+ {
+ err = ASN1_DER_ERROR;
+ goto error;
+ }
counter += len + len2;
}
+ else
+ {
+ err = ASN1_DER_ERROR;
+ goto error;
+ }
p_vet->end = counter;
p = p->right;
@@ -856,13 +924,9 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
counter = 0;
while (p2_vet)
{
- if ((p_vet->end - counter) > (p2_vet->end - p_vet->end))
- max = p_vet->end - counter;
- else
- max = p2_vet->end - p_vet->end;
-
+ length = MIN(p_vet->end - counter, p2_vet->end - p_vet->end);
change = -1;
- for (k = 0; k < max; k++)
+ for (k = 0; k < length; k++)
if (der[counter + k] > der[p_vet->end + k])
{
change = 1;
@@ -883,7 +947,10 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
/* change position */
temp = malloc (p_vet->end - counter);
if (temp == NULL)
- return;
+ {
+ err = ASN1_MEM_ALLOC_ERROR;
+ goto error;
+ }
memcpy (temp, der + counter, (p_vet->end) - counter);
memcpy (der + counter, der + (p_vet->end),
@@ -907,6 +974,16 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
free (p_vet);
p_vet = first;
}
+ return ASN1_SUCCESS;
+
+error:
+ while (first != NULL)
+ {
+ p_vet = first;
+ first = first->next;
+ free(p_vet);
+ }
+ return err;
}
/**
@@ -918,7 +995,7 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
* pointer to memory cells already allocated.
* @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy
* holds the sizeof of der vector.
- * @errorDescription : return the error description or an empty
+ * @ErrorDescription: return the error description or an empty
* string if success.
*
* Creates the DER encoding for the NAME structure (inside *POINTER
@@ -935,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;
@@ -1139,7 +1216,11 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
len2 = _asn1_strtol (p->value, NULL, 10);
_asn1_set_value (p, NULL, 0);
if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0))
- _asn1_ordering_set (der + len2, max_len - len2, p);
+ {
+ err = _asn1_ordering_set (der + len2, counter - len2, p);
+ if (err != ASN1_SUCCESS)
+ goto error;
+ }
asn1_length_der (counter - len2, temp, &len3);
max_len -= len3;
if (max_len >= 0)
@@ -1179,9 +1260,11 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
len2 = _asn1_strtol (p->value, NULL, 10);
_asn1_set_value (p, NULL, 0);
if ((type_field (p->type) == ASN1_ETYPE_SET_OF)
- && (max_len - len2 > 0))
+ && (counter - len2 > 0) && (max_len >= 0))
{
- _asn1_ordering_set_of (der + len2, max_len - len2, p);
+ err = _asn1_ordering_set_of (der + len2, counter - len2, p);
+ if (err != ASN1_SUCCESS)
+ goto error;
}
asn1_length_der (counter - len2, temp, &len3);
max_len -= len3;
diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c
index f02fe10686..a9aecc254b 100644
--- a/lib/minitasn1/decoding.c
+++ b/lib/minitasn1/decoding.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -26,14 +26,32 @@
/*****************************************************/
#include <int.h>
-#include "parser_aux.h"
+#include <parser_aux.h>
#include <gstr.h>
-#include "structure.h"
-#include "element.h"
+#include <structure.h>
+#include <element.h>
#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)
@@ -61,8 +79,8 @@ _asn1_error_description_tag_error (asn1_node node, char *ErrorDescription)
long
asn1_get_length_der (const unsigned char *der, int der_len, int *len)
{
- unsigned int ans, sum, last;
- int k, punt;
+ unsigned int ans;
+ int k, punt, sum;
*len = 0;
if (der_len <= 0)
@@ -84,12 +102,14 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len)
ans = 0;
while (punt <= k && punt < der_len)
{
- last = ans;
+ if (INT_MULTIPLY_OVERFLOW (ans, 256))
+ return -2;
+ ans *= 256;
- ans = (ans*256) + der[punt++];
- if (ans < last)
- /* we wrapped around, no bignum support... */
+ if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt])))
return -2;
+ ans += der[punt];
+ punt++;
}
}
else
@@ -101,14 +121,12 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len)
*len = punt;
}
- sum = ans + *len;
-
- /* check for overflow as well INT_MAX as a maximum upper
- * limit for length */
- if (sum >= INT_MAX || sum < ans)
+ sum = ans;
+ if (ans >= INT_MAX || INT_ADD_OVERFLOW (sum, (*len)))
return -2;
+ sum += *len;
- if (((int) sum) > der_len)
+ if (sum > der_len)
return -4;
return ans;
@@ -132,7 +150,6 @@ asn1_get_tag_der (const unsigned char *der, int der_len,
{
unsigned int ris;
int punt;
- unsigned int last;
if (der == NULL || der_len < 2 || len == NULL)
return ASN1_DER_ERROR;
@@ -149,27 +166,34 @@ asn1_get_tag_der (const unsigned char *der, int der_len,
/* Long form */
punt = 1;
ris = 0;
- while (punt <= der_len && der[punt] & 128)
+ while (punt < der_len && der[punt] & 128)
{
- last = ris;
- ris = (ris * 128) + (der[punt++] & 0x7F);
- if (ris < last)
- /* wrapped around, and no bignums... */
+ if (INT_MULTIPLY_OVERFLOW (ris, 128))
+ return ASN1_DER_ERROR;
+ ris *= 128;
+
+ if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
return ASN1_DER_ERROR;
+ ris += (der[punt] & 0x7F);
+ punt++;
}
if (punt >= der_len)
return ASN1_DER_ERROR;
- last = ris;
+ if (INT_MULTIPLY_OVERFLOW (ris, 128))
+ return ASN1_DER_ERROR;
+ ris *= 128;
- ris = (ris * 128) + (der[punt++] & 0x7F);
- if (ris < last)
+ if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
return ASN1_DER_ERROR;
+ ris += (der[punt] & 0x7F);
+ punt++;
*len = punt;
}
+
if (tag)
*tag = ris;
return ASN1_SUCCESS;
@@ -199,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;
}
@@ -226,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)
@@ -239,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;
@@ -258,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;
@@ -274,8 +301,8 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len,
{
int len_len, len, k;
int leading;
- char temp[20];
- unsigned long val, val1, prev_val;
+ char temp[LTOSTR_MAX_SIZE];
+ unsigned long val, val1;
*ret_len = 0;
if (str && str_size > 0)
@@ -283,9 +310,10 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len,
if (str == NULL || der_len <= 0)
return ASN1_GENERIC_ERROR;
+
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;
@@ -295,7 +323,6 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len,
_asn1_str_cat (str, str_size, ".");
_asn1_str_cat (str, str_size, _asn1_ltostr (val, temp));
- prev_val = 0;
val = 0;
leading = 1;
for (k = 1; k < len; k++)
@@ -307,23 +334,24 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len,
leading = 0;
/* check for wrap around */
- val = val << 7;
- val |= der[len_len + k] & 0x7F;
-
- if (val < prev_val)
+ if (INT_LEFT_SHIFT_OVERFLOW (val, 7))
return ASN1_DER_ERROR;
- prev_val = val;
+ val = val << 7;
+ val |= der[len_len + k] & 0x7F;
if (!(der[len_len + k] & 0x80))
{
_asn1_str_cat (str, str_size, ".");
_asn1_str_cat (str, str_size, _asn1_ltostr (val, temp));
val = 0;
- prev_val = 0;
leading = 1;
}
}
+
+ if (INT_ADD_OVERFLOW (len, len_len))
+ return ASN1_DER_ERROR;
+
*ret_len = len + len_len;
return ASN1_SUCCESS;
@@ -347,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;
@@ -358,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;
@@ -368,12 +403,14 @@ asn1_get_bit_der (const unsigned char *der, int der_len,
return ASN1_SUCCESS;
}
+
static int
_asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
int *ret_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;
@@ -401,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)
{
@@ -437,9 +472,9 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
if (!is_tag_implicit)
{
if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) ||
- (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) ||
- (type_field (node->type) == ASN1_ETYPE_SET) ||
- (type_field (node->type) == ASN1_ETYPE_SET_OF))
+ (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF)
+ || (type_field (node->type) == ASN1_ETYPE_SET)
+ || (type_field (node->type) == ASN1_ETYPE_SET_OF))
class2 |= ASN1_CLASS_STRUCTURED;
class_implicit = class2;
tag_implicit = strtoul ((char *) p->value, NULL, 10);
@@ -454,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))
{
@@ -477,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)
{
@@ -513,7 +546,8 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
case ASN1_ETYPE_SET_OF:
case ASN1_ETYPE_GENERALIZED_TIME:
case ASN1_ETYPE_UTC_TIME:
- if ((class != _asn1_tags[type].class) || (tag != _asn1_tags[type].tag))
+ if ((class != _asn1_tags[type].class)
+ || (tag != _asn1_tags[type].tag))
return ASN1_DER_ERROR;
break;
@@ -528,6 +562,9 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
case ASN1_ETYPE_ANY:
counter -= len2;
break;
+ case ASN1_ETYPE_CHOICE:
+ counter -= len2;
+ break;
default:
return ASN1_DER_ERROR;
break;
@@ -537,6 +574,34 @@ _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
+extract_tag_der_recursive(asn1_node node, const unsigned char *der, int der_len,
+ int *ret_len)
+{
+asn1_node p;
+int ris = ASN1_DER_ERROR;
+
+ if (type_field (node->type) == ASN1_ETYPE_CHOICE)
+ {
+ p = node->down;
+ while (p)
+ {
+ ris = _asn1_extract_tag_der (p, der, der_len, ret_len);
+ if (ris == ASN1_SUCCESS)
+ break;
+ p = p->right;
+ }
+
+ *ret_len = 0;
+ return ris;
+ }
+ else
+ return _asn1_extract_tag_der (node, der, der_len, ret_len);
}
static int
@@ -603,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);
@@ -701,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;
@@ -709,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);
@@ -721,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;
@@ -734,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;
@@ -748,36 +828,55 @@ _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)
+{
+ asn1_node p2;
+
+ while (p->right)
+ {
+ p2 = p->right;
+ asn1_delete_structure (&p2);
+ }
+}
+
+
+
/**
* 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.
*
@@ -793,7 +892,7 @@ _asn1_get_indefinite_length_string (const unsigned char *der, int *len)
* 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;
@@ -815,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;
}
@@ -832,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;
}
}
@@ -849,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;
@@ -856,23 +958,9 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
{
if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
{
- if (type_field (p2->type) != ASN1_ETYPE_CHOICE)
- ris =
- _asn1_extract_tag_der (p2, der + counter,
- len - counter, &len2);
- else
- {
- p3 = p2->down;
- while (p3)
- {
- ris =
- _asn1_extract_tag_der (p3, der + counter,
- len - counter, &len2);
- if (ris == ASN1_SUCCESS)
- break;
- p3 = p3->right;
- }
- }
+ ris =
+ extract_tag_der_recursive (p2, der + counter,
+ ider_len, &len2);
if (ris == ASN1_SUCCESS)
{
p2->type &= ~CONST_NOT_USED;
@@ -885,6 +973,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
if (p2 == NULL)
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -915,24 +1004,19 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
{
while (p->down)
{
- if (counter < len)
- ris =
- _asn1_extract_tag_der (p->down, der + counter,
- len - counter, &len2);
- else
- ris = ASN1_DER_ERROR;
+ ris =
+ extract_tag_der_recursive (p->down, der + counter,
+ ider_len, &len2);
+
if (ris == ASN1_SUCCESS)
{
- while (p->down->right)
- {
- p2 = p->down->right;
- asn1_delete_structure (&p2);
- }
+ delete_unneeded_choice_fields(p->down);
break;
}
else if (ris == ASN1_ERROR_TYPE_ANY)
{
result = ASN1_ERROR_TYPE_ANY;
+ warn();
goto cleanup;
}
else
@@ -947,10 +1031,11 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
if (!(p->type & CONST_OPTION))
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
- else
+ else if (type_field (p->type) != ASN1_ETYPE_CHOICE)
p = p->down;
}
@@ -958,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 =
- _asn1_extract_tag_der (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)
@@ -983,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)
@@ -995,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)
@@ -1018,71 +1114,92 @@ 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;
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_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);
+ 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;
@@ -1095,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;
}
@@ -1115,6 +1226,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
if (len2 != counter)
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -1123,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);
@@ -1168,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;
@@ -1183,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
@@ -1197,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;
}
}
@@ -1208,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)
{
@@ -1242,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;
@@ -1289,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;
@@ -1296,6 +1427,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
else
{
result = ASN1_DER_ERROR;
+ warn();
goto cleanup;
}
}
@@ -1331,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;
}
@@ -1365,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
@@ -1374,783 +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))
- {
- if (type_field (p2->type) != ASN1_ETYPE_CHOICE)
- ris =
- _asn1_extract_tag_der (p2, der + counter,
- len - counter, &len2);
- else
- {
- p3 = p2->down;
- while (p3)
- {
- ris =
- _asn1_extract_tag_der (p3, der + counter,
- len - counter, &len2);
- if (ris == ASN1_SUCCESS)
- break;
- p3 = p3->right;
- }
- }
- 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)
- {
- while (p->down->right)
- {
- p2 = p->down->right;
- asn1_delete_structure (&p2);
- }
- 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
- 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])
@@ -2172,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, p3;
+ 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;
@@ -2195,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;
}
@@ -2208,7 +1575,7 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
while (1)
{
if (p == NULL)
- return ASN1_DER_ERROR;
+ return ASN1_DER_ERROR;
ris = ASN1_SUCCESS;
@@ -2217,17 +1584,21 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
if (p->type & CONST_SET)
{
p2 = _asn1_find_up (p);
- if (p2 == NULL)
- return ASN1_DER_ERROR;
+ if (p2 == NULL)
+ {
+ 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;
}
}
@@ -2238,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;
@@ -2246,20 +1620,9 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
{
if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
{ /* CONTROLLARE */
- if (type_field (p2->type) != ASN1_ETYPE_CHOICE)
- ris =
- _asn1_extract_tag_der (p2, der + counter,
- len - counter, &len2);
- else
- {
- p3 = p2->down;
- if (p3 == NULL)
- return ASN1_DER_ERROR;
-
- ris =
- _asn1_extract_tag_der (p3, der + counter,
- len - counter, &len2);
- }
+ ris =
+ extract_tag_der_recursive (p2, der + counter,
+ ider_len, &len2);
if (ris == ASN1_SUCCESS)
{
p2->type &= ~CONST_NOT_USED;
@@ -2270,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)
@@ -2279,11 +1645,14 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
if (type_field (p->type) == ASN1_ETYPE_CHOICE)
{
p = p->down;
- if (p == NULL)
- return ASN1_DER_ERROR;
+ if (p == NULL)
+ {
+ 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;
@@ -2291,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)
@@ -2305,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)
@@ -2317,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;
@@ -2342,19 +1729,24 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
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_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);
+ 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;
@@ -2363,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
@@ -2374,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;
@@ -2384,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) ||
@@ -2401,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;
@@ -2484,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;
}
/**
@@ -2506,18 +1951,18 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
int
asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
{
- char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1],
+ char name[2 * ASN1_MAX_NAME_SIZE + 1],
value[ASN1_MAX_NAME_SIZE];
int retCode = ASN1_SUCCESS, result;
int len, len2, len3;
asn1_node p, p2, p3, aux = NULL;
char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+ const char *definitionsName;
if ((definitions == NULL) || (*element == NULL))
return ASN1_ELEMENT_NOT_FOUND;
- strcpy (definitionsName, definitions->name);
- strcat (definitionsName, ".");
+ definitionsName = definitions->name;
p = *element;
while (p)
@@ -2577,8 +2022,8 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
p3 = p3->right;
}
- if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) ||
- (p3->value == NULL))
+ if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
+ || (p3->value == NULL))
{
retCode = ASN1_ERROR_TYPE_ANY;
break;
@@ -2592,8 +2037,7 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) &&
(p2->type & CONST_ASSIGN))
{
- strcpy (name, definitionsName);
- strcat (name, p2->name);
+ snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name);
len = ASN1_MAX_NAME_SIZE;
result =
@@ -2609,8 +2053,7 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
if (p2)
{
- strcpy (name, definitionsName);
- strcat (name, p2->name);
+ snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name);
result =
asn1_create_element (definitions, name, &aux);
@@ -2868,14 +2311,15 @@ asn1_expand_octet_string (asn1_node definitions, asn1_node * element,
* Decodes a simple DER encoded type (e.g. a string, which is not constructed).
* The output is a pointer inside the @der.
*
- * Returns: %ASN1_SUCCESS if successful or an error value.
+ * Returns: %ASN1_SUCCESS if successful or an error value.
**/
int
-asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned int der_len,
- const unsigned char **str, unsigned int *str_len)
+asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
+ unsigned int der_len, const unsigned char **str,
+ unsigned int *str_len)
{
int tag_len, len_len;
- const unsigned char* p;
+ const unsigned char *p;
unsigned char class;
unsigned long tag;
long ret;
@@ -2883,31 +2327,31 @@ asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned i
if (der == NULL || der_len == 0)
return ASN1_VALUE_NOT_VALID;
- if (ETYPE_OK(etype) == 0)
+ if (ETYPE_OK (etype) == 0)
return ASN1_VALUE_NOT_VALID;
/* doesn't handle constructed classes */
- if (ETYPE_CLASS(etype) != ASN1_CLASS_UNIVERSAL)
+ if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL)
return ASN1_VALUE_NOT_VALID;
p = der;
ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag);
if (ret != ASN1_SUCCESS)
return ret;
-
- if (class != ETYPE_CLASS(etype) || tag != ETYPE_TAG(etype))
+
+ if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype))
return ASN1_DER_ERROR;
p += tag_len;
der_len -= tag_len;
-
+
ret = asn1_get_length_der (p, der_len, &len_len);
- if (ret < 0)
+ if (ret < 0)
return ASN1_DER_ERROR;
p += len_len;
der_len -= len_len;
-
+
*str_len = ret;
*str = p;
diff --git a/lib/minitasn1/element.c b/lib/minitasn1/element.c
index 763ac586b7..ac30e46610 100644
--- a/lib/minitasn1/element.c
+++ b/lib/minitasn1/element.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -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))
@@ -287,11 +290,10 @@ asn1_write_value (asn1_node node_root, const char *name,
asn1_delete_structure (&node);
return ASN1_SUCCESS;
}
-
- type = type_field(node->type);
- if ((type == ASN1_ETYPE_SEQUENCE_OF) && (value == NULL)
- && (len == 0))
+ type = type_field (node->type);
+
+ if ((type == ASN1_ETYPE_SEQUENCE_OF || type == ASN1_ETYPE_SET_OF) && (value == NULL) && (len == 0))
{
p = node->down;
while ((type_field (p->type) == ASN1_ETYPE_TAG)
@@ -304,6 +306,12 @@ asn1_write_value (asn1_node node_root, const char *name,
return ASN1_SUCCESS;
}
+ /* Don't allow element deletion for other types */
+ if (value == NULL)
+ {
+ return ASN1_VALUE_NOT_VALID;
+ }
+
switch (type)
{
case ASN1_ETYPE_BOOLEAN:
@@ -499,48 +507,48 @@ asn1_write_value (asn1_node node_root, const char *name,
_asn1_set_value (node, value, _asn1_strlen (value) + 1);
break;
case ASN1_ETYPE_UTC_TIME:
- {
- len = _asn1_strlen(value);
- if (len < 11)
+ {
+ len = _asn1_strlen (value);
+ if (len < 11)
+ return ASN1_VALUE_NOT_VALID;
+ for (k = 0; k < 10; k++)
+ if (!isdigit (value[k]))
return ASN1_VALUE_NOT_VALID;
- for (k = 0; k < 10; k++)
- if (!isdigit (value[k]))
+ switch (len)
+ {
+ case 11:
+ if (value[10] != 'Z')
return ASN1_VALUE_NOT_VALID;
- switch (len)
- {
- case 11:
- if (value[10] != 'Z')
- return ASN1_VALUE_NOT_VALID;
- break;
- case 13:
- if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
- (value[12] != 'Z'))
- return ASN1_VALUE_NOT_VALID;
- break;
- case 15:
- if ((value[10] != '+') && (value[10] != '-'))
- return ASN1_VALUE_NOT_VALID;
- for (k = 11; k < 15; k++)
- if (!isdigit (value[k]))
- return ASN1_VALUE_NOT_VALID;
- break;
- case 17:
- if ((!isdigit (value[10])) || (!isdigit (value[11])))
+ break;
+ case 13:
+ if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
+ (value[12] != 'Z'))
+ return ASN1_VALUE_NOT_VALID;
+ break;
+ case 15:
+ if ((value[10] != '+') && (value[10] != '-'))
+ return ASN1_VALUE_NOT_VALID;
+ for (k = 11; k < 15; k++)
+ if (!isdigit (value[k]))
return ASN1_VALUE_NOT_VALID;
- if ((value[12] != '+') && (value[12] != '-'))
+ break;
+ case 17:
+ if ((!isdigit (value[10])) || (!isdigit (value[11])))
+ return ASN1_VALUE_NOT_VALID;
+ if ((value[12] != '+') && (value[12] != '-'))
+ return ASN1_VALUE_NOT_VALID;
+ for (k = 13; k < 17; k++)
+ if (!isdigit (value[k]))
return ASN1_VALUE_NOT_VALID;
- for (k = 13; k < 17; k++)
- if (!isdigit (value[k]))
- return ASN1_VALUE_NOT_VALID;
- break;
- default:
- return ASN1_VALUE_NOT_FOUND;
- }
- _asn1_set_value (node, value, len);
- }
+ break;
+ default:
+ return ASN1_VALUE_NOT_FOUND;
+ }
+ _asn1_set_value (node, value, len);
+ }
break;
case ASN1_ETYPE_GENERALIZED_TIME:
- len = _asn1_strlen(value);
+ len = _asn1_strlen (value);
_asn1_set_value (node, value, len);
break;
case ASN1_ETYPE_OCTET_STRING:
@@ -616,16 +624,19 @@ asn1_write_value (asn1_node node_root, const char *name,
if (ptr_size < data_size) { \
return ASN1_MEM_ERROR; \
} else { \
- memcpy( ptr, data, data_size); \
+ if (ptr && data_size > 0) \
+ memcpy (ptr, data, data_size); \
}
#define PUT_STR_VALUE( ptr, ptr_size, data) \
- *len = _asn1_strlen(data) + 1; \
+ *len = _asn1_strlen (data) + 1; \
if (ptr_size < *len) { \
return ASN1_MEM_ERROR; \
} else { \
/* this strcpy is checked */ \
- _asn1_strcpy(ptr, data); \
+ if (ptr) { \
+ _asn1_strcpy (ptr, data); \
+ } \
}
#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
@@ -634,36 +645,42 @@ asn1_write_value (asn1_node node_root, const char *name,
return ASN1_MEM_ERROR; \
} else { \
/* this strcpy is checked */ \
- memcpy(ptr, data, data_size); \
- ptr[data_size] = 0; \
+ if (ptr) { \
+ 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 */ \
- _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.
@@ -711,7 +728,7 @@ asn1_write_value (asn1_node node_root, const char *name,
int
asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len)
{
- return asn1_read_value_type( root, name, ivalue, len, NULL);
+ return asn1_read_value_type (root, name, ivalue, len, NULL);
}
/**
@@ -719,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.
@@ -777,11 +797,11 @@ asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len)
* bytes needed.
**/
int
-asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len,
- unsigned int *etype)
+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;
@@ -839,9 +859,10 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len,
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 */
@@ -852,10 +873,11 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len,
{
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;
}
}
@@ -866,16 +888,19 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len,
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)
{
@@ -889,7 +914,7 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len,
}
p = p->right;
}
- *len = _asn1_strlen (value) + 1;
+ (*len)++;
}
else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
{
@@ -918,17 +943,19 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len,
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);
@@ -1038,12 +1065,13 @@ asn1_read_tag (asn1_node root, const char *name, int *tagValue,
*
* Returns: %ASN1_SUCCESS if the node exists.
**/
-int asn1_read_node_value (asn1_node node, asn1_data_node_st* data)
+int
+asn1_read_node_value (asn1_node node, asn1_data_node_st * data)
{
data->name = node->name;
data->value = node->value;
data->value_len = node->value_len;
- data->type = type_field(node->type);
-
+ data->type = type_field (node->type);
+
return ASN1_SUCCESS;
}
diff --git a/lib/minitasn1/element.h b/lib/minitasn1/element.h
index 3bd38bb923..fdecafb611 100644
--- a/lib/minitasn1/element.h
+++ b/lib/minitasn1/element.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -26,8 +26,8 @@
int _asn1_append_sequence_set (asn1_node node);
int _asn1_convert_integer (const unsigned char *value,
- unsigned char *value_out,
- int value_out_size, int *len);
+ unsigned char *value_out,
+ int value_out_size, int *len);
void _asn1_hierarchical_name (asn1_node node, char *name, int name_size);
diff --git a/lib/minitasn1/errors.c b/lib/minitasn1/errors.c
index e01c3ee9ea..e9fa302605 100644
--- a/lib/minitasn1/errors.c
+++ b/lib/minitasn1/errors.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -63,8 +63,6 @@ static const libtasn1_error_entry error_algorithms[] = {
* function is like perror(). The only difference is that it accepts
* an error returned by a libtasn1 function.
*
- * This function replaces libtasn1_perror() in older libtasn1.
- *
* Since: 1.6
**/
void
@@ -82,8 +80,6 @@ asn1_perror (int error)
* similar to strerror. The only difference is that it accepts an
* error (number) returned by a libtasn1 function.
*
- * This function replaces libtasn1_strerror() in older libtasn1.
- *
* Returns: Pointer to static zero-terminated string describing error
* code.
*
diff --git a/lib/minitasn1/gstr.c b/lib/minitasn1/gstr.c
index 0558c77771..e91a3a151c 100644
--- a/lib/minitasn1/gstr.c
+++ b/lib/minitasn1/gstr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -68,6 +68,7 @@ _asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src)
dest[str_size] = 0;
return str_size;
}
- else return 0;
+ else
+ return 0;
}
}
diff --git a/lib/minitasn1/gstr.h b/lib/minitasn1/gstr.h
index 672d59eb59..00c335ca93 100644
--- a/lib/minitasn1/gstr.h
+++ b/lib/minitasn1/gstr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -19,8 +19,24 @@
* 02110-1301, USA
*/
-unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src);
+unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size,
+ const char *src);
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/int.h b/lib/minitasn1/int.h
index 3163d50d14..3701e5f645 100644
--- a/lib/minitasn1/int.h
+++ b/lib/minitasn1/int.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -46,7 +46,7 @@
struct asn1_node_st
{
/* public fields: */
- char name[ASN1_MAX_NAME_SIZE+1]; /* Node name */
+ char name[ASN1_MAX_NAME_SIZE + 1]; /* Node name */
unsigned int name_hash;
unsigned int type; /* Node type */
unsigned char *value; /* Node value */
@@ -58,10 +58,11 @@ struct asn1_node_st
unsigned char small_value[ASN1_SMALL_VALUE_SIZE]; /* For small values */
};
-typedef struct tag_and_class_st {
+typedef struct tag_and_class_st
+{
unsigned tag;
unsigned class;
- const char* desc;
+ const char *desc;
} tag_and_class_st;
/* the types that are handled in _asn1_tags */
@@ -156,23 +157,25 @@ extern const tag_and_class_st _asn1_tags[];
/* Returns the first 8 bits. */
/* Used with the field type of asn1_node_st */
/****************************************/
-inline static unsigned int type_field(unsigned int ntype)
+inline static unsigned int
+type_field (unsigned int ntype)
{
return (ntype & 0xff);
}
/* To convert old types from a static structure */
-inline static unsigned int convert_old_type(unsigned int ntype)
+inline static unsigned int
+convert_old_type (unsigned int ntype)
{
-unsigned int type = ntype & 0xff;
+ unsigned int type = ntype & 0xff;
if (type == ASN1_ETYPE_TIME)
{
if (ntype & CONST_UTC)
- type = ASN1_ETYPE_UTC_TIME;
+ type = ASN1_ETYPE_UTC_TIME;
else
- type = ASN1_ETYPE_GENERALIZED_TIME;
+ type = ASN1_ETYPE_GENERALIZED_TIME;
- ntype &= ~(CONST_UTC|CONST_GENERALIZED);
+ ntype &= ~(CONST_UTC | CONST_GENERALIZED);
ntype &= 0xffffff00;
ntype |= type;
diff --git a/lib/minitasn1/libtasn1.h b/lib/minitasn1/libtasn1.h
index 06474f3f33..a4570682e0 100644
--- a/lib/minitasn1/libtasn1.h
+++ b/lib/minitasn1/libtasn1.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -21,30 +21,41 @@
*/
#ifndef LIBTASN1_H
-# define LIBTASN1_H
-
-# ifndef ASN1_API
-# if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY
-# define ASN1_API __attribute__((__visibility__("default")))
-# elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC
-# define ASN1_API __declspec(dllexport)
-# elif defined _MSC_VER && ! defined ASN1_STATIC
-# define ASN1_API __declspec(dllimport)
-# else
-# define ASN1_API
-# endif
-# endif
+#define LIBTASN1_H
+
+#ifndef ASN1_API
+#if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY
+#define ASN1_API __attribute__((__visibility__("default")))
+#elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC
+#define ASN1_API __declspec(dllexport)
+#elif defined _MSC_VER && ! defined ASN1_STATIC
+#define ASN1_API __declspec(dllimport)
+#else
+#define ASN1_API
+#endif
+#endif
-#include <stdio.h> /* for FILE* */
#include <sys/types.h>
#include <time.h>
+#include <stdio.h> /* for FILE* */
#ifdef __cplusplus
extern "C"
{
#endif
-#define ASN1_VERSION "3.1"
+#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 */
@@ -168,11 +179,17 @@ extern "C"
#define ASN1_ETYPE_UTC_TIME 36
#define ASN1_ETYPE_GENERALIZED_TIME 37
+/* Flags used by asn1_delete_structure2() */
+
+/* makes sure the values are zeroized prior to deinitialization */
+#define ASN1_DELETE_FLAG_ZEROIZE 1
+
+
struct asn1_data_node_st
{
const char *name; /* Node name */
const void *value; /* Node value */
- unsigned int value_len; /* Node value size */
+ unsigned int value_len; /* Node value size */
unsigned int type; /* Node value type (ASN1_ETYPE_*) */
};
typedef struct asn1_data_node_st asn1_data_node_st;
@@ -192,13 +209,13 @@ extern "C"
/***********************************/
extern ASN1_API int
- asn1_parser2tree (const char *file_name,
- asn1_node * definitions, char *errorDescription);
+ asn1_parser2tree (const char *file,
+ asn1_node * definitions, char *error_desc);
extern ASN1_API int
asn1_parser2array (const char *inputFileName,
const char *outputFileName,
- const char *vectorName, char *errorDescription);
+ const char *vectorName, char *error_desc);
extern ASN1_API int
asn1_array2tree (const asn1_static_node * array,
@@ -214,6 +231,8 @@ extern "C"
extern ASN1_API int asn1_delete_structure (asn1_node * structure);
+ extern ASN1_API int asn1_delete_structure2 (asn1_node * structure, unsigned int flags);
+
extern ASN1_API int
asn1_delete_element (asn1_node structure, const char *element_name);
@@ -227,10 +246,10 @@ extern "C"
extern ASN1_API int
asn1_read_value_type (asn1_node root, const char *name,
- void *ivalue, int *len, unsigned int* etype);
+ void *ivalue, int *len, unsigned int *etype);
extern ASN1_API int
- asn1_read_node_value (asn1_node node, asn1_data_node_st* data);
+ asn1_read_node_value (asn1_node node, asn1_data_node_st * data);
extern ASN1_API int
asn1_number_of_elements (asn1_node element, const char *name, int *num);
@@ -243,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,
@@ -288,17 +308,20 @@ extern "C"
asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len);
extern ASN1_API void
- asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len);
+ asn1_length_der (unsigned long int len, unsigned char *der, int *der_len);
/* Other utility functions. */
- extern ASN1_API
- int asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned int der_len,
- const unsigned char **str, unsigned int *str_len);
+ extern ASN1_API
+ int asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
+ unsigned int der_len,
+ const unsigned char **str,
+ unsigned int *str_len);
extern ASN1_API int
- asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned int str_len,
- unsigned char *tl, unsigned int *tl_len);
+ asn1_encode_simple_der (unsigned int etype, const unsigned char *str,
+ unsigned int str_len, unsigned char *tl,
+ unsigned int *tl_len);
extern ASN1_API asn1_node
asn1_find_node (asn1_node pointer, const char *name);
@@ -332,7 +355,7 @@ extern "C"
/* Compatibility types */
-typedef int asn1_retCode; /* type returned by libtasn1 functions */
+ typedef int asn1_retCode; /* type returned by libtasn1 functions */
#define node_asn_struct asn1_node_st
#define node_asn asn1_node_st
diff --git a/lib/minitasn1/parser_aux.c b/lib/minitasn1/parser_aux.c
index 50238d2c92..effedb2366 100644
--- a/lib/minitasn1/parser_aux.c
+++ b/lib/minitasn1/parser_aux.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -119,19 +119,19 @@ asn1_find_node (asn1_node pointer, const char *name)
n_start = n_end;
n_start++;
- nhash = hash_pjw_bare(n, nsize);
+ nhash = hash_pjw_bare (n, nsize);
}
else
{
nsize = _asn1_str_cpy (n, sizeof (n), n_start);
- nhash = hash_pjw_bare(n, nsize);
+ nhash = hash_pjw_bare (n, nsize);
n_start = NULL;
}
while (p)
{
- if ((p->name) && nhash == p->name_hash && (!strcmp (p->name, n)))
+ if (nhash == p->name_hash && (!strcmp (p->name, n)))
break;
else
p = p->right;
@@ -157,12 +157,12 @@ asn1_find_node (asn1_node pointer, const char *name)
n_start = n_end;
n_start++;
- nhash = hash_pjw_bare(n, nsize);
+ nhash = hash_pjw_bare (n, nsize);
}
else
{
nsize = _asn1_str_cpy (n, sizeof (n), n_start);
- nhash = hash_pjw_bare(n, nsize);
+ nhash = hash_pjw_bare (n, nsize);
n_start = NULL;
}
@@ -358,7 +358,7 @@ _asn1_append_value (asn1_node node, const void *value, unsigned int len)
asn1_node
_asn1_set_name (asn1_node node, const char *name)
{
-unsigned int nsize;
+ unsigned int nsize;
if (node == NULL)
return node;
@@ -366,12 +366,12 @@ unsigned int nsize;
if (name == NULL)
{
node->name[0] = 0;
- node->name_hash = hash_pjw_bare(node->name, 0);
+ node->name_hash = hash_pjw_bare (node->name, 0);
return node;
}
nsize = _asn1_str_cpy (node->name, sizeof (node->name), name);
- node->name_hash = hash_pjw_bare(node->name, nsize);
+ node->name_hash = hash_pjw_bare (node->name, nsize);
return node;
}
@@ -393,7 +393,7 @@ _asn1_cpy_name (asn1_node dst, asn1_node src)
if (src == NULL)
{
dst->name[0] = 0;
- dst->name_hash = hash_pjw_bare(dst->name, 0);
+ dst->name_hash = hash_pjw_bare (dst->name, 0);
return dst;
}
@@ -450,15 +450,24 @@ _asn1_get_last_right (asn1_node node)
/* element (not the elements pointed by it). */
/* Parameters: */
/* node: NODE_ASN element pointer. */
+/* flags: ASN1_DELETE_FLAG_* */
/******************************************************************/
void
-_asn1_remove_node (asn1_node node)
+_asn1_remove_node (asn1_node node, unsigned int flags)
{
if (node == NULL)
return;
- if (node->value != NULL && node->value != node->small_value)
- free (node->value);
+ if (node->value != NULL)
+ {
+ if (flags & ASN1_DELETE_FLAG_ZEROIZE)
+ {
+ safe_memset(node->value, 0, node->value_len);
+ }
+
+ if (node->value != node->small_value)
+ free (node->value);
+ }
free (node);
}
@@ -517,7 +526,7 @@ _asn1_delete_list_and_nodes (void)
{
listElement = firstElement;
firstElement = firstElement->next;
- _asn1_remove_node (listElement->node);
+ _asn1_remove_node (listElement->node, 0);
free (listElement);
}
}
@@ -527,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)
@@ -581,7 +590,8 @@ _asn1_change_integer_value (asn1_node node)
p = node;
while (p)
{
- if ((type_field (p->type) == ASN1_ETYPE_INTEGER) && (p->type & CONST_ASSIGN))
+ if ((type_field (p->type) == ASN1_ETYPE_INTEGER)
+ && (p->type & CONST_ASSIGN))
{
if (p->value)
{
@@ -666,18 +676,20 @@ _asn1_expand_object_id (asn1_node node)
_asn1_str_cat (name2, sizeof (name2),
(char *) p2->value);
p3 = asn1_find_node (node, name2);
- if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) ||
- !(p3->type & CONST_ASSIGN))
+ if (!p3
+ || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
+ || !(p3->type & CONST_ASSIGN))
return ASN1_ELEMENT_NOT_FOUND;
_asn1_set_down (p, p2->right);
- _asn1_remove_node (p2);
+ _asn1_remove_node (p2, 0);
p2 = p;
p4 = p3->down;
while (p4)
{
if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
{
- p5 = _asn1_add_single_node (ASN1_ETYPE_CONSTANT);
+ p5 =
+ _asn1_add_single_node (ASN1_ETYPE_CONSTANT);
_asn1_set_name (p5, p4->name);
tlen = _asn1_strlen (p4->value);
if (tlen > 0)
@@ -752,8 +764,8 @@ _asn1_expand_object_id (asn1_node node)
_asn1_str_cat (name2, sizeof (name2), ".");
_asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
p3 = asn1_find_node (node, name2);
- if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) ||
- !(p3->type & CONST_ASSIGN))
+ if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
+ || !(p3->type & CONST_ASSIGN))
return ASN1_ELEMENT_NOT_FOUND;
p4 = p3->down;
name2[0] = 0;
@@ -902,7 +914,7 @@ _asn1_check_identifier (asn1_node node)
p = node;
while (p)
{
- if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
+ if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
{
_asn1_str_cpy (name2, sizeof (name2), node->name);
_asn1_str_cat (name2, sizeof (name2), ".");
@@ -911,9 +923,9 @@ _asn1_check_identifier (asn1_node node)
if (p2 == NULL)
{
if (p->value)
- _asn1_strcpy (_asn1_identifierMissing, p->value);
- else
- _asn1_strcpy (_asn1_identifierMissing, "(null)");
+ _asn1_strcpy (_asn1_identifierMissing, p->value);
+ else
+ _asn1_strcpy (_asn1_identifierMissing, "(null)");
return ASN1_IDENTIFIER_NOT_FOUND;
}
}
@@ -948,8 +960,8 @@ _asn1_check_identifier (asn1_node node)
_asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
_asn1_strcpy (_asn1_identifierMissing, p2->value);
p2 = asn1_find_node (node, name2);
- if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) ||
- !(p2->type & CONST_ASSIGN))
+ if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID)
+ || !(p2->type & CONST_ASSIGN))
return ASN1_IDENTIFIER_NOT_FOUND;
else
_asn1_identifierMissing[0] = 0;
diff --git a/lib/minitasn1/parser_aux.h b/lib/minitasn1/parser_aux.h
index f270b73595..1f1aec2637 100644
--- a/lib/minitasn1/parser_aux.h
+++ b/lib/minitasn1/parser_aux.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -22,8 +22,6 @@
#ifndef _PARSER_AUX_H
#define _PARSER_AUX_H
-#define DER_LEN 16
-
/***************************************/
/* Functions used by ASN.1 parser */
/***************************************/
@@ -48,12 +46,13 @@ asn1_node _asn1_set_right (asn1_node node, asn1_node right);
asn1_node _asn1_get_last_right (asn1_node node);
-void _asn1_remove_node (asn1_node node);
+void _asn1_remove_node (asn1_node node, unsigned int flags);
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);
diff --git a/lib/minitasn1/structure.c b/lib/minitasn1/structure.c
index 31a5f654bb..27fbfe3a22 100644
--- a/lib/minitasn1/structure.c
+++ b/lib/minitasn1/structure.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -192,7 +192,7 @@ asn1_array2tree (const asn1_static_node * array, asn1_node * definitions,
k = 0;
while (array[k].value || array[k].type || array[k].name)
{
- type = convert_old_type(array[k].type);
+ type = convert_old_type (array[k].type);
p = _asn1_add_static_node (type & (~CONST_DOWN));
if (array[k].name)
@@ -287,6 +287,23 @@ asn1_array2tree (const asn1_static_node * array, asn1_node * definitions,
int
asn1_delete_structure (asn1_node * structure)
{
+ return asn1_delete_structure2(structure, 0);
+}
+
+/**
+ * asn1_delete_structure2:
+ * @structure: pointer to the structure that you want to delete.
+ * @flags: additional flags (see %ASN1_DELETE_FLAG)
+ *
+ * Deletes the structure *@structure. At the end, *@structure is set
+ * to NULL.
+ *
+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
+ * *@structure was NULL.
+ **/
+int
+asn1_delete_structure2 (asn1_node * structure, unsigned int flags)
+{
asn1_node p, p2, p3;
if (*structure == NULL)
@@ -306,7 +323,7 @@ asn1_delete_structure (asn1_node * structure)
{
p3 = _asn1_find_up (p);
_asn1_set_down (p3, p2);
- _asn1_remove_node (p);
+ _asn1_remove_node (p, flags);
p = p3;
}
else
@@ -325,7 +342,7 @@ asn1_delete_structure (asn1_node * structure)
}
else
_asn1_set_right (p3, p2);
- _asn1_remove_node (p);
+ _asn1_remove_node (p, flags);
p = NULL;
}
}
@@ -409,22 +426,22 @@ _asn1_copy_structure3 (asn1_node source_node)
}
if (p_s == source_node)
- break;
+ break;
if (p_s->right)
- {
- move = RIGHT;
- p_s = p_s->right;
- p_d_prev = p_d;
- p_d = _asn1_add_single_node (p_s->type);
- _asn1_set_right (p_d_prev, p_d);
- }
+ {
+ move = RIGHT;
+ p_s = p_s->right;
+ p_d_prev = p_d;
+ p_d = _asn1_add_single_node (p_s->type);
+ _asn1_set_right (p_d_prev, p_d);
+ }
else
- {
- move = UP;
- p_s = _asn1_find_up (p_s);
- p_d = _asn1_find_up (p_d);
- }
+ {
+ move = UP;
+ p_s = _asn1_find_up (p_s);
+ p_d = _asn1_find_up (p_d);
+ }
}
while (p_s != source_node);
@@ -460,7 +477,8 @@ _asn1_type_choice_config (asn1_node node)
{
if (move != UP)
{
- if ((type_field (p->type) == ASN1_ETYPE_CHOICE) && (p->type & CONST_TAG))
+ if ((type_field (p->type) == ASN1_ETYPE_CHOICE)
+ && (p->type & CONST_TAG))
{
p2 = p->down;
while (p2)
@@ -548,7 +566,7 @@ _asn1_expand_identifier (asn1_node * node, asn1_node root)
{
if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
{
- snprintf(name2, sizeof (name2), "%s.%s", root->name, p->value);
+ snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value);
p2 = _asn1_copy_structure2 (root, name2);
if (p2 == NULL)
{
@@ -597,7 +615,7 @@ _asn1_expand_identifier (asn1_node * node, asn1_node root)
if (p == *node)
*node = p2;
- _asn1_remove_node (p);
+ _asn1_remove_node (p, 0);
p = p2;
move = DOWN;
continue;
@@ -765,7 +783,7 @@ asn1_print_structure (FILE * out, asn1_node structure, const char *name,
case ASN1_ETYPE_DEFINITIONS:
fprintf (out, "type:DEFINITIONS");
break;
- CASE_HANDLED_ETYPES:
+ CASE_HANDLED_ETYPES:
fprintf (out, "%s", _asn1_tags[type].desc);
break;
default:
@@ -854,7 +872,7 @@ asn1_print_structure (FILE * out, asn1_node structure, const char *name,
if (p->value)
{
fprintf (out, " value:");
- for (k = 0; k < p->value_len; k++)
+ for (k = 0; k < p->value_len; k++)
fprintf (out, "%c", (p->value)[k]);
}
break;
@@ -1069,18 +1087,17 @@ asn1_number_of_elements (asn1_node element, const char *name, int *num)
const char *
asn1_find_structure_from_oid (asn1_node definitions, const char *oidValue)
{
- char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1];
+ char name[2 * ASN1_MAX_NAME_SIZE + 1];
char value[ASN1_MAX_NAME_SIZE];
asn1_node p;
int len;
int result;
+ const char *definitionsName;
if ((definitions == NULL) || (oidValue == NULL))
return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
-
- strcpy (definitionsName, definitions->name);
- strcat (definitionsName, ".");
+ definitionsName = definitions->name;
/* search the OBJECT_ID into definitions */
p = definitions->down;
@@ -1089,8 +1106,7 @@ asn1_find_structure_from_oid (asn1_node definitions, const char *oidValue)
if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
(p->type & CONST_ASSIGN))
{
- strcpy (name, definitionsName);
- strcat (name, p->name);
+ snprintf(name, sizeof(name), "%s.%s", definitionsName, p->name);
len = ASN1_MAX_NAME_SIZE;
result = asn1_read_value (definitions, name, value, &len);
diff --git a/lib/minitasn1/structure.h b/lib/minitasn1/structure.h
index 986e13a309..bb6e7a9b9a 100644
--- a/lib/minitasn1/structure.h
+++ b/lib/minitasn1/structure.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
@@ -29,8 +29,7 @@
#define _STRUCTURE_H
int _asn1_create_static_structure (asn1_node pointer,
- char *output_file_name,
- char *vector_name);
+ char *output_file_name, char *vector_name);
asn1_node _asn1_copy_structure3 (asn1_node source_node);
diff --git a/lib/minitasn1/version.c b/lib/minitasn1/version.c
index 83d70c9623..25f8a8f28e 100644
--- a/lib/minitasn1/version.c
+++ b/lib/minitasn1/version.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*