diff options
Diffstat (limited to 'lib/decoding.c')
-rw-r--r-- | lib/decoding.c | 847 |
1 files changed, 485 insertions, 362 deletions
diff --git a/lib/decoding.c b/lib/decoding.c index 56f9582..b9245c4 100644 --- a/lib/decoding.c +++ b/lib/decoding.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2016 Free Software Foundation, Inc. + * Copyright (C) 2002-2022 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * @@ -32,6 +32,7 @@ #include <element.h> #include <limits.h> #include <intprops.h> +#include "c-ctype.h" #ifdef DEBUG # define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__) @@ -45,8 +46,8 @@ /* Decoding flags (dflags) used in several decoding functions. * DECODE_FLAG_HAVE_TAG: The provided buffer includes a tag - * DECODE_FLAG_INDEFINITE: The provided buffer is of indefinite encoding (useful - * when no tags are present). + * DECODE_FLAG_CONSTRUCTED: The provided buffer is of indefinite encoding (useful + * when no tags are present). * DECODE_FLAG_LEVEL1: Internal flag to indicate a level of recursion for BER strings. * DECODE_FLAG_LEVEL2: Internal flag to indicate two levels of recursion for BER strings. * DECODE_FLAG_LEVEL3: Internal flag to indicate three levels of recursion for BER strings. @@ -55,7 +56,7 @@ */ #define DECODE_FLAG_HAVE_TAG 1 -#define DECODE_FLAG_INDEFINITE (1<<1) +#define DECODE_FLAG_CONSTRUCTED (1<<1) #define DECODE_FLAG_LEVEL1 (1<<2) #define DECODE_FLAG_LEVEL2 (1<<3) #define DECODE_FLAG_LEVEL3 (1<<4) @@ -70,18 +71,19 @@ } while (0) static int -_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int *len); +_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, + int *len); static int _asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, - unsigned int _der_len, unsigned char **str, - unsigned int *str_len, unsigned int *ber_len, - unsigned dflags); + unsigned int _der_len, unsigned char **str, + unsigned int *str_len, unsigned int *ber_len, + unsigned dflags); static int _asn1_decode_simple_der (unsigned int etype, const unsigned char *der, - unsigned int _der_len, const unsigned char **str, - unsigned int *str_len, unsigned dflags); + unsigned int _der_len, const unsigned char **str, + unsigned int *str_len, unsigned dflags); static void _asn1_error_description_tag_error (asn1_node node, char *ErrorDescription) @@ -128,7 +130,7 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len) k = der[0] & 0x7F; punt = 1; if (k) - { /* definite length method */ + { /* definite length method */ ans = 0; while (punt <= k && punt < der_len) { @@ -251,9 +253,10 @@ asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len) long err; ret = asn1_get_length_der (ber, ber_len, len); + if (ret == -1 && ber_len > 1) { /* indefinite length method */ - err = _asn1_get_indefinite_length_string (ber + 1, ber_len-1, &ret); + err = _asn1_get_indefinite_length_string (ber + 1, ber_len - 1, &ret); if (err != ASN1_SUCCESS) return -3; } @@ -295,7 +298,7 @@ asn1_get_octet_der (const unsigned char *der, int der_len, if (str_size >= *str_len) { if (*str_len > 0 && str != NULL) - memcpy (str, der + len_len, *str_len); + memcpy (str, der + len_len, *str_len); } else { @@ -323,8 +326,8 @@ asn1_get_octet_der (const unsigned char *der, int der_len, * Returns: %ASN1_SUCCESS on success, or an error. -*/ static int -_asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *ret_len, - char *str, int str_size, unsigned flags) +_asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, + int *ret_len, char *str, int str_size, unsigned flags) { int len_len, str_len; unsigned i; @@ -342,46 +345,47 @@ _asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *r /* perform some sanity checks on the data */ if (str_len < 8) { - warn(); + warn (); return ASN1_TIME_ENCODING_ERROR; } - if ((flags & ASN1_DECODE_FLAG_STRICT_DER) && !(flags & ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME)) + if ((flags & ASN1_DECODE_FLAG_STRICT_DER) + && !(flags & ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME)) { p = &der[len_len]; - for (i=0;i<(unsigned)(str_len-1);i++) - { - if (isdigit(p[i]) == 0) - { - if (type == ASN1_ETYPE_GENERALIZED_TIME) - { - /* tolerate lax encodings */ - if (p[i] == '.' && dot_count == 0) - { - dot_count++; - continue; - } - - /* This is not really valid DER, but there are - * structures using that */ - if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && - (p[i] == '+' || p[i] == '-') && sign_count == 0) - { - sign_count++; - continue; - } - } - - warn(); - return ASN1_TIME_ENCODING_ERROR; - } - } - - if (sign_count == 0 && p[str_len-1] != 'Z') - { - warn(); - return ASN1_TIME_ENCODING_ERROR; - } + for (i = 0; i < (unsigned) (str_len - 1); i++) + { + if (c_isdigit (p[i]) == 0) + { + if (type == ASN1_ETYPE_GENERALIZED_TIME) + { + /* tolerate lax encodings */ + if (p[i] == '.' && dot_count == 0) + { + dot_count++; + continue; + } + + /* This is not really valid DER, but there are + * structures using that */ + if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && + (p[i] == '+' || p[i] == '-') && sign_count == 0) + { + sign_count++; + continue; + } + } + + warn (); + return ASN1_TIME_ENCODING_ERROR; + } + } + + if (sign_count == 0 && p[str_len - 1] != 'Z') + { + warn (); + return ASN1_TIME_ENCODING_ERROR; + } } memcpy (str, der + len_len, str_len); str[str_len] = 0; @@ -408,9 +412,9 @@ asn1_get_object_id_der (const unsigned char *der, int der_len, int *ret_len, char *str, int str_size) { int len_len, len, k; - int leading; + int leading, parsed; char temp[LTOSTR_MAX_SIZE]; - uint64_t val, val1; + uint64_t val, val1, val0; *ret_len = 0; if (str && str_size > 0) @@ -424,16 +428,48 @@ asn1_get_object_id_der (const unsigned char *der, int der_len, int *ret_len, if (len <= 0 || len + len_len > der_len) return ASN1_DER_ERROR; - val1 = der[len_len] / 40; - val = der[len_len] - val1 * 40; + /* leading octet can never be 0x80 */ + if (der[len_len] == 0x80) + return ASN1_DER_ERROR; + + val0 = 0; + + for (k = 0; k < len; k++) + { + if (INT_LEFT_SHIFT_OVERFLOW (val0, 7)) + return ASN1_DER_ERROR; - _asn1_str_cpy (str, str_size, _asn1_ltostr (val1, temp)); + val0 <<= 7; + val0 |= der[len_len + k] & 0x7F; + if (!(der[len_len + k] & 0x80)) + break; + } + parsed = ++k; + + /* val0 = (X*40) + Y, X={0,1,2}, Y<=39 when X={0,1} */ + /* X = val, Y = val1 */ + + /* check if X == 0 */ + val = 0; + val1 = val0; + if (val1 > 39) + { + val = 1; + val1 = val0 - 40; + if (val1 > 39) + { + val = 2; + val1 = val0 - 80; + } + } + + _asn1_str_cpy (str, str_size, _asn1_ltostr (val, temp)); _asn1_str_cat (str, str_size, "."); - _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp)); + _asn1_str_cat (str, str_size, _asn1_ltostr (val1, temp)); val = 0; leading = 1; - for (k = 1; k < len; k++) + for (k = parsed; k < len; k++) { /* X.690 mandates that the leading byte must never be 0x80 */ @@ -501,7 +537,7 @@ asn1_get_bit_der (const unsigned char *der, int der_len, if (str_size >= len_byte) { if (len_byte > 0 && str) - memcpy (str, der + len_len + 1, len_byte); + memcpy (str, der + len_len + 1, len_byte); } else { @@ -552,21 +588,19 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, &tag) != ASN1_SUCCESS) return ASN1_DER_ERROR; - DECR_LEN(der_len, len2); + DECR_LEN (der_len, len2); counter += len2; if (flags & ASN1_DECODE_FLAG_STRICT_DER) len3 = - asn1_get_length_der (der + counter, der_len, - &len2); + asn1_get_length_der (der + counter, der_len, &len2); else len3 = - asn1_get_length_ber (der + counter, der_len, - &len2); + asn1_get_length_ber (der + counter, der_len, &len2); if (len3 < 0) return ASN1_DER_ERROR; - DECR_LEN(der_len, len2); + DECR_LEN (der_len, len2); counter += len2; if (!is_tag_implicit) @@ -604,11 +638,10 @@ _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, &class, &len2, - &tag) != ASN1_SUCCESS) + (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS) return ASN1_DER_ERROR; - DECR_LEN(der_len, len2); + DECR_LEN (der_len, len2); if ((class != class_implicit) || (tag != tag_implicit)) { @@ -634,11 +667,10 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, } if (asn1_get_tag_der - (der + counter, der_len, &class, &len2, - &tag) != ASN1_SUCCESS) + (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS) return ASN1_DER_ERROR; - DECR_LEN(der_len, len2); + DECR_LEN (der_len, len2); switch (type) { @@ -699,28 +731,32 @@ cleanup: } static int -extract_tag_der_recursive(asn1_node node, const unsigned char *der, int der_len, - int *ret_len, int *inner_len, unsigned flags) +extract_tag_der_recursive (asn1_node node, const unsigned char *der, + int der_len, int *ret_len, int *inner_len, + unsigned flags) { -asn1_node p; -int ris = ASN1_DER_ERROR; + 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, inner_len, flags); - if (ris == ASN1_SUCCESS) - break; - p = p->right; + { + ris = + _asn1_extract_tag_der (p, der, der_len, ret_len, inner_len, + flags); + 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, inner_len, flags); + return _asn1_extract_tag_der (node, der, der_len, ret_len, inner_len, + flags); } static int @@ -795,10 +831,11 @@ _asn1_get_indefinite_length_string (const unsigned char *der, while (1) { - if (HAVE_TWO(der_len) && (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); + DECR_LEN (der_len, 2); indefinite--; if (indefinite <= 0) @@ -808,11 +845,10 @@ _asn1_get_indefinite_length_string (const unsigned char *der, } if (asn1_get_tag_der - (der + counter, der_len, &class, &len2, - &tag) != ASN1_SUCCESS) + (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS) return ASN1_DER_ERROR; - DECR_LEN(der_len, len2); + DECR_LEN (der_len, len2); counter += len2; len2 = asn1_get_length_der (der + counter, der_len, &len3); @@ -823,12 +859,12 @@ _asn1_get_indefinite_length_string (const unsigned char *der, { indefinite++; counter += 1; - DECR_LEN(der_len, 1); + DECR_LEN (der_len, 1); } else { counter += len2 + len3; - DECR_LEN(der_len, len2+len3); + DECR_LEN (der_len, len2 + len3); } } @@ -839,7 +875,8 @@ cleanup: return result; } -static void delete_unneeded_choice_fields(asn1_node p) +static void +delete_unneeded_choice_fields (asn1_node p) { asn1_node p2; @@ -878,13 +915,13 @@ static void delete_unneeded_choice_fields(asn1_node p) * name (*@ELEMENT deleted). **/ int -asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, +asn1_der_decoding2 (asn1_node * element, const void *ider, int *max_ider_len, unsigned int flags, char *errorDescription) { asn1_node node, p, p2, p3; char temp[128]; int counter, len2, len3, len4, move, ris, tlen; - struct node_tail_cache_st tcache = {NULL, NULL}; + struct node_tail_cache_st tcache = { NULL, NULL }; unsigned char class; unsigned long tag; int tag_len; @@ -905,7 +942,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, if (node->type & CONST_OPTION) { result = ASN1_GENERIC_ERROR; - warn(); + warn (); goto cleanup; } @@ -925,12 +962,13 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, len2 = p2->tmp_ival; if (len2 == -1) { - if (HAVE_TWO(ider_len) && !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); + DECR_LEN (ider_len, 2); continue; } } @@ -943,7 +981,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, else if (counter > len2) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } p2 = p2->down; @@ -952,8 +990,9 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED)) { ris = - extract_tag_der_recursive (p2, der + counter, - ider_len, &len2, NULL, flags); + extract_tag_der_recursive (p2, der + counter, + ider_len, &len2, NULL, + flags); if (ris == ASN1_SUCCESS) { p2->type &= ~CONST_NOT_USED; @@ -966,7 +1005,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, if (p2 == NULL) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } } @@ -1002,18 +1041,18 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, while (p->down) { ris = - extract_tag_der_recursive (p->down, der + counter, - ider_len, &len2, NULL, flags); + extract_tag_der_recursive (p->down, der + counter, + ider_len, &len2, NULL, flags); if (ris == ASN1_SUCCESS) { - delete_unneeded_choice_fields(p->down); + delete_unneeded_choice_fields (p->down); break; } else if (ris == ASN1_ERROR_TYPE_ANY) { result = ASN1_ERROR_TYPE_ANY; - warn(); + warn (); goto cleanup; } else @@ -1028,7 +1067,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, if (!(p->type & CONST_OPTION)) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } } @@ -1050,7 +1089,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, if (ris == ASN1_SUCCESS) ris = extract_tag_der_recursive (p, der + counter, ider_len, - &tag_len, &inner_tag_len, flags); + &tag_len, &inner_tag_len, flags); if (ris != ASN1_SUCCESS) { @@ -1070,13 +1109,13 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, _asn1_error_description_tag_error (p, errorDescription); result = ASN1_TAG_ERROR; - warn(); + warn (); goto cleanup; } } else { - DECR_LEN(ider_len, tag_len); + DECR_LEN (ider_len, tag_len); counter += tag_len; } } @@ -1086,23 +1125,23 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, switch (type_field (p->type)) { case ASN1_ETYPE_NULL: - DECR_LEN(ider_len, 1); + DECR_LEN (ider_len, 1); if (der[counter]) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } counter++; move = RIGHT; break; case ASN1_ETYPE_BOOLEAN: - DECR_LEN(ider_len, 2); + DECR_LEN (ider_len, 2); if (der[counter++] != 1) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } if (der[counter++] == 0) @@ -1113,16 +1152,15 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, break; case ASN1_ETYPE_INTEGER: case ASN1_ETYPE_ENUMERATED: - len2 = - asn1_get_length_der (der + counter, ider_len, &len3); + len2 = asn1_get_length_der (der + counter, ider_len, &len3); if (len2 < 0) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } - DECR_LEN(ider_len, len3+len2); + DECR_LEN (ider_len, len3 + len2); _asn1_set_value (p, der + counter, len3 + len2); counter += len3 + len2; @@ -1133,12 +1171,12 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, asn1_get_object_id_der (der + counter, ider_len, &len2, temp, sizeof (temp)); if (result != ASN1_SUCCESS) - { - warn(); + { + warn (); goto cleanup; } - DECR_LEN(ider_len, len2); + DECR_LEN (ider_len, len2); tlen = strlen (temp); if (tlen > 0) @@ -1150,15 +1188,16 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, case ASN1_ETYPE_GENERALIZED_TIME: case ASN1_ETYPE_UTC_TIME: result = - _asn1_get_time_der (type_field (p->type), der + counter, ider_len, &len2, temp, - sizeof (temp) - 1, flags); + _asn1_get_time_der (type_field (p->type), der + counter, + ider_len, &len2, temp, sizeof (temp) - 1, + flags); if (result != ASN1_SUCCESS) - { - warn(); - goto cleanup; - } + { + warn (); + goto cleanup; + } - DECR_LEN(ider_len, len2); + DECR_LEN (ider_len, len2); tlen = strlen (temp); if (tlen > 0) @@ -1169,50 +1208,60 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, break; case ASN1_ETYPE_OCTET_STRING: if (counter < inner_tag_len) - { + { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; - } - - ptag = der + counter - inner_tag_len; - if (flags & ASN1_DECODE_FLAG_STRICT_DER || !(ptag[0] & ASN1_CLASS_STRUCTURED)) - { - len2 = - asn1_get_length_der (der + counter, ider_len, &len3); - if (len2 < 0) + } + + ptag = der + counter - inner_tag_len; + if ((flags & ASN1_DECODE_FLAG_STRICT_DER) + || !(ptag[0] & ASN1_CLASS_STRUCTURED)) + { + if (ptag[0] & ASN1_CLASS_STRUCTURED) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } - DECR_LEN(ider_len, len3+len2); + len2 = 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; - } - else - { - unsigned dflags = 0, vlen, ber_len; + _asn1_set_value (p, der + counter, len3 + len2); + counter += len3 + len2; + } + else + { + unsigned dflags = 0, vlen, ber_len; - if (ptag[0] & ASN1_CLASS_STRUCTURED) - dflags |= DECODE_FLAG_INDEFINITE; + if (ptag[0] & ASN1_CLASS_STRUCTURED) + dflags |= DECODE_FLAG_CONSTRUCTED; - result = _asn1_decode_simple_ber(type_field (p->type), der+counter, ider_len, &ptmp, &vlen, &ber_len, dflags); - if (result != ASN1_SUCCESS) - { - warn(); + result = + _asn1_decode_simple_ber (type_field (p->type), + der + counter, ider_len, &ptmp, + &vlen, &ber_len, dflags); + if (result != ASN1_SUCCESS) + { + warn (); goto cleanup; } - DECR_LEN(ider_len, ber_len); + DECR_LEN (ider_len, ber_len); _asn1_set_value_lv (p, ptmp, vlen); - counter += ber_len; - free(ptmp); - } + counter += ber_len; + free (ptmp); + } move = RIGHT; break; case ASN1_ETYPE_GENERALSTRING: @@ -1225,16 +1274,15 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, case ASN1_ETYPE_UTF8_STRING: case ASN1_ETYPE_VISIBLE_STRING: case ASN1_ETYPE_BIT_STRING: - len2 = - asn1_get_length_der (der + counter, ider_len, &len3); + len2 = asn1_get_length_der (der + counter, ider_len, &len3); if (len2 < 0) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } - DECR_LEN(ider_len, len3+len2); + DECR_LEN (ider_len, len3 + len2); _asn1_set_value (p, der + counter, len3 + len2); counter += len3 + len2; @@ -1248,12 +1296,12 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, p->tmp_ival = 0; if (len2 == -1) { /* indefinite length method */ - DECR_LEN(ider_len, 2); + DECR_LEN (ider_len, 2); if ((der[counter]) || der[counter + 1]) - { - result = ASN1_DER_ERROR; - warn(); - goto cleanup; + { + result = ASN1_DER_ERROR; + warn (); + goto cleanup; } counter += 2; } @@ -1262,7 +1310,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, if (len2 != counter) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } } @@ -1270,16 +1318,15 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, } else { /* move==DOWN || move==RIGHT */ - len3 = - asn1_get_length_der (der + counter, ider_len, &len2); - if (IS_ERR(len3, flags)) + len3 = asn1_get_length_der (der + counter, ider_len, &len2); + if (IS_ERR (len3, flags)) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } - DECR_LEN(ider_len, len2); + DECR_LEN (ider_len, len2); counter += len2; if (len3 > 0) @@ -1317,23 +1364,24 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, len2 = p->tmp_ival; if (len2 == -1) { /* indefinite length method */ - if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1])) + if (!HAVE_TWO (ider_len) + || ((der[counter]) || der[counter + 1])) { result = _asn1_append_sequence_set (p, &tcache); if (result != 0) { - warn(); - goto cleanup; - } + warn (); + goto cleanup; + } p = tcache.tail; move = RIGHT; continue; } p->tmp_ival = 0; - tcache.tail = NULL; /* finished decoding this structure */ + tcache.tail = NULL; /* finished decoding this structure */ tcache.head = NULL; - DECR_LEN(ider_len, 2); + DECR_LEN (ider_len, 2); counter += 2; } else @@ -1343,69 +1391,68 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, result = _asn1_append_sequence_set (p, &tcache); if (result != 0) { - warn(); - goto cleanup; - } + warn (); + goto cleanup; + } p = tcache.tail; move = RIGHT; continue; } p->tmp_ival = 0; - tcache.tail = NULL; /* finished decoding this structure */ + tcache.tail = NULL; /* finished decoding this structure */ tcache.head = NULL; if (len2 != counter) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } } } else { /* move==DOWN || move==RIGHT */ - len3 = - asn1_get_length_der (der + counter, ider_len, &len2); - if (IS_ERR(len3, flags)) + len3 = asn1_get_length_der (der + counter, ider_len, &len2); + if (IS_ERR (len3, flags)) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } - DECR_LEN(ider_len, len2); + DECR_LEN (ider_len, len2); counter += len2; if (len3) { if (len3 > 0) { /* definite length method */ - p->tmp_ival = counter + len3; + p->tmp_ival = counter + len3; } else { /* indefinite length method */ - p->tmp_ival = -1; + p->tmp_ival = -1; } p2 = p->down; - if (p2 == NULL) - { - result = ASN1_DER_ERROR; - warn(); - goto cleanup; - } + if (p2 == NULL) + { + result = ASN1_DER_ERROR; + warn (); + goto cleanup; + } while ((type_field (p2->type) == ASN1_ETYPE_TAG) || (type_field (p2->type) == ASN1_ETYPE_SIZE)) p2 = p2->right; if (p2->right == NULL) - { + { result = _asn1_append_sequence_set (p, &tcache); if (result != 0) { - warn(); - goto cleanup; - } + warn (); + goto cleanup; + } } p = p2; } @@ -1415,81 +1462,82 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, case ASN1_ETYPE_ANY: /* Check indefinite lenth method in an EXPLICIT TAG */ - if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && (p->type & CONST_TAG) && - tag_len == 2 && (der[counter - 1] == 0x80)) + if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) + && (p->type & CONST_TAG) && tag_len == 2 + && (der[counter - 1] == 0x80)) indefinite = 1; else - indefinite = 0; + indefinite = 0; if (asn1_get_tag_der (der + counter, ider_len, &class, &len2, &tag) != ASN1_SUCCESS) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } - DECR_LEN(ider_len, len2); + DECR_LEN (ider_len, len2); len4 = - asn1_get_length_der (der + counter + len2, - ider_len, &len3); - if (IS_ERR(len4, flags)) + asn1_get_length_der (der + counter + len2, ider_len, &len3); + if (IS_ERR (len4, flags)) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } - if (len4 != -1) /* definite */ + if (len4 != -1) /* definite */ { len2 += len4; - DECR_LEN(ider_len, len4+len3); + DECR_LEN (ider_len, len4 + len3); _asn1_set_value_lv (p, der + counter, len2 + len3); counter += len2 + len3; } - else /* == -1 */ + else /* == -1 */ { /* indefinite length */ - ider_len += len2; /* undo DECR_LEN */ + ider_len += len2; /* undo DECR_LEN */ if (counter == 0) { result = ASN1_DER_ERROR; - warn(); + warn (); goto cleanup; } result = - _asn1_get_indefinite_length_string (der + counter, ider_len, &len2); + _asn1_get_indefinite_length_string (der + counter, + ider_len, &len2); if (result != ASN1_SUCCESS) { - warn(); - goto cleanup; - } + warn (); + goto cleanup; + } - DECR_LEN(ider_len, len2); + DECR_LEN (ider_len, len2); _asn1_set_value_lv (p, der + counter, len2); counter += len2; } - /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with - an indefinite length method. */ - if (indefinite) - { - DECR_LEN(ider_len, 2); - if (!der[counter] && !der[counter + 1]) - { - counter += 2; - } - else - { - result = ASN1_DER_ERROR; - warn(); - goto cleanup; - } - } + /* 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 + { + result = ASN1_DER_ERROR; + warn (); + goto cleanup; + } + } move = RIGHT; break; @@ -1500,9 +1548,9 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, } if (p) - { - p->end = counter - 1; - } + { + p->end = counter - 1; + } if (p == node && move != DOWN) break; @@ -1530,7 +1578,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, if ((ider_len < 0) || (!(flags & ASN1_DECODE_FLAG_ALLOW_PADDING) && (ider_len != 0))) { - warn(); + warn (); result = ASN1_DER_ERROR; goto cleanup; } @@ -1600,7 +1648,7 @@ int asn1_der_decoding_element (asn1_node * structure, const char *elementName, const void *ider, int len, char *errorDescription) { - return asn1_der_decoding(structure, ider, len, errorDescription); + return asn1_der_decoding (structure, ider, len, errorDescription); } /** @@ -1654,19 +1702,19 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len, if (*start == 0 && *end == 0) { if (ider == NULL || ider_len == 0) - return ASN1_GENERIC_ERROR; + return ASN1_GENERIC_ERROR; /* it seems asn1_der_decoding() wasn't called before. Do it now */ result = asn1_der_decoding (&node, ider, ider_len, NULL); if (result != ASN1_SUCCESS) - { - warn(); - return result; - } + { + warn (); + return result; + } node_to_find = asn1_find_node (node, name_element); if (node_to_find == NULL) - return ASN1_ELEMENT_NOT_FOUND; + return ASN1_ELEMENT_NOT_FOUND; *start = node_to_find->start; *end = node_to_find->end; @@ -1697,8 +1745,7 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len, int asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element) { - char name[2 * ASN1_MAX_NAME_SIZE + 2], - value[ASN1_MAX_NAME_SIZE]; + char name[2 * ASN1_MAX_NAME_SIZE + 2], value[ASN1_MAX_NAME_SIZE]; int retCode = ASN1_SUCCESS, result; int len, len2, len3; asn1_node_const p2; @@ -1784,7 +1831,8 @@ asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element) if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && (p2->type & CONST_ASSIGN)) { - snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); + snprintf (name, sizeof (name), "%s.%s", definitionsName, + p2->name); len = ASN1_MAX_NAME_SIZE; result = @@ -1800,7 +1848,8 @@ asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element) if (p2) { - snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); + snprintf (name, sizeof (name), "%s.%s", + definitionsName, p2->name); result = asn1_create_element (definitions, name, &aux); @@ -2064,8 +2113,8 @@ asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, -*/ static int _asn1_decode_simple_der (unsigned int etype, const unsigned char *der, - unsigned int _der_len, const unsigned char **str, - unsigned int *str_len, unsigned dflags) + unsigned int _der_len, const unsigned char **str, + unsigned int *str_len, unsigned dflags) { int tag_len, len_len; const unsigned char *p; @@ -2077,11 +2126,11 @@ _asn1_decode_simple_der (unsigned int etype, const unsigned char *der, if (der == NULL || der_len == 0) return ASN1_VALUE_NOT_VALID; - if (ETYPE_OK (etype) == 0 || ETYPE_IS_STRING(etype) == 0) + if (ETYPE_OK (etype) == 0 || ETYPE_IS_STRING (etype) == 0) return ASN1_VALUE_NOT_VALID; /* doesn't handle constructed classes */ - class = ETYPE_CLASS(etype); + class = ETYPE_CLASS (etype); if (class != ASN1_CLASS_UNIVERSAL) return ASN1_VALUE_NOT_VALID; @@ -2091,18 +2140,18 @@ _asn1_decode_simple_der (unsigned int etype, const unsigned char *der, { ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); if (ret != ASN1_SUCCESS) - return ret; + return ret; if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype)) - { - warn(); - return ASN1_DER_ERROR; - } + { + warn (); + return ASN1_DER_ERROR; + } p += tag_len; der_len -= tag_len; if (der_len <= 0) - return ASN1_DER_ERROR; + return ASN1_DER_ERROR; } ret = asn1_get_length_der (p, der_len, &len_len); @@ -2138,15 +2187,21 @@ asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned int _der_len, const unsigned char **str, unsigned int *str_len) { - return _asn1_decode_simple_der(etype, der, _der_len, str, str_len, DECODE_FLAG_HAVE_TAG); + return _asn1_decode_simple_der (etype, der, _der_len, str, str_len, + DECODE_FLAG_HAVE_TAG); } -static int append(uint8_t **dst, unsigned *dst_size, const unsigned char *src, unsigned src_size) +static int +append (uint8_t ** dst, unsigned *dst_size, const unsigned char *src, + unsigned src_size) { - *dst = _asn1_realloc(*dst, *dst_size+src_size); + if (src_size == 0) + return ASN1_SUCCESS; + + *dst = _asn1_realloc (*dst, *dst_size + src_size); if (*dst == NULL) - return ASN1_MEM_ERROR; - memcpy(*dst + *dst_size, src, src_size); + return ASN1_MEM_ALLOC_ERROR; + memcpy (*dst + *dst_size, src, src_size); *dst_size += src_size; return ASN1_SUCCESS; } @@ -2169,9 +2224,9 @@ static int append(uint8_t **dst, unsigned *dst_size, const unsigned char *src, u -*/ static int _asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, - unsigned int _der_len, unsigned char **str, - unsigned int *str_len, unsigned int *ber_len, - unsigned dflags) + unsigned int _der_len, unsigned char **str, + unsigned int *str_len, unsigned int *ber_len, + unsigned dflags) { int tag_len, len_len; const unsigned char *p; @@ -2185,17 +2240,18 @@ _asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, unsigned out_len; long result; - if (ber_len) *ber_len = 0; + if (ber_len) + *ber_len = 0; if (der == NULL || der_len == 0) { - warn(); + warn (); return ASN1_VALUE_NOT_VALID; } if (ETYPE_OK (etype) == 0) { - warn(); + warn (); return ASN1_VALUE_NOT_VALID; } @@ -2203,7 +2259,7 @@ _asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, class = ETYPE_CLASS (etype); if (class != ASN1_CLASS_UNIVERSAL) { - warn(); + warn (); return ASN1_VALUE_NOT_VALID; } @@ -2212,134 +2268,200 @@ _asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, if (dflags & DECODE_FLAG_HAVE_TAG) { result = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); - if (result != ASN1_SUCCESS) - { - warn(); - return result; - } + if (result != ASN1_SUCCESS) + { + warn (); + return result; + } - if (tag != ETYPE_TAG (etype)) - { - warn(); - return ASN1_DER_ERROR; - } + if (tag != ETYPE_TAG (etype)) + { + warn (); + return ASN1_DER_ERROR; + } - p += tag_len; + p += tag_len; - DECR_LEN(der_len, tag_len); + DECR_LEN (der_len, tag_len); - if (ber_len) *ber_len += tag_len; + if (ber_len) + *ber_len += tag_len; } /* indefinite constructed */ - if ((((dflags & DECODE_FLAG_INDEFINITE) || class == ASN1_CLASS_STRUCTURED) && ETYPE_IS_STRING(etype)) && - !(dflags & DECODE_FLAG_LEVEL3)) + if ((((dflags & DECODE_FLAG_CONSTRUCTED) || class == ASN1_CLASS_STRUCTURED) + && ETYPE_IS_STRING (etype)) && !(dflags & DECODE_FLAG_LEVEL3)) { - len_len = 1; - - DECR_LEN(der_len, len_len); - if (p[0] != 0x80) - { - warn(); - result = ASN1_DER_ERROR; - goto cleanup; - } + if (der_len == 0) + { + warn (); + result = ASN1_DER_ERROR; + goto cleanup; + } - p += len_len; + if (der_len > 0 && p[0] == 0x80) /* indefinite */ + { + len_len = 1; + DECR_LEN (der_len, len_len); + p += len_len; - if (ber_len) *ber_len += len_len; + if (ber_len) + *ber_len += len_len; - /* decode the available octet strings */ - do - { - unsigned tmp_len; - unsigned flags = DECODE_FLAG_HAVE_TAG; + /* decode the available octet strings */ + do + { + unsigned tmp_len; + unsigned flags = DECODE_FLAG_HAVE_TAG; - if (dflags & DECODE_FLAG_LEVEL1) - flags |= DECODE_FLAG_LEVEL2; - else if (dflags & DECODE_FLAG_LEVEL2) + if (dflags & DECODE_FLAG_LEVEL1) + flags |= DECODE_FLAG_LEVEL2; + else if (dflags & DECODE_FLAG_LEVEL2) flags |= DECODE_FLAG_LEVEL3; - else + else flags |= DECODE_FLAG_LEVEL1; - result = _asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len, - flags); - if (result != ASN1_SUCCESS) - { - warn(); - goto cleanup; - } + result = + _asn1_decode_simple_ber (etype, p, der_len, &out, &out_len, + &tmp_len, flags); + if (result != ASN1_SUCCESS) + { + warn (); + goto cleanup; + } + + p += tmp_len; + DECR_LEN (der_len, tmp_len); - p += tmp_len; - DECR_LEN(der_len, tmp_len); + if (ber_len) + *ber_len += tmp_len; - if (ber_len) *ber_len += tmp_len; + DECR_LEN (der_len, 2); /* we need the EOC */ + + result = append (&total, &total_size, out, out_len); + if (result != ASN1_SUCCESS) + { + warn (); + goto cleanup; + } - DECR_LEN(der_len, 2); /* we need the EOC */ + free (out); + out = NULL; - if (out_len > 0) + if (p[0] == 0 && p[1] == 0) /* EOC */ + { + if (ber_len) + *ber_len += 2; + break; + } + + /* no EOC */ + der_len += 2; + + if (der_len == 2) + { + warn (); + result = ASN1_DER_ERROR; + goto cleanup; + } + } + while (1); + } + else /* constructed */ + { + long const_len; + + result = asn1_get_length_ber (p, der_len, &len_len); + if (result < 0) { - result = append(&total, &total_size, out, out_len); - if (result != ASN1_SUCCESS) - { - warn(); - goto cleanup; - } + warn (); + result = ASN1_DER_ERROR; + goto cleanup; } - free(out); - out = NULL; + DECR_LEN (der_len, len_len); + p += len_len; - if (p[0] == 0 && p[1] == 0) /* EOC */ + const_len = result; + + if (ber_len) + *ber_len += len_len; + + /* decode the available octet strings */ + while (const_len > 0) { - if (ber_len) *ber_len += 2; - break; - } - - /* no EOC */ - der_len += 2; - - if (der_len == 2) - { - warn(); - result = ASN1_DER_ERROR; - goto cleanup; - } - } - while(1); + unsigned tmp_len; + unsigned flags = DECODE_FLAG_HAVE_TAG; + + if (dflags & DECODE_FLAG_LEVEL1) + flags |= DECODE_FLAG_LEVEL2; + else if (dflags & DECODE_FLAG_LEVEL2) + flags |= DECODE_FLAG_LEVEL3; + else + flags |= DECODE_FLAG_LEVEL1; + + result = + _asn1_decode_simple_ber (etype, p, der_len, &out, &out_len, + &tmp_len, flags); + if (result != ASN1_SUCCESS) + { + warn (); + goto cleanup; + } + + p += tmp_len; + DECR_LEN (der_len, tmp_len); + DECR_LEN (const_len, tmp_len); + + if (ber_len) + *ber_len += tmp_len; + + result = append (&total, &total_size, out, out_len); + if (result != ASN1_SUCCESS) + { + warn (); + goto cleanup; + } + + free (out); + out = NULL; + } + } } - else if (class == ETYPE_CLASS(etype)) + else if (class == ETYPE_CLASS (etype)) { if (ber_len) - { - result = asn1_get_length_der (p, der_len, &len_len); - if (result < 0) - { - warn(); - result = ASN1_DER_ERROR; - goto cleanup; - } - *ber_len += result + len_len; - } + { + result = asn1_get_length_der (p, der_len, &len_len); + if (result < 0) + { + warn (); + result = ASN1_DER_ERROR; + goto cleanup; + } + *ber_len += result + len_len; + } /* non-string values are decoded as DER */ - result = _asn1_decode_simple_der(etype, der, _der_len, &cout, &out_len, dflags); + result = + _asn1_decode_simple_der (etype, der, _der_len, &cout, &out_len, + dflags); if (result != ASN1_SUCCESS) - { - warn(); - goto cleanup; - } + { + warn (); + goto cleanup; + } - result = append(&total, &total_size, cout, out_len); + result = append (&total, &total_size, cout, out_len); if (result != ASN1_SUCCESS) - { - warn(); - goto cleanup; - } + { + warn (); + goto cleanup; + } } else { - warn(); + warn (); result = ASN1_DER_ERROR; goto cleanup; } @@ -2349,8 +2471,8 @@ _asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, return ASN1_SUCCESS; cleanup: - free(out); - free(total); + free (out); + free (total); return result; } @@ -2374,5 +2496,6 @@ asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, unsigned int _der_len, unsigned char **str, unsigned int *str_len, unsigned int *ber_len) { - return _asn1_decode_simple_ber(etype, der, _der_len, str, str_len, ber_len, DECODE_FLAG_HAVE_TAG); + return _asn1_decode_simple_ber (etype, der, _der_len, str, str_len, ber_len, + DECODE_FLAG_HAVE_TAG); } |