diff options
Diffstat (limited to 'lib/minitasn1/element.c')
-rw-r--r-- | lib/minitasn1/element.c | 204 |
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; } |