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:36:21 +0000 (20:36 +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/6105)

crypto/asn1/a_strex.c
crypto/asn1/asn1_err.c
crypto/err/openssl.txt
include/openssl/asn1err.h

index 1d34f56b0b25f77e6906f4dd0556db41621d02fb..6a67bc8c33080ea8d77802013febe4684aba2c55 100644 (file)
@@ -139,7 +139,7 @@ static int do_buf(unsigned char *buf, int buflen,
                   int type, unsigned short flags, char *quotes, char_io *io_ch,
                   void *arg)
 {
-    int i, outlen, len;
+    int i, outlen, len, charwidth;
     unsigned short orflags;
     unsigned char *p, *q;
     unsigned long c;
@@ -147,12 +147,32 @@ static int do_buf(unsigned char *buf, int buflen,
     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;
@@ -173,6 +193,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 751d4414acfea816641a7b26a36a6c583914c0cf..22bf06f032af3ff8ac1892d10314fc237d25b0d6 100644 (file)
@@ -109,6 +109,7 @@ static const ERR_STRING_DATA ASN1_str_functs[] = {
      "d2i_AutoPrivateKey"},
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PRIVATEKEY, 0), "d2i_PrivateKey"},
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PUBLICKEY, 0), "d2i_PublicKey"},
+    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_BUF, 0), "do_buf"},
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_CREATE, 0), "do_create"},
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_DUMP, 0), "do_dump"},
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_TCREATE, 0), "do_tcreate"},
index 155a8f37392c1d8f5fc0cb29e430e7180cc089ab..209bd0d3c397591b4408a109ce8395045d1ac778 100644 (file)
@@ -82,6 +82,7 @@ ASN1_F_D2I_ASN1_UINTEGER:150:d2i_ASN1_UINTEGER
 ASN1_F_D2I_AUTOPRIVATEKEY:207:d2i_AutoPrivateKey
 ASN1_F_D2I_PRIVATEKEY:154:d2i_PrivateKey
 ASN1_F_D2I_PUBLICKEY:155:d2i_PublicKey
+ASN1_F_DO_BUF:142:do_buf
 ASN1_F_DO_CREATE:124:do_create
 ASN1_F_DO_DUMP:125:do_dump
 ASN1_F_DO_TCREATE:222:do_tcreate
index 9697898f97934b23f6684973379258112eef3a0e..048a737b142ae7b2eebbfb61c46be0c3dc78c6e5 100644 (file)
@@ -95,6 +95,7 @@ int ERR_load_ASN1_strings(void);
 # define ASN1_F_D2I_AUTOPRIVATEKEY                        207
 # define ASN1_F_D2I_PRIVATEKEY                            154
 # define ASN1_F_D2I_PUBLICKEY                             155
+# define ASN1_F_DO_BUF                                    142
 # define ASN1_F_DO_CREATE                                 124
 # define ASN1_F_DO_DUMP                                   125
 # define ASN1_F_DO_TCREATE                                222