diff options
author | Stef Walter <stefw@gnome.org> | 2012-11-07 21:27:24 +0100 |
---|---|---|
committer | Stef Walter <stefw@gnome.org> | 2012-11-09 12:15:39 +0100 |
commit | 0023ffdf3fa02785ec1982b851a372f138297452 (patch) | |
tree | a05c9c4808a0c1b35cac1fd3a40e75926864b71e /egg | |
parent | e078e8a79015176158c195e3016578d4b030a0e4 (diff) | |
download | gnome-keyring-0023ffdf3fa02785ec1982b851a372f138297452.tar.gz |
egg-asn1x: Fix corner case where long DER length overflows
* Better detection of the case where TLV length overflows
the size of an int.
Diffstat (limited to 'egg')
-rw-r--r-- | egg/egg-asn1x.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/egg/egg-asn1x.c b/egg/egg-asn1x.c index 105540f6..c35cf1e1 100644 --- a/egg/egg-asn1x.c +++ b/egg/egg-asn1x.c @@ -669,6 +669,7 @@ atlv_parse_cls_tag (const guchar *at, { gint punt, ris, last; gint n_data; + guchar val; g_assert (end >= at); g_assert (cls != NULL); @@ -690,23 +691,27 @@ atlv_parse_cls_tag (const guchar *at, } else { punt = 1; ris = 0; - while (punt <= n_data && at[punt] & 128) { - int last = ris; - ris = ris * 128 + (at[punt++] & 0x7F); + while (punt <= n_data) { + val = at[punt++]; + last = ris; + ris = ris * 128; /* wrapper around, and no bignums... */ if (ris < last) return FALSE; - } - if (punt >= n_data) - return FALSE; + last = ris; + ris += (val & 0x7F); + + /* wrapper around, and no bignums... */ + if (ris < last) + return FALSE; - last = ris; - ris = ris * 128 + (at[punt++] & 0x7F); + if ((val & 0x7F) == val) + break; + } - /* wrapper around, and no bignums... */ - if (ris < last) + if (punt >= n_data) return FALSE; *off = punt; @@ -753,7 +758,14 @@ atlv_parse_length (const guchar *at, ans = 0; while (punt <= k && punt < n_data) { last = ans; - ans = ans * 256 + at[punt++]; + ans = ans * 256; + + /* we wrapped around, no bignum support... */ + if (ans < last) + return -2; + + last = ans; + ans += at[punt++]; /* we wrapped around, no bignum support... */ if (ans < last) |