diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/minitasn1/decoding.c | 145 |
1 files changed, 79 insertions, 66 deletions
diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c index 968fa96bfd..1cfad3556b 100644 --- a/lib/minitasn1/decoding.c +++ b/lib/minitasn1/decoding.c @@ -30,6 +30,7 @@ #include <gstr.h> #include "structure.h" #include "element.h" +#include <limits.h> static asn1_retCode _asn1_get_indefinite_length_string (const unsigned char *der, int *len); @@ -60,8 +61,8 @@ _asn1_error_description_tag_error (ASN1_TYPE node, char *ErrorDescription) signed long asn1_get_length_der (const unsigned char *der, int der_len, int *len) { - int ans; - int k, punt; + unsigned int ans, sum, last; + unsigned int k, punt; *len = 0; if (der_len <= 0) @@ -71,7 +72,7 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len) { /* short form */ *len = 1; - return der[0]; + ans = der[0]; } else { @@ -83,10 +84,10 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len) ans = 0; while (punt <= k && punt < der_len) { - int last = ans; + last = ans; - ans = ans * 256 + der[punt++]; - if (ans < last) + ans = (ans*256) + der[punt++]; + if (ans < last) /* we wrapped around, no bignum support... */ return -2; } @@ -98,10 +99,19 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len) } *len = punt; - if (ans + *len < ans || ans + *len > der_len) - return -4; - return ans; } + + sum = ans + *len; + + /* check for overflow as well INT_MAX as a maximum upper + * limit for length */ + if (sum >= INT_MAX || sum < ans) + return -2; + + if (sum > der_len) + return -4; + + return ans; } /** @@ -120,7 +130,8 @@ int asn1_get_tag_der (const unsigned char *der, int der_len, unsigned char *cls, int *len, unsigned long *tag) { - int punt, ris; + unsigned int punt, ris; + unsigned int last; if (der == NULL || der_len < 2 || len == NULL) return ASN1_DER_ERROR; @@ -139,21 +150,23 @@ asn1_get_tag_der (const unsigned char *der, int der_len, ris = 0; while (punt <= der_len && der[punt] & 128) { - int last = ris; - ris = ris * 128 + (der[punt++] & 0x7F); + last = ris; + + ris = (ris * 128) + (der[punt++] & 0x7F); if (ris < last) - /* wrapper around, and no bignums... */ + /* wrapped around, and no bignums... */ return ASN1_DER_ERROR; } + if (punt >= der_len) return ASN1_DER_ERROR; - { - int last = ris; - ris = ris * 128 + (der[punt++] & 0x7F); - if (ris < last) - /* wrapper around, and no bignums... */ - return ASN1_DER_ERROR; - } + + last = ris; + + ris = (ris * 128) + (der[punt++] & 0x7F); + if (ris < last) + return ASN1_DER_ERROR; + *len = punt; } if (tag) @@ -1031,10 +1044,10 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, len2 = asn1_get_length_der (der + counter, len - counter, &len3); if (len2 < 0) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } _asn1_set_value (p, der + counter, len3 + len2); counter += len3 + len2; @@ -1045,7 +1058,7 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, _asn1_get_objectid_der (der + counter, len - counter, &len2, temp, sizeof (temp)); if (result != ASN1_SUCCESS) - goto cleanup; + goto cleanup; tlen = strlen (temp); if (tlen > 0) @@ -1070,7 +1083,7 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, len3 = len - counter; result = _asn1_get_octet_string (der + counter, p, &len3); if (result != ASN1_SUCCESS) - goto cleanup; + goto cleanup; counter += len3; move = RIGHT; @@ -1079,10 +1092,10 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, len2 = asn1_get_length_der (der + counter, len - counter, &len3); if (len2 < 0) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } _asn1_set_value (p, der + counter, len3 + len2); counter += len3 + len2; @@ -1092,10 +1105,10 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, len2 = asn1_get_length_der (der + counter, len - counter, &len3); if (len2 < 0) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } _asn1_set_value (p, der + counter, len3 + len2); counter += len3 + len2; @@ -1118,10 +1131,10 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, } } else - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } counter += 2; } else @@ -1142,7 +1155,7 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, { result = ASN1_DER_ERROR; goto cleanup; - } + } counter += len2; if (len3 > 0) { @@ -1183,10 +1196,10 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, if (len2 == -1) { /* indefinite length method */ if ((counter + 2) > len) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } if ((der[counter]) || der[counter + 1]) { @@ -1227,7 +1240,7 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, { result = ASN1_DER_ERROR; goto cleanup; - } + } counter += len2; if (len3) { @@ -1258,24 +1271,24 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, 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; @@ -1311,7 +1324,7 @@ asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len, { result = ASN1_DER_ERROR; goto cleanup; - } + } } } move = RIGHT; @@ -1657,10 +1670,10 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, len2 = asn1_get_length_der (der + counter, len - counter, &len3); if (len2 < 0) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } if (state == FOUND) { @@ -1668,7 +1681,7 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, { result = ASN1_DER_ERROR; goto cleanup; - } + } _asn1_set_value (p, der + counter, len3 + len2); if (p == nodeFound) @@ -1702,7 +1715,7 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, { result = ASN1_DER_ERROR; goto cleanup; - } + } len2 += len3; } @@ -1733,7 +1746,7 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, { result = ASN1_DER_ERROR; goto cleanup; - } + } len2 += len3; } @@ -1761,10 +1774,10 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, len2 = asn1_get_length_der (der + counter, len - counter, &len3); if (len2 < 0) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } if (state == FOUND) { @@ -1772,7 +1785,7 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, { result = ASN1_DER_ERROR; goto cleanup; - } + } _asn1_set_value (p, der + counter, len3 + len2); if (p == nodeFound) @@ -1785,17 +1798,17 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, 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) @@ -1839,10 +1852,10 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, asn1_get_length_der (der + counter, len - counter, &len2); if (len3 < 0) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } counter += len2 + len3; move = RIGHT; } @@ -1852,10 +1865,10 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, asn1_get_length_der (der + counter, len - counter, &len2); if (len3 < 0) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } counter += len2; if (len3 > 0) { @@ -1922,10 +1935,10 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, asn1_get_length_der (der + counter, len - counter, &len2); if (len3 < 0) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } counter += len2 + len3; move = RIGHT; } @@ -1935,10 +1948,10 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, asn1_get_length_der (der + counter, len - counter, &len2); if (len3 < 0) - { + { result = ASN1_DER_ERROR; goto cleanup; - } + } counter += len2; if (len3) { @@ -1964,25 +1977,25 @@ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName, 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) { |