summaryrefslogtreecommitdiff
path: root/lib/minitasn1/element.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/minitasn1/element.c')
-rw-r--r--lib/minitasn1/element.c204
1 files changed, 116 insertions, 88 deletions
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;
}