diff options
Diffstat (limited to 'lib/minitasn1/decoding.c')
-rw-r--r-- | lib/minitasn1/decoding.c | 4972 |
1 files changed, 2504 insertions, 2468 deletions
diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c index f02fe10686..40084d43b7 100644 --- a/lib/minitasn1/decoding.c +++ b/lib/minitasn1/decoding.c @@ -33,16 +33,18 @@ #include <limits.h> static int -_asn1_get_indefinite_length_string (const unsigned char *der, int *len); +_asn1_get_indefinite_length_string(const unsigned char *der, int *len); static void -_asn1_error_description_tag_error (asn1_node node, char *ErrorDescription) +_asn1_error_description_tag_error(asn1_node node, char *ErrorDescription) { - Estrcpy (ErrorDescription, ":: tag error near element '"); - _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription), - ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); - Estrcat (ErrorDescription, "'"); + Estrcpy(ErrorDescription, ":: tag error near element '"); + _asn1_hierarchical_name(node, + ErrorDescription + + strlen(ErrorDescription), + ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); + Estrcat(ErrorDescription, "'"); } @@ -58,60 +60,52 @@ _asn1_error_description_tag_error (asn1_node node, char *ErrorDescription) * length, or -2 when the value was too big to fit in a int, or -4 * when the decoded length value plus @len would exceed @der_len. **/ -long -asn1_get_length_der (const unsigned char *der, int der_len, int *len) +long asn1_get_length_der(const unsigned char *der, int der_len, int *len) { - unsigned int ans, sum, last; - int k, punt; - - *len = 0; - if (der_len <= 0) - return 0; - - if (!(der[0] & 128)) - { - /* short form */ - *len = 1; - ans = der[0]; - } - else - { - /* Long form */ - k = der[0] & 0x7F; - punt = 1; - if (k) - { /* definite length method */ - ans = 0; - while (punt <= k && punt < der_len) - { - last = ans; - - ans = (ans*256) + der[punt++]; - if (ans < last) - /* we wrapped around, no bignum support... */ - return -2; - } - } - else - { /* indefinite length method */ - *len = punt; - return -1; - } + unsigned int ans, sum, last; + int k, punt; + + *len = 0; + if (der_len <= 0) + return 0; + + if (!(der[0] & 128)) { + /* short form */ + *len = 1; + ans = der[0]; + } else { + /* Long form */ + k = der[0] & 0x7F; + punt = 1; + if (k) { /* definite length method */ + ans = 0; + while (punt <= k && punt < der_len) { + last = ans; + + ans = (ans * 256) + der[punt++]; + if (ans < last) + /* we wrapped around, no bignum support... */ + return -2; + } + } else { /* indefinite length method */ + *len = punt; + return -1; + } - *len = punt; - } + *len = punt; + } - sum = ans + *len; + sum = ans + *len; - /* check for overflow as well INT_MAX as a maximum upper - * limit for length */ - if (sum >= INT_MAX || sum < ans) - return -2; + /* check for overflow as well INT_MAX as a maximum upper + * limit for length */ + if (sum >= INT_MAX || sum < ans) + return -2; - if (((int) sum) > der_len) - return -4; + if (((int) sum) > der_len) + return -4; - return ans; + return ans; } /** @@ -127,52 +121,48 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len) * Returns: Returns %ASN1_SUCCESS on success, or an error. **/ int -asn1_get_tag_der (const unsigned char *der, int der_len, - unsigned char *cls, int *len, unsigned long *tag) +asn1_get_tag_der(const unsigned char *der, int der_len, + unsigned char *cls, int *len, unsigned long *tag) { - unsigned int ris; - int punt; - unsigned int last; - - if (der == NULL || der_len < 2 || len == NULL) - return ASN1_DER_ERROR; - - *cls = der[0] & 0xE0; - if ((der[0] & 0x1F) != 0x1F) - { - /* short form */ - *len = 1; - ris = der[0] & 0x1F; - } - else - { - /* Long form */ - punt = 1; - ris = 0; - while (punt <= der_len && der[punt] & 128) - { - last = ris; - - ris = (ris * 128) + (der[punt++] & 0x7F); - if (ris < last) - /* wrapped around, and no bignums... */ - return ASN1_DER_ERROR; - } + unsigned int ris; + int punt; + unsigned int last; - if (punt >= der_len) - return ASN1_DER_ERROR; + if (der == NULL || der_len < 2 || len == NULL) + return ASN1_DER_ERROR; - last = ris; + *cls = der[0] & 0xE0; + if ((der[0] & 0x1F) != 0x1F) { + /* short form */ + *len = 1; + ris = der[0] & 0x1F; + } else { + /* Long form */ + punt = 1; + ris = 0; + while (punt <= der_len && der[punt] & 128) { + last = ris; + + ris = (ris * 128) + (der[punt++] & 0x7F); + if (ris < last) + /* wrapped around, and no bignums... */ + return ASN1_DER_ERROR; + } + + if (punt >= der_len) + return ASN1_DER_ERROR; - ris = (ris * 128) + (der[punt++] & 0x7F); - if (ris < last) - return ASN1_DER_ERROR; + last = ris; - *len = punt; - } - if (tag) - *tag = ris; - return ASN1_SUCCESS; + ris = (ris * 128) + (der[punt++] & 0x7F); + if (ris < last) + return ASN1_DER_ERROR; + + *len = punt; + } + if (tag) + *tag = ris; + return ASN1_SUCCESS; } /** @@ -190,22 +180,20 @@ asn1_get_tag_der (const unsigned char *der, int der_len, * * Since: 2.0 **/ -long -asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len) +long asn1_get_length_ber(const unsigned char *ber, int ber_len, int *len) { - int ret; - long err; - - 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); - if (err != ASN1_SUCCESS) - return -3; - } - - return ret; + int ret; + long err; + + 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); + if (err != ASN1_SUCCESS) + return -3; + } + + return ret; } /** @@ -222,111 +210,109 @@ asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len) * Returns: Returns %ASN1_SUCCESS on success, or an error. **/ int -asn1_get_octet_der (const unsigned char *der, int der_len, - int *ret_len, unsigned char *str, int str_size, - int *str_len) +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; - if (der_len <= 0) - return ASN1_GENERIC_ERROR; + 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==NULL) return ASN1_SUCCESS; */ + *str_len = asn1_get_length_der(der, der_len, &len_len); - if (*str_len < 0) - return ASN1_DER_ERROR; + if (*str_len < 0) + return ASN1_DER_ERROR; - *ret_len = *str_len + len_len; - if (str_size >= *str_len) - memcpy (str, der + len_len, *str_len); - else - { - return ASN1_MEM_ERROR; - } + *ret_len = *str_len + len_len; + if (str_size >= *str_len) + memcpy(str, der + len_len, *str_len); + else { + return ASN1_MEM_ERROR; + } - return ASN1_SUCCESS; + return ASN1_SUCCESS; } /* Returns ASN1_SUCCESS on success or an error code on error. */ static int -_asn1_get_time_der (const unsigned char *der, int der_len, int *ret_len, - char *str, int str_size) +_asn1_get_time_der(const unsigned char *der, int der_len, int *ret_len, + char *str, int str_size) { - int len_len, str_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) - return ASN1_DER_ERROR; - memcpy (str, der + len_len, str_len); - str[str_len] = 0; - *ret_len = str_len + len_len; - - return ASN1_SUCCESS; + int len_len, str_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) + return ASN1_DER_ERROR; + memcpy(str, der + len_len, str_len); + str[str_len] = 0; + *ret_len = str_len + len_len; + + return ASN1_SUCCESS; } static int -_asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len, - char *str, int str_size) +_asn1_get_objectid_der(const unsigned char *der, int der_len, int *ret_len, + char *str, int str_size) { - int len_len, len, k; - int leading; - char temp[20]; - unsigned long val, val1, prev_val; - - *ret_len = 0; - if (str && str_size > 0) - str[0] = 0; /* no oid */ - - 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) - return ASN1_DER_ERROR; - - val1 = der[len_len] / 40; - val = der[len_len] - val1 * 40; - - _asn1_str_cpy (str, str_size, _asn1_ltostr (val1, temp)); - _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++) - { - /* X.690 mandates that the leading byte must never be 0x80 - */ - if (leading != 0 && der[len_len + k] == 0x80) - return ASN1_DER_ERROR; - leading = 0; - - /* check for wrap around */ - val = val << 7; - val |= der[len_len + k] & 0x7F; - - if (val < prev_val) - return ASN1_DER_ERROR; - - prev_val = val; - - 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; + int len_len, len, k; + int leading; + char temp[20]; + unsigned long val, val1, prev_val; + + *ret_len = 0; + if (str && str_size > 0) + str[0] = 0; /* no oid */ + + 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) + return ASN1_DER_ERROR; + + val1 = der[len_len] / 40; + val = der[len_len] - val1 * 40; + + _asn1_str_cpy(str, str_size, _asn1_ltostr(val1, temp)); + _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++) { + /* X.690 mandates that the leading byte must never be 0x80 + */ + if (leading != 0 && der[len_len + k] == 0x80) + return ASN1_DER_ERROR; + leading = 0; + + /* check for wrap around */ + val = val << 7; + val |= der[len_len + k] & 0x7F; + + if (val < prev_val) + return ASN1_DER_ERROR; + + prev_val = val; + + 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; + } } - } - *ret_len = len + len_len; + *ret_len = len + len_len; - return ASN1_SUCCESS; + return ASN1_SUCCESS; } /** @@ -343,433 +329,429 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len, * Returns: Return %ASN1_SUCCESS on success, or an error. **/ int -asn1_get_bit_der (const unsigned char *der, int der_len, - int *ret_len, unsigned char *str, int str_size, - int *bit_len) +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, 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; + 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; - *ret_len = len_byte + len_len + 1; - *bit_len = len_byte * 8 - der[len_len]; + *ret_len = len_byte + len_len + 1; + *bit_len = len_byte * 8 - der[len_len]; - if (str_size >= len_byte) - memcpy (str, der + len_len + 1, len_byte); - else - { - return ASN1_MEM_ERROR; - } + if (str_size >= len_byte) + memcpy(str, der + len_len + 1, len_byte); + else { + return ASN1_MEM_ERROR; + } - return ASN1_SUCCESS; + return ASN1_SUCCESS; } static int -_asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, - int *ret_len) +_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; - unsigned long tag, tag_implicit = 0; - unsigned char class, class2, class_implicit = 0; - - if (der_len <= 0) - return ASN1_GENERIC_ERROR; - - counter = is_tag_implicit = 0; - - if (node->type & CONST_TAG) - { - p = node->down; - while (p) - { - if (type_field (p->type) == ASN1_ETYPE_TAG) - { - if (p->type & CONST_APPLICATION) - class2 = ASN1_CLASS_APPLICATION; - else if (p->type & CONST_UNIVERSAL) - class2 = ASN1_CLASS_UNIVERSAL; - else if (p->type & CONST_PRIVATE) - class2 = ASN1_CLASS_PRIVATE; - else - class2 = ASN1_CLASS_CONTEXT_SPECIFIC; - - if (p->type & CONST_EXPLICIT) - { - if (asn1_get_tag_der - (der + counter, der_len - counter, &class, &len2, - &tag) != ASN1_SUCCESS) - return ASN1_DER_ERROR; - - if (counter + len2 > der_len) - return ASN1_DER_ERROR; - counter += len2; - - len3 = - asn1_get_length_ber (der + counter, der_len - counter, - &len2); - if (len3 < 0) - return ASN1_DER_ERROR; - - counter += len2; - if (counter > der_len) - return ASN1_DER_ERROR; - - if (!is_tag_implicit) - { - if ((class != (class2 | ASN1_CLASS_STRUCTURED)) || - (tag != strtoul ((char *) p->value, NULL, 10))) - return ASN1_TAG_ERROR; - } - else - { /* ASN1_TAG_IMPLICIT */ - if ((class != class_implicit) || (tag != tag_implicit)) - return ASN1_TAG_ERROR; - } - is_tag_implicit = 0; - } - else - { /* ASN1_TAG_IMPLICIT */ - 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)) - class2 |= ASN1_CLASS_STRUCTURED; - class_implicit = class2; - tag_implicit = strtoul ((char *) p->value, NULL, 10); - is_tag_implicit = 1; - } + asn1_node p; + int counter, len2, len3, is_tag_implicit; + unsigned long tag, tag_implicit = 0; + unsigned char class, class2, class_implicit = 0; + + if (der_len <= 0) + return ASN1_GENERIC_ERROR; + + counter = is_tag_implicit = 0; + + if (node->type & CONST_TAG) { + p = node->down; + while (p) { + if (type_field(p->type) == ASN1_ETYPE_TAG) { + if (p->type & CONST_APPLICATION) + class2 = ASN1_CLASS_APPLICATION; + else if (p->type & CONST_UNIVERSAL) + class2 = ASN1_CLASS_UNIVERSAL; + else if (p->type & CONST_PRIVATE) + class2 = ASN1_CLASS_PRIVATE; + else + class2 = + ASN1_CLASS_CONTEXT_SPECIFIC; + + if (p->type & CONST_EXPLICIT) { + if (asn1_get_tag_der + (der + counter, + der_len - counter, &class, + &len2, &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + + if (counter + len2 > der_len) + return ASN1_DER_ERROR; + counter += len2; + + len3 = + asn1_get_length_ber(der + + counter, + der_len - + counter, + &len2); + if (len3 < 0) + return ASN1_DER_ERROR; + + counter += len2; + if (counter > der_len) + return ASN1_DER_ERROR; + + if (!is_tag_implicit) { + if ((class != + (class2 | + ASN1_CLASS_STRUCTURED)) + || (tag != + strtoul((char *) + p->value, + NULL, 10))) + return + ASN1_TAG_ERROR; + } else { /* ASN1_TAG_IMPLICIT */ + if ((class != + class_implicit) + || (tag != + tag_implicit)) + return + ASN1_TAG_ERROR; + } + is_tag_implicit = 0; + } else { /* ASN1_TAG_IMPLICIT */ + 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)) + class2 |= + ASN1_CLASS_STRUCTURED; + class_implicit = class2; + tag_implicit = + strtoul((char *) p-> + value, NULL, + 10); + is_tag_implicit = 1; + } + } + } + p = p->right; } - } - p = p->right; - } - } - - if (is_tag_implicit) - { - if (asn1_get_tag_der - (der + counter, der_len - counter, &class, &len2, - &tag) != ASN1_SUCCESS) - return ASN1_DER_ERROR; - if (counter + len2 > der_len) - return ASN1_DER_ERROR; - - if ((class != class_implicit) || (tag != tag_implicit)) - { - if (type_field (node->type) == ASN1_ETYPE_OCTET_STRING) - { - class_implicit |= ASN1_CLASS_STRUCTURED; - if ((class != class_implicit) || (tag != tag_implicit)) - return ASN1_TAG_ERROR; - } - else - return ASN1_TAG_ERROR; - } - } - else - { - unsigned type = type_field (node->type); - if (type == ASN1_ETYPE_TAG) - { - counter = 0; - *ret_len = counter; - return ASN1_SUCCESS; } - if (asn1_get_tag_der - (der + counter, der_len - counter, &class, &len2, - &tag) != ASN1_SUCCESS) - return ASN1_DER_ERROR; - - if (counter + len2 > der_len) - return ASN1_DER_ERROR; - - switch (type) - { - case ASN1_ETYPE_NULL: - case ASN1_ETYPE_BOOLEAN: - case ASN1_ETYPE_INTEGER: - case ASN1_ETYPE_ENUMERATED: - case ASN1_ETYPE_OBJECT_ID: - 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: - case ASN1_ETYPE_SEQUENCE: - case ASN1_ETYPE_SEQUENCE_OF: - case ASN1_ETYPE_SET: - 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)) - return ASN1_DER_ERROR; - break; - - case ASN1_ETYPE_OCTET_STRING: - /* OCTET STRING is handled differently to allow - * BER encodings (structured class). */ - if (((class != ASN1_CLASS_UNIVERSAL) - && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))) - || (tag != ASN1_TAG_OCTET_STRING)) - return ASN1_DER_ERROR; - break; - case ASN1_ETYPE_ANY: - counter -= len2; - break; - default: - return ASN1_DER_ERROR; - break; - } - } + if (is_tag_implicit) { + if (asn1_get_tag_der + (der + counter, der_len - counter, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + if (counter + len2 > der_len) + return ASN1_DER_ERROR; - counter += len2; - *ret_len = counter; - return ASN1_SUCCESS; -} + if ((class != class_implicit) || (tag != tag_implicit)) { + if (type_field(node->type) == + ASN1_ETYPE_OCTET_STRING) { + class_implicit |= ASN1_CLASS_STRUCTURED; + if ((class != class_implicit) + || (tag != tag_implicit)) + return ASN1_TAG_ERROR; + } else + return ASN1_TAG_ERROR; + } + } else { + unsigned type = type_field(node->type); + if (type == ASN1_ETYPE_TAG) { + counter = 0; + *ret_len = counter; + return ASN1_SUCCESS; + } + + if (asn1_get_tag_der + (der + counter, der_len - counter, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; -static int -_asn1_delete_not_used (asn1_node node) -{ - asn1_node p, p2; - - if (node == NULL) - return ASN1_ELEMENT_NOT_FOUND; - - p = node; - while (p) - { - if (p->type & CONST_NOT_USED) - { - p2 = NULL; - if (p != node) - { - p2 = _asn1_find_left (p); - if (!p2) - p2 = _asn1_find_up (p); - } - asn1_delete_structure (&p); - p = p2; - } + if (counter + len2 > der_len) + return ASN1_DER_ERROR; - if (!p) - break; /* reach node */ + switch (type) { + case ASN1_ETYPE_NULL: + case ASN1_ETYPE_BOOLEAN: + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + case ASN1_ETYPE_OBJECT_ID: + 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: + case ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET: + 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)) + return ASN1_DER_ERROR; + break; - if (p->down) - { - p = p->down; + case ASN1_ETYPE_OCTET_STRING: + /* OCTET STRING is handled differently to allow + * BER encodings (structured class). */ + if (((class != ASN1_CLASS_UNIVERSAL) + && (class != + (ASN1_CLASS_UNIVERSAL | + ASN1_CLASS_STRUCTURED))) + || (tag != ASN1_TAG_OCTET_STRING)) + return ASN1_DER_ERROR; + break; + case ASN1_ETYPE_ANY: + counter -= len2; + break; + default: + return ASN1_DER_ERROR; + break; + } } - else - { - if (p == node) - p = NULL; - else if (p->right) - p = p->right; - else - { - while (1) - { - p = _asn1_find_up (p); - if (p == node) - { - p = NULL; - break; - } - if (p->right) - { - p = p->right; - break; - } + + counter += len2; + *ret_len = counter; + return ASN1_SUCCESS; +} + +static int _asn1_delete_not_used(asn1_node node) +{ + asn1_node p, p2; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + while (p) { + if (p->type & CONST_NOT_USED) { + p2 = NULL; + if (p != node) { + p2 = _asn1_find_left(p); + if (!p2) + p2 = _asn1_find_up(p); + } + asn1_delete_structure(&p); + p = p2; + } + + if (!p) + break; /* reach node */ + + if (p->down) { + p = p->down; + } else { + if (p == node) + p = NULL; + else if (p->right) + p = p->right; + else { + while (1) { + p = _asn1_find_up(p); + if (p == node) { + p = NULL; + break; + } + if (p->right) { + p = p->right; + break; + } + } + } } - } } - } - return ASN1_SUCCESS; + return ASN1_SUCCESS; } static int -_asn1_extract_der_octet (asn1_node node, const unsigned char *der, - int der_len) +_asn1_extract_der_octet(asn1_node node, const unsigned char *der, + int der_len) { - int len2, len3; - int counter2, counter_end; + int len2, len3; + int counter2, counter_end; - len2 = asn1_get_length_der (der, der_len, &len3); - if (len2 < -1) - return ASN1_DER_ERROR; + len2 = asn1_get_length_der(der, der_len, &len3); + if (len2 < -1) + return ASN1_DER_ERROR; - counter2 = len3 + 1; + counter2 = len3 + 1; - if (len2 == -1) - counter_end = der_len - 2; - else - counter_end = der_len; + if (len2 == -1) + counter_end = der_len - 2; + else + counter_end = der_len; - while (counter2 < counter_end) - { - len2 = asn1_get_length_der (der + counter2, der_len - counter2, &len3); + while (counter2 < counter_end) { + len2 = + asn1_get_length_der(der + counter2, der_len - counter2, + &len3); - if (len2 < -1) - return ASN1_DER_ERROR; + if (len2 < -1) + return ASN1_DER_ERROR; - if (len2 > 0) - { - _asn1_append_value (node, der + counter2 + len3, len2); - } - else - { /* indefinite */ - - len2 = - _asn1_extract_der_octet (node, der + counter2 + len3, - der_len - counter2 - len3); - if (len2 < 0) - return len2; - } + if (len2 > 0) { + _asn1_append_value(node, der + counter2 + len3, + len2); + } else { /* indefinite */ - counter2 += len2 + len3 + 1; - } + len2 = + _asn1_extract_der_octet(node, + der + counter2 + len3, + der_len - counter2 - + len3); + if (len2 < 0) + return len2; + } - return ASN1_SUCCESS; + counter2 += len2 + len3 + 1; + } + + return ASN1_SUCCESS; } static int -_asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len) +_asn1_get_octet_string(const unsigned char *der, asn1_node node, int *len) { - int len2, len3, counter, tot_len, indefinite; - - counter = 0; - - if (*(der - 1) & ASN1_CLASS_STRUCTURED) - { - tot_len = 0; - indefinite = asn1_get_length_der (der, *len, &len3); - if (indefinite < -1) - return ASN1_DER_ERROR; - - counter += 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)) - { - counter += 2; - break; - } - } - else if (counter >= indefinite) - break; + int len2, len3, counter, tot_len, indefinite; + + counter = 0; - if (der[counter] != ASN1_TAG_OCTET_STRING) - return ASN1_DER_ERROR; + if (*(der - 1) & ASN1_CLASS_STRUCTURED) { + tot_len = 0; + indefinite = asn1_get_length_der(der, *len, &len3); + if (indefinite < -1) + return ASN1_DER_ERROR; - counter++; + counter += len3; + if (indefinite >= 0) + indefinite += len3; - len2 = asn1_get_length_der (der + counter, *len - counter, &len3); - if (len2 <= 0) - return ASN1_DER_ERROR; + while (1) { + if (counter > (*len)) + return ASN1_DER_ERROR; - counter += len3 + len2; - tot_len += len2; - } + if (indefinite == -1) { + if ((der[counter] == 0) + && (der[counter + 1] == 0)) { + counter += 2; + break; + } + } else if (counter >= indefinite) + break; + + if (der[counter] != ASN1_TAG_OCTET_STRING) + return ASN1_DER_ERROR; - /* copy */ - if (node) - { - unsigned char temp[DER_LEN]; - int ret; + counter++; - len2 = sizeof (temp); + len2 = + asn1_get_length_der(der + counter, + *len - counter, &len3); + if (len2 <= 0) + return ASN1_DER_ERROR; - asn1_length_der (tot_len, temp, &len2); - _asn1_set_value (node, temp, len2); + counter += len3 + len2; + tot_len += len2; + } - ret = _asn1_extract_der_octet (node, der, *len); - if (ret != ASN1_SUCCESS) - return ret; + /* copy */ + if (node) { + unsigned char temp[DER_LEN]; + int ret; - } - } - else - { /* NOT STRUCTURED */ - len2 = asn1_get_length_der (der, *len, &len3); - if (len2 < 0) - return ASN1_DER_ERROR; + len2 = sizeof(temp); + + asn1_length_der(tot_len, temp, &len2); + _asn1_set_value(node, temp, len2); + + ret = _asn1_extract_der_octet(node, der, *len); + if (ret != ASN1_SUCCESS) + return ret; + + } + } else { /* NOT STRUCTURED */ + len2 = asn1_get_length_der(der, *len, &len3); + if (len2 < 0) + return ASN1_DER_ERROR; - counter = len3 + len2; - if (node) - _asn1_set_value (node, der, counter); - } + counter = len3 + len2; + if (node) + _asn1_set_value(node, der, counter); + } - *len = counter; - return ASN1_SUCCESS; + *len = counter; + return ASN1_SUCCESS; } static int -_asn1_get_indefinite_length_string (const unsigned char *der, int *len) +_asn1_get_indefinite_length_string(const unsigned char *der, int *len) { - int len2, len3, counter, indefinite; - unsigned long tag; - unsigned char class; - - counter = indefinite = 0; - - while (1) - { - if ((*len) < counter) - return ASN1_DER_ERROR; - - if ((der[counter] == 0) && (der[counter + 1] == 0)) - { - counter += 2; - indefinite--; - if (indefinite <= 0) - break; - else - continue; - } + int len2, len3, counter, indefinite; + unsigned long tag; + unsigned char class; - if (asn1_get_tag_der - (der + counter, *len - counter, &class, &len2, - &tag) != ASN1_SUCCESS) - return ASN1_DER_ERROR; - if (counter + len2 > *len) - return ASN1_DER_ERROR; - counter += len2; - len2 = asn1_get_length_der (der + counter, *len - counter, &len3); - if (len2 < -1) - return ASN1_DER_ERROR; - if (len2 == -1) - { - indefinite++; - counter += 1; - } - else - { - counter += len2 + len3; + counter = indefinite = 0; + + while (1) { + if ((*len) < counter) + return ASN1_DER_ERROR; + + if ((der[counter] == 0) && (der[counter + 1] == 0)) { + counter += 2; + indefinite--; + if (indefinite <= 0) + break; + else + continue; + } + + if (asn1_get_tag_der + (der + counter, *len - counter, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + if (counter + len2 > *len) + return ASN1_DER_ERROR; + counter += len2; + len2 = + asn1_get_length_der(der + counter, *len - counter, + &len3); + if (len2 < -1) + return ASN1_DER_ERROR; + if (len2 == -1) { + indefinite++; + counter += 1; + } else { + counter += len2 + len3; + } } - } - *len = counter; - return ASN1_SUCCESS; + *len = counter; + return ASN1_SUCCESS; } @@ -793,555 +775,563 @@ _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, - char *errorDescription) +asn1_der_decoding(asn1_node * element, const void *ider, int len, + char *errorDescription) { - asn1_node node, p, p2, p3; - char temp[128]; - int counter, len2, len3, len4, move, ris, tlen; - unsigned char class; - unsigned long tag; - int indefinite, result; - const unsigned char *der = ider; - - node = *element; - - if (errorDescription != NULL) - errorDescription[0] = 0; - - if (node == NULL) - return ASN1_ELEMENT_NOT_FOUND; - - if (node->type & CONST_OPTION) - { - result = ASN1_GENERIC_ERROR; - goto cleanup; - } - - 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 (len2 == -1) - { - if (!der[counter] && !der[counter + 1]) - { - p = p2; - move = UP; - counter += 2; - continue; - } - } - else 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); - } - } + asn1_node node, p, p2, p3; + char temp[128]; + int counter, len2, len3, len4, move, ris, tlen; + unsigned char class; + unsigned long tag; + int indefinite, result; + const unsigned char *der = ider; - 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 ((len2 != -1) && (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); + node = *element; - result = ASN1_TAG_ERROR; - goto cleanup; - } - } - else - counter += len2; - } + if (errorDescription != NULL) + errorDescription[0] = 0; - if (ris == ASN1_SUCCESS) - { - switch (type_field (p->type)) - { - case ASN1_ETYPE_NULL: - if (der[counter]) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - counter++; - move = RIGHT; - break; - case ASN1_ETYPE_BOOLEAN: - if (der[counter++] != 1) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - if (der[counter++] == 0) - _asn1_set_value (p, "F", 1); - else - _asn1_set_value (p, "T", 1); - 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 (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; - _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, - temp, sizeof (temp)); - if (result != ASN1_SUCCESS) + if (node->type & CONST_OPTION) { + result = ASN1_GENERIC_ERROR; goto cleanup; + } - 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, - sizeof (temp) - 1); - if (result != ASN1_SUCCESS) - goto cleanup; + 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 (len2 == -1) { + if (!der[counter] + && !der[counter + 1]) { + p = p2; + move = UP; + counter += 2; + continue; + } + } else 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; + } + } - 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); - if (result != ASN1_SUCCESS) - 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; + } + } - 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 (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); + } + } - _asn1_set_value (p, der + counter, len3 + len2); - 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 (len - counter + 1 > 0) - { - if ((der[counter]) || der[counter + 1]) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - } - else - { - result = ASN1_DER_ERROR; - goto cleanup; - } - counter += 2; - } - else - { /* definite length method */ - if (len2 != counter) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - } - move = RIGHT; - } - else - { /* move==DOWN || move==RIGHT */ - len3 = - asn1_get_length_der (der + counter, len - counter, &len2); - if (len3 < -1) - { - 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 == -1) - { /* indefinite length method */ - if ((counter + 2) > len) - { - result = ASN1_DER_ERROR; - goto cleanup; + if (p->down == NULL) { + if (!(p->type & CONST_OPTION)) { + result = ASN1_DER_ERROR; + goto cleanup; + } + } else + p = p->down; } - if ((der[counter]) || der[counter + 1]) - { - _asn1_append_sequence_set (p); - p = p->down; - while (p->right) - p = p->right; - move = RIGHT; - continue; - } - _asn1_set_value (p, NULL, 0); - counter += 2; - } - else - { /* definite length method */ - 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->type & CONST_OPTION) + || (p->type & CONST_DEFAULT)) { + 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); + 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; } - else - { /* move==DOWN || move==RIGHT */ - len3 = - asn1_get_length_der (der + counter, len - counter, &len2); - if (len3 < -1) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - counter += len2; - if (len3) - { - if (len3 > 0) - { /* definite length method */ - _asn1_ltostr (counter + len3, temp); - tlen = strlen (temp); - - if (tlen > 0) - _asn1_set_value (p, temp, tlen + 1); - } - else - { /* indefinite length method */ - _asn1_set_value (p, "-1", 3); + + if (ris == ASN1_SUCCESS) { + switch (type_field(p->type)) { + case ASN1_ETYPE_NULL: + if (der[counter]) { + result = ASN1_DER_ERROR; + goto cleanup; + } + counter++; + move = RIGHT; + break; + case ASN1_ETYPE_BOOLEAN: + if (der[counter++] != 1) { + result = ASN1_DER_ERROR; + goto cleanup; + } + if (der[counter++] == 0) + _asn1_set_value(p, "F", 1); + else + _asn1_set_value(p, "T", 1); + 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; + } + + _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, temp, + sizeof(temp)); + if (result != ASN1_SUCCESS) + goto cleanup; + + 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, + sizeof(temp) - 1); + if (result != ASN1_SUCCESS) + goto cleanup; + + 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); + 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; + } + + _asn1_set_value(p, der + counter, + len3 + len2); + 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 (len - counter + 1 > 0) { + if ((der[counter]) + || der[counter + + 1]) { + result = + ASN1_DER_ERROR; + goto cleanup; + } + } else { + result = + ASN1_DER_ERROR; + goto cleanup; + } + counter += 2; + } else { /* definite length method */ + if (len2 != counter) { + result = + ASN1_DER_ERROR; + goto cleanup; + } + } + move = RIGHT; + } else { /* move==DOWN || move==RIGHT */ + len3 = + asn1_get_length_der(der + + counter, + len - + counter, + &len2); + if (len3 < -1) { + 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 == -1) { /* indefinite length method */ + if ((counter + 2) > len) { + result = + ASN1_DER_ERROR; + goto cleanup; + } + + if ((der[counter]) + || der[counter + 1]) { + _asn1_append_sequence_set + (p); + p = p->down; + while (p->right) + p = p-> + right; + move = RIGHT; + continue; + } + _asn1_set_value(p, NULL, + 0); + counter += 2; + } else { /* definite length method */ + 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; + } + } + } else { /* move==DOWN || move==RIGHT */ + len3 = + asn1_get_length_der(der + + counter, + len - + counter, + &len2); + if (len3 < -1) { + result = ASN1_DER_ERROR; + goto cleanup; + } + counter += len2; + if (len3) { + if (len3 > 0) { /* definite length method */ + _asn1_ltostr + (counter + + len3, temp); + tlen = + strlen(temp); + + if (tlen > 0) + _asn1_set_value + (p, + temp, + tlen + + 1); + } else { /* indefinite length method */ + _asn1_set_value(p, + "-1", + 3); + } + 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; + } + } + move = RIGHT; + 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; + _asn1_set_value_lv(p, + der + counter, + len2 + len3); + 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; + + _asn1_set_value_lv(p, + der + counter, + len2); + 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; } - 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; - } - } - move = RIGHT; - 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; - _asn1_set_value_lv (p, der + counter, len2 + len3); - counter += len2 + len3; + if (p == node && move != DOWN) + break; + + if (move == DOWN) { + if (p->down) + p = p->down; + else + move = RIGHT; } - 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; - - _asn1_set_value_lv (p, der + counter, len2); - 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; - } - } + if ((move == RIGHT) && !(p->type & CONST_SET)) { + if (p->right) + p = p->right; + else + move = UP; } - move = RIGHT; - break; - default: - move = (move == UP) ? RIGHT : DOWN; - break; - } + if (move == UP) + p = _asn1_find_up(p); } - if (p == node && move != DOWN) - break; + _asn1_delete_not_used(*element); - if (move == DOWN) - { - if (p->down) - p = p->down; - else - move = RIGHT; - } - if ((move == RIGHT) && !(p->type & CONST_SET)) - { - if (p->right) - p = p->right; - else - move = UP; + if (counter != len) { + result = ASN1_DER_ERROR; + goto cleanup; } - if (move == UP) - p = _asn1_find_up (p); - } - - _asn1_delete_not_used (*element); - if (counter != len) - { - result = ASN1_DER_ERROR; - goto cleanup; - } + return ASN1_SUCCESS; - return ASN1_SUCCESS; - -cleanup: - asn1_delete_structure (element); - return result; + cleanup: + asn1_delete_structure(element); + return result; } #define FOUND 1 @@ -1371,779 +1361,796 @@ cleanup: * match the structure @structure (*ELEMENT deleted). **/ int -asn1_der_decoding_element (asn1_node * structure, const char *elementName, - const void *ider, int len, char *errorDescription) +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; + 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; } - else - { - state = SAME_BRANCH; + + if (node->type & CONST_OPTION) { + result = ASN1_GENERIC_ERROR; + goto cleanup; } - } - - 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; + + 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; } - 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; - } + } + + 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 (ris == ASN1_SUCCESS) - { - p2->type &= ~CONST_NOT_USED; - p = p2; - break; + + 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; + } } - } - 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); + + 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; } - 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); + 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; + } - result = ASN1_TAG_ERROR; - goto cleanup; + 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; } - } - 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 (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 (p == nodeFound) + state = EXIT; - if (state == FOUND) - { - if (der[counter++] == 0) - _asn1_set_value (p, "F", 1); - else - _asn1_set_value (p, "T", 1); + counter++; + move = RIGHT; + break; + case ASN1_ETYPE_BOOLEAN: + if (der[counter++] != 1) { + result = ASN1_DER_ERROR; + goto cleanup; + } - if (p == nodeFound) - state = EXIT; + if (state == FOUND) { + if (der[counter++] == 0) + _asn1_set_value(p, "F", 1); + else + _asn1_set_value(p, "T", 1); - } - 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 (p == nodeFound) + state = EXIT; - 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; - } + } else + counter++; - 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; - } + 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; + } - 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 (state == FOUND) { + if (len3 + len2 > len - counter) { + result = ASN1_DER_ERROR; + goto cleanup; + } + _asn1_set_value(p, der + counter, + len3 + len2); - if (result != ASN1_SUCCESS) - goto cleanup; + 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 += 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; - } + 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; + } - 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; + 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; } - 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 (state == FOUND) { + if (len3 + len2 > len - counter) { + result = ASN1_DER_ERROR; + goto cleanup; + } + _asn1_set_value(p, der + counter, + len3 + len2); - if (counter + len2 > len) - { - result = ASN1_DER_ERROR; - goto cleanup; - } + 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; + } - len4 = - asn1_get_length_der (der + counter + len2, - len - counter - len2, &len3); - if (len4 < -1) - { - 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; + } + } + } - 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; + 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; } - } } - move = RIGHT; - break; - default: - move = (move == UP) ? RIGHT : DOWN; - break; - } - } + if ((p == node && move != DOWN) || (state == EXIT)) + 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; + 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; } - } - 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 == 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++; + } - 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; + + 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; } - nameLen += strlen (currentName) - (dot_p - currentName); - *dot_p = 0; + if (move == UP) { + p = _asn1_find_up(p); - if (!(strcmp (currentName, elementName))) - { - state = FOUND; - nodeFound = 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; + } } - else - if (!memcmp (currentName, elementName, strlen (currentName))) - state = SAME_BRANCH; - else - state = OTHER_BRANCH; - } } - } - _asn1_delete_not_used (*structure); + _asn1_delete_not_used(*structure); - if (counter > len) - { - result = ASN1_DER_ERROR; - goto cleanup; - } + if (counter > len) { + result = ASN1_DER_ERROR; + goto cleanup; + } - return ASN1_SUCCESS; + return ASN1_SUCCESS; -cleanup: - asn1_delete_structure (structure); - return result; + cleanup: + asn1_delete_structure(structure); + return result; } /** @@ -2172,319 +2179,319 @@ cleanup: * doesn't match the structure ELEMENT. **/ int -asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, - const char *name_element, int *start, int *end) +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; - int counter, len2, len3, len4, move, ris; - unsigned char class; - unsigned long tag; - int indefinite; - const unsigned char *der = ider; - - node = element; - - if (node == NULL) - return ASN1_ELEMENT_NOT_FOUND; - - node_to_find = asn1_find_node (node, name_element); - - if (node_to_find == NULL) - return ASN1_ELEMENT_NOT_FOUND; - - if (node_to_find == node) - { - *start = 0; - *end = len - 1; - return ASN1_SUCCESS; - } - - if (node->type & CONST_OPTION) - return ASN1_GENERIC_ERROR; - - counter = 0; - move = DOWN; - p = node; - while (1) - { - if (p == NULL) - return ASN1_DER_ERROR; - - ris = ASN1_SUCCESS; - - if (move != UP) - { - if (p->type & CONST_SET) - { - p2 = _asn1_find_up (p); - if (p2 == NULL) - return ASN1_DER_ERROR; - - len2 = _asn1_strtol (p2->value, NULL, 10); - if (len2 == -1) - { - if (!der[counter] && !der[counter + 1]) - { - p = p2; - move = UP; - counter += 2; - continue; - } - } - else if (counter == len2) - { - p = p2; - move = UP; - continue; - } - else if (counter > len2) - return ASN1_DER_ERROR; + asn1_node node, node_to_find, p, p2, p3; + int counter, len2, len3, len4, move, ris; + unsigned char class; + unsigned long tag; + int indefinite; + const unsigned char *der = ider; + + node = element; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; - p2 = p2->down; - - while (p2) - { - 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); + node_to_find = asn1_find_node(node, name_element); + + if (node_to_find == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + if (node_to_find == node) { + *start = 0; + *end = len - 1; + return ASN1_SUCCESS; + } + + if (node->type & CONST_OPTION) + return ASN1_GENERIC_ERROR; + + counter = 0; + move = DOWN; + p = node; + while (1) { + if (p == NULL) + return ASN1_DER_ERROR; + + ris = ASN1_SUCCESS; + + if (move != UP) { + if (p->type & CONST_SET) { + p2 = _asn1_find_up(p); + if (p2 == NULL) + return ASN1_DER_ERROR; + + len2 = _asn1_strtol(p2->value, NULL, 10); + if (len2 == -1) { + if (!der[counter] + && !der[counter + 1]) { + p = p2; + move = UP; + counter += 2; + continue; + } + } else if (counter == len2) { + p = p2; + move = UP; + continue; + } else if (counter > len2) + return ASN1_DER_ERROR; + + p2 = p2->down; + + while (p2) { + 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); + } + if (ris == ASN1_SUCCESS) { + p2->type &= + ~CONST_NOT_USED; + p = p2; + break; + } + } + p2 = p2->right; + } + if (p2 == NULL) + return ASN1_DER_ERROR; } - if (ris == ASN1_SUCCESS) - { - p2->type &= ~CONST_NOT_USED; - p = p2; - break; + + if (p == node_to_find) + *start = counter; + + if (type_field(p->type) == ASN1_ETYPE_CHOICE) { + p = p->down; + if (p == NULL) + return ASN1_DER_ERROR; + + ris = + _asn1_extract_tag_der(p, der + counter, + len - counter, + &len2); + if (p == node_to_find) + *start = counter; } - } - p2 = p2->right; - } - if (p2 == NULL) - return ASN1_DER_ERROR; - } - - if (p == node_to_find) - *start = counter; - - if (type_field (p->type) == ASN1_ETYPE_CHOICE) - { - p = p->down; - if (p == NULL) - return ASN1_DER_ERROR; - - ris = - _asn1_extract_tag_der (p, der + counter, len - counter, - &len2); - if (p == node_to_find) - *start = counter; - } - - 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) - { - move = RIGHT; - } - else - { - return ASN1_TAG_ERROR; - } - } - else - counter += len2; - } - if (ris == ASN1_SUCCESS) - { - switch (type_field (p->type)) - { - case ASN1_ETYPE_NULL: - if (der[counter]) - return ASN1_DER_ERROR; - counter++; - move = RIGHT; - break; - case ASN1_ETYPE_BOOLEAN: - if (der[counter++] != 1) - return ASN1_DER_ERROR; - counter++; - move = RIGHT; - break; - case ASN1_ETYPE_OCTET_STRING: - len3 = len - counter; - ris = _asn1_get_octet_string (der + counter, NULL, &len3); - if (ris != ASN1_SUCCESS) - return ris; - counter += len3; - move = RIGHT; - break; - case ASN1_ETYPE_UTC_TIME: - case ASN1_ETYPE_GENERALIZED_TIME: - case ASN1_ETYPE_OBJECT_ID: - case ASN1_ETYPE_INTEGER: - case ASN1_ETYPE_ENUMERATED: - case ASN1_ETYPE_GENERALSTRING: - case ASN1_ETYPE_NUMERIC_STRING: - case ASN1_ETYPE_IA5_STRING: - case ASN1_ETYPE_TELETEX_STRING: - case ASN1_ETYPE_PRINTABLE_STRING: - case ASN1_ETYPE_UNIVERSAL_STRING: - case ASN1_ETYPE_BMP_STRING: - case ASN1_ETYPE_UTF8_STRING: - case ASN1_ETYPE_VISIBLE_STRING: - case ASN1_ETYPE_BIT_STRING: - len2 = - asn1_get_length_der (der + counter, len - counter, &len3); - if (len2 < 0) - return ASN1_DER_ERROR; - counter += len3 + len2; - move = RIGHT; - break; - case ASN1_ETYPE_SEQUENCE: - case ASN1_ETYPE_SET: - if (move != UP) - { - len3 = - asn1_get_length_der (der + counter, len - counter, &len2); - if (len3 < -1) - return ASN1_DER_ERROR; - counter += len2; - if (len3 == 0) - move = RIGHT; - else - move = DOWN; - } - else - { - if (!der[counter] && !der[counter + 1]) /* indefinite length method */ - counter += 2; - move = RIGHT; + 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) { + move = RIGHT; + } else { + return ASN1_TAG_ERROR; + } + } else + counter += len2; } - break; - case ASN1_ETYPE_SEQUENCE_OF: - case ASN1_ETYPE_SET_OF: - if (move != UP) - { - len3 = - asn1_get_length_der (der + counter, len - counter, &len2); - if (len3 < -1) - return ASN1_DER_ERROR; - counter += len2; - if ((len3 == -1) && !der[counter] && !der[counter + 1]) - counter += 2; - else if (len3) - { - p2 = p->down; - while ((type_field (p2->type) == ASN1_ETYPE_TAG) || - (type_field (p2->type) == ASN1_ETYPE_SIZE)) - p2 = p2->right; - p = p2; - } + + if (ris == ASN1_SUCCESS) { + switch (type_field(p->type)) { + case ASN1_ETYPE_NULL: + if (der[counter]) + return ASN1_DER_ERROR; + counter++; + move = RIGHT; + break; + case ASN1_ETYPE_BOOLEAN: + if (der[counter++] != 1) + return ASN1_DER_ERROR; + counter++; + move = RIGHT; + break; + case ASN1_ETYPE_OCTET_STRING: + len3 = len - counter; + ris = + _asn1_get_octet_string(der + counter, + NULL, &len3); + if (ris != ASN1_SUCCESS) + return ris; + counter += len3; + move = RIGHT; + break; + case ASN1_ETYPE_UTC_TIME: + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_OBJECT_ID: + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + case ASN1_ETYPE_BIT_STRING: + len2 = + asn1_get_length_der(der + counter, + len - counter, + &len3); + if (len2 < 0) + return ASN1_DER_ERROR; + counter += len3 + len2; + move = RIGHT; + break; + case ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_SET: + if (move != UP) { + len3 = + asn1_get_length_der(der + + counter, + len - + counter, + &len2); + if (len3 < -1) + return ASN1_DER_ERROR; + counter += len2; + if (len3 == 0) + move = RIGHT; + else + move = DOWN; + } else { + if (!der[counter] && !der[counter + 1]) /* indefinite length method */ + counter += 2; + move = RIGHT; + } + break; + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET_OF: + if (move != UP) { + len3 = + asn1_get_length_der(der + + counter, + len - + counter, + &len2); + if (len3 < -1) + return ASN1_DER_ERROR; + counter += len2; + if ((len3 == -1) && !der[counter] + && !der[counter + 1]) + counter += 2; + else if (len3) { + p2 = p->down; + while ((type_field + (p2->type) == + ASN1_ETYPE_TAG) + || + (type_field + (p2->type) == + ASN1_ETYPE_SIZE)) + p2 = p2->right; + p = p2; + } + } else { + if (!der[counter] && !der[counter + 1]) /* indefinite length method */ + counter += 2; + } + move = RIGHT; + break; + case ASN1_ETYPE_ANY: + if (asn1_get_tag_der + (der + counter, len - counter, &class, + &len2, &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + if (counter + len2 > len) + return ASN1_DER_ERROR; + + len4 = + asn1_get_length_der(der + counter + + len2, + len - counter - + len2, &len3); + if (len4 < -1) + return ASN1_DER_ERROR; + + if (len4 != -1) { + counter += len2 + len4 + 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; + ris = + _asn1_get_indefinite_length_string + (der + counter, &len2); + if (ris != ASN1_SUCCESS) + return ris; + 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 + return + ASN1_DER_ERROR; + } + } + move = RIGHT; + break; + default: + move = (move == UP) ? RIGHT : DOWN; + break; + } } - else - { - if (!der[counter] && !der[counter + 1]) /* indefinite length method */ - counter += 2; + + if ((p == node_to_find) && (move == RIGHT)) { + *end = counter - 1; + return ASN1_SUCCESS; } - move = RIGHT; - break; - case ASN1_ETYPE_ANY: - if (asn1_get_tag_der - (der + counter, len - counter, &class, &len2, - &tag) != ASN1_SUCCESS) - return ASN1_DER_ERROR; - if (counter + len2 > len) - return ASN1_DER_ERROR; - len4 = - asn1_get_length_der (der + counter + len2, - len - counter - len2, &len3); - if (len4 < -1) - return ASN1_DER_ERROR; + if (p == node && move != DOWN) + break; - if (len4 != -1) - { - counter += len2 + len4 + len3; + if (move == DOWN) { + if (p->down) + p = p->down; + else + move = RIGHT; } - 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; - ris = - _asn1_get_indefinite_length_string (der + counter, &len2); - if (ris != ASN1_SUCCESS) - return ris; - 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 - return ASN1_DER_ERROR; - } + if ((move == RIGHT) && !(p->type & CONST_SET)) { + if (p->right) + p = p->right; + else + move = UP; } - move = RIGHT; - break; - default: - move = (move == UP) ? RIGHT : DOWN; - break; - } - } - - if ((p == node_to_find) && (move == RIGHT)) - { - *end = counter - 1; - return ASN1_SUCCESS; + if (move == UP) + p = _asn1_find_up(p); } - if (p == node && move != DOWN) - break; - - if (move == DOWN) - { - if (p->down) - p = p->down; - else - move = RIGHT; - } - if ((move == RIGHT) && !(p->type & CONST_SET)) - { - if (p->right) - p = p->right; - else - move = UP; - } - if (move == UP) - p = _asn1_find_up (p); - } - - return ASN1_ELEMENT_NOT_FOUND; + return ASN1_ELEMENT_NOT_FOUND; } /** @@ -2503,216 +2510,236 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, * problem in OBJECT_ID -> TYPE association, or other error codes * depending on DER decoding. **/ -int -asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element) +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], - 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]; - - if ((definitions == NULL) || (*element == NULL)) - return ASN1_ELEMENT_NOT_FOUND; - - strcpy (definitionsName, definitions->name); - strcat (definitionsName, "."); - - p = *element; - while (p) - { - - switch (type_field (p->type)) - { - case ASN1_ETYPE_ANY: - if ((p->type & CONST_DEFINED_BY) && (p->value)) - { - /* search the "DEF_BY" element */ - p2 = p->down; - while ((p2) && (type_field (p2->type) != ASN1_ETYPE_CONSTANT)) - p2 = p2->right; - - if (!p2) - { - retCode = ASN1_ERROR_TYPE_ANY; - break; - } + char definitionsName[ASN1_MAX_NAME_SIZE], + 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]; + + if ((definitions == NULL) || (*element == NULL)) + return ASN1_ELEMENT_NOT_FOUND; + + strcpy(definitionsName, definitions->name); + strcat(definitionsName, "."); + + p = *element; + while (p) { + + switch (type_field(p->type)) { + case ASN1_ETYPE_ANY: + if ((p->type & CONST_DEFINED_BY) && (p->value)) { + /* search the "DEF_BY" element */ + p2 = p->down; + while ((p2) + && (type_field(p2->type) != + ASN1_ETYPE_CONSTANT)) + p2 = p2->right; + + if (!p2) { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } - p3 = _asn1_find_up (p); + p3 = _asn1_find_up(p); - if (!p3) - { - retCode = ASN1_ERROR_TYPE_ANY; - break; - } - - p3 = p3->down; - while (p3) - { - if (!(strcmp (p3->name, p2->name))) - break; - p3 = p3->right; - } + if (!p3) { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } - if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || - (p3->value == NULL)) - { + p3 = p3->down; + while (p3) { + if (!(strcmp(p3->name, p2->name))) + break; + p3 = p3->right; + } - p3 = _asn1_find_up (p); - p3 = _asn1_find_up (p3); + if ((!p3) + || (type_field(p3->type) != + ASN1_ETYPE_OBJECT_ID) + || (p3->value == NULL)) { - if (!p3) - { - retCode = ASN1_ERROR_TYPE_ANY; - break; - } + p3 = _asn1_find_up(p); + p3 = _asn1_find_up(p3); - p3 = p3->down; + if (!p3) { + retCode = + ASN1_ERROR_TYPE_ANY; + break; + } - while (p3) - { - if (!(strcmp (p3->name, p2->name))) - break; - p3 = p3->right; - } - - if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || - (p3->value == NULL)) - { - retCode = ASN1_ERROR_TYPE_ANY; - break; - } - } + p3 = p3->down; - /* search the OBJECT_ID into definitions */ - p2 = definitions->down; - while (p2) - { - if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && - (p2->type & CONST_ASSIGN)) - { - strcpy (name, definitionsName); - strcat (name, p2->name); - - len = ASN1_MAX_NAME_SIZE; - result = - asn1_read_value (definitions, name, value, &len); - - if ((result == ASN1_SUCCESS) - && (!_asn1_strcmp (p3->value, value))) - { - p2 = p2->right; /* pointer to the structure to - use for expansion */ - while ((p2) && (p2->type & CONST_ASSIGN)) - p2 = p2->right; - - if (p2) - { - strcpy (name, definitionsName); - strcat (name, p2->name); - - result = - asn1_create_element (definitions, name, &aux); - if (result == ASN1_SUCCESS) - { - _asn1_cpy_name (aux, p); - len2 = - asn1_get_length_der (p->value, - p->value_len, &len3); - if (len2 < 0) - return ASN1_DER_ERROR; - - result = - asn1_der_decoding (&aux, p->value + len3, - len2, - errorDescription); - if (result == ASN1_SUCCESS) - { - - _asn1_set_right (aux, p->right); - _asn1_set_right (p, aux); - - result = asn1_delete_structure (&p); - if (result == ASN1_SUCCESS) - { - p = aux; - aux = NULL; - break; + while (p3) { + if (! + (strcmp + (p3->name, p2->name))) + break; + p3 = p3->right; } - else - { /* error with asn1_delete_structure */ - asn1_delete_structure (&aux); - retCode = result; - break; + + if ((!p3) + || (type_field(p3->type) != + ASN1_ETYPE_OBJECT_ID) + || (p3->value == NULL)) { + retCode = + ASN1_ERROR_TYPE_ANY; + break; } - } - else - { /* error with asn1_der_decoding */ - retCode = result; - break; - } } - else - { /* error with asn1_create_element */ - retCode = result; - break; + + /* search the OBJECT_ID into definitions */ + p2 = definitions->down; + while (p2) { + if ((type_field(p2->type) == + ASN1_ETYPE_OBJECT_ID) + && (p2->type & CONST_ASSIGN)) { + strcpy(name, + definitionsName); + strcat(name, p2->name); + + len = ASN1_MAX_NAME_SIZE; + result = + asn1_read_value + (definitions, name, + value, &len); + + if ((result == + ASN1_SUCCESS) + && + (!_asn1_strcmp + (p3->value, value))) { + p2 = p2->right; /* pointer to the structure to + use for expansion */ + while ((p2) + && (p2-> + type & + CONST_ASSIGN)) + p2 = p2-> + right; + + if (p2) { + strcpy + (name, + definitionsName); + strcat + (name, + p2-> + name); + + result = + asn1_create_element + (definitions, + name, + &aux); + if (result + == + ASN1_SUCCESS) + { + _asn1_cpy_name + (aux, + p); + len2 = asn1_get_length_der(p->value, p->value_len, &len3); + if (len2 < 0) + return + ASN1_DER_ERROR; + + result + = + asn1_der_decoding + (&aux, + p-> + value + + + len3, + len2, + errorDescription); + if (result == ASN1_SUCCESS) { + + _asn1_set_right + (aux, + p-> + right); + _asn1_set_right + (p, + aux); + + result + = + asn1_delete_structure + (&p); + if (result == ASN1_SUCCESS) { + p = aux; + aux = NULL; + break; + } else { /* error with asn1_delete_structure */ + asn1_delete_structure + (&aux); + retCode + = + result; + break; + } + } else { /* error with asn1_der_decoding */ + retCode + = + result; + break; + } + } else { /* error with asn1_create_element */ + retCode + = + result; + break; + } + } else { /* error with the pointer to the structure to exapand */ + retCode = + ASN1_ERROR_TYPE_ANY; + break; + } + } + } + p2 = p2->right; + } /* end while */ + + if (!p2) { + retCode = ASN1_ERROR_TYPE_ANY; + break; } - } - else - { /* error with the pointer to the structure to exapand */ - retCode = ASN1_ERROR_TYPE_ANY; - break; - } + } - } - p2 = p2->right; - } /* end while */ - - if (!p2) - { - retCode = ASN1_ERROR_TYPE_ANY; - break; + break; + default: + break; } - } - break; - default: - break; - } - - if (p->down) - { - p = p->down; - } - else if (p == *element) - { - p = NULL; - break; - } - else if (p->right) - p = p->right; - else - { - while (1) - { - p = _asn1_find_up (p); - if (p == *element) - { - p = NULL; - break; - } - if (p->right) - { - p = p->right; - break; + if (p->down) { + p = p->down; + } else if (p == *element) { + p = NULL; + break; + } else if (p->right) + p = p->right; + else { + while (1) { + p = _asn1_find_up(p); + if (p == *element) { + p = NULL; + break; + } + if (p->right) { + p = p->right; + break; + } + } } - } } - } - return retCode; + return retCode; } /** @@ -2734,127 +2761,135 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element) * use for expansion, or other errors depending on DER decoding. **/ int -asn1_expand_octet_string (asn1_node definitions, asn1_node * element, - const char *octetName, const char *objectName) +asn1_expand_octet_string(asn1_node definitions, asn1_node * element, + const char *octetName, const char *objectName) { - char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE]; - int retCode = ASN1_SUCCESS, result; - int len, len2, len3; - asn1_node p2, aux = NULL; - asn1_node octetNode = NULL, objectNode = NULL; - char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; - - if ((definitions == NULL) || (*element == NULL)) - return ASN1_ELEMENT_NOT_FOUND; - - octetNode = asn1_find_node (*element, octetName); - if (octetNode == NULL) - return ASN1_ELEMENT_NOT_FOUND; - if (type_field (octetNode->type) != ASN1_ETYPE_OCTET_STRING) - return ASN1_ELEMENT_NOT_FOUND; - if (octetNode->value == NULL) - return ASN1_VALUE_NOT_FOUND; - - objectNode = asn1_find_node (*element, objectName); - if (objectNode == NULL) - return ASN1_ELEMENT_NOT_FOUND; - - if (type_field (objectNode->type) != ASN1_ETYPE_OBJECT_ID) - return ASN1_ELEMENT_NOT_FOUND; - - if (objectNode->value == NULL) - return ASN1_VALUE_NOT_FOUND; - - - /* search the OBJECT_ID into definitions */ - p2 = definitions->down; - while (p2) - { - if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && - (p2->type & CONST_ASSIGN)) - { - strcpy (name, definitions->name); - strcat (name, "."); - strcat (name, p2->name); - - len = sizeof (value); - result = asn1_read_value (definitions, name, value, &len); - - if ((result == ASN1_SUCCESS) - && (!_asn1_strcmp (objectNode->value, value))) - { - - p2 = p2->right; /* pointer to the structure to - use for expansion */ - while ((p2) && (p2->type & CONST_ASSIGN)) - p2 = p2->right; - - if (p2) - { - strcpy (name, definitions->name); - strcat (name, "."); - strcat (name, p2->name); - - result = asn1_create_element (definitions, name, &aux); - if (result == ASN1_SUCCESS) - { - _asn1_cpy_name (aux, octetNode); - len2 = - asn1_get_length_der (octetNode->value, - octetNode->value_len, &len3); - if (len2 < 0) - return ASN1_DER_ERROR; - - result = - asn1_der_decoding (&aux, octetNode->value + len3, - len2, errorDescription); - if (result == ASN1_SUCCESS) - { - - _asn1_set_right (aux, octetNode->right); - _asn1_set_right (octetNode, aux); - - result = asn1_delete_structure (&octetNode); - if (result == ASN1_SUCCESS) - { - aux = NULL; - break; - } - else - { /* error with asn1_delete_structure */ - asn1_delete_structure (&aux); - retCode = result; - break; - } - } - else - { /* error with asn1_der_decoding */ - retCode = result; - break; + char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE]; + int retCode = ASN1_SUCCESS, result; + int len, len2, len3; + asn1_node p2, aux = NULL; + asn1_node octetNode = NULL, objectNode = NULL; + char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + + if ((definitions == NULL) || (*element == NULL)) + return ASN1_ELEMENT_NOT_FOUND; + + octetNode = asn1_find_node(*element, octetName); + if (octetNode == NULL) + return ASN1_ELEMENT_NOT_FOUND; + if (type_field(octetNode->type) != ASN1_ETYPE_OCTET_STRING) + return ASN1_ELEMENT_NOT_FOUND; + if (octetNode->value == NULL) + return ASN1_VALUE_NOT_FOUND; + + objectNode = asn1_find_node(*element, objectName); + if (objectNode == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + if (type_field(objectNode->type) != ASN1_ETYPE_OBJECT_ID) + return ASN1_ELEMENT_NOT_FOUND; + + if (objectNode->value == NULL) + return ASN1_VALUE_NOT_FOUND; + + + /* search the OBJECT_ID into definitions */ + p2 = definitions->down; + while (p2) { + if ((type_field(p2->type) == ASN1_ETYPE_OBJECT_ID) && + (p2->type & CONST_ASSIGN)) { + strcpy(name, definitions->name); + strcat(name, "."); + strcat(name, p2->name); + + len = sizeof(value); + result = + asn1_read_value(definitions, name, value, + &len); + + if ((result == ASN1_SUCCESS) + && (!_asn1_strcmp(objectNode->value, value))) { + + p2 = p2->right; /* pointer to the structure to + use for expansion */ + while ((p2) && (p2->type & CONST_ASSIGN)) + p2 = p2->right; + + if (p2) { + strcpy(name, definitions->name); + strcat(name, "."); + strcat(name, p2->name); + + result = + asn1_create_element + (definitions, name, &aux); + if (result == ASN1_SUCCESS) { + _asn1_cpy_name(aux, + octetNode); + len2 = + asn1_get_length_der + (octetNode->value, + octetNode->value_len, + &len3); + if (len2 < 0) + return + ASN1_DER_ERROR; + + result = + asn1_der_decoding(&aux, + octetNode-> + value + + + len3, + len2, + errorDescription); + if (result == ASN1_SUCCESS) { + + _asn1_set_right + (aux, + octetNode-> + right); + _asn1_set_right + (octetNode, + aux); + + result = + asn1_delete_structure + (&octetNode); + if (result == + ASN1_SUCCESS) { + aux = NULL; + break; + } else { /* error with asn1_delete_structure */ + asn1_delete_structure + (&aux); + retCode = + result; + break; + } + } else { /* error with asn1_der_decoding */ + retCode = result; + break; + } + } else { /* error with asn1_create_element */ + retCode = result; + break; + } + } else { /* error with the pointer to the structure to exapand */ + retCode = ASN1_VALUE_NOT_VALID; + break; + } } - } - else - { /* error with asn1_create_element */ - retCode = result; - break; - } } - else - { /* error with the pointer to the structure to exapand */ - retCode = ASN1_VALUE_NOT_VALID; - break; - } - } - } - p2 = p2->right; + p2 = p2->right; - } + } - if (!p2) - retCode = ASN1_VALUE_NOT_VALID; + if (!p2) + retCode = ASN1_VALUE_NOT_VALID; - return retCode; + return retCode; } /** @@ -2871,45 +2906,46 @@ asn1_expand_octet_string (asn1_node definitions, asn1_node * element, * 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; - unsigned char class; - unsigned long tag; - long ret; - - if (der == NULL || der_len == 0) - return ASN1_VALUE_NOT_VALID; - - if (ETYPE_OK(etype) == 0) - return ASN1_VALUE_NOT_VALID; - - /* doesn't handle constructed classes */ - 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)) - return ASN1_DER_ERROR; - - p += tag_len; - der_len -= tag_len; - - ret = asn1_get_length_der (p, der_len, &len_len); - if (ret < 0) - return ASN1_DER_ERROR; - - p += len_len; - der_len -= len_len; - - *str_len = ret; - *str = p; - - return ASN1_SUCCESS; + int tag_len, len_len; + const unsigned char *p; + unsigned char class; + unsigned long tag; + long ret; + + if (der == NULL || der_len == 0) + return ASN1_VALUE_NOT_VALID; + + if (ETYPE_OK(etype) == 0) + return ASN1_VALUE_NOT_VALID; + + /* doesn't handle constructed classes */ + 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)) + return ASN1_DER_ERROR; + + p += tag_len; + der_len -= tag_len; + + ret = asn1_get_length_der(p, der_len, &len_len); + if (ret < 0) + return ASN1_DER_ERROR; + + p += len_len; + der_len -= len_len; + + *str_len = ret; + *str = p; + + return ASN1_SUCCESS; } |