diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2014-05-25 21:37:19 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2014-05-29 19:02:34 +0200 |
commit | 492ddda46fe985b0001128a287193e611079fd17 (patch) | |
tree | 54ad8162fca1f1e1b86a01ff46ccc69580da6afc | |
parent | e933e7d8bb32d7d0936510eba3120f94e15d9b97 (diff) | |
download | gnutls-492ddda46fe985b0001128a287193e611079fd17.tar.gz |
updated libtasn1
-rw-r--r-- | lib/minitasn1/coding.c | 265 | ||||
-rw-r--r-- | lib/minitasn1/decoding.c | 1520 | ||||
-rw-r--r-- | lib/minitasn1/element.c | 204 | ||||
-rw-r--r-- | lib/minitasn1/element.h | 6 | ||||
-rw-r--r-- | lib/minitasn1/errors.c | 6 | ||||
-rw-r--r-- | lib/minitasn1/gstr.c | 5 | ||||
-rw-r--r-- | lib/minitasn1/gstr.h | 20 | ||||
-rw-r--r-- | lib/minitasn1/int.h | 23 | ||||
-rw-r--r-- | lib/minitasn1/libtasn1.h | 83 | ||||
-rw-r--r-- | lib/minitasn1/parser_aux.c | 68 | ||||
-rw-r--r-- | lib/minitasn1/parser_aux.h | 7 | ||||
-rw-r--r-- | lib/minitasn1/structure.c | 72 | ||||
-rw-r--r-- | lib/minitasn1/structure.h | 5 | ||||
-rw-r--r-- | lib/minitasn1/version.c | 2 |
14 files changed, 953 insertions, 1333 deletions
diff --git a/lib/minitasn1/coding.c b/lib/minitasn1/coding.c index 5361b3f068..d6b7cf4114 100644 --- a/lib/minitasn1/coding.c +++ b/lib/minitasn1/coding.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -30,6 +30,7 @@ #include "parser_aux.h" #include <gstr.h> #include "element.h" +#include "minmax.h" #include <structure.h> #define MAX_TAG_LEN 16 @@ -61,13 +62,13 @@ _asn1_error_description_value_not_found (asn1_node node, /** * asn1_length_der: * @len: value to convert. - * @der: the encoding (may be %NULL). + * @der: buffer to hold the returned encoding (may be %NULL). * @der_len: number of meaningful bytes of ANS (der[0]..der[der_len-1]). * * Creates the DER encoding of the provided length value. * The @der buffer must have enough room for the output. The maximum * length this function will encode is %ASN1_MAX_LENGTH_SIZE. - * + * * To know the size of the DER encoding use a %NULL value for @der. **/ void @@ -140,9 +141,9 @@ _asn1_tag_der (unsigned char class, unsigned int tag_value, { temp[k++] = tag_value & 0x7F; tag_value >>= 7; - - if (k > ASN1_MAX_TAG_SIZE-1) - break; /* will not encode larger tags */ + + if (k > ASN1_MAX_TAG_SIZE - 1) + break; /* will not encode larger tags */ } *ans_len = k + 1; while (k--) @@ -192,52 +193,52 @@ asn1_octet_der (const unsigned char *str, int str_len, * @tl_len: the bytes of the @tl field * * Creates the DER encoding for various simple ASN.1 types like strings etc. - * It stores the tag and length in @tl, which should have space for at least + * It stores the tag and length in @tl, which should have space for at least * %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl. * * The complete DER encoding should consist of the value in @tl appended * with the provided @str. * - * Returns: %ASN1_SUCCESS if successful or an error value. + * Returns: %ASN1_SUCCESS if successful or an error value. **/ int -asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned int str_len, - unsigned char *tl, unsigned int *tl_len) +asn1_encode_simple_der (unsigned int etype, const unsigned char *str, + unsigned int str_len, unsigned char *tl, + unsigned int *tl_len) { int tag_len, len_len; unsigned tlen; unsigned char der_tag[ASN1_MAX_TAG_SIZE]; unsigned char der_length[ASN1_MAX_LENGTH_SIZE]; - unsigned char* p; + unsigned char *p; if (str == NULL) return ASN1_VALUE_NOT_VALID; - if (ETYPE_OK(etype) == 0) + if (ETYPE_OK (etype) == 0) return ASN1_VALUE_NOT_VALID; /* doesn't handle constructed classes */ - if (ETYPE_CLASS(etype) != ASN1_CLASS_UNIVERSAL) + if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL) return ASN1_VALUE_NOT_VALID; - _asn1_tag_der (ETYPE_CLASS(etype), ETYPE_TAG(etype), - der_tag, &tag_len); + _asn1_tag_der (ETYPE_CLASS (etype), ETYPE_TAG (etype), der_tag, &tag_len); - asn1_length_der(str_len, der_length, &len_len); + asn1_length_der (str_len, der_length, &len_len); if (tag_len <= 0 || len_len <= 0) return ASN1_VALUE_NOT_VALID; - + tlen = tag_len + len_len; if (*tl_len < tlen) return ASN1_MEM_ERROR; p = tl; - memcpy(p, der_tag, tag_len); - p+=tag_len; - memcpy(p, der_length, len_len); - + memcpy (p, der_tag, tag_len); + p += tag_len; + memcpy (p, der_length, len_len); + *tl_len = tlen; return ASN1_SUCCESS; @@ -258,7 +259,8 @@ asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned i /* ASN1_SUCCESS otherwise */ /******************************************************/ static int -_asn1_time_der (unsigned char *str, int str_len, unsigned char *der, int *der_len) +_asn1_time_der (unsigned char *str, int str_len, unsigned char *der, + int *der_len) { int len_len; int max_len; @@ -326,7 +328,8 @@ _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str) /* must store the length of DER. */ /* Return: */ /* ASN1_MEM_ERROR when DER isn't big enough */ -/* ASN1_SUCCESS otherwise */ +/* ASN1_SUCCESS if succesful */ +/* or an error value. */ /******************************************************/ static int _asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len) @@ -473,6 +476,8 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der, if (node->type & CONST_TAG) { p = node->down; + if (p == NULL) + return ASN1_DER_ERROR; /* When there are nested tags we must complete them reverse to the order they were created. This is because completing a tag modifies all data within it, including the incomplete tags @@ -517,33 +522,56 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der, return ASN1_SUCCESS; } -const tag_and_class_st _asn1_tags[] = -{ - [ASN1_ETYPE_GENERALSTRING] = {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"}, - [ASN1_ETYPE_NUMERIC_STRING] = {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"}, - [ASN1_ETYPE_IA5_STRING] = {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"}, - [ASN1_ETYPE_TELETEX_STRING] = {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"}, - [ASN1_ETYPE_PRINTABLE_STRING] = {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"}, - [ASN1_ETYPE_UNIVERSAL_STRING] = {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"}, - [ASN1_ETYPE_BMP_STRING] = {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"}, - [ASN1_ETYPE_UTF8_STRING] = {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"}, - [ASN1_ETYPE_VISIBLE_STRING] = {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"}, - [ASN1_ETYPE_OCTET_STRING] = {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"}, - [ASN1_ETYPE_BIT_STRING] = {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"}, - [ASN1_ETYPE_OBJECT_ID] = {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"}, - [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"}, - [ASN1_ETYPE_BOOLEAN] = {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"}, - [ASN1_ETYPE_INTEGER] = {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"}, - [ASN1_ETYPE_ENUMERATED] = {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"}, - [ASN1_ETYPE_SEQUENCE] = {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SEQUENCE"}, - [ASN1_ETYPE_SEQUENCE_OF] ={ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SEQ_OF"}, - [ASN1_ETYPE_SET] = {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"}, - [ASN1_ETYPE_SET_OF] = {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET_OF"}, - [ASN1_ETYPE_GENERALIZED_TIME] = {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"}, - [ASN1_ETYPE_UTC_TIME] = {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"}, +const tag_and_class_st _asn1_tags[] = { + [ASN1_ETYPE_GENERALSTRING] = + {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"}, + [ASN1_ETYPE_NUMERIC_STRING] = + {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"}, + [ASN1_ETYPE_IA5_STRING] = + {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"}, + [ASN1_ETYPE_TELETEX_STRING] = + {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"}, + [ASN1_ETYPE_PRINTABLE_STRING] = + {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"}, + [ASN1_ETYPE_UNIVERSAL_STRING] = + {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"}, + [ASN1_ETYPE_BMP_STRING] = + {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"}, + [ASN1_ETYPE_UTF8_STRING] = + {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"}, + [ASN1_ETYPE_VISIBLE_STRING] = + {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"}, + [ASN1_ETYPE_OCTET_STRING] = + {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"}, + [ASN1_ETYPE_BIT_STRING] = + {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"}, + [ASN1_ETYPE_OBJECT_ID] = + {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"}, + [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"}, + [ASN1_ETYPE_BOOLEAN] = + {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"}, + [ASN1_ETYPE_INTEGER] = + {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"}, + [ASN1_ETYPE_ENUMERATED] = + {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"}, + [ASN1_ETYPE_SEQUENCE] = + {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, + "type:SEQUENCE"}, + [ASN1_ETYPE_SEQUENCE_OF] = + {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, + "type:SEQ_OF"}, + [ASN1_ETYPE_SET] = + {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"}, + [ASN1_ETYPE_SET_OF] = + {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, + "type:SET_OF"}, + [ASN1_ETYPE_GENERALIZED_TIME] = + {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"}, + [ASN1_ETYPE_UTC_TIME] = + {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"}, }; -unsigned int _asn1_tags_size = sizeof(_asn1_tags)/sizeof(_asn1_tags[0]); +unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]); /******************************************************/ /* Function : _asn1_insert_tag_der */ @@ -566,7 +594,7 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter, { asn1_node p; int tag_len, is_tag_implicit; - unsigned char class, class_implicit = 0, temp[SIZEOF_UNSIGNED_INT * 3 + 1]; + unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)]; unsigned long tag_implicit = 0; unsigned char tag_der[MAX_TAG_LEN]; @@ -613,9 +641,9 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter, if (!is_tag_implicit) { if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || - (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) || - (type_field (node->type) == ASN1_ETYPE_SET) || - (type_field (node->type) == ASN1_ETYPE_SET_OF)) + (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) + || (type_field (node->type) == ASN1_ETYPE_SET) + || (type_field (node->type) == ASN1_ETYPE_SET_OF)) class |= ASN1_CLASS_STRUCTURED; class_implicit = class; tag_implicit = _asn1_strtoul (p->value, NULL, 10); @@ -636,7 +664,7 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter, unsigned type = type_field (node->type); switch (type) { - CASE_HANDLED_ETYPES: + CASE_HANDLED_ETYPES: _asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag, tag_der, &tag_len); break; @@ -669,8 +697,10 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter, /* der: string with the DER coding. */ /* node: pointer to the SET element. */ /* Return: */ +/* ASN1_SUCCESS if successful */ +/* or an error value. */ /******************************************************/ -static void +static int _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) { struct vet @@ -684,27 +714,31 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) struct vet *first, *last, *p_vet, *p2_vet; asn1_node p; unsigned char class, *temp; - unsigned long tag; + unsigned long tag, t; + int err; counter = 0; if (type_field (node->type) != ASN1_ETYPE_SET) - return; + return ASN1_VALUE_NOT_VALID; p = node->down; - while ((type_field (p->type) == ASN1_ETYPE_TAG) - || (type_field (p->type) == ASN1_ETYPE_SIZE)) + while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || + (type_field (p->type) == ASN1_ETYPE_SIZE))) p = p->right; if ((p == NULL) || (p->right == NULL)) - return; + return ASN1_SUCCESS; first = last = NULL; while (p) { p_vet = malloc (sizeof (struct vet)); if (p_vet == NULL) - return; + { + err = ASN1_MEM_ALLOC_ERROR; + goto error; + } p_vet->next = NULL; p_vet->prev = last; @@ -715,17 +749,22 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) last = p_vet; /* tag value calculation */ - if (asn1_get_tag_der - (der + counter, der_len - counter, &class, &len2, - &tag) != ASN1_SUCCESS) - return; - p_vet->value = (class << 24) | tag; + err = asn1_get_tag_der (der + counter, der_len - counter, &class, &len2, + &tag); + if (err != ASN1_SUCCESS) + goto error; + + t = class << 24; + p_vet->value = t | tag; counter += len2; /* extraction and length */ len2 = asn1_get_length_der (der + counter, der_len - counter, &len); if (len2 < 0) - return; + { + err = ASN1_DER_ERROR; + goto error; + } counter += len + len2; p_vet->end = counter; @@ -745,7 +784,10 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) /* change position */ temp = malloc (p_vet->end - counter); if (temp == NULL) - return; + { + err = ASN1_MEM_ALLOC_ERROR; + goto error; + } memcpy (temp, der + counter, p_vet->end - counter); memcpy (der + counter, der + p_vet->end, @@ -773,6 +815,16 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) free (p_vet); p_vet = first; } + return ASN1_SUCCESS; + +error: + while (first != NULL) + { + p_vet = first; + first = first->next; + free(p_vet); + } + return err; } /******************************************************/ @@ -783,8 +835,10 @@ _asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) /* der: string with the DER coding. */ /* node: pointer to the SET OF element. */ /* Return: */ +/* ASN1_SUCCESS if successful */ +/* or an error value. */ /******************************************************/ -static void +static int _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) { struct vet @@ -797,28 +851,34 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) struct vet *first, *last, *p_vet, *p2_vet; asn1_node p; unsigned char *temp, class; - unsigned long k, max; + unsigned long k, length; + int err; counter = 0; if (type_field (node->type) != ASN1_ETYPE_SET_OF) - return; + return ASN1_VALUE_NOT_VALID; p = node->down; - while ((type_field (p->type) == ASN1_ETYPE_TAG) - || (type_field (p->type) == ASN1_ETYPE_SIZE)) + while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || + (type_field (p->type) == ASN1_ETYPE_SIZE))) p = p->right; + if (p == NULL) + return ASN1_VALUE_NOT_VALID; p = p->right; if ((p == NULL) || (p->right == NULL)) - return; + return ASN1_SUCCESS; first = last = NULL; while (p) { p_vet = malloc (sizeof (struct vet)); if (p_vet == NULL) - return; + { + err = ASN1_MEM_ALLOC_ERROR; + goto error; + } p_vet->next = NULL; p_vet->prev = last; @@ -832,17 +892,25 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) if (der_len - counter > 0) { - if (asn1_get_tag_der - (der + counter, der_len - counter, &class, &len, - NULL) != ASN1_SUCCESS) - return; + err = asn1_get_tag_der (der + counter, der_len - counter, &class, + &len, NULL); + if (err != ASN1_SUCCESS) + goto error; counter += len; len2 = asn1_get_length_der (der + counter, der_len - counter, &len); if (len2 < 0) - return; + { + err = ASN1_DER_ERROR; + goto error; + } counter += len + len2; } + else + { + err = ASN1_DER_ERROR; + goto error; + } p_vet->end = counter; p = p->right; @@ -856,13 +924,9 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) counter = 0; while (p2_vet) { - if ((p_vet->end - counter) > (p2_vet->end - p_vet->end)) - max = p_vet->end - counter; - else - max = p2_vet->end - p_vet->end; - + length = MIN(p_vet->end - counter, p2_vet->end - p_vet->end); change = -1; - for (k = 0; k < max; k++) + for (k = 0; k < length; k++) if (der[counter + k] > der[p_vet->end + k]) { change = 1; @@ -883,7 +947,10 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) /* change position */ temp = malloc (p_vet->end - counter); if (temp == NULL) - return; + { + err = ASN1_MEM_ALLOC_ERROR; + goto error; + } memcpy (temp, der + counter, (p_vet->end) - counter); memcpy (der + counter, der + (p_vet->end), @@ -907,6 +974,16 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) free (p_vet); p_vet = first; } + return ASN1_SUCCESS; + +error: + while (first != NULL) + { + p_vet = first; + first = first->next; + free(p_vet); + } + return err; } /** @@ -918,7 +995,7 @@ _asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) * pointer to memory cells already allocated. * @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy * holds the sizeof of der vector. - * @errorDescription : return the error description or an empty + * @ErrorDescription: return the error description or an empty * string if success. * * Creates the DER encoding for the NAME structure (inside *POINTER @@ -935,7 +1012,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, char *ErrorDescription) { asn1_node node, p, p2; - unsigned char temp[SIZEOF_UNSIGNED_LONG_INT * 3 + 1]; + unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)]; int counter, counter_old, len2, len3, tlen, move, max_len, max_len_old; int err; unsigned char *der = ider; @@ -1139,7 +1216,11 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, len2 = _asn1_strtol (p->value, NULL, 10); _asn1_set_value (p, NULL, 0); if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0)) - _asn1_ordering_set (der + len2, max_len - len2, p); + { + err = _asn1_ordering_set (der + len2, counter - len2, p); + if (err != ASN1_SUCCESS) + goto error; + } asn1_length_der (counter - len2, temp, &len3); max_len -= len3; if (max_len >= 0) @@ -1179,9 +1260,11 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, len2 = _asn1_strtol (p->value, NULL, 10); _asn1_set_value (p, NULL, 0); if ((type_field (p->type) == ASN1_ETYPE_SET_OF) - && (max_len - len2 > 0)) + && (counter - len2 > 0) && (max_len >= 0)) { - _asn1_ordering_set_of (der + len2, max_len - len2, p); + err = _asn1_ordering_set_of (der + len2, counter - len2, p); + if (err != ASN1_SUCCESS) + goto error; } asn1_length_der (counter - len2, temp, &len3); max_len -= len3; diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c index f02fe10686..a9aecc254b 100644 --- a/lib/minitasn1/decoding.c +++ b/lib/minitasn1/decoding.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -26,14 +26,32 @@ /*****************************************************/ #include <int.h> -#include "parser_aux.h" +#include <parser_aux.h> #include <gstr.h> -#include "structure.h" -#include "element.h" +#include <structure.h> +#include <element.h> #include <limits.h> +#include <intprops.h> + +#ifdef DEBUG +# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__) +#else +# define warn() +#endif + +#define HAVE_TWO(x) (x>=2?1:0) + +#define DECR_LEN(l, s) do { \ + l -= s; \ + if (l < 0) { \ + warn(); \ + result = ASN1_DER_ERROR; \ + goto cleanup; \ + } \ + } while (0) static int -_asn1_get_indefinite_length_string (const unsigned char *der, int *len); +_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int *len); static void _asn1_error_description_tag_error (asn1_node node, char *ErrorDescription) @@ -61,8 +79,8 @@ _asn1_error_description_tag_error (asn1_node node, char *ErrorDescription) long asn1_get_length_der (const unsigned char *der, int der_len, int *len) { - unsigned int ans, sum, last; - int k, punt; + unsigned int ans; + int k, punt, sum; *len = 0; if (der_len <= 0) @@ -84,12 +102,14 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len) ans = 0; while (punt <= k && punt < der_len) { - last = ans; + if (INT_MULTIPLY_OVERFLOW (ans, 256)) + return -2; + ans *= 256; - ans = (ans*256) + der[punt++]; - if (ans < last) - /* we wrapped around, no bignum support... */ + if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt]))) return -2; + ans += der[punt]; + punt++; } } else @@ -101,14 +121,12 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len) *len = punt; } - sum = ans + *len; - - /* check for overflow as well INT_MAX as a maximum upper - * limit for length */ - if (sum >= INT_MAX || sum < ans) + sum = ans; + if (ans >= INT_MAX || INT_ADD_OVERFLOW (sum, (*len))) return -2; + sum += *len; - if (((int) sum) > der_len) + if (sum > der_len) return -4; return ans; @@ -132,7 +150,6 @@ asn1_get_tag_der (const unsigned char *der, int der_len, { unsigned int ris; int punt; - unsigned int last; if (der == NULL || der_len < 2 || len == NULL) return ASN1_DER_ERROR; @@ -149,27 +166,34 @@ asn1_get_tag_der (const unsigned char *der, int der_len, /* Long form */ punt = 1; ris = 0; - while (punt <= der_len && der[punt] & 128) + while (punt < der_len && der[punt] & 128) { - last = ris; - ris = (ris * 128) + (der[punt++] & 0x7F); - if (ris < last) - /* wrapped around, and no bignums... */ + if (INT_MULTIPLY_OVERFLOW (ris, 128)) + return ASN1_DER_ERROR; + ris *= 128; + + if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F)))) return ASN1_DER_ERROR; + ris += (der[punt] & 0x7F); + punt++; } if (punt >= der_len) return ASN1_DER_ERROR; - last = ris; + if (INT_MULTIPLY_OVERFLOW (ris, 128)) + return ASN1_DER_ERROR; + ris *= 128; - ris = (ris * 128) + (der[punt++] & 0x7F); - if (ris < last) + if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F)))) return ASN1_DER_ERROR; + ris += (der[punt] & 0x7F); + punt++; *len = punt; } + if (tag) *tag = ris; return ASN1_SUCCESS; @@ -199,8 +223,7 @@ asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len) ret = asn1_get_length_der (ber, ber_len, len); if (ret == -1) { /* indefinite length method */ - ret = ber_len; - err = _asn1_get_indefinite_length_string (ber + 1, &ret); + err = _asn1_get_indefinite_length_string (ber + 1, ber_len, &ret); if (err != ASN1_SUCCESS) return -3; } @@ -226,12 +249,11 @@ asn1_get_octet_der (const unsigned char *der, int der_len, int *ret_len, unsigned char *str, int str_size, int *str_len) { - int len_len; + int len_len = 0; if (der_len <= 0) return ASN1_GENERIC_ERROR; - /* if(str==NULL) return ASN1_SUCCESS; */ *str_len = asn1_get_length_der (der, der_len, &len_len); if (*str_len < 0) @@ -239,7 +261,10 @@ asn1_get_octet_der (const unsigned char *der, int der_len, *ret_len = *str_len + len_len; if (str_size >= *str_len) - memcpy (str, der + len_len, *str_len); + { + if (*str_len > 0 && str != NULL) + memcpy (str, der + len_len, *str_len); + } else { return ASN1_MEM_ERROR; @@ -258,9 +283,11 @@ _asn1_get_time_der (const unsigned char *der, int der_len, int *ret_len, if (der_len <= 0 || str == NULL) return ASN1_DER_ERROR; + str_len = asn1_get_length_der (der, der_len, &len_len); - if (str_len < 0 || str_size < str_len) + if (str_len <= 0 || str_size < str_len) return ASN1_DER_ERROR; + memcpy (str, der + len_len, str_len); str[str_len] = 0; *ret_len = str_len + len_len; @@ -274,8 +301,8 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len, { int len_len, len, k; int leading; - char temp[20]; - unsigned long val, val1, prev_val; + char temp[LTOSTR_MAX_SIZE]; + unsigned long val, val1; *ret_len = 0; if (str && str_size > 0) @@ -283,9 +310,10 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len, if (str == NULL || der_len <= 0) return ASN1_GENERIC_ERROR; + len = asn1_get_length_der (der, der_len, &len_len); - if (len < 0 || len > der_len || len_len > der_len) + if (len <= 0 || len + len_len > der_len) return ASN1_DER_ERROR; val1 = der[len_len] / 40; @@ -295,7 +323,6 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len, _asn1_str_cat (str, str_size, "."); _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp)); - prev_val = 0; val = 0; leading = 1; for (k = 1; k < len; k++) @@ -307,23 +334,24 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len, leading = 0; /* check for wrap around */ - val = val << 7; - val |= der[len_len + k] & 0x7F; - - if (val < prev_val) + if (INT_LEFT_SHIFT_OVERFLOW (val, 7)) return ASN1_DER_ERROR; - prev_val = val; + val = val << 7; + val |= der[len_len + k] & 0x7F; if (!(der[len_len + k] & 0x80)) { _asn1_str_cat (str, str_size, "."); _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp)); val = 0; - prev_val = 0; leading = 1; } } + + if (INT_ADD_OVERFLOW (len, len_len)) + return ASN1_DER_ERROR; + *ret_len = len + len_len; return ASN1_SUCCESS; @@ -347,10 +375,11 @@ asn1_get_bit_der (const unsigned char *der, int der_len, int *ret_len, unsigned char *str, int str_size, int *bit_len) { - int len_len, len_byte; + int len_len = 0, len_byte; if (der_len <= 0) return ASN1_GENERIC_ERROR; + len_byte = asn1_get_length_der (der, der_len, &len_len) - 1; if (len_byte < 0) return ASN1_DER_ERROR; @@ -358,8 +387,14 @@ asn1_get_bit_der (const unsigned char *der, int der_len, *ret_len = len_byte + len_len + 1; *bit_len = len_byte * 8 - der[len_len]; + if (*bit_len < 0) + return ASN1_DER_ERROR; + if (str_size >= len_byte) - memcpy (str, der + len_len + 1, len_byte); + { + if (len_byte > 0 && str) + memcpy (str, der + len_len + 1, len_byte); + } else { return ASN1_MEM_ERROR; @@ -368,12 +403,14 @@ asn1_get_bit_der (const unsigned char *der, int der_len, return ASN1_SUCCESS; } + static int _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, int *ret_len) { asn1_node p; int counter, len2, len3, is_tag_implicit; + int result; unsigned long tag, tag_implicit = 0; unsigned char class, class2, class_implicit = 0; @@ -401,23 +438,21 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, if (p->type & CONST_EXPLICIT) { if (asn1_get_tag_der - (der + counter, der_len - counter, &class, &len2, + (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS) return ASN1_DER_ERROR; - if (counter + len2 > der_len) - return ASN1_DER_ERROR; + DECR_LEN(der_len, len2); counter += len2; len3 = - asn1_get_length_ber (der + counter, der_len - counter, + asn1_get_length_ber (der + counter, der_len, &len2); if (len3 < 0) return ASN1_DER_ERROR; + DECR_LEN(der_len, len2); counter += len2; - if (counter > der_len) - return ASN1_DER_ERROR; if (!is_tag_implicit) { @@ -437,9 +472,9 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, if (!is_tag_implicit) { if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || - (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) || - (type_field (node->type) == ASN1_ETYPE_SET) || - (type_field (node->type) == ASN1_ETYPE_SET_OF)) + (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) + || (type_field (node->type) == ASN1_ETYPE_SET) + || (type_field (node->type) == ASN1_ETYPE_SET_OF)) class2 |= ASN1_CLASS_STRUCTURED; class_implicit = class2; tag_implicit = strtoul ((char *) p->value, NULL, 10); @@ -454,11 +489,11 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, if (is_tag_implicit) { if (asn1_get_tag_der - (der + counter, der_len - counter, &class, &len2, + (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS) return ASN1_DER_ERROR; - if (counter + len2 > der_len) - return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); if ((class != class_implicit) || (tag != tag_implicit)) { @@ -477,18 +512,16 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, unsigned type = type_field (node->type); if (type == ASN1_ETYPE_TAG) { - counter = 0; - *ret_len = counter; + *ret_len = 0; return ASN1_SUCCESS; } if (asn1_get_tag_der - (der + counter, der_len - counter, &class, &len2, + (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS) return ASN1_DER_ERROR; - if (counter + len2 > der_len) - return ASN1_DER_ERROR; + DECR_LEN(der_len, len2); switch (type) { @@ -513,7 +546,8 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, case ASN1_ETYPE_SET_OF: case ASN1_ETYPE_GENERALIZED_TIME: case ASN1_ETYPE_UTC_TIME: - if ((class != _asn1_tags[type].class) || (tag != _asn1_tags[type].tag)) + if ((class != _asn1_tags[type].class) + || (tag != _asn1_tags[type].tag)) return ASN1_DER_ERROR; break; @@ -528,6 +562,9 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, case ASN1_ETYPE_ANY: counter -= len2; break; + case ASN1_ETYPE_CHOICE: + counter -= len2; + break; default: return ASN1_DER_ERROR; break; @@ -537,6 +574,34 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, counter += len2; *ret_len = counter; return ASN1_SUCCESS; + +cleanup: + return result; +} + +static int +extract_tag_der_recursive(asn1_node node, const unsigned char *der, int der_len, + int *ret_len) +{ +asn1_node p; +int ris = ASN1_DER_ERROR; + + if (type_field (node->type) == ASN1_ETYPE_CHOICE) + { + p = node->down; + while (p) + { + ris = _asn1_extract_tag_der (p, der, der_len, ret_len); + if (ris == ASN1_SUCCESS) + break; + p = p->right; + } + + *ret_len = 0; + return ris; + } + else + return _asn1_extract_tag_der (node, der, der_len, ret_len); } static int @@ -603,97 +668,108 @@ _asn1_extract_der_octet (asn1_node node, const unsigned char *der, int der_len) { int len2, len3; - int counter2, counter_end; + int counter, counter_end; + int result; len2 = asn1_get_length_der (der, der_len, &len3); if (len2 < -1) return ASN1_DER_ERROR; - counter2 = len3 + 1; + counter = len3 + 1; if (len2 == -1) counter_end = der_len - 2; else counter_end = der_len; - while (counter2 < counter_end) + while (counter < counter_end) { - len2 = asn1_get_length_der (der + counter2, der_len - counter2, &len3); + len2 = asn1_get_length_der (der + counter, der_len, &len3); if (len2 < -1) return ASN1_DER_ERROR; - if (len2 > 0) + if (len2 >= 0) { - _asn1_append_value (node, der + counter2 + len3, len2); + DECR_LEN(der_len, len2+len3); + _asn1_append_value (node, der + counter + len3, len2); } else { /* indefinite */ - - len2 = - _asn1_extract_der_octet (node, der + counter2 + len3, - der_len - counter2 - len3); - if (len2 < 0) - return len2; + DECR_LEN(der_len, len3); + result = + _asn1_extract_der_octet (node, der + counter + len3, + der_len); + if (result != ASN1_SUCCESS) + return result; + len2 = 0; } - counter2 += len2 + len3 + 1; + DECR_LEN(der_len, 1); + counter += len2 + len3 + 1; } return ASN1_SUCCESS; + +cleanup: + return result; } static int -_asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len) +_asn1_get_octet_string (asn1_node node, const unsigned char *der, int der_len, int *len) { int len2, len3, counter, tot_len, indefinite; + int result; counter = 0; if (*(der - 1) & ASN1_CLASS_STRUCTURED) { tot_len = 0; - indefinite = asn1_get_length_der (der, *len, &len3); + indefinite = asn1_get_length_der (der, der_len, &len3); if (indefinite < -1) return ASN1_DER_ERROR; counter += len3; + DECR_LEN(der_len, len3); + if (indefinite >= 0) indefinite += len3; while (1) { - if (counter > (*len)) - return ASN1_DER_ERROR; - if (indefinite == -1) { - if ((der[counter] == 0) && (der[counter + 1] == 0)) + if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0)) { counter += 2; + DECR_LEN(der_len, 2); break; } } else if (counter >= indefinite) break; + DECR_LEN(der_len, 1); if (der[counter] != ASN1_TAG_OCTET_STRING) return ASN1_DER_ERROR; counter++; - len2 = asn1_get_length_der (der + counter, *len - counter, &len3); + len2 = asn1_get_length_der (der + counter, der_len, &len3); if (len2 <= 0) return ASN1_DER_ERROR; + DECR_LEN(der_len, len3 + len2); counter += len3 + len2; + tot_len += len2; } /* copy */ if (node) { - unsigned char temp[DER_LEN]; + unsigned char temp[ASN1_MAX_LENGTH_SIZE]; int ret; len2 = sizeof (temp); @@ -701,7 +777,7 @@ _asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len) asn1_length_der (tot_len, temp, &len2); _asn1_set_value (node, temp, len2); - ret = _asn1_extract_der_octet (node, der, *len); + ret = _asn1_extract_der_octet (node, der, der_len); if (ret != ASN1_SUCCESS) return ret; @@ -709,10 +785,11 @@ _asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len) } else { /* NOT STRUCTURED */ - len2 = asn1_get_length_der (der, *len, &len3); + len2 = asn1_get_length_der (der, der_len, &len3); if (len2 < 0) return ASN1_DER_ERROR; + DECR_LEN(der_len, len3+len2); counter = len3 + len2; if (node) _asn1_set_value (node, der, counter); @@ -721,12 +798,16 @@ _asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len) *len = counter; return ASN1_SUCCESS; +cleanup: + return result; } static int -_asn1_get_indefinite_length_string (const unsigned char *der, int *len) +_asn1_get_indefinite_length_string (const unsigned char *der, + int der_len, int *len) { int len2, len3, counter, indefinite; + int result; unsigned long tag; unsigned char class; @@ -734,12 +815,11 @@ _asn1_get_indefinite_length_string (const unsigned char *der, int *len) while (1) { - if ((*len) < counter) - return ASN1_DER_ERROR; - - if ((der[counter] == 0) && (der[counter + 1] == 0)) + if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0)) { counter += 2; + DECR_LEN(der_len, 2); + indefinite--; if (indefinite <= 0) break; @@ -748,36 +828,55 @@ _asn1_get_indefinite_length_string (const unsigned char *der, int *len) } if (asn1_get_tag_der - (der + counter, *len - counter, &class, &len2, + (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS) return ASN1_DER_ERROR; - if (counter + len2 > *len) - return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); counter += len2; - len2 = asn1_get_length_der (der + counter, *len - counter, &len3); + + len2 = asn1_get_length_der (der + counter, der_len, &len3); if (len2 < -1) return ASN1_DER_ERROR; + if (len2 == -1) { indefinite++; counter += 1; + DECR_LEN(der_len, 1); } else { counter += len2 + len3; + DECR_LEN(der_len, len2+len3); } } *len = counter; return ASN1_SUCCESS; +cleanup: + return result; } +static void delete_unneeded_choice_fields(asn1_node p) +{ + asn1_node p2; + + while (p->right) + { + p2 = p->right; + asn1_delete_structure (&p2); + } +} + + + /** * asn1_der_decoding: * @element: pointer to an ASN1 structure. * @ider: vector that contains the DER encoding. - * @len: number of bytes of *@ider: @ider[0]..@ider[len-1]. + * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]. * @errorDescription: null-terminated string contains details when an * error occurred. * @@ -793,7 +892,7 @@ _asn1_get_indefinite_length_string (const unsigned char *der, int *len) * name (*@ELEMENT deleted). **/ int -asn1_der_decoding (asn1_node * element, const void *ider, int len, +asn1_der_decoding (asn1_node * element, const void *ider, int ider_len, char *errorDescription) { asn1_node node, p, p2, p3; @@ -815,6 +914,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, if (node->type & CONST_OPTION) { result = ASN1_GENERIC_ERROR; + warn(); goto cleanup; } @@ -832,11 +932,12 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, len2 = _asn1_strtol (p2->value, NULL, 10); if (len2 == -1) { - if (!der[counter] && !der[counter + 1]) + if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) { p = p2; move = UP; counter += 2; + DECR_LEN(ider_len, 2); continue; } } @@ -849,6 +950,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, else if (counter > len2) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } p2 = p2->down; @@ -856,23 +958,9 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, { if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED)) { - if (type_field (p2->type) != ASN1_ETYPE_CHOICE) - ris = - _asn1_extract_tag_der (p2, der + counter, - len - counter, &len2); - else - { - p3 = p2->down; - while (p3) - { - ris = - _asn1_extract_tag_der (p3, der + counter, - len - counter, &len2); - if (ris == ASN1_SUCCESS) - break; - p3 = p3->right; - } - } + ris = + extract_tag_der_recursive (p2, der + counter, + ider_len, &len2); if (ris == ASN1_SUCCESS) { p2->type &= ~CONST_NOT_USED; @@ -885,6 +973,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, if (p2 == NULL) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } } @@ -915,24 +1004,19 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, { while (p->down) { - if (counter < len) - ris = - _asn1_extract_tag_der (p->down, der + counter, - len - counter, &len2); - else - ris = ASN1_DER_ERROR; + ris = + extract_tag_der_recursive (p->down, der + counter, + ider_len, &len2); + if (ris == ASN1_SUCCESS) { - while (p->down->right) - { - p2 = p->down->right; - asn1_delete_structure (&p2); - } + delete_unneeded_choice_fields(p->down); break; } else if (ris == ASN1_ERROR_TYPE_ANY) { result = ASN1_ERROR_TYPE_ANY; + warn(); goto cleanup; } else @@ -947,10 +1031,11 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, if (!(p->type & CONST_OPTION)) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } } - else + else if (type_field (p->type) != ASN1_ETYPE_CHOICE) p = p->down; } @@ -958,13 +1043,15 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, { p2 = _asn1_find_up (p); len2 = _asn1_strtol (p2->value, NULL, 10); + if ((len2 != -1) && (counter > len2)) ris = ASN1_TAG_ERROR; } if (ris == ASN1_SUCCESS) ris = - _asn1_extract_tag_der (p, der + counter, len - counter, &len2); + extract_tag_der_recursive (p, der + counter, ider_len, &len2); + if (ris != ASN1_SUCCESS) { if (p->type & CONST_OPTION) @@ -983,11 +1070,15 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, _asn1_error_description_tag_error (p, errorDescription); result = ASN1_TAG_ERROR; + warn(); goto cleanup; } } else - counter += len2; + { + DECR_LEN(ider_len, len2); + counter += len2; + } } if (ris == ASN1_SUCCESS) @@ -995,18 +1086,23 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, switch (type_field (p->type)) { case ASN1_ETYPE_NULL: + DECR_LEN(ider_len, 1); if (der[counter]) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } counter++; move = RIGHT; break; case ASN1_ETYPE_BOOLEAN: + DECR_LEN(ider_len, 2); + if (der[counter++] != 1) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } if (der[counter++] == 0) @@ -1018,71 +1114,92 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, case ASN1_ETYPE_INTEGER: case ASN1_ETYPE_ENUMERATED: len2 = - asn1_get_length_der (der + counter, len - counter, &len3); + asn1_get_length_der (der + counter, ider_len, &len3); if (len2 < 0) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } + DECR_LEN(ider_len, len3+len2); + _asn1_set_value (p, der + counter, len3 + len2); counter += len3 + len2; move = RIGHT; break; case ASN1_ETYPE_OBJECT_ID: result = - _asn1_get_objectid_der (der + counter, len - counter, &len2, + _asn1_get_objectid_der (der + counter, ider_len, &len2, temp, sizeof (temp)); if (result != ASN1_SUCCESS) - goto cleanup; + { + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); tlen = strlen (temp); if (tlen > 0) _asn1_set_value (p, temp, tlen + 1); + counter += len2; move = RIGHT; break; case ASN1_ETYPE_GENERALIZED_TIME: case ASN1_ETYPE_UTC_TIME: result = - _asn1_get_time_der (der + counter, len - counter, &len2, temp, + _asn1_get_time_der (der + counter, ider_len, &len2, temp, sizeof (temp) - 1); if (result != ASN1_SUCCESS) - goto cleanup; + { + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); tlen = strlen (temp); if (tlen > 0) _asn1_set_value (p, temp, tlen); + counter += len2; move = RIGHT; break; case ASN1_ETYPE_OCTET_STRING: - len3 = len - counter; - result = _asn1_get_octet_string (der + counter, p, &len3); + result = _asn1_get_octet_string (p, der + counter, ider_len, &len3); if (result != ASN1_SUCCESS) - goto cleanup; + { + warn(); + goto cleanup; + } + DECR_LEN(ider_len, len3); counter += len3; move = RIGHT; break; case ASN1_ETYPE_GENERALSTRING: - case ASN1_ETYPE_NUMERIC_STRING: - case ASN1_ETYPE_IA5_STRING: - case ASN1_ETYPE_TELETEX_STRING: - case ASN1_ETYPE_PRINTABLE_STRING: - case ASN1_ETYPE_UNIVERSAL_STRING: - case ASN1_ETYPE_BMP_STRING: - case ASN1_ETYPE_UTF8_STRING: - case ASN1_ETYPE_VISIBLE_STRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: case ASN1_ETYPE_BIT_STRING: len2 = - asn1_get_length_der (der + counter, len - counter, &len3); + asn1_get_length_der (der + counter, ider_len, &len3); if (len2 < 0) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } + DECR_LEN(ider_len, len3+len2); + _asn1_set_value (p, der + counter, len3 + len2); counter += len3 + len2; move = RIGHT; @@ -1095,18 +1212,12 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, _asn1_set_value (p, NULL, 0); if (len2 == -1) { /* indefinite length method */ - if (len - counter + 1 > 0) - { - if ((der[counter]) || der[counter + 1]) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - } - else - { - result = ASN1_DER_ERROR; - goto cleanup; + DECR_LEN(ider_len, 2); + if ((der[counter]) || der[counter + 1]) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; } counter += 2; } @@ -1115,6 +1226,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, if (len2 != counter) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } } @@ -1123,13 +1235,17 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, else { /* move==DOWN || move==RIGHT */ len3 = - asn1_get_length_der (der + counter, len - counter, &len2); + asn1_get_length_der (der + counter, ider_len, &len2); if (len3 < -1) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } + + DECR_LEN(ider_len, len2); counter += len2; + if (len3 > 0) { _asn1_ltostr (counter + len3, temp); @@ -1168,13 +1284,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, len2 = _asn1_strtol (p->value, NULL, 10); if (len2 == -1) { /* indefinite length method */ - if ((counter + 2) > len) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - if ((der[counter]) || der[counter + 1]) + if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1])) { _asn1_append_sequence_set (p); p = p->down; @@ -1183,7 +1293,9 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, move = RIGHT; continue; } + _asn1_set_value (p, NULL, 0); + DECR_LEN(ider_len, 2); counter += 2; } else @@ -1197,10 +1309,12 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, move = RIGHT; continue; } + _asn1_set_value (p, NULL, 0); if (len2 != counter) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } } @@ -1208,12 +1322,15 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, else { /* move==DOWN || move==RIGHT */ len3 = - asn1_get_length_der (der + counter, len - counter, &len2); + asn1_get_length_der (der + counter, ider_len, &len2); if (len3 < -1) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } + + DECR_LEN(ider_len, len2); counter += len2; if (len3) { @@ -1242,46 +1359,59 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, break; case ASN1_ETYPE_ANY: if (asn1_get_tag_der - (der + counter, len - counter, &class, &len2, + (der + counter, ider_len, &class, &len2, &tag) != ASN1_SUCCESS) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } - if (counter + len2 > len) - { - result = ASN1_DER_ERROR; - goto cleanup; - } + DECR_LEN(ider_len, len2); + len4 = asn1_get_length_der (der + counter + len2, - len - counter - len2, &len3); + ider_len, &len3); if (len4 < -1) { result = ASN1_DER_ERROR; + warn(); goto cleanup; } - if (len4 != -1) + if (len4 != -1) /* definite */ { len2 += len4; + + DECR_LEN(ider_len, len4+len3); _asn1_set_value_lv (p, der + counter, len2 + len3); counter += len2 + len3; } - else + else /* == -1 */ { /* indefinite length */ + ider_len += len2; /* undo DECR_LEN */ + + if (counter == 0) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + /* Check indefinite lenth method in an EXPLICIT TAG */ if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80)) indefinite = 1; else indefinite = 0; - len2 = len - counter; result = - _asn1_get_indefinite_length_string (der + counter, &len2); + _asn1_get_indefinite_length_string (der + counter, ider_len, &len2); if (result != ASN1_SUCCESS) - goto cleanup; + { + warn(); + goto cleanup; + } + DECR_LEN(ider_len, len2); _asn1_set_value_lv (p, der + counter, len2); counter += len2; @@ -1289,6 +1419,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, an indefinite length method. */ if (indefinite) { + DECR_LEN(ider_len, 2); if (!der[counter] && !der[counter + 1]) { counter += 2; @@ -1296,6 +1427,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, else { result = ASN1_DER_ERROR; + warn(); goto cleanup; } } @@ -1331,8 +1463,9 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, _asn1_delete_not_used (*element); - if (counter != len) + if (ider_len != 0) { + warn(); result = ASN1_DER_ERROR; goto cleanup; } @@ -1365,6 +1498,9 @@ cleanup: * decoding procedure, the *@STRUCTURE is deleted and set equal to * %NULL. * + * This function is deprecated and may just be an alias to asn1_der_decoding + * in future versions. Use asn1_der_decoding() instead. + * * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND * if ELEMENT is %NULL or @elementName == NULL, and * %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't @@ -1374,783 +1510,14 @@ int asn1_der_decoding_element (asn1_node * structure, const char *elementName, const void *ider, int len, char *errorDescription) { - asn1_node node, p, p2, p3, nodeFound = NULL; - char temp[128], currentName[ASN1_MAX_NAME_SIZE * 10], *dot_p, *char_p; - int nameLen = ASN1_MAX_NAME_SIZE * 10 - 1, state; - int counter, len2, len3, len4, move, ris, tlen; - unsigned char class; - unsigned long tag; - int indefinite, result; - const unsigned char *der = ider; - - node = *structure; - - if (node == NULL) - return ASN1_ELEMENT_NOT_FOUND; - - if (elementName == NULL) - { - result = ASN1_ELEMENT_NOT_FOUND; - goto cleanup; - } - - if (node->type & CONST_OPTION) - { - result = ASN1_GENERIC_ERROR; - goto cleanup; - } - - if ((*structure)->name[0] != 0) - { /* Has *structure got a name? */ - nameLen -= strlen ((*structure)->name); - if (nameLen > 0) - strcpy (currentName, (*structure)->name); - else - { - result = ASN1_MEM_ERROR; - goto cleanup; - } - if (!(strcmp (currentName, elementName))) - { - state = FOUND; - nodeFound = *structure; - } - else if (!memcmp (currentName, elementName, strlen (currentName))) - state = SAME_BRANCH; - else - state = OTHER_BRANCH; - } - else - { /* *structure doesn't have a name? */ - currentName[0] = 0; - if (elementName[0] == 0) - { - state = FOUND; - nodeFound = *structure; - } - else - { - state = SAME_BRANCH; - } - } - - counter = 0; - move = DOWN; - p = node; - while (1) - { - - ris = ASN1_SUCCESS; - - if (move != UP) - { - if (p->type & CONST_SET) - { - p2 = _asn1_find_up (p); - len2 = _asn1_strtol (p2->value, NULL, 10); - if (counter == len2) - { - p = p2; - move = UP; - continue; - } - else if (counter > len2) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - p2 = p2->down; - while (p2) - { - if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED)) - { - if (type_field (p2->type) != ASN1_ETYPE_CHOICE) - ris = - _asn1_extract_tag_der (p2, der + counter, - len - counter, &len2); - else - { - p3 = p2->down; - while (p3) - { - ris = - _asn1_extract_tag_der (p3, der + counter, - len - counter, &len2); - if (ris == ASN1_SUCCESS) - break; - p3 = p3->right; - } - } - if (ris == ASN1_SUCCESS) - { - p2->type &= ~CONST_NOT_USED; - p = p2; - break; - } - } - p2 = p2->right; - } - if (p2 == NULL) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - } - - if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) - { - p2 = _asn1_find_up (p); - len2 = _asn1_strtol (p2->value, NULL, 10); - if (counter == len2) - { - if (p->right) - { - p2 = p->right; - move = RIGHT; - } - else - move = UP; - - if (p->type & CONST_OPTION) - asn1_delete_structure (&p); - - p = p2; - continue; - } - } - - if (type_field (p->type) == ASN1_ETYPE_CHOICE) - { - while (p->down) - { - if (counter < len) - ris = - _asn1_extract_tag_der (p->down, der + counter, - len - counter, &len2); - else - ris = ASN1_DER_ERROR; - if (ris == ASN1_SUCCESS) - { - while (p->down->right) - { - p2 = p->down->right; - asn1_delete_structure (&p2); - } - break; - } - else if (ris == ASN1_ERROR_TYPE_ANY) - { - result = ASN1_ERROR_TYPE_ANY; - goto cleanup; - } - else - { - p2 = p->down; - asn1_delete_structure (&p2); - } - } - - if (p->down == NULL) - { - if (!(p->type & CONST_OPTION)) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - } - else - p = p->down; - } - - if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) - { - p2 = _asn1_find_up (p); - len2 = _asn1_strtol (p2->value, NULL, 10); - if (counter > len2) - ris = ASN1_TAG_ERROR; - } - - if (ris == ASN1_SUCCESS) - ris = - _asn1_extract_tag_der (p, der + counter, len - counter, &len2); - if (ris != ASN1_SUCCESS) - { - if (p->type & CONST_OPTION) - { - p->type |= CONST_NOT_USED; - move = RIGHT; - } - else if (p->type & CONST_DEFAULT) - { - _asn1_set_value (p, NULL, 0); - move = RIGHT; - } - else - { - if (errorDescription != NULL) - _asn1_error_description_tag_error (p, errorDescription); - - result = ASN1_TAG_ERROR; - goto cleanup; - } - } - else - counter += len2; - } - - if (ris == ASN1_SUCCESS) - { - switch (type_field (p->type)) - { - case ASN1_ETYPE_NULL: - if (der[counter]) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - if (p == nodeFound) - state = EXIT; - - counter++; - move = RIGHT; - break; - case ASN1_ETYPE_BOOLEAN: - if (der[counter++] != 1) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - if (state == FOUND) - { - if (der[counter++] == 0) - _asn1_set_value (p, "F", 1); - else - _asn1_set_value (p, "T", 1); - - if (p == nodeFound) - state = EXIT; - - } - else - counter++; - - move = RIGHT; - break; - case ASN1_ETYPE_INTEGER: - case ASN1_ETYPE_ENUMERATED: - len2 = - asn1_get_length_der (der + counter, len - counter, &len3); - if (len2 < 0) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - if (state == FOUND) - { - if (len3 + len2 > len - counter) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - _asn1_set_value (p, der + counter, len3 + len2); - - if (p == nodeFound) - state = EXIT; - } - counter += len3 + len2; - move = RIGHT; - break; - case ASN1_ETYPE_OBJECT_ID: - if (state == FOUND) - { - result = - _asn1_get_objectid_der (der + counter, len - counter, - &len2, temp, sizeof (temp)); - if (result != ASN1_SUCCESS) - goto cleanup; - - tlen = strlen (temp); - - if (tlen > 0) - _asn1_set_value (p, temp, tlen + 1); - - if (p == nodeFound) - state = EXIT; - } - else - { - len2 = - asn1_get_length_der (der + counter, len - counter, &len3); - if (len2 < 0) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - len2 += len3; - } - - counter += len2; - move = RIGHT; - break; - case ASN1_ETYPE_GENERALIZED_TIME: - case ASN1_ETYPE_UTC_TIME: - if (state == FOUND) - { - result = - _asn1_get_time_der (der + counter, len - counter, &len2, - temp, sizeof (temp) - 1); - if (result != ASN1_SUCCESS) - goto cleanup; - - tlen = strlen (temp); - if (tlen > 0) - _asn1_set_value (p, temp, tlen + 1); - - if (p == nodeFound) - state = EXIT; - } - else - { - len2 = - asn1_get_length_der (der + counter, len - counter, &len3); - if (len2 < 0) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - len2 += len3; - } - - counter += len2; - move = RIGHT; - break; - case ASN1_ETYPE_OCTET_STRING: - len3 = len - counter; - if (state == FOUND) - { - result = _asn1_get_octet_string (der + counter, p, &len3); - if (p == nodeFound) - state = EXIT; - } - else - result = _asn1_get_octet_string (der + counter, NULL, &len3); - - if (result != ASN1_SUCCESS) - goto cleanup; - - counter += len3; - move = RIGHT; - break; - case ASN1_ETYPE_GENERALSTRING: - case ASN1_ETYPE_NUMERIC_STRING: - case ASN1_ETYPE_IA5_STRING: - case ASN1_ETYPE_TELETEX_STRING: - case ASN1_ETYPE_PRINTABLE_STRING: - case ASN1_ETYPE_UNIVERSAL_STRING: - case ASN1_ETYPE_BMP_STRING: - case ASN1_ETYPE_UTF8_STRING: - case ASN1_ETYPE_VISIBLE_STRING: - case ASN1_ETYPE_BIT_STRING: - len2 = - asn1_get_length_der (der + counter, len - counter, &len3); - if (len2 < 0) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - if (state == FOUND) - { - if (len3 + len2 > len - counter) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - _asn1_set_value (p, der + counter, len3 + len2); - - if (p == nodeFound) - state = EXIT; - } - counter += len3 + len2; - move = RIGHT; - break; - case ASN1_ETYPE_SEQUENCE: - case ASN1_ETYPE_SET: - if (move == UP) - { - len2 = _asn1_strtol (p->value, NULL, 10); - _asn1_set_value (p, NULL, 0); - if (len2 == -1) - { /* indefinite length method */ - if ((der[counter]) || der[counter + 1]) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - counter += 2; - } - else - { /* definite length method */ - if (len2 != counter) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - } - if (p == nodeFound) - state = EXIT; - move = RIGHT; - } - else - { /* move==DOWN || move==RIGHT */ - if (state == OTHER_BRANCH) - { - len3 = - asn1_get_length_der (der + counter, len - counter, - &len2); - if (len3 < 0) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - counter += len2 + len3; - move = RIGHT; - } - else - { /* state==SAME_BRANCH or state==FOUND */ - len3 = - asn1_get_length_der (der + counter, len - counter, - &len2); - if (len3 < 0) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - counter += len2; - if (len3 > 0) - { - _asn1_ltostr (counter + len3, temp); - tlen = strlen (temp); - - if (tlen > 0) - _asn1_set_value (p, temp, tlen + 1); - move = DOWN; - } - else if (len3 == 0) - { - p2 = p->down; - while (p2) - { - if (type_field (p2->type) != ASN1_ETYPE_TAG) - { - p3 = p2->right; - asn1_delete_structure (&p2); - p2 = p3; - } - else - p2 = p2->right; - } - move = RIGHT; - } - else - { /* indefinite length method */ - _asn1_set_value (p, "-1", 3); - move = DOWN; - } - } - } - break; - case ASN1_ETYPE_SEQUENCE_OF: - case ASN1_ETYPE_SET_OF: - if (move == UP) - { - len2 = _asn1_strtol (p->value, NULL, 10); - if (len2 > counter) - { - _asn1_append_sequence_set (p); - p = p->down; - while (p->right) - p = p->right; - move = RIGHT; - continue; - } - _asn1_set_value (p, NULL, 0); - if (len2 != counter) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - if (p == nodeFound) - state = EXIT; - } - else - { /* move==DOWN || move==RIGHT */ - if (state == OTHER_BRANCH) - { - len3 = - asn1_get_length_der (der + counter, len - counter, - &len2); - if (len3 < 0) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - counter += len2 + len3; - move = RIGHT; - } - else - { /* state==FOUND or state==SAME_BRANCH */ - len3 = - asn1_get_length_der (der + counter, len - counter, - &len2); - if (len3 < 0) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - counter += len2; - if (len3) - { - _asn1_ltostr (counter + len3, temp); - tlen = strlen (temp); - - if (tlen > 0) - _asn1_set_value (p, temp, tlen + 1); - p2 = p->down; - while ((type_field (p2->type) == ASN1_ETYPE_TAG) - || (type_field (p2->type) == ASN1_ETYPE_SIZE)) - p2 = p2->right; - if (p2->right == NULL) - _asn1_append_sequence_set (p); - p = p2; - state = FOUND; - } - } - } - - break; - case ASN1_ETYPE_ANY: - if (asn1_get_tag_der - (der + counter, len - counter, &class, &len2, - &tag) != ASN1_SUCCESS) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - if (counter + len2 > len) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - len4 = - asn1_get_length_der (der + counter + len2, - len - counter - len2, &len3); - if (len4 < -1) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - if (len4 != -1) - { - len2 += len4; - if (state == FOUND) - { - _asn1_set_value_lv (p, der + counter, len2 + len3); - - if (p == nodeFound) - state = EXIT; - } - counter += len2 + len3; - } - else - { /* indefinite length */ - /* Check indefinite lenth method in an EXPLICIT TAG */ - if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80)) - indefinite = 1; - else - indefinite = 0; - - len2 = len - counter; - result = - _asn1_get_indefinite_length_string (der + counter, &len2); - if (result != ASN1_SUCCESS) - goto cleanup; - - if (state == FOUND) - { - _asn1_set_value_lv (p, der + counter, len2); - - if (p == nodeFound) - state = EXIT; - } - - counter += len2; - - /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with - an indefinite length method. */ - if (indefinite) - { - if (!der[counter] && !der[counter + 1]) - { - counter += 2; - } - else - { - result = ASN1_DER_ERROR; - goto cleanup; - } - } - } - move = RIGHT; - break; - - default: - move = (move == UP) ? RIGHT : DOWN; - break; - } - } - - if ((p == node && move != DOWN) || (state == EXIT)) - break; - - if (move == DOWN) - { - if (p->down) - { - p = p->down; - - if (state != FOUND) - { - nameLen -= strlen (p->name) + 1; - if (nameLen > 0) - { - if (currentName[0]) - strcat (currentName, "."); - strcat (currentName, p->name); - } - else - { - result = ASN1_MEM_ERROR; - goto cleanup; - } - if (!(strcmp (currentName, elementName))) - { - state = FOUND; - nodeFound = p; - } - else - if (!memcmp - (currentName, elementName, strlen (currentName))) - state = SAME_BRANCH; - else - state = OTHER_BRANCH; - } - } - else - move = RIGHT; - } - - if ((move == RIGHT) && !(p->type & CONST_SET)) - { - if (p->right) - { - p = p->right; - - if (state != FOUND) - { - dot_p = char_p = currentName; - while ((char_p = strchr (char_p, '.'))) - { - dot_p = char_p++; - dot_p++; - } - - nameLen += strlen (currentName) - (dot_p - currentName); - *dot_p = 0; - - nameLen -= strlen (p->name); - if (nameLen > 0) - strcat (currentName, p->name); - else - { - result = ASN1_MEM_ERROR; - goto cleanup; - } - - if (!(strcmp (currentName, elementName))) - { - state = FOUND; - nodeFound = p; - } - else - if (!memcmp - (currentName, elementName, strlen (currentName))) - state = SAME_BRANCH; - else - state = OTHER_BRANCH; - } - } - else - move = UP; - } - - if (move == UP) - { - p = _asn1_find_up (p); - - if (state != FOUND) - { - dot_p = char_p = currentName; - while ((char_p = strchr (char_p, '.'))) - { - dot_p = char_p++; - dot_p++; - } - - nameLen += strlen (currentName) - (dot_p - currentName); - *dot_p = 0; - - if (!(strcmp (currentName, elementName))) - { - state = FOUND; - nodeFound = p; - } - else - if (!memcmp (currentName, elementName, strlen (currentName))) - state = SAME_BRANCH; - else - state = OTHER_BRANCH; - } - } - } - - _asn1_delete_not_used (*structure); - - if (counter > len) - { - result = ASN1_DER_ERROR; - goto cleanup; - } - - return ASN1_SUCCESS; - -cleanup: - asn1_delete_structure (structure); - return result; + return asn1_der_decoding(structure, ider, len, errorDescription); } /** * asn1_der_decoding_startEnd: * @element: pointer to an ASN1 element * @ider: vector that contains the DER encoding. - * @len: number of bytes of *@ider: @ider[0]..@ider[len-1] + * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1] * @name_element: an element of NAME structure. * @start: the position of the first byte of NAME_ELEMENT decoding * (@ider[*start]) @@ -2172,14 +1539,14 @@ cleanup: * doesn't match the structure ELEMENT. **/ int -asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, +asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len, const char *name_element, int *start, int *end) { - asn1_node node, node_to_find, p, p2, p3; + asn1_node node, node_to_find, p, p2; int counter, len2, len3, len4, move, ris; unsigned char class; unsigned long tag; - int indefinite; + int indefinite, result = ASN1_DER_ERROR; const unsigned char *der = ider; node = element; @@ -2195,7 +1562,7 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, if (node_to_find == node) { *start = 0; - *end = len - 1; + *end = ider_len - 1; return ASN1_SUCCESS; } @@ -2208,7 +1575,7 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, while (1) { if (p == NULL) - return ASN1_DER_ERROR; + return ASN1_DER_ERROR; ris = ASN1_SUCCESS; @@ -2217,17 +1584,21 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, if (p->type & CONST_SET) { p2 = _asn1_find_up (p); - if (p2 == NULL) - return ASN1_DER_ERROR; + if (p2 == NULL) + { + warn(); + return ASN1_DER_ERROR; + } len2 = _asn1_strtol (p2->value, NULL, 10); if (len2 == -1) { - if (!der[counter] && !der[counter + 1]) + if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) { p = p2; move = UP; counter += 2; + DECR_LEN(ider_len, 2); continue; } } @@ -2238,7 +1609,10 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, continue; } else if (counter > len2) - return ASN1_DER_ERROR; + { + warn(); + return ASN1_DER_ERROR; + } p2 = p2->down; @@ -2246,20 +1620,9 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, { if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED)) { /* CONTROLLARE */ - if (type_field (p2->type) != ASN1_ETYPE_CHOICE) - ris = - _asn1_extract_tag_der (p2, der + counter, - len - counter, &len2); - else - { - p3 = p2->down; - if (p3 == NULL) - return ASN1_DER_ERROR; - - ris = - _asn1_extract_tag_der (p3, der + counter, - len - counter, &len2); - } + ris = + extract_tag_der_recursive (p2, der + counter, + ider_len, &len2); if (ris == ASN1_SUCCESS) { p2->type &= ~CONST_NOT_USED; @@ -2270,7 +1633,10 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, p2 = p2->right; } if (p2 == NULL) - return ASN1_DER_ERROR; + { + warn(); + return ASN1_DER_ERROR; + } } if (p == node_to_find) @@ -2279,11 +1645,14 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, if (type_field (p->type) == ASN1_ETYPE_CHOICE) { p = p->down; - if (p == NULL) - return ASN1_DER_ERROR; + if (p == NULL) + { + warn(); + return ASN1_DER_ERROR; + } ris = - _asn1_extract_tag_der (p, der + counter, len - counter, + _asn1_extract_tag_der (p, der + counter, ider_len, &len2); if (p == node_to_find) *start = counter; @@ -2291,7 +1660,7 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, if (ris == ASN1_SUCCESS) ris = - _asn1_extract_tag_der (p, der + counter, len - counter, &len2); + _asn1_extract_tag_der (p, der + counter, ider_len, &len2); if (ris != ASN1_SUCCESS) { if (p->type & CONST_OPTION) @@ -2305,11 +1674,15 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, } else { + warn(); return ASN1_TAG_ERROR; } } else - counter += len2; + { + DECR_LEN(ider_len, len2); + counter += len2; + } } if (ris == ASN1_SUCCESS) @@ -2317,22 +1690,36 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, switch (type_field (p->type)) { case ASN1_ETYPE_NULL: + DECR_LEN(ider_len, 1); + if (der[counter]) - return ASN1_DER_ERROR; + { + warn(); + return ASN1_DER_ERROR; + } counter++; move = RIGHT; break; case ASN1_ETYPE_BOOLEAN: - if (der[counter++] != 1) - return ASN1_DER_ERROR; - counter++; + DECR_LEN(ider_len, 2); + + if (der[counter] != 1) + { + warn(); + return ASN1_DER_ERROR; + } + + counter += 2; move = RIGHT; break; case ASN1_ETYPE_OCTET_STRING: - len3 = len - counter; - ris = _asn1_get_octet_string (der + counter, NULL, &len3); + ris = _asn1_get_octet_string (NULL, der + counter, ider_len, &len3); if (ris != ASN1_SUCCESS) - return ris; + { + warn(); + return ris; + } + DECR_LEN(ider_len, len3); counter += len3; move = RIGHT; break; @@ -2342,19 +1729,24 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, case ASN1_ETYPE_INTEGER: case ASN1_ETYPE_ENUMERATED: case ASN1_ETYPE_GENERALSTRING: - case ASN1_ETYPE_NUMERIC_STRING: - case ASN1_ETYPE_IA5_STRING: - case ASN1_ETYPE_TELETEX_STRING: - case ASN1_ETYPE_PRINTABLE_STRING: - case ASN1_ETYPE_UNIVERSAL_STRING: - case ASN1_ETYPE_BMP_STRING: - case ASN1_ETYPE_UTF8_STRING: - case ASN1_ETYPE_VISIBLE_STRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: case ASN1_ETYPE_BIT_STRING: len2 = - asn1_get_length_der (der + counter, len - counter, &len3); + asn1_get_length_der (der + counter, ider_len, &len3); if (len2 < 0) - return ASN1_DER_ERROR; + { + warn(); + return ASN1_DER_ERROR; + } + + DECR_LEN(ider_len, len3 + len2); counter += len3 + len2; move = RIGHT; break; @@ -2363,10 +1755,16 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, if (move != UP) { len3 = - asn1_get_length_der (der + counter, len - counter, &len2); + asn1_get_length_der (der + counter, ider_len, &len2); if (len3 < -1) - return ASN1_DER_ERROR; + { + warn(); + return ASN1_DER_ERROR; + } + + DECR_LEN(ider_len, len2); counter += len2; + if (len3 == 0) move = RIGHT; else @@ -2374,8 +1772,11 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, } else { - if (!der[counter] && !der[counter + 1]) /* indefinite length method */ - counter += 2; + if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) /* indefinite length method */ + { + counter += 2; + DECR_LEN(ider_len, 2); + } move = RIGHT; } break; @@ -2384,13 +1785,26 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, if (move != UP) { len3 = - asn1_get_length_der (der + counter, len - counter, &len2); + asn1_get_length_der (der + counter, ider_len, &len2); if (len3 < -1) - return ASN1_DER_ERROR; + { + warn(); + return ASN1_DER_ERROR; + } + + DECR_LEN(ider_len, len2); counter += len2; - if ((len3 == -1) && !der[counter] && !der[counter + 1]) - counter += 2; - else if (len3) + + if (len3 == -1) + { + if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) + { + DECR_LEN(ider_len, 2); + counter += 2; + } + } + + if (len3) { p2 = p->down; while ((type_field (p2->type) == ASN1_ETYPE_TAG) || @@ -2401,52 +1815,79 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, } else { - if (!der[counter] && !der[counter + 1]) /* indefinite length method */ - counter += 2; + if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) /* indefinite length method */ + { + DECR_LEN(ider_len, 2); + counter += 2; + } } move = RIGHT; break; case ASN1_ETYPE_ANY: if (asn1_get_tag_der - (der + counter, len - counter, &class, &len2, + (der + counter, ider_len, &class, &len2, &tag) != ASN1_SUCCESS) - return ASN1_DER_ERROR; - if (counter + len2 > len) - return ASN1_DER_ERROR; + { + warn(); + return ASN1_DER_ERROR; + } + + DECR_LEN(ider_len, len2); len4 = asn1_get_length_der (der + counter + len2, - len - counter - len2, &len3); + ider_len, &len3); if (len4 < -1) - return ASN1_DER_ERROR; + { + warn(); + return ASN1_DER_ERROR; + } if (len4 != -1) { - counter += len2 + len4 + len3; + DECR_LEN(ider_len, len3 + len4); + counter += len2 + len3 + len4; } else { /* indefinite length */ /* Check indefinite lenth method in an EXPLICIT TAG */ + ider_len += len2; /* undo DECR_LEN */ + + if (counter == 0) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80)) indefinite = 1; else indefinite = 0; - len2 = len - counter; ris = - _asn1_get_indefinite_length_string (der + counter, &len2); + _asn1_get_indefinite_length_string (der + counter, ider_len, &len2); if (ris != ASN1_SUCCESS) - return ris; + { + warn(); + return ris; + } counter += len2; + DECR_LEN(ider_len, len2); /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with an indefinite length method. */ if (indefinite) { + DECR_LEN(ider_len, 2); + if (!der[counter] && !der[counter + 1]) counter += 2; else - return ASN1_DER_ERROR; + { + warn(); + return ASN1_DER_ERROR; + } } } move = RIGHT; @@ -2484,7 +1925,11 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, p = _asn1_find_up (p); } + warn(); return ASN1_ELEMENT_NOT_FOUND; + +cleanup: + return result; } /** @@ -2506,18 +1951,18 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, int asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element) { - char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1], + char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE]; int retCode = ASN1_SUCCESS, result; int len, len2, len3; asn1_node p, p2, p3, aux = NULL; char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + const char *definitionsName; if ((definitions == NULL) || (*element == NULL)) return ASN1_ELEMENT_NOT_FOUND; - strcpy (definitionsName, definitions->name); - strcat (definitionsName, "."); + definitionsName = definitions->name; p = *element; while (p) @@ -2577,8 +2022,8 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element) p3 = p3->right; } - if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || - (p3->value == NULL)) + if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) + || (p3->value == NULL)) { retCode = ASN1_ERROR_TYPE_ANY; break; @@ -2592,8 +2037,7 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element) if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && (p2->type & CONST_ASSIGN)) { - strcpy (name, definitionsName); - strcat (name, p2->name); + snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); len = ASN1_MAX_NAME_SIZE; result = @@ -2609,8 +2053,7 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element) if (p2) { - strcpy (name, definitionsName); - strcat (name, p2->name); + snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); result = asn1_create_element (definitions, name, &aux); @@ -2868,14 +2311,15 @@ asn1_expand_octet_string (asn1_node definitions, asn1_node * element, * Decodes a simple DER encoded type (e.g. a string, which is not constructed). * The output is a pointer inside the @der. * - * Returns: %ASN1_SUCCESS if successful or an error value. + * Returns: %ASN1_SUCCESS if successful or an error value. **/ int -asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned int der_len, - const unsigned char **str, unsigned int *str_len) +asn1_decode_simple_der (unsigned int etype, const unsigned char *der, + unsigned int der_len, const unsigned char **str, + unsigned int *str_len) { int tag_len, len_len; - const unsigned char* p; + const unsigned char *p; unsigned char class; unsigned long tag; long ret; @@ -2883,31 +2327,31 @@ asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned i if (der == NULL || der_len == 0) return ASN1_VALUE_NOT_VALID; - if (ETYPE_OK(etype) == 0) + if (ETYPE_OK (etype) == 0) return ASN1_VALUE_NOT_VALID; /* doesn't handle constructed classes */ - if (ETYPE_CLASS(etype) != ASN1_CLASS_UNIVERSAL) + if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL) return ASN1_VALUE_NOT_VALID; p = der; ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); if (ret != ASN1_SUCCESS) return ret; - - if (class != ETYPE_CLASS(etype) || tag != ETYPE_TAG(etype)) + + if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype)) return ASN1_DER_ERROR; p += tag_len; der_len -= tag_len; - + ret = asn1_get_length_der (p, der_len, &len_len); - if (ret < 0) + if (ret < 0) return ASN1_DER_ERROR; p += len_len; der_len -= len_len; - + *str_len = ret; *str = p; diff --git a/lib/minitasn1/element.c b/lib/minitasn1/element.c index 763ac586b7..ac30e46610 100644 --- a/lib/minitasn1/element.c +++ b/lib/minitasn1/element.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2012 Free Software Foundation, Inc. + * Copyright (C) 2000-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -112,8 +112,11 @@ _asn1_convert_integer (const unsigned char *value, unsigned char *value_out, /* VALUE_OUT is too short to contain the value conversion */ return ASN1_MEM_ERROR; - for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++) - value_out[k2 - k] = val[k2]; + if (value_out != NULL) + { + for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++) + value_out[k2 - k] = val[k2]; + } #if 0 printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len); @@ -130,7 +133,7 @@ int _asn1_append_sequence_set (asn1_node node) { asn1_node p, p2; - char temp[10]; + char temp[LTOSTR_MAX_SIZE]; long n; if (!node || !(node->down)) @@ -287,11 +290,10 @@ asn1_write_value (asn1_node node_root, const char *name, asn1_delete_structure (&node); return ASN1_SUCCESS; } - - type = type_field(node->type); - if ((type == ASN1_ETYPE_SEQUENCE_OF) && (value == NULL) - && (len == 0)) + type = type_field (node->type); + + if ((type == ASN1_ETYPE_SEQUENCE_OF || type == ASN1_ETYPE_SET_OF) && (value == NULL) && (len == 0)) { p = node->down; while ((type_field (p->type) == ASN1_ETYPE_TAG) @@ -304,6 +306,12 @@ asn1_write_value (asn1_node node_root, const char *name, return ASN1_SUCCESS; } + /* Don't allow element deletion for other types */ + if (value == NULL) + { + return ASN1_VALUE_NOT_VALID; + } + switch (type) { case ASN1_ETYPE_BOOLEAN: @@ -499,48 +507,48 @@ asn1_write_value (asn1_node node_root, const char *name, _asn1_set_value (node, value, _asn1_strlen (value) + 1); break; case ASN1_ETYPE_UTC_TIME: - { - len = _asn1_strlen(value); - if (len < 11) + { + len = _asn1_strlen (value); + if (len < 11) + return ASN1_VALUE_NOT_VALID; + for (k = 0; k < 10; k++) + if (!isdigit (value[k])) return ASN1_VALUE_NOT_VALID; - for (k = 0; k < 10; k++) - if (!isdigit (value[k])) + switch (len) + { + case 11: + if (value[10] != 'Z') return ASN1_VALUE_NOT_VALID; - switch (len) - { - case 11: - if (value[10] != 'Z') - return ASN1_VALUE_NOT_VALID; - break; - case 13: - if ((!isdigit (value[10])) || (!isdigit (value[11])) || - (value[12] != 'Z')) - return ASN1_VALUE_NOT_VALID; - break; - case 15: - if ((value[10] != '+') && (value[10] != '-')) - return ASN1_VALUE_NOT_VALID; - for (k = 11; k < 15; k++) - if (!isdigit (value[k])) - return ASN1_VALUE_NOT_VALID; - break; - case 17: - if ((!isdigit (value[10])) || (!isdigit (value[11]))) + break; + case 13: + if ((!isdigit (value[10])) || (!isdigit (value[11])) || + (value[12] != 'Z')) + return ASN1_VALUE_NOT_VALID; + break; + case 15: + if ((value[10] != '+') && (value[10] != '-')) + return ASN1_VALUE_NOT_VALID; + for (k = 11; k < 15; k++) + if (!isdigit (value[k])) return ASN1_VALUE_NOT_VALID; - if ((value[12] != '+') && (value[12] != '-')) + break; + case 17: + if ((!isdigit (value[10])) || (!isdigit (value[11]))) + return ASN1_VALUE_NOT_VALID; + if ((value[12] != '+') && (value[12] != '-')) + return ASN1_VALUE_NOT_VALID; + for (k = 13; k < 17; k++) + if (!isdigit (value[k])) return ASN1_VALUE_NOT_VALID; - for (k = 13; k < 17; k++) - if (!isdigit (value[k])) - return ASN1_VALUE_NOT_VALID; - break; - default: - return ASN1_VALUE_NOT_FOUND; - } - _asn1_set_value (node, value, len); - } + break; + default: + return ASN1_VALUE_NOT_FOUND; + } + _asn1_set_value (node, value, len); + } break; case ASN1_ETYPE_GENERALIZED_TIME: - len = _asn1_strlen(value); + len = _asn1_strlen (value); _asn1_set_value (node, value, len); break; case ASN1_ETYPE_OCTET_STRING: @@ -616,16 +624,19 @@ asn1_write_value (asn1_node node_root, const char *name, if (ptr_size < data_size) { \ return ASN1_MEM_ERROR; \ } else { \ - memcpy( ptr, data, data_size); \ + if (ptr && data_size > 0) \ + memcpy (ptr, data, data_size); \ } #define PUT_STR_VALUE( ptr, ptr_size, data) \ - *len = _asn1_strlen(data) + 1; \ + *len = _asn1_strlen (data) + 1; \ if (ptr_size < *len) { \ return ASN1_MEM_ERROR; \ } else { \ /* this strcpy is checked */ \ - _asn1_strcpy(ptr, data); \ + if (ptr) { \ + _asn1_strcpy (ptr, data); \ + } \ } #define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \ @@ -634,36 +645,42 @@ asn1_write_value (asn1_node node_root, const char *name, return ASN1_MEM_ERROR; \ } else { \ /* this strcpy is checked */ \ - memcpy(ptr, data, data_size); \ - ptr[data_size] = 0; \ + if (ptr) { \ + if (data_size > 0) \ + memcpy (ptr, data, data_size); \ + ptr[data_size] = 0; \ + } \ } #define ADD_STR_VALUE( ptr, ptr_size, data) \ - *len = (int) _asn1_strlen(data) + 1; \ - if (ptr_size < (int) _asn1_strlen(ptr)+(*len)) { \ - return ASN1_MEM_ERROR; \ - } else { \ - /* this strcat is checked */ \ - _asn1_strcat(ptr, data); \ - } + *len += _asn1_strlen(data); \ + if (ptr_size < (int) *len) { \ + (*len)++; \ + return ASN1_MEM_ERROR; \ + } else { \ + /* this strcat is checked */ \ + if (ptr) _asn1_strcat (ptr, data); \ + } /** * asn1_read_value: * @root: pointer to a structure. * @name: the name of the element inside a structure that you want to read. * @ivalue: vector that will contain the element's content, must be a - * pointer to memory cells already allocated. + * pointer to memory cells already allocated (may be %NULL). * @len: number of bytes of *value: value[0]..value[len-1]. Initialy * holds the sizeof value. * - * Returns the value of one element inside a structure. - * - * If an element is OPTIONAL and the function "read_value" returns + * Returns the value of one element inside a structure. + * If an element is OPTIONAL and this returns * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present * in the der encoding that created the structure. The first element * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and * so on. * + * Note that there can be valid values with length zero. In these case + * this function will succeed and @len will be zero. + * * INTEGER: VALUE will contain a two's complement form integer. * * integer=-1 -> value[0]=0xFF , len=1. @@ -711,7 +728,7 @@ asn1_write_value (asn1_node node_root, const char *name, int asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len) { - return asn1_read_value_type( root, name, ivalue, len, NULL); + return asn1_read_value_type (root, name, ivalue, len, NULL); } /** @@ -719,19 +736,22 @@ asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len) * @root: pointer to a structure. * @name: the name of the element inside a structure that you want to read. * @ivalue: vector that will contain the element's content, must be a - * pointer to memory cells already allocated. + * pointer to memory cells already allocated (may be %NULL). * @len: number of bytes of *value: value[0]..value[len-1]. Initialy * holds the sizeof value. * @etype: The type of the value read (ASN1_ETYPE) * - * Returns the value of one element inside a structure. - * - * If an element is OPTIONAL and the function "read_value" returns + * Returns the value of one element inside a structure. + * If an element is OPTIONAL and this returns * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present * in the der encoding that created the structure. The first element * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and * so on. * + * Note that there can be valid values with length zero. In these case + * this function will succeed and @len will be zero. + * + * * INTEGER: VALUE will contain a two's complement form integer. * * integer=-1 -> value[0]=0xFF , len=1. @@ -777,11 +797,11 @@ asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len) * bytes needed. **/ int -asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len, - unsigned int *etype) +asn1_read_value_type (asn1_node root, const char *name, void *ivalue, + int *len, unsigned int *etype) { asn1_node node, p, p2; - int len2, len3; + int len2, len3, result; int value_size = *len; unsigned char *value = ivalue; unsigned type; @@ -839,9 +859,10 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len, if ((isdigit (p->value[0])) || (p->value[0] == '-') || (p->value[0] == '+')) { - if (_asn1_convert_integer - (p->value, value, value_size, len) != ASN1_SUCCESS) - return ASN1_MEM_ERROR; + result = _asn1_convert_integer + (p->value, value, value_size, len); + if (result != ASN1_SUCCESS) + return result; } else { /* is an identifier like v1 */ @@ -852,10 +873,11 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len, { if (!_asn1_strcmp (p2->name, p->value)) { - if (_asn1_convert_integer + result = _asn1_convert_integer (p2->value, value, value_size, - len) != ASN1_SUCCESS) - return ASN1_MEM_ERROR; + len); + if (result != ASN1_SUCCESS) + return result; break; } } @@ -866,16 +888,19 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len, else { len2 = -1; - if (asn1_get_octet_der + result = asn1_get_octet_der (node->value, node->value_len, &len2, value, value_size, - len) != ASN1_SUCCESS) - return ASN1_MEM_ERROR; + len); + if (result != ASN1_SUCCESS) + return result; } break; case ASN1_ETYPE_OBJECT_ID: if (node->type & CONST_ASSIGN) { - value[0] = 0; + *len = 0; + if (value) + value[0] = 0; p = node->down; while (p) { @@ -889,7 +914,7 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len, } p = p->right; } - *len = _asn1_strlen (value) + 1; + (*len)++; } else if ((node->type & CONST_DEFAULT) && (node->value == NULL)) { @@ -918,17 +943,19 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len, case ASN1_ETYPE_UTF8_STRING: case ASN1_ETYPE_VISIBLE_STRING: len2 = -1; - if (asn1_get_octet_der + result = asn1_get_octet_der (node->value, node->value_len, &len2, value, value_size, - len) != ASN1_SUCCESS) - return ASN1_MEM_ERROR; + len); + if (result != ASN1_SUCCESS) + return result; break; case ASN1_ETYPE_BIT_STRING: len2 = -1; - if (asn1_get_bit_der + result = asn1_get_bit_der (node->value, node->value_len, &len2, value, value_size, - len) != ASN1_SUCCESS) - return ASN1_MEM_ERROR; + len); + if (result != ASN1_SUCCESS) + return result; break; case ASN1_ETYPE_CHOICE: PUT_STR_VALUE (value, value_size, node->down->name); @@ -1038,12 +1065,13 @@ asn1_read_tag (asn1_node root, const char *name, int *tagValue, * * Returns: %ASN1_SUCCESS if the node exists. **/ -int asn1_read_node_value (asn1_node node, asn1_data_node_st* data) +int +asn1_read_node_value (asn1_node node, asn1_data_node_st * data) { data->name = node->name; data->value = node->value; data->value_len = node->value_len; - data->type = type_field(node->type); - + data->type = type_field (node->type); + return ASN1_SUCCESS; } diff --git a/lib/minitasn1/element.h b/lib/minitasn1/element.h index 3bd38bb923..fdecafb611 100644 --- a/lib/minitasn1/element.h +++ b/lib/minitasn1/element.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2012 Free Software Foundation, Inc. + * Copyright (C) 2000-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -26,8 +26,8 @@ int _asn1_append_sequence_set (asn1_node node); int _asn1_convert_integer (const unsigned char *value, - unsigned char *value_out, - int value_out_size, int *len); + unsigned char *value_out, + int value_out_size, int *len); void _asn1_hierarchical_name (asn1_node node, char *name, int name_size); diff --git a/lib/minitasn1/errors.c b/lib/minitasn1/errors.c index e01c3ee9ea..e9fa302605 100644 --- a/lib/minitasn1/errors.c +++ b/lib/minitasn1/errors.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -63,8 +63,6 @@ static const libtasn1_error_entry error_algorithms[] = { * function is like perror(). The only difference is that it accepts * an error returned by a libtasn1 function. * - * This function replaces libtasn1_perror() in older libtasn1. - * * Since: 1.6 **/ void @@ -82,8 +80,6 @@ asn1_perror (int error) * similar to strerror. The only difference is that it accepts an * error (number) returned by a libtasn1 function. * - * This function replaces libtasn1_strerror() in older libtasn1. - * * Returns: Pointer to static zero-terminated string describing error * code. * diff --git a/lib/minitasn1/gstr.c b/lib/minitasn1/gstr.c index 0558c77771..e91a3a151c 100644 --- a/lib/minitasn1/gstr.c +++ b/lib/minitasn1/gstr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -68,6 +68,7 @@ _asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src) dest[str_size] = 0; return str_size; } - else return 0; + else + return 0; } } diff --git a/lib/minitasn1/gstr.h b/lib/minitasn1/gstr.h index 672d59eb59..00c335ca93 100644 --- a/lib/minitasn1/gstr.h +++ b/lib/minitasn1/gstr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -19,8 +19,24 @@ * 02110-1301, USA */ -unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src); +unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size, + const char *src); void _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src); #define Estrcpy(x,y) _asn1_str_cpy(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y) #define Estrcat(x,y) _asn1_str_cat(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y) + +inline static +void safe_memset(void *data, int c, size_t size) +{ + volatile unsigned volatile_zero = 0; + volatile char *vdata = (volatile char*)data; + + /* This is based on a nice trick for safe memset, + * sent by David Jacobson in the openssl-dev mailing list. + */ + + if (size > 0) do { + memset(data, c, size); + } while(vdata[volatile_zero] != c); +} diff --git a/lib/minitasn1/int.h b/lib/minitasn1/int.h index 3163d50d14..3701e5f645 100644 --- a/lib/minitasn1/int.h +++ b/lib/minitasn1/int.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -46,7 +46,7 @@ struct asn1_node_st { /* public fields: */ - char name[ASN1_MAX_NAME_SIZE+1]; /* Node name */ + char name[ASN1_MAX_NAME_SIZE + 1]; /* Node name */ unsigned int name_hash; unsigned int type; /* Node type */ unsigned char *value; /* Node value */ @@ -58,10 +58,11 @@ struct asn1_node_st unsigned char small_value[ASN1_SMALL_VALUE_SIZE]; /* For small values */ }; -typedef struct tag_and_class_st { +typedef struct tag_and_class_st +{ unsigned tag; unsigned class; - const char* desc; + const char *desc; } tag_and_class_st; /* the types that are handled in _asn1_tags */ @@ -156,23 +157,25 @@ extern const tag_and_class_st _asn1_tags[]; /* Returns the first 8 bits. */ /* Used with the field type of asn1_node_st */ /****************************************/ -inline static unsigned int type_field(unsigned int ntype) +inline static unsigned int +type_field (unsigned int ntype) { return (ntype & 0xff); } /* To convert old types from a static structure */ -inline static unsigned int convert_old_type(unsigned int ntype) +inline static unsigned int +convert_old_type (unsigned int ntype) { -unsigned int type = ntype & 0xff; + unsigned int type = ntype & 0xff; if (type == ASN1_ETYPE_TIME) { if (ntype & CONST_UTC) - type = ASN1_ETYPE_UTC_TIME; + type = ASN1_ETYPE_UTC_TIME; else - type = ASN1_ETYPE_GENERALIZED_TIME; + type = ASN1_ETYPE_GENERALIZED_TIME; - ntype &= ~(CONST_UTC|CONST_GENERALIZED); + ntype &= ~(CONST_UTC | CONST_GENERALIZED); ntype &= 0xffffff00; ntype |= type; diff --git a/lib/minitasn1/libtasn1.h b/lib/minitasn1/libtasn1.h index 06474f3f33..a4570682e0 100644 --- a/lib/minitasn1/libtasn1.h +++ b/lib/minitasn1/libtasn1.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -21,30 +21,41 @@ */ #ifndef LIBTASN1_H -# define LIBTASN1_H - -# ifndef ASN1_API -# if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY -# define ASN1_API __attribute__((__visibility__("default"))) -# elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC -# define ASN1_API __declspec(dllexport) -# elif defined _MSC_VER && ! defined ASN1_STATIC -# define ASN1_API __declspec(dllimport) -# else -# define ASN1_API -# endif -# endif +#define LIBTASN1_H + +#ifndef ASN1_API +#if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY +#define ASN1_API __attribute__((__visibility__("default"))) +#elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC +#define ASN1_API __declspec(dllexport) +#elif defined _MSC_VER && ! defined ASN1_STATIC +#define ASN1_API __declspec(dllimport) +#else +#define ASN1_API +#endif +#endif -#include <stdio.h> /* for FILE* */ #include <sys/types.h> #include <time.h> +#include <stdio.h> /* for FILE* */ #ifdef __cplusplus extern "C" { #endif -#define ASN1_VERSION "3.1" +#define ASN1_VERSION "3.6" + +#if defined(__GNUC__) && !defined(ASN1_INTERNAL_BUILD) +# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +# if _ASN1_GCC_VERSION >= 30100 +# define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__)) +# endif +#endif + +#ifndef _ASN1_GCC_ATTR_DEPRECATED +#define _ASN1_GCC_ATTR_DEPRECATED +#endif /*****************************************/ /* Errors returned by libtasn1 functions */ @@ -168,11 +179,17 @@ extern "C" #define ASN1_ETYPE_UTC_TIME 36 #define ASN1_ETYPE_GENERALIZED_TIME 37 +/* Flags used by asn1_delete_structure2() */ + +/* makes sure the values are zeroized prior to deinitialization */ +#define ASN1_DELETE_FLAG_ZEROIZE 1 + + struct asn1_data_node_st { const char *name; /* Node name */ const void *value; /* Node value */ - unsigned int value_len; /* Node value size */ + unsigned int value_len; /* Node value size */ unsigned int type; /* Node value type (ASN1_ETYPE_*) */ }; typedef struct asn1_data_node_st asn1_data_node_st; @@ -192,13 +209,13 @@ extern "C" /***********************************/ extern ASN1_API int - asn1_parser2tree (const char *file_name, - asn1_node * definitions, char *errorDescription); + asn1_parser2tree (const char *file, + asn1_node * definitions, char *error_desc); extern ASN1_API int asn1_parser2array (const char *inputFileName, const char *outputFileName, - const char *vectorName, char *errorDescription); + const char *vectorName, char *error_desc); extern ASN1_API int asn1_array2tree (const asn1_static_node * array, @@ -214,6 +231,8 @@ extern "C" extern ASN1_API int asn1_delete_structure (asn1_node * structure); + extern ASN1_API int asn1_delete_structure2 (asn1_node * structure, unsigned int flags); + extern ASN1_API int asn1_delete_element (asn1_node structure, const char *element_name); @@ -227,10 +246,10 @@ extern "C" extern ASN1_API int asn1_read_value_type (asn1_node root, const char *name, - void *ivalue, int *len, unsigned int* etype); + void *ivalue, int *len, unsigned int *etype); extern ASN1_API int - asn1_read_node_value (asn1_node node, asn1_data_node_st* data); + asn1_read_node_value (asn1_node node, asn1_data_node_st * data); extern ASN1_API int asn1_number_of_elements (asn1_node element, const char *name, int *num); @@ -243,11 +262,12 @@ extern "C" asn1_der_decoding (asn1_node * element, const void *ider, int len, char *errorDescription); + /* Do not use. Use asn1_der_decoding() instead. */ extern ASN1_API int asn1_der_decoding_element (asn1_node * structure, const char *elementName, const void *ider, int len, - char *errorDescription); + char *errorDescription) _ASN1_GCC_ATTR_DEPRECATED; extern ASN1_API int asn1_der_decoding_startEnd (asn1_node element, @@ -288,17 +308,20 @@ extern "C" asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len); extern ASN1_API void - asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len); + asn1_length_der (unsigned long int len, unsigned char *der, int *der_len); /* Other utility functions. */ - extern ASN1_API - int asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned int der_len, - const unsigned char **str, unsigned int *str_len); + extern ASN1_API + int asn1_decode_simple_der (unsigned int etype, const unsigned char *der, + unsigned int der_len, + const unsigned char **str, + unsigned int *str_len); extern ASN1_API int - asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned int str_len, - unsigned char *tl, unsigned int *tl_len); + asn1_encode_simple_der (unsigned int etype, const unsigned char *str, + unsigned int str_len, unsigned char *tl, + unsigned int *tl_len); extern ASN1_API asn1_node asn1_find_node (asn1_node pointer, const char *name); @@ -332,7 +355,7 @@ extern "C" /* Compatibility types */ -typedef int asn1_retCode; /* type returned by libtasn1 functions */ + typedef int asn1_retCode; /* type returned by libtasn1 functions */ #define node_asn_struct asn1_node_st #define node_asn asn1_node_st diff --git a/lib/minitasn1/parser_aux.c b/lib/minitasn1/parser_aux.c index 50238d2c92..effedb2366 100644 --- a/lib/minitasn1/parser_aux.c +++ b/lib/minitasn1/parser_aux.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2012 Free Software Foundation, Inc. + * Copyright (C) 2000-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -119,19 +119,19 @@ asn1_find_node (asn1_node pointer, const char *name) n_start = n_end; n_start++; - nhash = hash_pjw_bare(n, nsize); + nhash = hash_pjw_bare (n, nsize); } else { nsize = _asn1_str_cpy (n, sizeof (n), n_start); - nhash = hash_pjw_bare(n, nsize); + nhash = hash_pjw_bare (n, nsize); n_start = NULL; } while (p) { - if ((p->name) && nhash == p->name_hash && (!strcmp (p->name, n))) + if (nhash == p->name_hash && (!strcmp (p->name, n))) break; else p = p->right; @@ -157,12 +157,12 @@ asn1_find_node (asn1_node pointer, const char *name) n_start = n_end; n_start++; - nhash = hash_pjw_bare(n, nsize); + nhash = hash_pjw_bare (n, nsize); } else { nsize = _asn1_str_cpy (n, sizeof (n), n_start); - nhash = hash_pjw_bare(n, nsize); + nhash = hash_pjw_bare (n, nsize); n_start = NULL; } @@ -358,7 +358,7 @@ _asn1_append_value (asn1_node node, const void *value, unsigned int len) asn1_node _asn1_set_name (asn1_node node, const char *name) { -unsigned int nsize; + unsigned int nsize; if (node == NULL) return node; @@ -366,12 +366,12 @@ unsigned int nsize; if (name == NULL) { node->name[0] = 0; - node->name_hash = hash_pjw_bare(node->name, 0); + node->name_hash = hash_pjw_bare (node->name, 0); return node; } nsize = _asn1_str_cpy (node->name, sizeof (node->name), name); - node->name_hash = hash_pjw_bare(node->name, nsize); + node->name_hash = hash_pjw_bare (node->name, nsize); return node; } @@ -393,7 +393,7 @@ _asn1_cpy_name (asn1_node dst, asn1_node src) if (src == NULL) { dst->name[0] = 0; - dst->name_hash = hash_pjw_bare(dst->name, 0); + dst->name_hash = hash_pjw_bare (dst->name, 0); return dst; } @@ -450,15 +450,24 @@ _asn1_get_last_right (asn1_node node) /* element (not the elements pointed by it). */ /* Parameters: */ /* node: NODE_ASN element pointer. */ +/* flags: ASN1_DELETE_FLAG_* */ /******************************************************************/ void -_asn1_remove_node (asn1_node node) +_asn1_remove_node (asn1_node node, unsigned int flags) { if (node == NULL) return; - if (node->value != NULL && node->value != node->small_value) - free (node->value); + if (node->value != NULL) + { + if (flags & ASN1_DELETE_FLAG_ZEROIZE) + { + safe_memset(node->value, 0, node->value_len); + } + + if (node->value != node->small_value) + free (node->value); + } free (node); } @@ -517,7 +526,7 @@ _asn1_delete_list_and_nodes (void) { listElement = firstElement; firstElement = firstElement->next; - _asn1_remove_node (listElement->node); + _asn1_remove_node (listElement->node, 0); free (listElement); } } @@ -527,7 +536,7 @@ char * _asn1_ltostr (long v, char *str) { long d, r; - char temp[20]; + char temp[LTOSTR_MAX_SIZE]; int count, k, start; if (v < 0) @@ -581,7 +590,8 @@ _asn1_change_integer_value (asn1_node node) p = node; while (p) { - if ((type_field (p->type) == ASN1_ETYPE_INTEGER) && (p->type & CONST_ASSIGN)) + if ((type_field (p->type) == ASN1_ETYPE_INTEGER) + && (p->type & CONST_ASSIGN)) { if (p->value) { @@ -666,18 +676,20 @@ _asn1_expand_object_id (asn1_node node) _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); p3 = asn1_find_node (node, name2); - if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || - !(p3->type & CONST_ASSIGN)) + if (!p3 + || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) + || !(p3->type & CONST_ASSIGN)) return ASN1_ELEMENT_NOT_FOUND; _asn1_set_down (p, p2->right); - _asn1_remove_node (p2); + _asn1_remove_node (p2, 0); p2 = p; p4 = p3->down; while (p4) { if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) { - p5 = _asn1_add_single_node (ASN1_ETYPE_CONSTANT); + p5 = + _asn1_add_single_node (ASN1_ETYPE_CONSTANT); _asn1_set_name (p5, p4->name); tlen = _asn1_strlen (p4->value); if (tlen > 0) @@ -752,8 +764,8 @@ _asn1_expand_object_id (asn1_node node) _asn1_str_cat (name2, sizeof (name2), "."); _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); p3 = asn1_find_node (node, name2); - if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || - !(p3->type & CONST_ASSIGN)) + if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) + || !(p3->type & CONST_ASSIGN)) return ASN1_ELEMENT_NOT_FOUND; p4 = p3->down; name2[0] = 0; @@ -902,7 +914,7 @@ _asn1_check_identifier (asn1_node node) p = node; while (p) { - if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER) + if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER) { _asn1_str_cpy (name2, sizeof (name2), node->name); _asn1_str_cat (name2, sizeof (name2), "."); @@ -911,9 +923,9 @@ _asn1_check_identifier (asn1_node node) if (p2 == NULL) { if (p->value) - _asn1_strcpy (_asn1_identifierMissing, p->value); - else - _asn1_strcpy (_asn1_identifierMissing, "(null)"); + _asn1_strcpy (_asn1_identifierMissing, p->value); + else + _asn1_strcpy (_asn1_identifierMissing, "(null)"); return ASN1_IDENTIFIER_NOT_FOUND; } } @@ -948,8 +960,8 @@ _asn1_check_identifier (asn1_node node) _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); _asn1_strcpy (_asn1_identifierMissing, p2->value); p2 = asn1_find_node (node, name2); - if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) || - !(p2->type & CONST_ASSIGN)) + if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) + || !(p2->type & CONST_ASSIGN)) return ASN1_IDENTIFIER_NOT_FOUND; else _asn1_identifierMissing[0] = 0; diff --git a/lib/minitasn1/parser_aux.h b/lib/minitasn1/parser_aux.h index f270b73595..1f1aec2637 100644 --- a/lib/minitasn1/parser_aux.h +++ b/lib/minitasn1/parser_aux.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2012 Free Software Foundation, Inc. + * Copyright (C) 2000-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -22,8 +22,6 @@ #ifndef _PARSER_AUX_H #define _PARSER_AUX_H -#define DER_LEN 16 - /***************************************/ /* Functions used by ASN.1 parser */ /***************************************/ @@ -48,12 +46,13 @@ asn1_node _asn1_set_right (asn1_node node, asn1_node right); asn1_node _asn1_get_last_right (asn1_node node); -void _asn1_remove_node (asn1_node node); +void _asn1_remove_node (asn1_node node, unsigned int flags); void _asn1_delete_list (void); void _asn1_delete_list_and_nodes (void); +#define LTOSTR_MAX_SIZE 20 char *_asn1_ltostr (long v, char *str); asn1_node _asn1_find_up (asn1_node node); diff --git a/lib/minitasn1/structure.c b/lib/minitasn1/structure.c index 31a5f654bb..27fbfe3a22 100644 --- a/lib/minitasn1/structure.c +++ b/lib/minitasn1/structure.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -192,7 +192,7 @@ asn1_array2tree (const asn1_static_node * array, asn1_node * definitions, k = 0; while (array[k].value || array[k].type || array[k].name) { - type = convert_old_type(array[k].type); + type = convert_old_type (array[k].type); p = _asn1_add_static_node (type & (~CONST_DOWN)); if (array[k].name) @@ -287,6 +287,23 @@ asn1_array2tree (const asn1_static_node * array, asn1_node * definitions, int asn1_delete_structure (asn1_node * structure) { + return asn1_delete_structure2(structure, 0); +} + +/** + * asn1_delete_structure2: + * @structure: pointer to the structure that you want to delete. + * @flags: additional flags (see %ASN1_DELETE_FLAG) + * + * Deletes the structure *@structure. At the end, *@structure is set + * to NULL. + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * *@structure was NULL. + **/ +int +asn1_delete_structure2 (asn1_node * structure, unsigned int flags) +{ asn1_node p, p2, p3; if (*structure == NULL) @@ -306,7 +323,7 @@ asn1_delete_structure (asn1_node * structure) { p3 = _asn1_find_up (p); _asn1_set_down (p3, p2); - _asn1_remove_node (p); + _asn1_remove_node (p, flags); p = p3; } else @@ -325,7 +342,7 @@ asn1_delete_structure (asn1_node * structure) } else _asn1_set_right (p3, p2); - _asn1_remove_node (p); + _asn1_remove_node (p, flags); p = NULL; } } @@ -409,22 +426,22 @@ _asn1_copy_structure3 (asn1_node source_node) } if (p_s == source_node) - break; + break; if (p_s->right) - { - move = RIGHT; - p_s = p_s->right; - p_d_prev = p_d; - p_d = _asn1_add_single_node (p_s->type); - _asn1_set_right (p_d_prev, p_d); - } + { + move = RIGHT; + p_s = p_s->right; + p_d_prev = p_d; + p_d = _asn1_add_single_node (p_s->type); + _asn1_set_right (p_d_prev, p_d); + } else - { - move = UP; - p_s = _asn1_find_up (p_s); - p_d = _asn1_find_up (p_d); - } + { + move = UP; + p_s = _asn1_find_up (p_s); + p_d = _asn1_find_up (p_d); + } } while (p_s != source_node); @@ -460,7 +477,8 @@ _asn1_type_choice_config (asn1_node node) { if (move != UP) { - if ((type_field (p->type) == ASN1_ETYPE_CHOICE) && (p->type & CONST_TAG)) + if ((type_field (p->type) == ASN1_ETYPE_CHOICE) + && (p->type & CONST_TAG)) { p2 = p->down; while (p2) @@ -548,7 +566,7 @@ _asn1_expand_identifier (asn1_node * node, asn1_node root) { if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER) { - snprintf(name2, sizeof (name2), "%s.%s", root->name, p->value); + snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value); p2 = _asn1_copy_structure2 (root, name2); if (p2 == NULL) { @@ -597,7 +615,7 @@ _asn1_expand_identifier (asn1_node * node, asn1_node root) if (p == *node) *node = p2; - _asn1_remove_node (p); + _asn1_remove_node (p, 0); p = p2; move = DOWN; continue; @@ -765,7 +783,7 @@ asn1_print_structure (FILE * out, asn1_node structure, const char *name, case ASN1_ETYPE_DEFINITIONS: fprintf (out, "type:DEFINITIONS"); break; - CASE_HANDLED_ETYPES: + CASE_HANDLED_ETYPES: fprintf (out, "%s", _asn1_tags[type].desc); break; default: @@ -854,7 +872,7 @@ asn1_print_structure (FILE * out, asn1_node structure, const char *name, if (p->value) { fprintf (out, " value:"); - for (k = 0; k < p->value_len; k++) + for (k = 0; k < p->value_len; k++) fprintf (out, "%c", (p->value)[k]); } break; @@ -1069,18 +1087,17 @@ asn1_number_of_elements (asn1_node element, const char *name, int *num) const char * asn1_find_structure_from_oid (asn1_node definitions, const char *oidValue) { - char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1]; + char name[2 * ASN1_MAX_NAME_SIZE + 1]; char value[ASN1_MAX_NAME_SIZE]; asn1_node p; int len; int result; + const char *definitionsName; if ((definitions == NULL) || (oidValue == NULL)) return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ - - strcpy (definitionsName, definitions->name); - strcat (definitionsName, "."); + definitionsName = definitions->name; /* search the OBJECT_ID into definitions */ p = definitions->down; @@ -1089,8 +1106,7 @@ asn1_find_structure_from_oid (asn1_node definitions, const char *oidValue) if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && (p->type & CONST_ASSIGN)) { - strcpy (name, definitionsName); - strcat (name, p->name); + snprintf(name, sizeof(name), "%s.%s", definitionsName, p->name); len = ASN1_MAX_NAME_SIZE; result = asn1_read_value (definitions, name, value, &len); diff --git a/lib/minitasn1/structure.h b/lib/minitasn1/structure.h index 986e13a309..bb6e7a9b9a 100644 --- a/lib/minitasn1/structure.h +++ b/lib/minitasn1/structure.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -29,8 +29,7 @@ #define _STRUCTURE_H int _asn1_create_static_structure (asn1_node pointer, - char *output_file_name, - char *vector_name); + char *output_file_name, char *vector_name); asn1_node _asn1_copy_structure3 (asn1_node source_node); diff --git a/lib/minitasn1/version.c b/lib/minitasn1/version.c index 83d70c9623..25f8a8f28e 100644 --- a/lib/minitasn1/version.c +++ b/lib/minitasn1/version.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2012 Free Software Foundation, Inc. + * Copyright (C) 2000-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * |