From a8bf137287009b869634a79cabb4af802c4f35b1 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jun 10 2014 12:41:54 +0000 Subject: import libtasn1-3.3-5.el7_0 --- diff --git a/SOURCES/libtasn1-3.3-decoding.patch b/SOURCES/libtasn1-3.3-decoding.patch new file mode 100644 index 0000000..9af65a0 --- /dev/null +++ b/SOURCES/libtasn1-3.3-decoding.patch @@ -0,0 +1,1304 @@ +diff -ur libtasn1-3.3/lib/decoding.c libtasn1-3.3.new/lib/decoding.c +--- libtasn1-3.3/lib/decoding.c 2013-03-24 10:55:30.000000000 +0100 ++++ libtasn1-3.3.new/lib/decoding.c 2014-05-29 11:03:39.837782788 +0200 +@@ -33,8 +33,25 @@ + #include + #include + ++#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) +@@ -149,7 +166,7 @@ + /* Long form */ + punt = 1; + ris = 0; +- while (punt <= der_len && der[punt] & 128) ++ while (punt < der_len && der[punt] & 128) + { + + if (INT_MULTIPLY_OVERFLOW (ris, 128)) +@@ -206,8 +223,7 @@ + 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; + } +@@ -233,12 +249,11 @@ + 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) +@@ -246,7 +261,10 @@ + + *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; +@@ -265,9 +283,11 @@ + + 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; +@@ -293,7 +313,7 @@ + + 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; +@@ -355,10 +375,11 @@ + 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; +@@ -366,8 +387,14 @@ + *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; +@@ -382,6 +409,7 @@ + { + 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; + +@@ -409,23 +437,21 @@ + 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) + { +@@ -462,11 +488,11 @@ + 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)) + { +@@ -485,18 +511,16 @@ + 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) + { +@@ -546,6 +570,9 @@ + counter += len2; + *ret_len = counter; + return ASN1_SUCCESS; ++ ++cleanup: ++ return result; + } + + static int +@@ -612,97 +639,108 @@ + 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); +@@ -710,7 +748,7 @@ + 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; + +@@ -718,10 +756,11 @@ + } + 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); +@@ -730,12 +769,16 @@ + *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; + +@@ -743,12 +786,11 @@ + + 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; +@@ -757,36 +799,44 @@ + } + + 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; + } + ++ ++ + /** + * 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. + * +@@ -802,7 +852,7 @@ + * 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; +@@ -824,6 +874,7 @@ + if (node->type & CONST_OPTION) + { + result = ASN1_GENERIC_ERROR; ++ warn(); + goto cleanup; + } + +@@ -841,11 +892,12 @@ + 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; + } + } +@@ -858,6 +910,7 @@ + else if (counter > len2) + { + result = ASN1_DER_ERROR; ++ warn(); + goto cleanup; + } + p2 = p2->down; +@@ -868,7 +921,7 @@ + if (type_field (p2->type) != ASN1_ETYPE_CHOICE) + ris = + _asn1_extract_tag_der (p2, der + counter, +- len - counter, &len2); ++ ider_len, &len2); + else + { + p3 = p2->down; +@@ -876,7 +929,7 @@ + { + ris = + _asn1_extract_tag_der (p3, der + counter, +- len - counter, &len2); ++ ider_len, &len2); + if (ris == ASN1_SUCCESS) + break; + p3 = p3->right; +@@ -894,6 +947,7 @@ + if (p2 == NULL) + { + result = ASN1_DER_ERROR; ++ warn(); + goto cleanup; + } + } +@@ -924,12 +978,9 @@ + { + while (p->down) + { +- if (counter < len) +- ris = ++ ris = + _asn1_extract_tag_der (p->down, der + counter, +- len - counter, &len2); +- else +- ris = ASN1_DER_ERROR; ++ ider_len, &len2); + if (ris == ASN1_SUCCESS) + { + while (p->down->right) +@@ -942,6 +993,7 @@ + else if (ris == ASN1_ERROR_TYPE_ANY) + { + result = ASN1_ERROR_TYPE_ANY; ++ warn(); + goto cleanup; + } + else +@@ -956,6 +1008,7 @@ + if (!(p->type & CONST_OPTION)) + { + result = ASN1_DER_ERROR; ++ warn(); + goto cleanup; + } + } +@@ -973,7 +1026,7 @@ + + 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) +@@ -992,11 +1045,15 @@ + _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) +@@ -1004,18 +1061,23 @@ + 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) +@@ -1027,50 +1089,68 @@ + 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; +@@ -1085,13 +1165,16 @@ + 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; +@@ -1104,18 +1187,12 @@ + _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; + } +@@ -1124,6 +1201,7 @@ + if (len2 != counter) + { + result = ASN1_DER_ERROR; ++ warn(); + goto cleanup; + } + } +@@ -1132,13 +1210,17 @@ + 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); +@@ -1177,13 +1259,7 @@ + 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; +@@ -1192,7 +1268,9 @@ + move = RIGHT; + continue; + } ++ + _asn1_set_value (p, NULL, 0); ++ DECR_LEN(ider_len, 2); + counter += 2; + } + else +@@ -1206,10 +1284,12 @@ + move = RIGHT; + continue; + } ++ + _asn1_set_value (p, NULL, 0); + if (len2 != counter) + { + result = ASN1_DER_ERROR; ++ warn(); + goto cleanup; + } + } +@@ -1217,12 +1297,15 @@ + 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) + { +@@ -1251,46 +1334,59 @@ + 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; + +@@ -1298,6 +1394,7 @@ + an indefinite length method. */ + if (indefinite) + { ++ DECR_LEN(ider_len, 2); + if (!der[counter] && !der[counter + 1]) + { + counter += 2; +@@ -1305,6 +1402,7 @@ + else + { + result = ASN1_DER_ERROR; ++ warn(); + goto cleanup; + } + } +@@ -1340,8 +1438,9 @@ + + _asn1_delete_not_used (*element); + +- if (counter != len) ++ if (ider_len != 0) + { ++ warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } +@@ -1374,6 +1473,9 @@ + * 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 +@@ -1737,15 +1839,14 @@ + move = RIGHT; + break; + case ASN1_ETYPE_OCTET_STRING: +- len3 = len - counter; + if (state == FOUND) + { +- result = _asn1_get_octet_string (der + counter, p, &len3); ++ result = _asn1_get_octet_string (p, der + counter, len-counter, &len3); + if (p == nodeFound) + state = EXIT; + } + else +- result = _asn1_get_octet_string (der + counter, NULL, &len3); ++ result = _asn1_get_octet_string (NULL, der + counter, len-counter, &len3); + + if (result != ASN1_SUCCESS) + goto cleanup; +@@ -1987,9 +2088,8 @@ + else + indefinite = 0; + +- len2 = len - counter; + result = +- _asn1_get_indefinite_length_string (der + counter, &len2); ++ _asn1_get_indefinite_length_string (der + counter, len-counter, &len2); + if (result != ASN1_SUCCESS) + goto cleanup; + +@@ -2160,7 +2260,7 @@ + * 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]) +@@ -2182,14 +2282,14 @@ + * 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; + 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; +@@ -2205,7 +2305,7 @@ + if (node_to_find == node) + { + *start = 0; +- *end = len - 1; ++ *end = ider_len - 1; + return ASN1_SUCCESS; + } + +@@ -2228,16 +2328,20 @@ + { + p2 = _asn1_find_up (p); + if (p2 == NULL) +- return ASN1_DER_ERROR; ++ { ++ 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; + } + } +@@ -2248,7 +2352,10 @@ + continue; + } + else if (counter > len2) +- return ASN1_DER_ERROR; ++ { ++ warn(); ++ return ASN1_DER_ERROR; ++ } + + p2 = p2->down; + +@@ -2259,7 +2366,7 @@ + if (type_field (p2->type) != ASN1_ETYPE_CHOICE) + ris = + _asn1_extract_tag_der (p2, der + counter, +- len - counter, &len2); ++ ider_len, &len2); + else + { + p3 = p2->down; +@@ -2268,7 +2375,7 @@ + + ris = + _asn1_extract_tag_der (p3, der + counter, +- len - counter, &len2); ++ ider_len, &len2); + } + if (ris == ASN1_SUCCESS) + { +@@ -2280,7 +2387,10 @@ + p2 = p2->right; + } + if (p2 == NULL) +- return ASN1_DER_ERROR; ++ { ++ warn(); ++ return ASN1_DER_ERROR; ++ } + } + + if (p == node_to_find) +@@ -2290,10 +2400,13 @@ + { + p = p->down; + if (p == NULL) +- return ASN1_DER_ERROR; ++ { ++ 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; +@@ -2301,7 +2414,7 @@ + + 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) +@@ -2315,11 +2428,15 @@ + } + else + { ++ warn(); + return ASN1_TAG_ERROR; + } + } + else +- counter += len2; ++ { ++ DECR_LEN(ider_len, len2); ++ counter += len2; ++ } + } + + if (ris == ASN1_SUCCESS) +@@ -2327,22 +2444,36 @@ + 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; +@@ -2362,9 +2493,14 @@ + 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; +@@ -2373,10 +2509,16 @@ + 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 +@@ -2384,8 +2526,11 @@ + } + 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; +@@ -2394,13 +2539,26 @@ + 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) || +@@ -2411,52 +2569,79 @@ + } + 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; +@@ -2494,7 +2679,11 @@ + p = _asn1_find_up (p); + } + ++ warn(); + return ASN1_ELEMENT_NOT_FOUND; ++ ++cleanup: ++ return result; + } + + /** diff --git a/SOURCES/libtasn1-3.3-null-deref.patch b/SOURCES/libtasn1-3.3-null-deref.patch new file mode 100644 index 0000000..4e90c64 --- /dev/null +++ b/SOURCES/libtasn1-3.3-null-deref.patch @@ -0,0 +1,113 @@ +diff --git a/lib/element.c b/lib/element.c +index 8604c24..8de3308 100644 +--- a/lib/element.c ++++ b/lib/element.c +@@ -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); +@@ -614,7 +617,7 @@ asn1_write_value (asn1_node node_root, const char *name, + *len = data_size; \ + if (ptr_size < data_size) { \ + return ASN1_MEM_ERROR; \ +- } else { \ ++ } else if (ptr) { \ + memcpy( ptr, data, data_size); \ + } + +@@ -622,7 +625,7 @@ asn1_write_value (asn1_node node_root, const char *name, + *len = _asn1_strlen(data) + 1; \ + if (ptr_size < *len) { \ + return ASN1_MEM_ERROR; \ +- } else { \ ++ } else if (ptr) { \ + /* this strcpy is checked */ \ + _asn1_strcpy(ptr, data); \ + } +@@ -631,20 +634,21 @@ asn1_write_value (asn1_node node_root, const char *name, + *len = data_size + 1; \ + if (ptr_size < *len) { \ + return ASN1_MEM_ERROR; \ +- } else { \ ++ } else if (ptr) { \ + /* this strcpy is checked */ \ + 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: +@@ -718,19 +722,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. +@@ -874,7 +881,9 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, + 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) + { +@@ -888,7 +897,7 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, + } + p = p->right; + } +- *len = _asn1_strlen (value) + 1; ++ (*len)++; + } + else if ((node->type & CONST_DEFAULT) && (node->value == NULL)) + { diff --git a/SPECS/libtasn1.spec b/SPECS/libtasn1.spec index 95223d2..5a38b64 100644 --- a/SPECS/libtasn1.spec +++ b/SPECS/libtasn1.spec @@ -1,7 +1,7 @@ Summary: The ASN.1 library used in GNUTLS Name: libtasn1 Version: 3.3 -Release: 3%{?dist} +Release: 5%{?dist} # The libtasn1 library is LGPLv2+, utilities are GPLv3+ License: GPLv3+ and LGPLv2+ @@ -10,6 +10,8 @@ URL: http://www.gnu.org/software/libtasn1/ Source0: http://ftp.gnu.org/gnu/libtasn1/%name-%version.tar.gz Source1: http://ftp.gnu.org/gnu/libtasn1/%name-%version.tar.gz.sig Patch1: libtasn1-2.12-rpath.patch +Patch2: libtasn1-3.3-decoding.patch +Patch3: libtasn1-3.3-null-deref.patch BuildRequires: bison, pkgconfig %ifarch %ix86 x86_64 ppc ppc64 BuildRequires: valgrind @@ -52,6 +54,8 @@ data. %setup -q %patch1 -p1 -b .rpath +%patch2 -p1 -b .der-decoding +%patch3 -p1 -b .null-deref %build %configure --disable-static --disable-silent-rules @@ -102,6 +106,12 @@ test "$1" = 0 -a -f %_infodir/%name.info.gz && \ %changelog +* Fri May 30 2014 Nikos Mavrogiannopoulos - 3.3-5 +- Added missing check for null pointer (#1102338) + +* Thu May 29 2014 Nikos Mavrogiannopoulos - 3.3-4 +- Fix multiple decoding issues (#1102338) + * Fri Jan 24 2014 Daniel Mach - 3.3-3 - Mass rebuild 2014-01-24