/*
- * Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
#include "parser_aux.h"
#include <gstr.h>
#include "element.h"
+#include "minmax.h"
#include <structure.h>
#define MAX_TAG_LEN 16
/* 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)
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
/* 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
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;
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;
/* 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,
free (p_vet);
p_vet = first;
}
+ return ASN1_SUCCESS;
+
+error:
+ while (first != NULL)
+ {
+ p_vet = first;
+ first = first->next;
+ free(p_vet);
+ }
+ return err;
}
/******************************************************/
/* 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
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;
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;
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;
/* 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),
free (p_vet);
p_vet = first;
}
+ return ASN1_SUCCESS;
+
+error:
+ while (first != NULL)
+ {
+ p_vet = first;
+ first = first->next;
+ free(p_vet);
+ }
+ return err;
}
/**
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)
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;
/*
- * Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
return ASN1_SUCCESS;
}
+
static int
_asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
int *ret_len)
case ASN1_ETYPE_ANY:
counter -= len2;
break;
+ case ASN1_ETYPE_CHOICE:
+ counter -= len2;
+ break;
default:
return ASN1_DER_ERROR;
break;
return ASN1_SUCCESS;
}
+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
_asn1_delete_not_used (asn1_node node)
{
}
+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.
{
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,
+ ris =
+ extract_tag_der_recursive (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;
{
if (counter < len)
ris =
- _asn1_extract_tag_der (p->down, der + counter,
+ extract_tag_der_recursive (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);
- }
+ delete_unneeded_choice_fields(p->down);
break;
}
else if (ris == ASN1_ERROR_TYPE_ANY)
goto cleanup;
}
}
- else
+ else if (type_field (p->type) != ASN1_ETYPE_CHOICE)
p = p->down;
}
if (ris == ASN1_SUCCESS)
ris =
- _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
+ extract_tag_der_recursive (p, der + counter, len - counter, &len2);
if (ris != ASN1_SUCCESS)
{
if (p->type & CONST_OPTION)
{
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,
+ ris =
+ extract_tag_der_recursive (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;
ris = ASN1_DER_ERROR;
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)
goto cleanup;
}
}
- else
+ else if (type_field (p->type) != ASN1_ETYPE_CHOICE)
p = p->down;
}
asn1_der_decoding_startEnd (asn1_node element, const void *ider, int 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;
{
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,
+ ris =
+ extract_tag_der_recursive (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);
- }
if (ris == ASN1_SUCCESS)
{
p2->type &= ~CONST_NOT_USED;
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)
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 =
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);
/*
- * Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
type = type_field (node->type);
- if ((type == ASN1_ETYPE_SEQUENCE_OF) && (value == NULL) && (len == 0))
+ 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)
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:
if (ptr_size < data_size) { \
return ASN1_MEM_ERROR; \
} else { \
- memcpy( ptr, data, data_size); \
+ if (ptr) \
+ 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) \
return ASN1_MEM_ERROR; \
} else { \
/* this strcpy is checked */ \
- memcpy(ptr, data, data_size); \
- ptr[data_size] = 0; \
+ if (ptr) { \
+ 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)) { \
+ *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); \
+ if (ptr) _asn1_strcat (ptr, data); \
}
/**
/*
- * Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
/*
- * Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
/*
- * Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
/*
- * Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
/*
- * Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
/*
- * Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
{
#endif
-#define ASN1_VERSION "3.4"
+#define ASN1_VERSION "3.5"
/*****************************************/
/* Errors returned by libtasn1 functions */
/*
- * Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
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;
{
if (node == NULL)
return;
-
+
if (flags & ASN1_DELETE_FLAG_ZEROIZE)
memset(node->value, 0, node->value_len);
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), ".");
/*
- * Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
/*
- * Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
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;
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);
/*
- * Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2002-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*
/*
- * Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
*
* This file is part of LIBTASN1.
*