From 6f3bce4bdaf45c23107ba07b65eeaa00c1436346 Mon Sep 17 00:00:00 2001 From: mancha Date: Thu, 3 Oct 2013 Subject: CVE-2012-1569 [GNUTLS-SA-2012-3] asn1_get_length_der() in decoding.c in GNU Libtasn1 before 2.12 does not properly handle certain large length values. This can be exploited by attackers to cause a DoS or other impacts via a crafted ASN.1 structure. Fix adapted for use with libtasn1 embedded in GnuTLS 2.8.4. Relevant upstream patch: ------------------------ http://article.gmane.org/gmane.comp.gnu.libtasn1.general/54 --- decoding.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) --- a/lib/minitasn1/decoding.c +++ b/lib/minitasn1/decoding.c @@ -55,12 +55,13 @@ _asn1_error_description_tag_error (ASN1_TYPE node, char *ErrorDescription) * Extract a length field from DER data. * * Return value: 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 decoded 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 +84,7 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len) 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 +94,13 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len) } else { /* indefinite length method */ - ans = -1; + *len = punt; + return -1; } *len = punt; + if (ans + *len < ans || ans + *len > der_len) + return -4; return ans; } }