Check for overflows in EOC.
authorDr. Stephen Henson <steve@openssl.org>
Sat, 4 Jun 2016 11:48:00 +0000 (12:48 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Sat, 4 Jun 2016 12:54:49 +0000 (13:54 +0100)
RT#4474 (partial)

Reviewed-by: Rich Salz <rsalz@openssl.org>
crypto/asn1/a_d2i_fp.c
crypto/asn1/tasn_dec.c

index 9676ab7..e5c1d0e 100644 (file)
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <limits.h>
 #include "internal/cryptlib.h"
+#include "internal/numbers.h"
 #include <openssl/buffer.h>
 #include <openssl/asn1.h>
 
@@ -97,7 +98,7 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
     unsigned char *p;
     int i;
     size_t want = HEADER_SIZE;
-    int eos = 0;
+    uint32_t eos = 0;
     size_t off = 0;
     size_t len = 0;
 
@@ -152,16 +153,16 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
 
         if (inf & 1) {
             /* no data body so go round again */
-            eos++;
-            if (eos < 0) {
+            if (eos == UINT32_MAX) {
                 ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG);
                 goto err;
             }
+            eos++;
             want = HEADER_SIZE;
         } else if (eos && (slen == 0) && (tag == V_ASN1_EOC)) {
             /* eos value, so go back and read another header */
             eos--;
-            if (eos <= 0)
+            if (eos == 0)
                 break;
             else
                 want = HEADER_SIZE;
@@ -214,7 +215,7 @@ static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
                 goto err;
             }
             off += slen;
-            if (eos <= 0) {
+            if (eos == 0) {
                 break;
             } else
                 want = HEADER_SIZE;
index 64bbe40..aad838a 100644 (file)
@@ -14,6 +14,7 @@
 #include <openssl/objects.h>
 #include <openssl/buffer.h>
 #include <openssl/err.h>
+#include "internal/numbers.h"
 #include "asn1_locl.h"
 
 static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
@@ -895,7 +896,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
 
 static int asn1_find_end(const unsigned char **in, long len, char inf)
 {
-    int expected_eoc;
+    uint32_t expected_eoc;
     long plen;
     const unsigned char *p = *in, *q;
     /* If not indefinite length constructed just add length */
@@ -925,10 +926,15 @@ static int asn1_find_end(const unsigned char **in, long len, char inf)
             ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR);
             return 0;
         }
-        if (inf)
+        if (inf) {
+            if (expected_eoc == UINT32_MAX) {
+                ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR);
+                return 0;
+            }
             expected_eoc++;
-        else
+        } else {
             p += plen;
+        }
         len -= p - q;
     }
     if (expected_eoc) {