summaryrefslogtreecommitdiff
path: root/egg
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2012-11-07 21:27:24 +0100
committerStef Walter <stefw@gnome.org>2012-11-09 12:15:39 +0100
commit0023ffdf3fa02785ec1982b851a372f138297452 (patch)
treea05c9c4808a0c1b35cac1fd3a40e75926864b71e /egg
parente078e8a79015176158c195e3016578d4b030a0e4 (diff)
downloadgnome-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.c34
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)