a_strex.c: prevent out of bound read in do_buf()
authorDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Thu, 26 Apr 2018 18:36:41 +0000 (20:36 +0200)
committerDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Wed, 2 May 2018 18:39:25 +0000 (20:39 +0200)
which is used for ASN1_STRING_print_ex*() and X509_NAME_print_ex*().

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6118)

crypto/asn1/a_strex.c
crypto/asn1/asn1.h
crypto/asn1/asn1_err.c

index 95f041620735835d4196de744309e34199c2884d..65f47a7c2227d3b0badfd7005f53f08ba0cd4ea5 100644 (file)
@@ -194,18 +194,38 @@ static int do_buf(unsigned char *buf, int buflen,
                   int type, unsigned char flags, char *quotes, char_io *io_ch,
                   void *arg)
 {
-    int i, outlen, len;
+    int i, outlen, len, charwidth;
     unsigned char orflags, *p, *q;
     unsigned long c;
     p = buf;
     q = buf + buflen;
     outlen = 0;
+    charwidth = type & BUF_TYPE_WIDTH_MASK;
+
+    switch (charwidth) {
+    case 4:
+        if (buflen & 3) {
+            ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+            return -1;
+        }
+        break;
+    case 2:
+        if (buflen & 1) {
+            ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_BMPSTRING_LENGTH);
+            return -1;
+        }
+        break;
+    default:
+        break;
+    }
+
     while (p != q) {
         if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
             orflags = CHARTYPE_FIRST_ESC_2253;
         else
             orflags = 0;
-        switch (type & BUF_TYPE_WIDTH_MASK) {
+
+        switch (charwidth) {
         case 4:
             c = ((unsigned long)*p++) << 24;
             c |= ((unsigned long)*p++) << 16;
@@ -226,6 +246,7 @@ static int do_buf(unsigned char *buf, int buflen,
             i = UTF8_getc(p, buflen, &c);
             if (i < 0)
                 return -1;      /* Invalid UTF8String */
+            buflen -= i;
             p += i;
             break;
         default:
index 35a2b2aa02381145d7827557ab4473c7db009c95..256c531811a4bf6c20dd01a9b61698025f73d31f 100644 (file)
@@ -1164,6 +1164,7 @@ int SMIME_text(BIO *in, BIO *out);
  * The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
  */
+
 void ERR_load_ASN1_strings(void);
 
 /* Error codes for the ASN1 functions. */
@@ -1264,6 +1265,7 @@ void ERR_load_ASN1_strings(void);
 # define ASN1_F_D2I_X509                                  156
 # define ASN1_F_D2I_X509_CINF                             157
 # define ASN1_F_D2I_X509_PKEY                             159
+# define ASN1_F_DO_BUF                                    221
 # define ASN1_F_I2D_ASN1_BIO_STREAM                       211
 # define ASN1_F_I2D_ASN1_SET                              188
 # define ASN1_F_I2D_ASN1_TIME                             160
@@ -1414,7 +1416,7 @@ void ERR_load_ASN1_strings(void);
 # define ASN1_R_WRONG_TAG                                 168
 # define ASN1_R_WRONG_TYPE                                169
 
-#ifdef  __cplusplus
+# ifdef  __cplusplus
 }
-#endif
+# endif
 #endif
index cfc1512f9d0747c78dcbc13813847caefb98f56b..c1441808363ffd82b278e16b5f759bb81e643d46 100644 (file)
@@ -166,6 +166,7 @@ static ERR_STRING_DATA ASN1_str_functs[] = {
     {ERR_FUNC(ASN1_F_D2I_X509), "D2I_X509"},
     {ERR_FUNC(ASN1_F_D2I_X509_CINF), "D2I_X509_CINF"},
     {ERR_FUNC(ASN1_F_D2I_X509_PKEY), "d2i_X509_PKEY"},
+    {ERR_FUNC(ASN1_F_DO_BUF), "DO_BUF"},
     {ERR_FUNC(ASN1_F_I2D_ASN1_BIO_STREAM), "i2d_ASN1_bio_stream"},
     {ERR_FUNC(ASN1_F_I2D_ASN1_SET), "i2d_ASN1_SET"},
     {ERR_FUNC(ASN1_F_I2D_ASN1_TIME), "I2D_ASN1_TIME"},