Source:
Internal
Info:
The asn1_get_length_der function in decoding.c in GNU Libtasn1 before 2.12, as
used in GnuTLS before 3.0.16 and other products, does not properly handle
certain large length values, which allows remote attackers to cause a denial
of service (heap memory corruption and application crash) or possibly have
unspecified other impact via a crafted ASN.1 structure.
Status:
Need to determine if this patch has been sent upstream.
--- libtasn1-2.8/lib/decoding.c.orig 2012-04-06 12:19:39.986443804 +0800
+++ libtasn1-2.8/lib/decoding.c 2012-04-06 12:38:38.607157322 +0800
@@ -55,12 +55,14 @@
* Extract a length field from DER data.
*
* Returns: Return the decoded length value, or -1 on indefinite
- * length, or -2 when the value was too big.
+ * length, or -2 when the value was too big to fit in a int, or -4
+ * when the decoed length value plus @len would exceed @der_len.
+
**/
signed long
asn1_get_length_der (const unsigned char *der, int der_len, int *len)
{
- unsigned long ans;
+ int ans;
int k, punt;
*len = 0;
@@ -83,7 +85,7 @@
ans = 0;
while (punt <= k && punt < der_len)
{
- unsigned long last = ans;
+ int last = ans;
ans = ans * 256 + der[punt++];
if (ans < last)
@@ -93,10 +95,13 @@
}
else
{ /* indefinite length method */
- ans = -1;
+ *len = punt;
+ return -1;
}
*len = punt;
+ if (ans + *len < ans || ans + *len > der_len)
+ return -4;
return ans;
}
}